/// <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 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; }
/// <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 DISCONNECT message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>DISCONNECT message instance</returns> public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { MqttMsgDisconnect msg = new MqttMsgDisconnect(); // get remaining length and allocate buffer int remainingLength = 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="channel">Channel connected to the broker</param> /// <returns>PINGRESP message instance</returns> public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { 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(channel); 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; }
/// <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 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 int remainingLength = MqttMsgBase.decodeRemainingLength(channel); // NOTE : remainingLength must be 0 return msg; }
/// <summary> /// Parse bytes for a UNSUBACK message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>UNSUBACK message instance</returns> public static MqttMsgUnsuback Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttMsgUnsuback msg = new MqttMsgUnsuback(); // 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="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 PUBREL message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PUBREL message instance</returns> public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttMsgPubrel msg = new MqttMsgPubrel(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.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; }
/// <summary> /// Parse bytes for a DISCONNECT message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">MQTT Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>DISCONNECT message instance</returns> public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttMsgDisconnect msg = new MqttMsgDisconnect(); if (((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5)) && ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS)) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } // get remaining length and allocate buffer int remainingLength = DecodeVariableByte(channel); // NOTE : remainingLength must be 0 if ((remainingLength != 0) && (protocolVersion == MqttProtocolVersion.Version_5)) { // V5.0 specific buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); msg.ResonCode = (MqttReasonCode)buffer[index++]; int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index); propSize += index; MqttProperty prop; while (propSize > index) { prop = (MqttProperty)buffer[index++]; switch (prop) { case MqttProperty.SessionExpiryInterval: // 4 bytes msg.SessionExpiryInterval = EncodeDecodeHelper.DecodeUint(buffer, ref index); break; case MqttProperty.ReasonString: // UTF8 encoded msg.Reason = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.UserProperty: // UTF8 key value encoding, so 2 strings in a raw string key = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); msg.UserProperties.Add(new UserProperty(key, value)); break; case MqttProperty.ServerReference: // UTF8 encoded msg.ServerReference = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; default: // non supported property index = propSize; break; } } } return(msg); }
/// <summary> /// Parse bytes for a SUBSCRIBE message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>SUBSCRIBE message instance</returns> public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgSubscribe msg = new MqttMsgSubscribe(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... int received = 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 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> /// 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); }
/// <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; }
/// <summary> /// Parse bytes for a PUBLISH message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">MQTT Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PUBLISH message instance</returns> public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgPublish msg = new MqttMsgPublish(); // get remaining length and allocate buffer int remainingLength = DecodeVariableByte(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 = (MqttQoSLevel)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // check wrong QoS level (both bits can't be set 1) if (msg.QosLevel > MqttQoSLevel.ExactlyOnce) { throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); } // 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 == MqttQoSLevel.AtLeastOnce) || (msg.QosLevel == MqttQoSLevel.ExactlyOnce)) { // message id msg.MessageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.MessageId |= buffer[index++]; } // We do have the properties here to decode if (protocolVersion == MqttProtocolVersion.Version_5) { // size of the properties int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index); propSize += index; MqttProperty prop; while (propSize > index) { prop = (MqttProperty)buffer[index++]; switch (prop) { case MqttProperty.PayloadFormatIndicator: msg.IsPayloadUTF8 = buffer[index++] != 0; break; case MqttProperty.MessageExpiryInterval: msg.MessageExpiryInterval = EncodeDecodeHelper.DecodeUint(buffer, ref index); break; case MqttProperty.TopicAlias: msg.TopicAlias = (ushort)(buffer[index++] << 8); msg.TopicAlias |= buffer[index++]; break; case MqttProperty.ResponseTopic: msg.ResponseTopic = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.CorrelationData: // byte[] int length = ((buffer[index++] << 8) & 0xFF00); length |= buffer[index++]; msg.CorrelationData = new byte[length]; Array.Copy(buffer, index, msg.CorrelationData, 0, length); index += length; break; case MqttProperty.UserProperty: // UTF8 key value encoding, so 2 strings in a raw string key = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); msg.UserProperties.Add(new UserProperty(key, value)); break; case MqttProperty.SubscriptionIdentifier: msg.SubscriptionIdentifier = EncodeDecodeHelper.DecodeVariableByte(buffer, ref index); break; case MqttProperty.ContentType: msg.ContentType = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; default: // non supported property index = propSize; break; } } } // 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> /// 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, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttMsgConnack msg = new MqttMsgConnack(); if ((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5)) { // [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 = DecodeVariableByte(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); if ((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5)) { // [v3.1.1] ... set session present flag ... msg.SessionPresent = (buffer[index++] & SESSION_PRESENT_FLAG_MASK) != 0x00; } // ...and set return code from broker msg.ReturnCode = (MqttReasonCode)buffer[index++]; // v5.0 properties if (protocolVersion == MqttProtocolVersion.Version_5) { // size of the properties int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index); propSize += index; MqttProperty prop; while (propSize > index) { prop = (MqttProperty)buffer[index++]; switch (prop) { case MqttProperty.SessionExpiryInterval: // 4 bytes msg.SessionExpiryInterval = EncodeDecodeHelper.DecodeUint(buffer, ref index); break; case MqttProperty.ReceiveMaximum: // 2 bytes msg.ReceiveMaximum = (ushort)(buffer[index++] << 8); msg.ReceiveMaximum |= buffer[index++]; break; case MqttProperty.MaximumQoS: msg.MaximumQoS = buffer[index++] != 0; break; case MqttProperty.RetainAvailable: msg.RetainAvailable = buffer[index++] != 0; break; case MqttProperty.MaximumPacketSize: // 4 bytes msg.MaximumPacketSize = EncodeDecodeHelper.DecodeUint(buffer, ref index); break; case MqttProperty.AssignedClientIdentifier: // UTF8 encoded msg.AssignedClientIdentifier = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.TopicAliasMaximum: // 2 bytes msg.TopicAliasMaximum = (ushort)(buffer[index++] << 8); msg.TopicAliasMaximum |= buffer[index++]; break; case MqttProperty.ReasonString: // UTF8 encoded msg.Reason = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.UserProperty: // UTF8 key value encoding, so 2 strings in a raw string key = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); msg.UserProperties.Add(new UserProperty(key, value)); break; case MqttProperty.WildcardSubscriptionAvailable: msg.WildcardSubscriptionAvailable = buffer[index++] != 0; break; case MqttProperty.SubscriptionIdentifierAvailable: msg.SubscriptionIdentifiersAvailable = buffer[index++] != 0; break; case MqttProperty.SharedSubscriptionAvailable: msg.SharedSubscriptionAvailable = buffer[index++] != 0; break; case MqttProperty.ServerKeepAlive: // 2 bytes msg.ServerKeepAlive = (ushort)(buffer[index++] << 8); msg.ServerKeepAlive |= buffer[index++]; break; case MqttProperty.ResponseInformation: // UTF8 encoded msg.ResponseInformation = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.ServerReference: // UTF8 encoded msg.ServerReference = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.AuthenticationMethod: // UTF8 encoded msg.AuthenticationMethod = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.AuthenticationData: // byte[] int length = ((buffer[index++] << 8) & 0xFF00); length |= buffer[index++]; msg.AuthenticationData = new byte[length]; Array.Copy(buffer, index, msg.AuthenticationData, 0, length); index += length; break; default: // non supported property index = propSize; break; } } } return(msg); }
public MQTTClientBase(IMqttNetworkChannel channel) { _channel = channel; _clientId = Guid.NewGuid().ToString(); }
/// <summary> /// Decode remaining length reading bytes from socket /// </summary> /// <param name="channel">Channel from reading bytes</param> /// <returns>Decoded remaining length</returns> protected static int decodeRemainingLength(IMqttNetworkChannel channel) { int multiplier = 1; int value = 0; int digit = 0; byte[] nextByte = new byte[1]; do { // next digit from stream channel.Receive(nextByte); digit = nextByte[0]; value += ((digit & 127) * multiplier); multiplier *= 128; } while ((digit & 128) != 0); return value; }
/// <summary> /// Parse bytes for a PUBREC message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">MQTT Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PUBREC message instance</returns> public static MqttMsgAuthentication Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel) { if (protocolVersion != MqttProtocolVersion.Version_5) { throw new NotSupportedException(); } if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_AUTH_FLAG_BITS) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } MqttMsgAuthentication msg = new(); byte[] buffer; int index = 0; int length = 0; // get remaining length and allocate buffer int remainingLength = DecodeVariableByte(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); msg.ReasonCode = (MqttReasonCode)buffer[index++]; int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index); propSize += index; MqttProperty prop; while (propSize > index) { prop = (MqttProperty)buffer[index++]; switch (prop) { case MqttProperty.AuthenticationMethod: // UTF8 encoded msg.AuthenticationMethod = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.AuthenticationData: // byte[] length = ((buffer[index++] << 8) & 0xFF00); length |= buffer[index++]; msg.AuthenticationData = new byte[length]; Array.Copy(buffer, index, msg.AuthenticationData, 0, length); index += length; break; case MqttProperty.ReasonString: // UTF8 encoded msg.Reason = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.UserProperty: // UTF8 key value encoding, so 2 strings in a raw string key = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); msg.UserProperties.Add(new UserProperty(key, value)); break; default: // non supported property index = propSize; break; } } return(msg); }
/// <summary> /// Connect to broker /// </summary> /// <param name="clientId">Client identifier</param> /// <param name="username">Username</param> /// <param name="password">Password</param> /// <param name="willRetain">Will retain flag</param> /// <param name="willQosLevel">Will QOS level</param> /// <param name="willFlag">Will flag</param> /// <param name="willTopic">Will topic</param> /// <param name="willMessage">Will message</param> /// <param name="cleanSession">Clean sessione flag</param> /// <param name="keepAlivePeriod">Keep alive period</param> /// <returns>Return code of CONNACK message from broker</returns> public byte Connect(string clientId, string username, string password, bool willRetain, byte willQosLevel, bool willFlag, string willTopic, string willMessage, bool cleanSession, ushort keepAlivePeriod) { // create CONNECT message MqttMsgConnect connect = new MqttMsgConnect(clientId, username, password, willRetain, willQosLevel, willFlag, willTopic, willMessage, cleanSession, keepAlivePeriod); try { // create network channel and connect to broker #if WINDOWS_PHONE this.channel = new WPMqttNetworkChannel(this.brokerHostName, this.brokerIpAddress, this.brokerPort, this.secure, this.caCert); #else this.channel = new MqttNetworkChannel(this.brokerHostName, this.brokerIpAddress, this.brokerPort, this.secure, this.caCert); #endif this.channel.Connect(); } catch (Exception ex) { throw new MqttConnectionException("Exception connecting to the broker", ex); } this.lastCommTime = 0; this.isRunning = true; // start thread for receiving messages from broker this.receiveThread = new Thread(this.ReceiveThread); this.receiveThread.Start(); MqttMsgConnack connack = (MqttMsgConnack)this.SendReceive(connect); // if connection accepted, start keep alive timer and if (connack.ReturnCode == MqttMsgConnack.CONN_ACCEPTED) { // set all client properties this.ClientId = clientId; this.CleanSession = cleanSession; this.WillFlag = willFlag; this.WillTopic = willTopic; this.WillMessage = willMessage; this.WillQosLevel = willQosLevel; this.keepAlivePeriod = keepAlivePeriod * 1000; // convert in ms // start thread for sending keep alive message to the broker this.keepAliveThread = new Thread(this.KeepAliveThread); this.keepAliveThread.Start(); // start thread for raising received message event from broker this.receiveEventThread = new Thread(this.ReceiveEventThread); this.receiveEventThread.Start(); // start thread for handling inflight messages queue to broker asynchronously (publish and acknowledge) this.processInflightThread = new Thread(this.ProcessInflightThread); this.processInflightThread.Start(); this.IsConnected = true; } return connack.ReturnCode; }
/// <summary> /// Parse bytes for a PINGRESP message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">MQTT Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PINGRESP message instance</returns> public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel) { MqttMsgPingResp msg = new MqttMsgPingResp(); if ((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5)) { // [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 DecodeVariableByte(channel); 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 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); }
/// <summary> /// Parse bytes for a CONNECT message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">MQTT Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>CONNECT message instance</returns> public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; bool isUsernameFlag; bool isPasswordFlag; int length; MqttMsgConnect msg = new MqttMsgConnect(); // get remaining length and allocate buffer int remainingLength = DecodeVariableByte(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); // protocol name msg.ProtocolName = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); // [v3.1.1] wrong protocol name valid for 5.0 as well 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 = (MqttProtocolVersion)buffer[index]; index += PROTOCOL_VERSION_SIZE; // connect flags // [v3.1.1] check lsb (reserved) must be 0 if (((msg.ProtocolVersion == MqttProtocolVersion.Version_3_1_1) || (msg.ProtocolVersion == MqttProtocolVersion.Version_5)) && ((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++]; // In case of v5, we have properties encoded with length and type. // This is different than in the v3.x protocols if (msg.ProtocolVersion == MqttProtocolVersion.Version_5) { // size of the properties int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index); propSize += index; MqttProperty prop; while (propSize > index) { prop = (MqttProperty)buffer[index++]; switch (prop) { case MqttProperty.AuthenticationMethod: // UTF8 encoded msg.AuthenticationMethod = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.AuthenticationData: // byte[] length = ((buffer[index++] << 8) & 0xFF00); length |= buffer[index++]; msg.AuthenticationData = new byte[length]; Array.Copy(buffer, index, msg.AuthenticationData, 0, length); index += length; break; case MqttProperty.RequestProblemInformation: // 1 byte msg.RequestProblemInformation = buffer[index++] != 0; break; case MqttProperty.RequestResponseInformation: // 1 byte msg.RequestResponseInformation = buffer[index++] != 0; break; case MqttProperty.ReceiveMaximum: // 2 bytes msg.ReceiveMaximum = (ushort)(buffer[index++] << 8); msg.ReceiveMaximum |= buffer[index++]; break; case MqttProperty.TopicAliasMaximum: // 2 bytes msg.TopicAliasMaximum = (ushort)(buffer[index++] << 8); msg.TopicAliasMaximum |= buffer[index++]; break; case MqttProperty.UserProperty: // UTF8 key value encoding, so 2 strings in a raw string key = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); msg.UserProperties.Add(new UserProperty(key, value)); break; case MqttProperty.MaximumPacketSize: // 4 bytes msg.MaximumPacketSize = EncodeDecodeHelper.DecodeUint(buffer, ref index); break; case MqttProperty.SessionExpiryInterval: // 4 bytes msg.SessionExpiryInterval = EncodeDecodeHelper.DecodeUint(buffer, ref index); break; case MqttProperty.WillDelayInterval: // 4 bytes msg.WillDelayInterval = EncodeDecodeHelper.DecodeUint(buffer, ref index); break; default: // non supported property index = propSize; break; } } } // client identifier [v3.1.1] it may be zero bytes long (empty string) msg.ClientId = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); // [v3.1.1] if client identifier is zero bytes long, clean session must be true if ((msg.ProtocolVersion == MqttProtocolVersion.Version_3_1_1) && (msg.ClientId.Length == 0) && (!msg.CleanSession)) { throw new MqttClientException(MqttClientErrorCode.InvalidClientId); } // will topic and will message if (msg.WillFlag) { msg.WillTopic = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); msg.WillMessage = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); } // username if (isUsernameFlag) { msg.Username = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); } // password if (isPasswordFlag) { msg.Password = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); } return(msg); }
/// <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; }
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); }
/// <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) { msg._qosLevel = ((byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET)).ToQOS(); msg._dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); // retain flag not used msg._retainFlag = 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) IList <String> tmpTopics = new List <String>(); IList <byte> tmpQosLevels = new List <byte>(); 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 QOS[tmpQosLevels.Count]; for (int i = 0; i < tmpTopics.Count; i++) { msg._topics[i] = (string)tmpTopics[i]; msg._qosLevels[i] = ((byte)tmpQosLevels[i]).ToQOS(); } return(msg); }
/// <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 int remainingLength = MqttMsgBase.decodeRemainingLength(channel); // NOTE : remainingLength must be 0 return(msg); }
/// <summary> /// Parse bytes for a SUBSCRIBE message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>SUBSCRIBE message instance</returns> public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgSubscribe msg = new MqttMsgSubscribe(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... int received = 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 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); }
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); }
public MQTTDeviceClient(IMqttNetworkChannel channel) : base(channel) { }
/// <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); }
/// <summary> /// Parse bytes for a UNSUBSCRIBE 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>UNSUBSCRIBE message instance</returns> public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe(); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_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 // 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 || NANOFRAMEWORK_V1_0) 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="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); }
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> /// Parse bytes for a PUBLISH 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>PUBLISH message instance</returns> public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, byte protocolVersion, 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); // check wrong QoS level (both bits can't be set 1) if (msg.qosLevel > QOS_LEVEL_EXACTLY_ONCE) throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); // 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> /// 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); }
/// <summary> /// Parse bytes for a PUBACK 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>PUBACK message instance</returns> public static MqttPublishAcknowledgeMessage Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttPublishAcknowledgeMessage msg = new MqttPublishAcknowledgeMessage(); if (protocolVersion == MqttConnectMessage.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBACK_FLAG_BITS) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } } // get remaining length and allocate buffer int remainingLength = MqttMessage.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); }
public MQTTAppClient(IMqttNetworkChannel channel) : base(channel) { }
/// <summary> /// Parse bytes for a UNSUBSCRIBE 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>UNSUBSCRIBE message instance</returns> public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe(); if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_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 // 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; }
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); }
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="protocolVersion">MQTT Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>SUBACK message instance</returns> public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttMsgSuback msg = new MqttMsgSuback(); if ((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5)) { // [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 = DecodeVariableByte(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++]); if ((protocolVersion == MqttProtocolVersion.Version_5) && (index < buffer.Length)) { // size of the properties int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index); propSize += index; MqttProperty prop; while (propSize > index) { prop = (MqttProperty)buffer[index++]; switch (prop) { case MqttProperty.ReasonString: // UTF8 encoded msg.Reason = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.UserProperty: // UTF8 key value encoding, so 2 strings in a raw string key = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); msg.UserProperties.Add(new UserProperty(key, value)); break; default: // non supported property index = propSize; break; } } } // payload contains QoS levels granted msg.GrantedQoSLevels = new MqttQoSLevel[remainingLength - index]; if (protocolVersion == MqttProtocolVersion.Version_5) { msg.ReasonCodes = new MqttReasonCode[remainingLength - index]; } int qosIdx = 0; do { if (protocolVersion == MqttProtocolVersion.Version_5) { msg.ReasonCodes[qosIdx] = (MqttReasonCode)buffer[index]; } msg.GrantedQoSLevels[qosIdx++] = (MqttQoSLevel)buffer[index++]; } while (index < remainingLength); return(msg); }
/// <summary> /// Parse bytes for a PUBLISH 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>PUBLISH message instance</returns> public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, byte protocolVersion, 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); // check wrong QoS level (both bits can't be set 1) if (msg.qosLevel > QOS_LEVEL_EXACTLY_ONCE) { throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); } // 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> /// Parse bytes for a UNSUBSCRIBE message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">MQTT Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>UNSUBSCRIBE message instance</returns> public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int indexUnsub = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe(); if (protocolVersion == MqttProtocolVersion.Version_3_1_1) { // [v3.1.1] check flag bits if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_FLAG_BITS) { throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); } } // get remaining length and allocate buffer int remainingLength = DecodeVariableByte(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); if (protocolVersion == MqttProtocolVersion.Version_3_1) { // only 3.1.0 // read QoS level from fixed header msg.QosLevel = (MqttQoSLevel)((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[indexUnsub++] << 8) & 0xFF00); msg.MessageId |= buffer[indexUnsub++]; if (protocolVersion == MqttProtocolVersion.Version_5) { // size of the properties int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref indexUnsub); propSize += indexUnsub; MqttProperty prop; while (propSize > indexUnsub) { prop = (MqttProperty)buffer[indexUnsub++]; switch (prop) { case MqttProperty.UserProperty: // UTF8 key value encoding, so 2 strings in a raw string key = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref indexUnsub); string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref indexUnsub); msg.UserProperties.Add(new UserProperty(key, value)); break; default: // non supported property indexUnsub = propSize; break; } } } // payload contains topics // NOTE : before, I don't know how many topics will be in the payload (so use List) IList tmpTopics = new ArrayList(); do { // topic name topicUtf8Length = ((buffer[indexUnsub++] << 8) & 0xFF00); topicUtf8Length |= buffer[indexUnsub++]; topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, indexUnsub, topicUtf8, 0, topicUtf8Length); indexUnsub += topicUtf8Length; tmpTopics.Add(Encoding.UTF8.GetString(topicUtf8, 0, topicUtf8.Length)); } while (indexUnsub < 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 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 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; }
/// <summary> /// Constructor /// </summary> /// <param name="socket">Raw socket for communication</param> public MqttClient(Socket socket) { this.channel = new MqttNetworkChannel(socket); // reference to MQTT settings this.settings = MqttSettings.Instance; // client not connected yet (CONNACK not send from client), some default values this.IsConnected = false; this.ClientId = null; this.CleanSession = true; this.keepAliveEvent = new AutoResetEvent(false); // queue for handling inflight messages (publishing and acknowledge) this.inflightWaitHandle = new AutoResetEvent(false); this.inflightQueue = new Queue(); // queue for received message this.receiveEventWaitHandle = new AutoResetEvent(false); this.receiveQueue = new Queue(); this.internalQueue = new Queue(); }
/// <summary> /// Parse bytes for a PUBREL message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">MQTT Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PUBREL message instance</returns> public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; MqttMsgPubrel msg = new MqttMsgPubrel(); if ((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5)) { // [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 = DecodeVariableByte(channel); buffer = new byte[remainingLength]; // read bytes from socket... channel.Receive(buffer); if (protocolVersion == MqttProtocolVersion.Version_3_1) { // only 3.1.0 // read QoS level from fixed header (would be QoS Level 1) msg.QosLevel = (MqttQoSLevel)((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++]; if (protocolVersion == MqttProtocolVersion.Version_5) { msg.ReasonCode = (MqttReasonCode)buffer[index++]; // size of the properties int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index); propSize += index; MqttProperty prop; while (propSize > index) { prop = (MqttProperty)buffer[index++]; switch (prop) { case MqttProperty.ReasonString: // UTF8 encoded msg.Reason = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); break; case MqttProperty.UserProperty: // UTF8 key value encoding, so 2 strings in a raw string key = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index); msg.UserProperties.Add(new UserProperty(key, value)); break; default: // non supported property index = propSize; break; } } } return(msg); }