/* * Copyright (c) 2012-2015 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package org.red5.server.mqtt.codec.parser; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.eclipse.moquette.proto.messages.AbstractMessage; import org.eclipse.moquette.proto.messages.PublishMessage; import org.red5.server.mqtt.codec.MQTTDecoder; import org.red5.server.mqtt.codec.MQTTProtocol; import org.red5.server.mqtt.codec.exception.CorruptedFrameException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Publish decoder. * * @author andrea * @author Paul Gregoire */ public class PublishDecoder extends DemuxDecoder { private static Logger LOG = LoggerFactory.getLogger(PublishDecoder.class); @Override public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { LOG.info("decode invoked with buffer {}", in); in.reset(); int startPos = in.markValue(); //Common decoding part PublishMessage message = new PublishMessage(); if (!decodeCommonHeader(message, in)) { LOG.info("decode ask for more data after {}", in); in.reset(); return; } if (((int) session.getAttribute(MQTTDecoder.PROTOCOL_VERSION)) == MQTTProtocol.VERSION_3_1_1) { if (message.getQos() == AbstractMessage.QOSType.MOST_ONE && message.isDupFlag()) { //bad protocol, if QoS=0 => DUP = 0 throw new CorruptedFrameException("Received a PUBLISH with QoS=0 & DUP = 1, MQTT 3.1.1 violation"); } if (message.getQos() == AbstractMessage.QOSType.RESERVED) { throw new CorruptedFrameException("Received a PUBLISH with QoS flags setted 10 b11, MQTT 3.1.1 violation"); } } int remainingLength = message.getRemainingLength(); //Topic name String topic = MQTTProtocol.decodeString(in); if (topic == null) { in.reset(); return; } if (topic.contains("+") || topic.contains("#")) { throw new CorruptedFrameException("Received a PUBLISH with topic containting wild card chars, topic: " + topic); } message.setTopicName(topic); if (message.getQos() == AbstractMessage.QOSType.LEAST_ONE || message.getQos() == AbstractMessage.QOSType.EXACTLY_ONCE) { message.setMessageID(in.getUnsignedShort()); } int stopPos = in.position(); //read the payload int payloadSize = remainingLength - (stopPos - startPos - 2) + (MQTTProtocol.numBytesToEncode(remainingLength) - 1); LOG.info("payload size: {}", payloadSize); if (in.remaining() < payloadSize) { in.reset(); return; } byte[] payload = new byte[payloadSize]; in.get(payload); message.setPayload(payload); out.write(message); } }