/// <summary> /// Parse bytes for a CONNACK message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>CONNACK message instance</returns> public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; MqttMsgConnack msg = new MqttMsgConnack(); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } } // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] ... set session present flag ... msg.sessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00; } // ...and set return code from broker msg.returnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET]; return(msg); }
public static MqttMsgPuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { int num1 = 0; MqttMsgPuback mqttMsgPuback1 = new MqttMsgPuback(); if (protocolVersion == (byte)4 && ((uint)fixedHeaderFirstByte & 15U) > 0U) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } byte[] buffer = new byte[MqttMsgBase.decodeRemainingLength(channel)]; channel.Receive(buffer); MqttMsgPuback mqttMsgPuback2 = mqttMsgPuback1; byte[] numArray1 = buffer; int index1 = num1; int num2 = checked (index1 + 1); int num3 = (int)checked ((ushort)((int)numArray1[index1] << 8 & 65280)); mqttMsgPuback2.messageId = (ushort)num3; MqttMsgPuback mqttMsgPuback3 = mqttMsgPuback1; int messageId = (int)mqttMsgPuback3.messageId; byte[] numArray2 = buffer; int index2 = num2; int num4 = checked (index2 + 1); int num5 = (int)numArray2[index2]; mqttMsgPuback3.messageId = (ushort)(messageId | num5); return(mqttMsgPuback1); }
/// <summary> /// Parse bytes for a SUBACK message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>SUBACK message instance</returns> public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttMsgSuback msg = new MqttMsgSuback(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); // payload contains QoS levels granted msg.grantedQosLevels = new byte[remainingLength - MESSAGE_ID_SIZE]; int qosIdx = 0; do { msg.grantedQosLevels[qosIdx++] = buffer[index++]; } while (index < remainingLength); return(msg); }
/// <summary> /// Parse bytes for a PUBREC message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PUBREC message instance</returns> public static MqttMsgPubrec Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttMsgPubrec msg = new MqttMsgPubrec(); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREC_FLAG_BITS) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } } // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); return(msg); }
/// <summary> /// Parse bytes for a PUBREL message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="socket">Socket connected to the broker</param> /// <returns>PUBREL message instance</returns> public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, Socket socket) { byte[] buffer; int index = 0; MqttMsgPubrel msg = new MqttMsgPubrel(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(socket); buffer = new byte[remainingLength]; // read bytes from socket... socket.Receive(buffer); // read QoS level from fixed header (would be QoS Level 1) msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // read DUP flag from fixed header msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); return(msg); }
public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { int num1 = 0; MqttMsgPubrel mqttMsgPubrel1 = new MqttMsgPubrel(); if (protocolVersion == (byte)4 && ((int)fixedHeaderFirstByte & 15) != 2) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } byte[] buffer = new byte[MqttMsgBase.decodeRemainingLength(channel)]; channel.Receive(buffer); if (protocolVersion == (byte)3) { mqttMsgPubrel1.qosLevel = checked ((byte)(((int)fixedHeaderFirstByte & 6) >> 1)); mqttMsgPubrel1.dupFlag = ((int)fixedHeaderFirstByte & 8) >> 3 == 1; } MqttMsgPubrel mqttMsgPubrel2 = mqttMsgPubrel1; byte[] numArray1 = buffer; int index1 = num1; int num2 = checked (index1 + 1); int num3 = (int)checked ((ushort)((int)numArray1[index1] << 8 & 65280)); mqttMsgPubrel2.messageId = (ushort)num3; MqttMsgPubrel mqttMsgPubrel3 = mqttMsgPubrel1; int messageId = (int)mqttMsgPubrel3.messageId; byte[] numArray2 = buffer; int index2 = num2; int num4 = checked (index2 + 1); int num5 = (int)numArray2[index2]; mqttMsgPubrel3.messageId = (ushort)(messageId | num5); return(mqttMsgPubrel1); }
/// <summary> /// Parse bytes for a UNSUBSCRIBE message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>UNSUBSCRIBE message instance</returns> public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... //int received = channel.Receive(buffer); channel.Receive(buffer); // read QoS level from fixed header msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // read DUP flag from fixed header msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); // retain flag not used msg.retain = false; // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); // payload contains topics // NOTE : before, I don't know how many topics will be in the payload (so use List) // if .Net Micro Framework #if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) IList tmpTopics = new ArrayList(); // else other frameworks (.Net, .Net Compact, Mono, Windows Phone) #else IList <String> tmpTopics = new List <String>(); #endif do { // topic name topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length |= buffer[index++]; topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); index += topicUtf8Length; tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8))); } while (index < remainingLength); // copy from list to array msg.topics = new string[tmpTopics.Count]; for (int i = 0; i < tmpTopics.Count; i++) { msg.topics[i] = (string)tmpTopics[i]; } return(msg); }
/// <summary> /// Parse bytes for a PINGRESP message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="socket">Socket connected to the broker</param> /// <returns>PINGRESP message instance</returns> public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, Socket socket) { MqttMsgPingResp msg = new MqttMsgPingResp(); // already know remaininglength is zero (MQTT specification), // so it isn't necessary to read other data from socket int remainingLength = MqttMsgBase.decodeRemainingLength(socket); return(msg); }
public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { MqttMsgPingResp mqttMsgPingResp = new MqttMsgPingResp(); if (protocolVersion == (byte)4 && ((uint)fixedHeaderFirstByte & 15U) > 0U) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } MqttMsgBase.decodeRemainingLength(channel); return(mqttMsgPingResp); }
public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, Socket socket) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgPublish msg = new MqttMsgPublish(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(socket); buffer = new byte[remainingLength]; // read bytes from socket... socket.Receive(buffer); // topic name topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length |= buffer[index++]; topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); index += topicUtf8Length; msg.topic = new String(Encoding.UTF8.GetChars(topicUtf8)); // read QoS level from fixed header msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // read DUP flag from fixed header msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); // read retain flag from fixed header msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01); // message id is valid only with QOS level 1 or QOS level 2 if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); } // get payload with message data msg.message = new byte[remainingLength - index]; Array.Copy(buffer, index, msg.message, 0, msg.message.Length); return(msg); }
/// <summary> /// Parse bytes for a CONNACK message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>CONNACK message instance</returns> public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { byte[] buffer; MqttMsgConnack msg = new MqttMsgConnack(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); // ...and set return code from broker msg.returnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET]; return(msg); }
public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { MqttMsgConnack mqttMsgConnack = new MqttMsgConnack(); if (protocolVersion == (byte)4 && ((uint)fixedHeaderFirstByte & 15U) > 0U) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } byte[] buffer = new byte[MqttMsgBase.decodeRemainingLength(channel)]; channel.Receive(buffer); if (protocolVersion == (byte)4) { mqttMsgConnack.sessionPresent = ((uint)buffer[0] & 1U) > 0U; } mqttMsgConnack.returnCode = buffer[1]; return(mqttMsgConnack); }
/// <summary> /// Parse bytes for a DISCONNECT message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>DISCONNECT message instance</returns> public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { MqttMsgDisconnect msg = new MqttMsgDisconnect(); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } } // get remaining length and allocate buffer MqttMsgBase.decodeRemainingLength(channel); // NOTE : remainingLength must be 0 return(msg); }
/// <summary> /// Parse bytes for a PINGRESP message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PINGRESP message instance</returns> public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { MqttMsgPingResp msg = new MqttMsgPingResp(); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGRESP_FLAG_BITS) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } } // already know remaininglength is zero (MQTT specification), // so it isn't necessary to read other data from socket int remainingLength = MqttMsgBase.decodeRemainingLength(channel); return(msg); }
/// <summary> /// Parse bytes for a UNSUBACK message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="socket">Socket connected to the broker</param> /// <returns>UNSUBACK message instance</returns> public static MqttMsgUnsuback Parse(byte fixedHeaderFirstByte, Socket socket) { byte[] buffer; int index = 0; MqttMsgUnsuback msg = new MqttMsgUnsuback(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(socket); buffer = new byte[remainingLength]; // read bytes from socket... socket.Receive(buffer); // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); return(msg); }
/// <summary> /// Parse bytes for a PUBREL message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PUBREL message instance</returns> public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttMsgPubrel msg = new MqttMsgPubrel(); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREL_FLAG_BITS) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } } // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) { // only 3.1.0 // read QoS level from fixed header (would be QoS Level 1) msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // read DUP flag from fixed header msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); } // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); return(msg); }
/// <summary> /// Parse bytes for a SUBACK message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>SUBACK message instance</returns> public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttMsgSuback msg = new MqttMsgSuback(); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBACK_FLAG_BITS) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } } // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); // payload contains QoS levels granted msg.grantedQosLevels = new byte[remainingLength - MESSAGE_ID_SIZE]; int qosIdx = 0; do { msg.grantedQosLevels[qosIdx++] = buffer[index++]; } while (index < remainingLength); return(msg); }
public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { int num1 = 0; MqttMsgPublish mqttMsgPublish1 = new MqttMsgPublish(); int length1 = MqttMsgBase.decodeRemainingLength(channel); byte[] buffer = new byte[length1]; int num2 = channel.Receive(buffer); byte[] numArray1 = buffer; int index1 = num1; int num3 = checked (index1 + 1); int num4 = (int)numArray1[index1] << 8 & 65280; byte[] numArray2 = buffer; int index2 = num3; int sourceIndex1 = checked (index2 + 1); int num5 = (int)numArray2[index2]; int length2 = num4 | num5; byte[] bytes = new byte[length2]; Array.Copy((Array)buffer, sourceIndex1, (Array)bytes, 0, length2); int sourceIndex2 = checked (sourceIndex1 + length2); mqttMsgPublish1.topic = new string(Encoding.UTF8.GetChars(bytes)); mqttMsgPublish1.qosLevel = checked ((byte)(((int)fixedHeaderFirstByte & 6) >> 1)); if (mqttMsgPublish1.qosLevel > (byte)2) { throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); } mqttMsgPublish1.dupFlag = ((int)fixedHeaderFirstByte & 8) >> 3 == 1; mqttMsgPublish1.retain = ((int)fixedHeaderFirstByte & 1) == 1; if (mqttMsgPublish1.qosLevel == (byte)1 || mqttMsgPublish1.qosLevel == (byte)2) { MqttMsgPublish mqttMsgPublish2 = mqttMsgPublish1; byte[] numArray3 = buffer; int index3 = sourceIndex2; int num6 = checked (index3 + 1); int num7 = (int)checked ((ushort)((int)numArray3[index3] << 8 & 65280)); mqttMsgPublish2.messageId = (ushort)num7; MqttMsgPublish mqttMsgPublish3 = mqttMsgPublish1; int messageId = (int)mqttMsgPublish3.messageId; byte[] numArray4 = buffer; int index4 = num6; sourceIndex2 = checked (index4 + 1); int num8 = (int)numArray4[index4]; mqttMsgPublish3.messageId = (ushort)(messageId | num8); } int length3 = checked (length1 - sourceIndex2); int num9 = length3; int destinationIndex1 = 0; mqttMsgPublish1.message = new byte[length3]; Array.Copy((Array)buffer, sourceIndex2, (Array)mqttMsgPublish1.message, destinationIndex1, checked (num2 - sourceIndex2)); int num10 = checked (num9 - num2 - sourceIndex2); int destinationIndex2 = checked (destinationIndex1 + num2 - sourceIndex2); while (num10 > 0) { int length4 = channel.Receive(buffer); Array.Copy((Array)buffer, 0, (Array)mqttMsgPublish1.message, destinationIndex2, length4); checked { num10 -= length4; } checked { destinationIndex2 += length4; } } return(mqttMsgPublish1); }
/// <summary> /// Parse bytes for a SUBSCRIBE message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>SUBSCRIBE message instance</returns> public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgSubscribe msg = new MqttMsgSubscribe(); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } } // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... int received = channel.Receive(buffer); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) { // only 3.1.0 // read QoS level from fixed header msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // read DUP flag from fixed header msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); // retain flag not used msg.retain = false; } // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); // payload contains topics and QoS levels // NOTE : before, I don't know how many topics will be in the payload (so use List) // if .Net Micro Framework #if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) IList tmpTopics = new ArrayList(); IList tmpQosLevels = new ArrayList(); // else other frameworks (.Net, .Net Compact, Mono, Windows Phone) #else IList <String> tmpTopics = new List <String>(); IList <byte> tmpQosLevels = new List <byte>(); #endif do { // topic name topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length |= buffer[index++]; topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); index += topicUtf8Length; tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8))); // QoS level tmpQosLevels.Add(buffer[index++]); } while (index < remainingLength); // copy from list to array msg.topics = new string[tmpTopics.Count]; msg.qosLevels = new byte[tmpQosLevels.Count]; for (int i = 0; i < tmpTopics.Count; i++) { msg.topics[i] = (string)tmpTopics[i]; msg.qosLevels[i] = (byte)tmpQosLevels[i]; } return(msg); }
/// <summary> /// Constructor /// </summary> /// <param name="msg">Related message</param> public MsgInternalEvent(MqttMsgBase msg) { this.msg = msg; }
/// <summary> /// Enqueue a message into the inflight queue /// </summary> /// <param name="msg">Message to enqueue</param> /// <param name="flow">Message flow (publish, acknowledge)</param> private void EnqueueInflight(MqttMsgBase msg, MqttMsgFlow flow) { // enqueue is needed (or not) bool enqueue = true; // if it is a PUBLISH message with QoS Level 2 if ((msg.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && (msg.QosLevel == MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE)) { lock (this.inflightQueue) { // if it is a PUBLISH message already received (it is in the inflight queue), the publisher // re-sent it because it didn't received the PUBREC. In this case, we have to re-send PUBREC // NOTE : I need to find on message id and flow because the broker could be publish/received // to/from client and message id could be the same (one tracked by broker and the other by client) MqttMsgContextFinder msgCtxFinder = new MqttMsgContextFinder(((MqttMsgPublish)msg).MessageId, MqttMsgFlow.ToAcknowledge); MqttMsgContext msgCtx = (MqttMsgContext)this.inflightQueue.Get(msgCtxFinder.Find); // the PUBLISH message is alredy in the inflight queue, we don't need to re-enqueue but we need // to change state to re-send PUBREC if (msgCtx != null) { msgCtx.State = MqttMsgState.QueuedQos2; msgCtx.Flow = MqttMsgFlow.ToAcknowledge; enqueue = false; } } } if (enqueue) { // set a default state MqttMsgState state = MqttMsgState.QueuedQos0; // based on QoS level, the messages flow between broker and client changes switch (msg.QosLevel) { // QoS Level 0 case MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE: state = MqttMsgState.QueuedQos0; break; // QoS Level 1 case MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE: state = MqttMsgState.QueuedQos1; break; // QoS Level 2 case MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE: state = MqttMsgState.QueuedQos2; break; } // queue message context MqttMsgContext msgContext = new MqttMsgContext() { Message = msg, State = state, Flow = flow, Attempt = 0 }; lock (this.inflightQueue) { // enqueue message and unlock send thread this.inflightQueue.Enqueue(msgContext); } } this.inflightWaitHandle.Set(); }
/// <summary> /// Parse bytes for a CONNECT message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>CONNECT message instance</returns> public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; int protNameUtf8Length; byte[] protNameUtf8; bool isUsernameFlag; bool isPasswordFlag; int clientIdUtf8Length; byte[] clientIdUtf8; int willTopicUtf8Length; byte[] willTopicUtf8; int willMessageUtf8Length; byte[] willMessageUtf8; int usernameUtf8Length; byte[] usernameUtf8; int passwordUtf8Length; byte[] passwordUtf8; MqttMsgConnect msg = new MqttMsgConnect(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); // protocol name protNameUtf8Length = ((buffer[index++] << 8) & 0xFF00); protNameUtf8Length |= buffer[index++]; protNameUtf8 = new byte[protNameUtf8Length]; Array.Copy(buffer, index, protNameUtf8, 0, protNameUtf8Length); index += protNameUtf8Length; msg.protocolName = new String(Encoding.UTF8.GetChars(protNameUtf8)); // protocol version msg.protocolVersion = buffer[index]; index += PROTOCOL_VERSION_NUMBER_SIZE; // connect flags isUsernameFlag = (buffer[index] & USERNAME_FLAG_MASK) != 0x00; isPasswordFlag = (buffer[index] & PASSWORD_FLAG_MASK) != 0x00; msg.willRetain = (buffer[index] & WILL_RETAIN_FLAG_MASK) != 0x00; msg.willQosLevel = (byte)((buffer[index] & WILL_QOS_FLAG_MASK) >> WILL_QOS_FLAG_OFFSET); msg.willFlag = (buffer[index] & WILL_FLAG_MASK) != 0x00; msg.cleanSession = (buffer[index] & CLEAN_SESSION_FLAG_MASK) != 0x00; index += CONNECT_FLAGS_SIZE; // keep alive timer msg.keepAlivePeriod = (ushort)((buffer[index++] << 8) & 0xFF00); msg.keepAlivePeriod |= buffer[index++]; // client identifier clientIdUtf8Length = ((buffer[index++] << 8) & 0xFF00); clientIdUtf8Length |= buffer[index++]; clientIdUtf8 = new byte[clientIdUtf8Length]; Array.Copy(buffer, index, clientIdUtf8, 0, clientIdUtf8Length); index += clientIdUtf8Length; msg.clientId = new String(Encoding.UTF8.GetChars(clientIdUtf8)); // will topic and will message if (msg.willFlag) { willTopicUtf8Length = ((buffer[index++] << 8) & 0xFF00); willTopicUtf8Length |= buffer[index++]; willTopicUtf8 = new byte[willTopicUtf8Length]; Array.Copy(buffer, index, willTopicUtf8, 0, willTopicUtf8Length); index += willTopicUtf8Length; msg.willTopic = new String(Encoding.UTF8.GetChars(willTopicUtf8)); willMessageUtf8Length = ((buffer[index++] << 8) & 0xFF00); willMessageUtf8Length |= buffer[index++]; willMessageUtf8 = new byte[willMessageUtf8Length]; Array.Copy(buffer, index, willMessageUtf8, 0, willMessageUtf8Length); index += willMessageUtf8Length; msg.willMessage = new String(Encoding.UTF8.GetChars(willMessageUtf8)); } // username if (isUsernameFlag) { usernameUtf8Length = ((buffer[index++] << 8) & 0xFF00); usernameUtf8Length |= buffer[index++]; usernameUtf8 = new byte[usernameUtf8Length]; Array.Copy(buffer, index, usernameUtf8, 0, usernameUtf8Length); index += usernameUtf8Length; msg.username = new String(Encoding.UTF8.GetChars(usernameUtf8)); } // password if (isPasswordFlag) { passwordUtf8Length = ((buffer[index++] << 8) & 0xFF00); passwordUtf8Length |= buffer[index++]; passwordUtf8 = new byte[passwordUtf8Length]; Array.Copy(buffer, index, passwordUtf8, 0, passwordUtf8Length); index += passwordUtf8Length; msg.password = new String(Encoding.UTF8.GetChars(passwordUtf8)); } return(msg); }
public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { int num1 = 0; MqttMsgConnect mqttMsgConnect1 = new MqttMsgConnect(); byte[] buffer = new byte[MqttMsgBase.decodeRemainingLength(channel)]; channel.Receive(buffer); byte[] numArray1 = buffer; int index1 = num1; int num2 = checked (index1 + 1); int num3 = (int)numArray1[index1] << 8 & 65280; byte[] numArray2 = buffer; int index2 = num2; int sourceIndex1 = checked (index2 + 1); int num4 = (int)numArray2[index2]; int length1 = num3 | num4; byte[] bytes1 = new byte[length1]; Array.Copy((Array)buffer, sourceIndex1, (Array)bytes1, 0, length1); int index3 = checked (sourceIndex1 + length1); mqttMsgConnect1.protocolName = new string(Encoding.UTF8.GetChars(bytes1)); if (!mqttMsgConnect1.protocolName.Equals("MQIsdp") && !mqttMsgConnect1.protocolName.Equals("MQTT")) { throw new MqttClientException(MqttClientErrorCode.InvalidProtocolName); } mqttMsgConnect1.protocolVersion = buffer[index3]; int index4 = checked (index3 + 1); if (mqttMsgConnect1.protocolVersion == (byte)4 && ((uint)buffer[index4] & 1U) > 0U) { throw new MqttClientException(MqttClientErrorCode.InvalidConnectFlags); } bool flag1 = ((uint)buffer[index4] & 128U) > 0U; bool flag2 = ((uint)buffer[index4] & 64U) > 0U; mqttMsgConnect1.willRetain = ((uint)buffer[index4] & 32U) > 0U; mqttMsgConnect1.willQosLevel = checked ((byte)(((int)buffer[index4] & 24) >> 3)); mqttMsgConnect1.willFlag = ((uint)buffer[index4] & 4U) > 0U; mqttMsgConnect1.cleanSession = ((uint)buffer[index4] & 2U) > 0U; int num5 = checked (index4 + 1); MqttMsgConnect mqttMsgConnect2 = mqttMsgConnect1; byte[] numArray3 = buffer; int index5 = num5; int num6 = checked (index5 + 1); int num7 = (int)checked ((ushort)((int)numArray3[index5] << 8 & 65280)); mqttMsgConnect2.keepAlivePeriod = (ushort)num7; MqttMsgConnect mqttMsgConnect3 = mqttMsgConnect1; int keepAlivePeriod = (int)mqttMsgConnect3.keepAlivePeriod; byte[] numArray4 = buffer; int index6 = num6; int num8 = checked (index6 + 1); int num9 = (int)numArray4[index6]; mqttMsgConnect3.keepAlivePeriod = (ushort)(keepAlivePeriod | num9); byte[] numArray5 = buffer; int index7 = num8; int num10 = checked (index7 + 1); int num11 = (int)numArray5[index7] << 8 & 65280; byte[] numArray6 = buffer; int index8 = num10; int sourceIndex2 = checked (index8 + 1); int num12 = (int)numArray6[index8]; int length2 = num11 | num12; byte[] bytes2 = new byte[length2]; Array.Copy((Array)buffer, sourceIndex2, (Array)bytes2, 0, length2); int num13 = checked (sourceIndex2 + length2); mqttMsgConnect1.clientId = new string(Encoding.UTF8.GetChars(bytes2)); if (mqttMsgConnect1.protocolVersion == (byte)4 && length2 == 0 && !mqttMsgConnect1.cleanSession) { throw new MqttClientException(MqttClientErrorCode.InvalidClientId); } if (mqttMsgConnect1.willFlag) { byte[] numArray7 = buffer; int index9 = num13; int num14 = checked (index9 + 1); int num15 = (int)numArray7[index9] << 8 & 65280; byte[] numArray8 = buffer; int index10 = num14; int sourceIndex3 = checked (index10 + 1); int num16 = (int)numArray8[index10]; int length3 = num15 | num16; byte[] bytes3 = new byte[length3]; Array.Copy((Array)buffer, sourceIndex3, (Array)bytes3, 0, length3); int num17 = checked (sourceIndex3 + length3); mqttMsgConnect1.willTopic = new string(Encoding.UTF8.GetChars(bytes3)); byte[] numArray9 = buffer; int index11 = num17; int num18 = checked (index11 + 1); int num19 = (int)numArray9[index11] << 8 & 65280; byte[] numArray10 = buffer; int index12 = num18; int sourceIndex4 = checked (index12 + 1); int num20 = (int)numArray10[index12]; int length4 = num19 | num20; byte[] bytes4 = new byte[length4]; Array.Copy((Array)buffer, sourceIndex4, (Array)bytes4, 0, length4); num13 = checked (sourceIndex4 + length4); mqttMsgConnect1.willMessage = new string(Encoding.UTF8.GetChars(bytes4)); } if (flag1) { byte[] numArray7 = buffer; int index9 = num13; int num14 = checked (index9 + 1); int num15 = (int)numArray7[index9] << 8 & 65280; byte[] numArray8 = buffer; int index10 = num14; int sourceIndex3 = checked (index10 + 1); int num16 = (int)numArray8[index10]; int length3 = num15 | num16; byte[] bytes3 = new byte[length3]; Array.Copy((Array)buffer, sourceIndex3, (Array)bytes3, 0, length3); num13 = checked (sourceIndex3 + length3); mqttMsgConnect1.username = new string(Encoding.UTF8.GetChars(bytes3)); } if (flag2) { byte[] numArray7 = buffer; int index9 = num13; int num14 = checked (index9 + 1); int num15 = (int)numArray7[index9] << 8 & 65280; byte[] numArray8 = buffer; int index10 = num14; int sourceIndex3 = checked (index10 + 1); int num16 = (int)numArray8[index10]; int length3 = num15 | num16; byte[] bytes3 = new byte[length3]; Array.Copy((Array)buffer, sourceIndex3, (Array)bytes3, 0, length3); int num17 = checked (sourceIndex3 + length3); mqttMsgConnect1.password = new string(Encoding.UTF8.GetChars(bytes3)); } return(mqttMsgConnect1); }
/// <summary> /// Thread for receiving messages from broker /// </summary> private void ReceiveThread() { int readBytes; byte[] fixedHeaderFirstByte = new byte[1]; byte msgType; while (this.isRunning) { try { // read first byte (fixed header) readBytes = this.socket.Receive(fixedHeaderFirstByte); if (readBytes > 0) { // extract message type from received byte msgType = (byte)((fixedHeaderFirstByte[0] & MqttMsgBase.MSG_TYPE_MASK) >> MqttMsgBase.MSG_TYPE_OFFSET); switch (msgType) { // impossible, broker can't send CONNECT message case MqttMsgBase.MQTT_MSG_CONNECT_TYPE: throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); // CONNACK message received from broker case MqttMsgBase.MQTT_MSG_CONNACK_TYPE: this.msgReceived = MqttMsgConnack.Parse(fixedHeaderFirstByte[0], this.socket); this.endReceiving.Set(); break; // impossible, broker can't send PINGREQ message case MqttMsgBase.MQTT_MSG_PINGREQ_TYPE: throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); // CONNACK message received from broker case MqttMsgBase.MQTT_MSG_PINGRESP_TYPE: this.msgReceived = MqttMsgPingResp.Parse(fixedHeaderFirstByte[0], this.socket); this.endReceiving.Set(); break; // impossible, broker can't send SUBSCRIBE message case MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE: throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); // SUBACK message received from broker case MqttMsgBase.MQTT_MSG_SUBACK_TYPE: this.msgReceived = MqttMsgSuback.Parse(fixedHeaderFirstByte[0], this.socket); this.endReceiving.Set(); // raise subscribed topic event (SUBACK message received) this.OnMqttMsgSubscribed((MqttMsgSuback)this.msgReceived); break; // PUBLISH message received from broker case MqttMsgBase.MQTT_MSG_PUBLISH_TYPE: MqttMsgPublish msgReceived = MqttMsgPublish.Parse(fixedHeaderFirstByte[0], this.socket); // for QoS Level 1 and 2, client sends PUBACK message to broker if ((this.msgReceived.QosLevel == MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE) || (this.msgReceived.QosLevel == MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE)) { MqttMsgPuback puback = new MqttMsgPuback(); puback.MessageId = (msgReceived).MessageId; this.Send(puback.GetBytes()); } // raise PUBLISH message received event this.OnMqttMsgPublishReceived(msgReceived); break; // PUBACK message received from broker case MqttMsgBase.MQTT_MSG_PUBACK_TYPE: this.msgReceived = MqttMsgPuback.Parse(fixedHeaderFirstByte[0], this.socket); this.endReceiving.Set(); // raise published message event // (PUBACK received for QoS Level 1) this.OnMqttMsgPublished(((MqttMsgPuback)this.msgReceived).MessageId); break; // PUBREC message received from broker case MqttMsgBase.MQTT_MSG_PUBREC_TYPE: this.msgReceived = MqttMsgPubrec.Parse(fixedHeaderFirstByte[0], this.socket); this.endReceiving.Set(); break; // impossible, broker can't send PUBREL message case MqttMsgBase.MQTT_MSG_PUBREL_TYPE: throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); // PUBCOMP message received from broker case MqttMsgBase.MQTT_MSG_PUBCOMP_TYPE: this.msgReceived = MqttMsgPubcomp.Parse(fixedHeaderFirstByte[0], this.socket); this.endReceiving.Set(); // raise published message event // (PUBCOMP received for QoS Level 2) this.OnMqttMsgPublished(((MqttMsgPuback)this.msgReceived).MessageId); break; // impossible, broker can't send UNSUBSCRIBE message case MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE: throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); // UNSUBACK message received from broker case MqttMsgBase.MQTT_MSG_UNSUBACK_TYPE: this.msgReceived = MqttMsgUnsuback.Parse(fixedHeaderFirstByte[0], this.socket); this.endReceiving.Set(); // raise unsubscribed topic event this.OnMqttMsgUnsubscribed(((MqttMsgUnsuback)this.msgReceived).MessageId); break; default: throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); } this.exReceiving = null; } } catch (Exception) { this.exReceiving = new MqttCommunicationException(); } } }
/// <summary> /// Thread for receiving messages /// </summary> private void ReceiveThread() { int readBytes = 0; byte[] fixedHeaderFirstByte = new byte[1]; byte msgType; #if BROKER long now = 0; // receive thread started, broker need to receive the first message // (CONNECT) within a reasonable amount of time after TCP/IP connection long connectTime = Environment.TickCount; #endif while (this.isRunning) { try { if (this.channel.DataAvailable) // read first byte (fixed header) readBytes = this.channel.Receive(fixedHeaderFirstByte); else { #if BROKER // client not connected (client didn't send CONNECT yet) if (!this.IsConnected) { now = Environment.TickCount; // if connect timeout exceeded ... if ((now - connectTime) >= this.settings.TimeoutOnConnection) { // client must close connection this.Close(); // client raw disconnection this.OnMqttMsgDisconnected(); } } #endif // no bytes available, sleep before retry readBytes = 0; Thread.Sleep(10); } if (readBytes > 0) { #if BROKER // update last message received ticks this.lastCommTime = Environment.TickCount; #endif // extract message type from received byte msgType = (byte)((fixedHeaderFirstByte[0] & MqttMsgBase.MSG_TYPE_MASK) >> MqttMsgBase.MSG_TYPE_OFFSET); switch (msgType) { // CONNECT message received case MqttMsgBase.MQTT_MSG_CONNECT_TYPE: #if BROKER MqttMsgConnect connect = MqttMsgConnect.Parse(fixedHeaderFirstByte[0], this.channel); Trace.WriteLine(TraceLevel.Frame, "RECV {0}", connect); // raise message received event this.OnMqttMsgReceived(connect); break; #else throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); #endif // CONNACK message received case MqttMsgBase.MQTT_MSG_CONNACK_TYPE: #if BROKER throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); #else this.msgReceived = MqttMsgConnack.Parse(fixedHeaderFirstByte[0], this.channel); MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", this.msgReceived); this.syncEndReceiving.Set(); break; #endif // PINGREQ message received case MqttMsgBase.MQTT_MSG_PINGREQ_TYPE: #if BROKER this.msgReceived = MqttMsgPingReq.Parse(fixedHeaderFirstByte[0], this.channel); Trace.WriteLine(TraceLevel.Frame, "RECV {0}", this.msgReceived); MqttMsgPingResp pingresp = new MqttMsgPingResp(); this.Send(pingresp); // raise message received event //this.OnMqttMsgReceived(this.msgReceived); break; #else throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); #endif // PINGRESP message received case MqttMsgBase.MQTT_MSG_PINGRESP_TYPE: #if BROKER throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); #else this.msgReceived = MqttMsgPingResp.Parse(fixedHeaderFirstByte[0], this.channel); MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", this.msgReceived); this.syncEndReceiving.Set(); break; #endif // SUBSCRIBE message received case MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE: #if BROKER MqttMsgSubscribe subscribe = MqttMsgSubscribe.Parse(fixedHeaderFirstByte[0], this.channel); Trace.WriteLine(TraceLevel.Frame, "RECV {0}", subscribe); // raise message received event this.OnMqttMsgReceived(subscribe); break; #else throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); #endif // SUBACK message received case MqttMsgBase.MQTT_MSG_SUBACK_TYPE: #if BROKER throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); #else // enqueue SUBACK message received (for QoS Level 1) into the internal queue MqttMsgSuback suback = MqttMsgSuback.Parse(fixedHeaderFirstByte[0], this.channel); MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", suback); // enqueue SUBACK message into the internal queue this.EnqueueInternal(suback); break; #endif // PUBLISH message received case MqttMsgBase.MQTT_MSG_PUBLISH_TYPE: MqttMsgPublish publish = MqttMsgPublish.Parse(fixedHeaderFirstByte[0], this.channel); MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", publish); // enqueue PUBLISH message to acknowledge into the inflight queue this.EnqueueInflight(publish, MqttMsgFlow.ToAcknowledge); break; // PUBACK message received case MqttMsgBase.MQTT_MSG_PUBACK_TYPE: // enqueue PUBACK message received (for QoS Level 1) into the internal queue MqttMsgPuback puback = MqttMsgPuback.Parse(fixedHeaderFirstByte[0], this.channel); MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", puback); // enqueue PUBACK message into the internal queue this.EnqueueInternal(puback); break; // PUBREC message received case MqttMsgBase.MQTT_MSG_PUBREC_TYPE: // enqueue PUBREC message received (for QoS Level 2) into the internal queue MqttMsgPubrec pubrec = MqttMsgPubrec.Parse(fixedHeaderFirstByte[0], this.channel); MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", pubrec); // enqueue PUBREC message into the internal queue this.EnqueueInternal(pubrec); break; // PUBREL message received case MqttMsgBase.MQTT_MSG_PUBREL_TYPE: // enqueue PUBREL message received (for QoS Level 2) into the internal queue MqttMsgPubrel pubrel = MqttMsgPubrel.Parse(fixedHeaderFirstByte[0], this.channel); MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", pubrel); // enqueue PUBREL message into the internal queue this.EnqueueInternal(pubrel); break; // PUBCOMP message received case MqttMsgBase.MQTT_MSG_PUBCOMP_TYPE: // enqueue PUBCOMP message received (for QoS Level 2) into the internal queue MqttMsgPubcomp pubcomp = MqttMsgPubcomp.Parse(fixedHeaderFirstByte[0], this.channel); MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", pubcomp); // enqueue PUBCOMP message into the internal queue this.EnqueueInternal(pubcomp); break; // UNSUBSCRIBE message received case MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE: #if BROKER MqttMsgUnsubscribe unsubscribe = MqttMsgUnsubscribe.Parse(fixedHeaderFirstByte[0], this.channel); Trace.WriteLine(TraceLevel.Frame, "RECV {0}", unsubscribe); // raise message received event this.OnMqttMsgReceived(unsubscribe); break; #else throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); #endif // UNSUBACK message received case MqttMsgBase.MQTT_MSG_UNSUBACK_TYPE: #if BROKER throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); #else // enqueue UNSUBACK message received (for QoS Level 1) into the internal queue MqttMsgUnsuback unsuback = MqttMsgUnsuback.Parse(fixedHeaderFirstByte[0], this.channel); MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", unsuback); // enqueue UNSUBACK message into the internal queue this.EnqueueInternal(unsuback); break; #endif // DISCONNECT message received case MqttMsgDisconnect.MQTT_MSG_DISCONNECT_TYPE: #if BROKER MqttMsgDisconnect disconnect = MqttMsgDisconnect.Parse(fixedHeaderFirstByte[0], this.channel); Trace.WriteLine(TraceLevel.Frame, "RECV {0}", disconnect); // raise message received event this.OnMqttMsgReceived(disconnect); break; #else throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); #endif default: throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); } this.exReceiving = null; } } catch (Exception e) { MqttUtility.Trace.WriteLine(TraceLevel.Error, "Exception occurred: {0}", e.ToString()); this.exReceiving = new MqttCommunicationException(e); } } }
/// <summary> /// Enqueue a message into the internal queue /// </summary> /// <param name="msg">Message to enqueue</param> private void EnqueueInternal(MqttMsgBase msg) { // enqueue is needed (or not) bool enqueue = true; // if it is a PUBREL message (for QoS Level 2) if (msg.Type == MqttMsgBase.MQTT_MSG_PUBREL_TYPE) { lock (this.inflightQueue) { // if it is a PUBREL but the corresponding PUBLISH isn't in the inflight queue, // it means that we processed PUBLISH message and received PUBREL and we sent PUBCOMP // but publisher didn't receive PUBCOMP so it re-sent PUBREL. We need only to re-send PUBCOMP. // NOTE : I need to find on message id and flow because the broker could be publish/received // to/from client and message id could be the same (one tracked by broker and the other by client) MqttMsgContextFinder msgCtxFinder = new MqttMsgContextFinder(((MqttMsgPubrel)msg).MessageId, MqttMsgFlow.ToAcknowledge); MqttMsgContext msgCtx = (MqttMsgContext)this.inflightQueue.Get(msgCtxFinder.Find); // the PUBLISH message isn't in the inflight queue, it was already processed so // we need to re-send PUBCOMP only if (msgCtx == null) { MqttMsgPubcomp pubcomp = new MqttMsgPubcomp(); pubcomp.MessageId = ((MqttMsgPubrel)msg).MessageId; this.Send(pubcomp); enqueue = false; } } } if (enqueue) { lock (this.internalQueue) { this.internalQueue.Enqueue(msg); this.inflightWaitHandle.Set(); } } }
/// <summary> /// Constructor /// </summary> /// <param name="msg">Message published</param> /// <param name="isPublished">Publish flag</param> public MsgPublishedInternalEvent(MqttMsgBase msg, bool isPublished) : base(msg) { this.isPublished = isPublished; }
/// <summary> /// Wrapper method for raising message received event /// </summary> /// <param name="msg">Message received</param> private void OnMqttMsgReceived(MqttMsgBase msg) { lock (this.receiveQueue) { this.receiveQueue.Enqueue(msg); } this.receiveEventWaitHandle.Set(); }
/// <summary> /// Send a message /// </summary> /// <param name="msg">Message</param> private void Send(MqttMsgBase msg) { MqttUtility.Trace.WriteLine(TraceLevel.Frame, "SEND {0}", msg); this.Send(msg.GetBytes()); }
public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { int num1 = 0; MqttMsgSubscribe mqttMsgSubscribe1 = new MqttMsgSubscribe(); if (protocolVersion == (byte)4 && ((int)fixedHeaderFirstByte & 15) != 2) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } int length1 = MqttMsgBase.decodeRemainingLength(channel); byte[] buffer = new byte[length1]; channel.Receive(buffer); if (protocolVersion == (byte)3) { mqttMsgSubscribe1.qosLevel = checked ((byte)(((int)fixedHeaderFirstByte & 6) >> 1)); mqttMsgSubscribe1.dupFlag = ((int)fixedHeaderFirstByte & 8) >> 3 == 1; mqttMsgSubscribe1.retain = false; } MqttMsgSubscribe mqttMsgSubscribe2 = mqttMsgSubscribe1; byte[] numArray1 = buffer; int index1 = num1; int num2 = checked (index1 + 1); int num3 = (int)checked ((ushort)((int)numArray1[index1] << 8 & 65280)); mqttMsgSubscribe2.messageId = (ushort)num3; MqttMsgSubscribe mqttMsgSubscribe3 = mqttMsgSubscribe1; int messageId = (int)mqttMsgSubscribe3.messageId; byte[] numArray2 = buffer; int index2 = num2; int num4 = checked (index2 + 1); int num5 = (int)numArray2[index2]; mqttMsgSubscribe3.messageId = (ushort)(messageId | num5); IList <string> stringList = (IList <string>) new List <string>(); IList <byte> byteList1 = (IList <byte>) new List <byte>(); do { byte[] numArray3 = buffer; int index3 = num4; int num6 = checked (index3 + 1); int num7 = (int)numArray3[index3] << 8 & 65280; byte[] numArray4 = buffer; int index4 = num6; int sourceIndex = checked (index4 + 1); int num8 = (int)numArray4[index4]; int length2 = num7 | num8; byte[] bytes = new byte[length2]; Array.Copy((Array)buffer, sourceIndex, (Array)bytes, 0, length2); int num9 = checked (sourceIndex + length2); stringList.Add(new string(Encoding.UTF8.GetChars(bytes))); IList <byte> byteList2 = byteList1; byte[] numArray5 = buffer; int index5 = num9; num4 = checked (index5 + 1); int num10 = (int)numArray5[index5]; byteList2.Add((byte)num10); }while (num4 < length1); mqttMsgSubscribe1.topics = new string[stringList.Count]; mqttMsgSubscribe1.qosLevels = new byte[byteList1.Count]; int index6 = 0; while (index6 < stringList.Count) { mqttMsgSubscribe1.topics[index6] = stringList[index6]; mqttMsgSubscribe1.qosLevels[index6] = byteList1[index6]; checked { ++index6; } } return(mqttMsgSubscribe1); }
/// <summary> /// Send a message to the broker and wait answer /// </summary> /// <param name="msg">Message</param> /// <returns>MQTT message response</returns> private MqttMsgBase SendReceive(MqttMsgBase msg) { return this.SendReceive(msg, MqttSettings.MQTT_DEFAULT_TIMEOUT); }
/// <summary> /// Parse bytes for a PUBLISH message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PUBLISH message instance</returns> public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgPublish msg = new MqttMsgPublish(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... int received = channel.Receive(buffer); // topic name topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length |= buffer[index++]; topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); index += topicUtf8Length; msg.topic = new String(Encoding.UTF8.GetChars(topicUtf8)); // read QoS level from fixed header msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // read DUP flag from fixed header msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); // read retain flag from fixed header msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01); // message id is valid only with QOS level 1 or QOS level 2 if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); } // get payload with message data int messageSize = remainingLength - index; int remaining = messageSize; int messageOffset = 0; msg.message = new byte[messageSize]; // BUG FIX 26/07/2013 : receiving large payload // copy first part of payload data received Array.Copy(buffer, index, msg.message, messageOffset, received - index); remaining -= (received - index); messageOffset += (received - index); // if payload isn't finished while (remaining > 0) { // receive other payload data received = channel.Receive(buffer); Array.Copy(buffer, 0, msg.message, messageOffset, received); remaining -= received; messageOffset += received; } return(msg); }
/// <summary> /// Send a message to the broker and wait answer /// </summary> /// <param name="msg">Message</param> /// <param name="timeout">Timeout for receiving answer</param> /// <returns>MQTT message response</returns> private MqttMsgBase SendReceive(MqttMsgBase msg, int timeout) { MqttUtility.Trace.WriteLine(TraceLevel.Frame, "SEND {0}", msg); return this.SendReceive(msg.GetBytes(), timeout); }
/// <summary> /// Process inflight messages queue /// </summary> private void ProcessInflightThread() { MqttMsgContext msgContext = null; MqttMsgBase msgInflight = null; MqttMsgBase msgReceived = null; bool acknowledge = false; int timeout = Timeout.Infinite; try { while (this.isRunning) { #if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) // wait on message queueud to inflight this.inflightWaitHandle.WaitOne(timeout, false); #else // wait on message queueud to inflight this.inflightWaitHandle.WaitOne(timeout); #endif // it could be unblocked because Close() method is joining if (this.isRunning) { lock (this.inflightQueue) { // set timeout tu MaxValue instead of Infinte (-1) to perform // compare with calcultad current msgTimeout timeout = Int32.MaxValue; // a message inflight could be re-enqueued but we have to // analyze it only just one time for cycle int count = this.inflightQueue.Count; // process all inflight queued messages while (count > 0) { count--; acknowledge = false; msgReceived = null; // dequeue message context from queue msgContext = (MqttMsgContext)this.inflightQueue.Dequeue(); // get inflight message msgInflight = (MqttMsgBase)msgContext.Message; switch (msgContext.State) { case MqttMsgState.QueuedQos0: // QoS 0, PUBLISH message to send to broker, no state change, no acknowledge if (msgContext.Flow == MqttMsgFlow.ToPublish) { this.Send(msgInflight); } // QoS 0, no need acknowledge else if (msgContext.Flow == MqttMsgFlow.ToAcknowledge) { // notify published message from broker (no need acknowledged) this.OnMqttMsgReceived(msgInflight); } break; case MqttMsgState.QueuedQos1: // QoS 1, PUBLISH or SUBSCRIBE/UNSUBSCRIBE message to send to broker, state change to wait PUBACK or SUBACK/UNSUBACK if (msgContext.Flow == MqttMsgFlow.ToPublish) { if (msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) // PUBLISH message to send, wait for PUBACK msgContext.State = MqttMsgState.WaitForPuback; else if (msgInflight.Type == MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE) // SUBSCRIBE message to send, wait for SUBACK msgContext.State = MqttMsgState.WaitForSuback; else if (msgInflight.Type == MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE) // UNSUBSCRIBE message to send, wait for UNSUBACK msgContext.State = MqttMsgState.WaitForUnsuback; msgContext.Timestamp = Environment.TickCount; msgContext.Attempt++; // retry ? set dup flag if (msgContext.Attempt > 1) msgInflight.DupFlag = true; this.Send(msgInflight); // update timeout int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp)); timeout = (msgTimeout < timeout) ? msgTimeout : timeout; // re-enqueue message (I have to re-analyze for receiving PUBACK, SUBACK or UNSUBACK) this.inflightQueue.Enqueue(msgContext); } // QoS 1, PUBLISH message received from broker to acknowledge, send PUBACK else if (msgContext.Flow == MqttMsgFlow.ToAcknowledge) { MqttMsgPuback puback = new MqttMsgPuback(); puback.MessageId = ((MqttMsgPublish)msgInflight).MessageId; this.Send(puback); // notify published message from broker and acknowledged this.OnMqttMsgReceived(msgInflight); } break; case MqttMsgState.QueuedQos2: // QoS 2, PUBLISH message to send to broker, state change to wait PUBREC if (msgContext.Flow == MqttMsgFlow.ToPublish) { msgContext.State = MqttMsgState.WaitForPubrec; msgContext.Timestamp = Environment.TickCount; msgContext.Attempt++; // retry ? set dup flag if (msgContext.Attempt > 1) msgInflight.DupFlag = true; this.Send(msgInflight); // update timeout int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp)); timeout = (msgTimeout < timeout) ? msgTimeout : timeout; // re-enqueue message (I have to re-analyze for receiving PUBREC) this.inflightQueue.Enqueue(msgContext); } // QoS 2, PUBLISH message received from broker to acknowledge, send PUBREC, state change to wait PUBREL else if (msgContext.Flow == MqttMsgFlow.ToAcknowledge) { MqttMsgPubrec pubrec = new MqttMsgPubrec(); pubrec.MessageId = ((MqttMsgPublish)msgInflight).MessageId; msgContext.State = MqttMsgState.WaitForPubrel; this.Send(pubrec); // re-enqueue message (I have to re-analyze for receiving PUBREL) this.inflightQueue.Enqueue(msgContext); } break; case MqttMsgState.WaitForPuback: case MqttMsgState.WaitForSuback: case MqttMsgState.WaitForUnsuback: // QoS 1, waiting for PUBACK of a PUBLISH message sent or // waiting for SUBACK of a SUBSCRIBE message sent or // waiting for UNSUBACK of a UNSUBSCRIBE message sent or if (msgContext.Flow == MqttMsgFlow.ToPublish) { acknowledge = false; lock (this.internalQueue) { if (this.internalQueue.Count > 0) msgReceived = (MqttMsgBase)this.internalQueue.Peek(); } // it is a PUBACK message or a SUBACK/UNSUBACK message if ((msgReceived != null) && ((msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBACK_TYPE) || (msgReceived.Type == MqttMsgBase.MQTT_MSG_SUBACK_TYPE) || (msgReceived.Type == MqttMsgBase.MQTT_MSG_UNSUBACK_TYPE))) { // PUBACK message or SUBACK message for the current message if (((msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && (((MqttMsgPuback)msgReceived).MessageId == ((MqttMsgPublish)msgInflight).MessageId)) || ((msgInflight.Type == MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE) && (((MqttMsgSuback)msgReceived).MessageId == ((MqttMsgSubscribe)msgInflight).MessageId)) || ((msgInflight.Type == MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE) && (((MqttMsgUnsuback)msgReceived).MessageId == ((MqttMsgUnsubscribe)msgInflight).MessageId))) { lock (this.internalQueue) { // received message processed this.internalQueue.Dequeue(); acknowledge = true; } // notify received acknowledge from broker of a published message or subscribe/unsubscribe message this.OnMqttMsgReceived(msgReceived); } } // current message not acknowledged, no PUBACK or SUBACK/UNSUBACK or not equal messageid if (!acknowledge) { // check timeout for receiving PUBACK since PUBLISH was sent or // for receiving SUBACK since SUBSCRIBE was sent or // for receiving UNSUBACK since UNSUBSCRIBE was sent if ((Environment.TickCount - msgContext.Timestamp) >= this.settings.DelayOnRetry) { // max retry not reached, resend if (msgContext.Attempt <= this.settings.AttemptsOnRetry) { msgContext.State = MqttMsgState.QueuedQos1; // re-enqueue message this.inflightQueue.Enqueue(msgContext); // update timeout (0 -> reanalyze queue immediately) timeout = 0; } } else { // re-enqueue message (I have to re-analyze for receiving PUBACK, SUBACK or UNSUBACK) this.inflightQueue.Enqueue(msgContext); // update timeout int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp)); timeout = (msgTimeout < timeout) ? msgTimeout : timeout; } } } break; case MqttMsgState.WaitForPubrec: // QoS 2, waiting for PUBREC of a PUBLISH message sent if (msgContext.Flow == MqttMsgFlow.ToPublish) { acknowledge = false; lock (this.internalQueue) { if (this.internalQueue.Count > 0) msgReceived = (MqttMsgBase)this.internalQueue.Peek(); } // it is a PUBREC message if ((msgReceived != null) && (msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBREC_TYPE)) { // PUBREC message for the current PUBLISH message, send PUBREL, wait for PUBCOMP if (((MqttMsgPubrec)msgReceived).MessageId == ((MqttMsgPublish)msgInflight).MessageId) { lock (this.internalQueue) { // received message processed this.internalQueue.Dequeue(); acknowledge = true; } MqttMsgPubrel pubrel = new MqttMsgPubrel(); pubrel.MessageId = ((MqttMsgPublish)msgInflight).MessageId; msgContext.State = MqttMsgState.WaitForPubcomp; msgContext.Timestamp = Environment.TickCount; msgContext.Attempt = 1; this.Send(pubrel); // update timeout int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp)); timeout = (msgTimeout < timeout) ? msgTimeout : timeout; // re-enqueue message this.inflightQueue.Enqueue(msgContext); } } // current message not acknowledged if (!acknowledge) { // check timeout for receiving PUBREC since PUBLISH was sent if ((Environment.TickCount - msgContext.Timestamp) >= this.settings.DelayOnRetry) { // max retry not reached, resend if (msgContext.Attempt <= this.settings.AttemptsOnRetry) { msgContext.State = MqttMsgState.QueuedQos2; // re-enqueue message this.inflightQueue.Enqueue(msgContext); // update timeout (0 -> reanalyze queue immediately) timeout = 0; } } else { // re-enqueue message this.inflightQueue.Enqueue(msgContext); // update timeout int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp)); timeout = (msgTimeout < timeout) ? msgTimeout : timeout; } } } break; case MqttMsgState.WaitForPubrel: // QoS 2, waiting for PUBREL of a PUBREC message sent if (msgContext.Flow == MqttMsgFlow.ToAcknowledge) { lock (this.internalQueue) { if (this.internalQueue.Count > 0) msgReceived = (MqttMsgBase)this.internalQueue.Peek(); } // it is a PUBREL message if ((msgReceived != null) && (msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBREL_TYPE)) { // PUBREL message for the current message, send PUBCOMP if (((MqttMsgPubrel)msgReceived).MessageId == ((MqttMsgPublish)msgInflight).MessageId) { lock (this.internalQueue) { // received message processed this.internalQueue.Dequeue(); } MqttMsgPubcomp pubcomp = new MqttMsgPubcomp(); pubcomp.MessageId = ((MqttMsgPublish)msgInflight).MessageId; this.Send(pubcomp); // notify published message from broker and acknowledged this.OnMqttMsgReceived(msgInflight); } else { // re-enqueue message this.inflightQueue.Enqueue(msgContext); } } else { // re-enqueue message this.inflightQueue.Enqueue(msgContext); } } break; case MqttMsgState.WaitForPubcomp: // QoS 2, waiting for PUBCOMP of a PUBREL message sent if (msgContext.Flow == MqttMsgFlow.ToPublish) { acknowledge = false; lock (this.internalQueue) { if (this.internalQueue.Count > 0) msgReceived = (MqttMsgBase)this.internalQueue.Peek(); } // it is a PUBCOMP message if ((msgReceived != null) && (msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBCOMP_TYPE)) { // PUBCOMP message for the current message if (((MqttMsgPubcomp)msgReceived).MessageId == ((MqttMsgPublish)msgInflight).MessageId) { lock (this.internalQueue) { // received message processed this.internalQueue.Dequeue(); acknowledge = true; } // notify received acknowledge from broker of a published message this.OnMqttMsgReceived(msgReceived); } } // current message not acknowledged if (!acknowledge) { // check timeout for receiving PUBCOMP since PUBREL was sent if ((Environment.TickCount - msgContext.Timestamp) >= this.settings.DelayOnRetry) { // max retry not reached, resend if (msgContext.Attempt < this.settings.AttemptsOnRetry) { msgContext.State = MqttMsgState.SendPubrel; // re-enqueue message this.inflightQueue.Enqueue(msgContext); // update timeout (0 -> reanalyze queue immediately) timeout = 0; } } else { // re-enqueue message this.inflightQueue.Enqueue(msgContext); // update timeout int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp)); timeout = (msgTimeout < timeout) ? msgTimeout : timeout; } } } break; case MqttMsgState.SendPubrec: // TODO : impossible ? --> QueuedQos2 ToAcknowledge break; case MqttMsgState.SendPubrel: // QoS 2, PUBREL message to send to broker, state change to wait PUBCOMP if (msgContext.Flow == MqttMsgFlow.ToPublish) { MqttMsgPubrel pubrel = new MqttMsgPubrel(); pubrel.MessageId = ((MqttMsgPublish)msgInflight).MessageId; msgContext.State = MqttMsgState.WaitForPubcomp; msgContext.Timestamp = Environment.TickCount; msgContext.Attempt++; // retry ? set dup flag if (msgContext.Attempt > 1) pubrel.DupFlag = true; this.Send(pubrel); // update timeout int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp)); timeout = (msgTimeout < timeout) ? msgTimeout : timeout; // re-enqueue message this.inflightQueue.Enqueue(msgContext); } break; case MqttMsgState.SendPubcomp: // TODO : impossible ? break; case MqttMsgState.SendPuback: // TODO : impossible ? --> QueuedQos1 ToAcknowledge break; default: break; } } // if calculated timeout is MaxValue, it means that must be Infinite (-1) if (timeout == Int32.MaxValue) timeout = Timeout.Infinite; } } } } catch (MqttCommunicationException e) { MqttUtility.Trace.WriteLine(TraceLevel.Error, "Exception occurred: {0}", e.ToString()); this.Close(); // raise disconnection client event this.OnMqttMsgDisconnected(); } }
/// <summary> /// Parse bytes for a CONNECT message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>CONNECT message instance</returns> public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; int protNameUtf8Length; byte[] protNameUtf8; bool isUsernameFlag; bool isPasswordFlag; int clientIdUtf8Length; byte[] clientIdUtf8; int willTopicUtf8Length; byte[] willTopicUtf8; int willMessageUtf8Length; byte[] willMessageUtf8; int usernameUtf8Length; byte[] usernameUtf8; int passwordUtf8Length; byte[] passwordUtf8; MqttMsgConnect msg = new MqttMsgConnect(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); // protocol name protNameUtf8Length = ((buffer[index++] << 8) & 0xFF00); protNameUtf8Length |= buffer[index++]; protNameUtf8 = new byte[protNameUtf8Length]; Array.Copy(buffer, index, protNameUtf8, 0, protNameUtf8Length); index += protNameUtf8Length; msg.protocolName = new String(Encoding.UTF8.GetChars(protNameUtf8)); // [v3.1.1] wrong protocol name if (!msg.protocolName.Equals(PROTOCOL_NAME_V3_1) && !msg.protocolName.Equals(PROTOCOL_NAME_V3_1_1)) { throw new MqttClientException(MqttClientErrorCode.InvalidProtocolName); } // protocol version msg.protocolVersion = buffer[index]; index += PROTOCOL_VERSION_SIZE; // connect flags // [v3.1.1] check lsb (reserved) must be 0 if ((msg.protocolVersion == PROTOCOL_VERSION_V3_1_1) && ((buffer[index] & RESERVED_FLAG_MASK) != 0x00)) { throw new MqttClientException(MqttClientErrorCode.InvalidConnectFlags); } isUsernameFlag = (buffer[index] & USERNAME_FLAG_MASK) != 0x00; isPasswordFlag = (buffer[index] & PASSWORD_FLAG_MASK) != 0x00; msg.willRetain = (buffer[index] & WILL_RETAIN_FLAG_MASK) != 0x00; msg.willQosLevel = (byte)((buffer[index] & WILL_QOS_FLAG_MASK) >> WILL_QOS_FLAG_OFFSET); msg.willFlag = (buffer[index] & WILL_FLAG_MASK) != 0x00; msg.cleanSession = (buffer[index] & CLEAN_SESSION_FLAG_MASK) != 0x00; index += CONNECT_FLAGS_SIZE; // keep alive timer msg.keepAlivePeriod = (ushort)((buffer[index++] << 8) & 0xFF00); msg.keepAlivePeriod |= buffer[index++]; // client identifier [v3.1.1] it may be zero bytes long (empty string) clientIdUtf8Length = ((buffer[index++] << 8) & 0xFF00); clientIdUtf8Length |= buffer[index++]; clientIdUtf8 = new byte[clientIdUtf8Length]; Array.Copy(buffer, index, clientIdUtf8, 0, clientIdUtf8Length); index += clientIdUtf8Length; msg.clientId = new String(Encoding.UTF8.GetChars(clientIdUtf8)); // [v3.1.1] if client identifier is zero bytes long, clean session must be true if ((msg.protocolVersion == PROTOCOL_VERSION_V3_1_1) && (clientIdUtf8Length == 0) && (!msg.cleanSession)) { throw new MqttClientException(MqttClientErrorCode.InvalidClientId); } // will topic and will message if (msg.willFlag) { willTopicUtf8Length = ((buffer[index++] << 8) & 0xFF00); willTopicUtf8Length |= buffer[index++]; willTopicUtf8 = new byte[willTopicUtf8Length]; Array.Copy(buffer, index, willTopicUtf8, 0, willTopicUtf8Length); index += willTopicUtf8Length; msg.willTopic = new String(Encoding.UTF8.GetChars(willTopicUtf8)); willMessageUtf8Length = ((buffer[index++] << 8) & 0xFF00); willMessageUtf8Length |= buffer[index++]; willMessageUtf8 = new byte[willMessageUtf8Length]; Array.Copy(buffer, index, willMessageUtf8, 0, willMessageUtf8Length); index += willMessageUtf8Length; msg.willMessage = new String(Encoding.UTF8.GetChars(willMessageUtf8)); } // username if (isUsernameFlag) { usernameUtf8Length = ((buffer[index++] << 8) & 0xFF00); usernameUtf8Length |= buffer[index++]; usernameUtf8 = new byte[usernameUtf8Length]; Array.Copy(buffer, index, usernameUtf8, 0, usernameUtf8Length); index += usernameUtf8Length; msg.username = new String(Encoding.UTF8.GetChars(usernameUtf8)); } // password if (isPasswordFlag) { passwordUtf8Length = ((buffer[index++] << 8) & 0xFF00); passwordUtf8Length |= buffer[index++]; passwordUtf8 = new byte[passwordUtf8Length]; Array.Copy(buffer, index, passwordUtf8, 0, passwordUtf8Length); index += passwordUtf8Length; msg.password = new String(Encoding.UTF8.GetChars(passwordUtf8)); } return(msg); }