private void OnPacketToSend(MqttMsgBase packet)
 {
     if (PacketToSend != null)
     {
         PacketToSend(this, new PacketToSendEventArgs(packet));
     }
 }
        public void DecodeMultiplePacketsByteArray(byte[] data)
        {
            List <MqttMsgBase> packetsInTheByteArray = new List <MqttMsgBase>();
            int numberOfBytesProcessed = 0;
            int numberOfBytesToProcess = 0;
            int numberOfBytesReceived  = data.Length;

            byte[]      packetByteArray;
            MqttMsgBase tmpPacket = new MqttMsgSubscribe();

            while (numberOfBytesProcessed != numberOfBytesReceived)
            {
                int remainingLength      = MqttMsgBase.decodeRemainingLength(data);
                int remainingLenghtIndex = tmpPacket.encodeRemainingLength(remainingLength, data, 1);
                numberOfBytesToProcess = remainingLength + remainingLenghtIndex;
                packetByteArray        = new byte[numberOfBytesToProcess];
                Array.Copy(data, 0, packetByteArray, 0, numberOfBytesToProcess);
                {
                    byte[] tmp = new byte[data.Length - numberOfBytesToProcess];
                    Array.Copy(data, numberOfBytesToProcess, tmp, 0, tmp.Length);
                    data = tmp;
                }
                numberOfBytesProcessed += numberOfBytesToProcess;
                MqttMsgBase packet = PacketDecoder.DecodeControlPacket(packetByteArray);
                //RouteControlPacketDelegate r = new RouteControlPacketDelegate(RouteControlPacketToMethodHandler);
                //r.Invoke(packet);
                CrestronInvoke.BeginInvoke(RouteControlPacketToMethodHandler, packet);
            }
        }
示例#3
0
        /// <summary>
        /// Parse bytes for a PUBCOMP 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>PUBCOMP message instance</returns>
        public static MqttMsgPubcomp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            byte[]         buffer;
            int            index = 0;
            MqttMsgPubcomp msg   = new MqttMsgPubcomp();

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
            {
                // [v3.1.1] check flag bits
                if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBCOMP_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);
        }
 private void ConnectToServerCallback(SecureTCPClient myTCPClient)
 {
     try
     {
         if (myTCPClient.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED)
         {
             MqttMsgConnect connect = MsgBuilder.BuildConnect(this.ClientId, MqttSettings.Instance.Username, MqttSettings.Instance.Password, this.WillRetain,
                                                              this.WillQosLevel, this.WillFlag, this.WillTopic, this.WillMessage, this.CleanSession, this.KeepAlivePeriod, ProtocolVersion);
             Send(connect);
             //TODO: timer for connack
             tcpClient.ReceiveData();
             MqttMsgBase packet = PacketDecoder.DecodeControlPacket(tcpClient.IncomingDataBuffer);
             if (packet.Type == MqttMsgBase.MQTT_MSG_CONNACK_TYPE)
             {
                 RouteControlPacketToMethodHandler(packet);
             }
             else
             {
                 throw new MqttConnectionException("MQTTCLIENT - ConnectToServerCallback - " + PayloadMapper.ClientType + " , Expected CONNACK , received " + packet, new ArgumentException());
             }
         }
     }
     catch (MqttClientException e)
     {
         CrestronLogger.WriteToLog("MQTTCLIENT - ConnectToServerCallback - Error occured : " + e.ErrorCode, 7);
         CrestronLogger.WriteToLog("MQTTCLIENT - ConnectToServerCallback - Error occured : " + e.StackTrace, 7);
     }
     catch (Exception e)
     {
         CrestronLogger.WriteToLog("MQTTCLIENT - ConnectToServerCallback - Error occured : " + e.Message, 7);
         CrestronLogger.WriteToLog("MQTTCLIENT - ConnectToServerCallback - Error occured : " + e.StackTrace, 7);
         //Disconnect from server , signal error at module lvl;
     }
 }
示例#5
0
 override protected void ConnectionCallback(SecureTCPServer server, uint clientIndex)
 {
     try
     {
         Server.WaitForConnectionAsync(IPAddress.Parse("0.0.0.0"), this.ConnectionCallback);
         if (Server.ClientConnected(clientIndex))
         {
             oldDecodedFrame.Add(clientIndex, new List <byte>());
             int         lenghtOfData = Server.ReceiveData(clientIndex);
             byte[]      data         = Server.GetIncomingDataBufferForSpecificClient(clientIndex);
             MqttMsgBase packet       = PacketDecoder.DecodeControlPacket(data);
             if (packet.Type == MqttMsgBase.MQTT_MSG_CONNECT_TYPE)
             {
                 OnPacketReceived(clientIndex, packet, false);
             }
             else
             {
                 throw new ArgumentException("Attempted connection with a non CONNECT packet");
             }
         }
     }
     catch (Exception e)
     {
         DisconnectClient(clientIndex, false);
     }
 }
示例#6
0
        /// <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);
        }
        private int SendPubrel(
            MqttConnection connection,
            MqttMsgContext msgContext,
            MqttMsgBase msgInflight,
            int timeout)
        {
            // QoS 2, PUBREL message to send to broker, state change to wait PUBCOMP
            if (msgContext.Flow == MqttMsgFlow.ToPublish)
            {
                msgContext.State     = MqttMsgState.WaitForPubcomp;
                msgContext.Timestamp = Environment.TickCount;
                msgContext.Attempt++;

                // retry ? set dup flag [v3.1.1] no needed
                if (connection.ProtocolVersion == MqttProtocolVersion.Version_3_1 && msgContext.Attempt > 1)
                {
                    outgoingMessageHandler.Pubrel(connection, msgInflight.MessageId, true);
                }
                else
                {
                    outgoingMessageHandler.Pubrel(connection, msgInflight.MessageId, false);
                }

                // update timeout : minimum between delay (based on current message sent) or current timeout
                timeout = connection.Settings.DelayOnRetry < timeout ? connection.Settings.DelayOnRetry : timeout;

                // re-enqueue message
                connection.EnqueueInflight(msgContext);
            }

            return(timeout);
        }
示例#8
0
 public void OnPacketReceived(uint clientIndex, MqttMsgBase packet, bool isWebSocketClient)
 {
     if (PacketReceived != null)
     {
         PacketReceived(this, new PacketReceivedEventHandler(clientIndex, packet, isWebSocketClient));
     }
 }
示例#9
0
 public void Send(MqttMsgBase packet)
 {
     CrestronLogger.WriteToLog("MQTTCLIENT - SEND - Sending packet type " + packet, 2);
     #if PACKET_DEBUG
     CrestronLogger.WriteToLog("MQTTCLIENT - SEND - " + BitConverter.ToString(packet.GetBytes(ProtocolVersion)), 2);
     #endif
     ClientSendDataAsync(packet.GetBytes(ProtocolVersion));
 }
        private int HandleQueuedQos1SendSubscribeAndSendUnsubscribe(
            MqttConnection connection,
            MqttMsgContext msgContext,
            MqttMsgBase msgInflight,
            int timeout)
        {
            InternalEvent internalEvent;

            // QoS 1, PUBLISH or SUBSCRIBE/UNSUBSCRIBE message to send to broker, state change to wait PUBACK or SUBACK/UNSUBACK
            if (msgContext.Flow == MqttMsgFlow.ToPublish)
            {
                msgContext.Timestamp = Environment.TickCount;
                msgContext.Attempt++;

                if (msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE)
                {
                    // PUBLISH message to send, wait for PUBACK
                    msgContext.State = MqttMsgState.WaitForPuback;

                    // retry ? set dup flag [v3.1.1] only for PUBLISH message
                    if (msgContext.Attempt > 1)
                    {
                        msgInflight.DupFlag = true;
                    }
                }
                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;
                }

                outgoingMessageHandler.Send(connection, msgInflight);

                // update timeout : minimum between delay (based on current message sent) or current timeout
                timeout = connection.Settings.DelayOnRetry < timeout ? connection.Settings.DelayOnRetry : timeout;

                // re-enqueue message (I have to re-analyze for receiving PUBACK, SUBACK or UNSUBACK)
                connection.EnqueueInflight(msgContext);
            }

            // QoS 1, PUBLISH message received from broker to acknowledge, send PUBACK
            else if (msgContext.Flow == MqttMsgFlow.ToAcknowledge)
            {
                outgoingMessageHandler.Puback(connection, msgInflight.MessageId);

                internalEvent = new InternalEvent(msgInflight);

                // notify published message from broker and acknowledged
                connection.EnqueueInternalEvent(internalEvent);
            }

            return(timeout);
        }
        private MqttMsgBase WaitForPubrel(
            MqttConnection connection,
            MqttMsgContext msgContext,
            MqttMsgBase msgInflight,
            ref bool msgReceivedProcessed)
        {
            // QoS 2, waiting for PUBREL of a PUBREC message sent
            if (msgContext.Flow != MqttMsgFlow.ToAcknowledge)
            {
                return(null);
            }

            if (!connection.InternalQueue.TryPeek(out MqttMsgBase msgReceived))
            {
                return(null);
            }

            InternalEvent internalEvent;

            // it is a PUBREL message
            if (msgReceived != null && msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBREL_TYPE)
            {
                if (msgReceived.MessageId == msgInflight.MessageId)
                {
                    // received message processed
                    connection.InternalQueue.TryDequeue(out MqttMsgBase dequeuedMsg);
                    msgReceivedProcessed = true;

                    outgoingMessageHandler.Pubcomp(connection, msgInflight.MessageId);

                    internalEvent = new InternalEvent(msgInflight);

                    // notify published message from broker and acknowledged
                    connection.EnqueueInternalEvent(internalEvent);

                    // PUBREL received (and PUBCOMP sent) for PUBLISH message with QoS Level 2, remove from session state
                    if (msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE && connection.Session != null &&
                        connection.Session.InflightMessages.ContainsKey(msgContext.Key))
                    {
                        connection.Session.InflightMessages.TryRemove(
                            msgContext.Key,
                            out MqttMsgContext contextToBeRemoved);
                    }
                }
                else
                {
                    // re-enqueue message
                    connection.EnqueueInflight(msgContext);
                }
            }
            else
            {
                connection.EnqueueInflight(msgContext);
            }

            return(msgReceived);
        }
示例#12
0
        public void AddInflightMessage(MqttMsgBase packet)
        {
            MqttMsgContext context = new MqttMsgContext();
            Del            d       = delegate() { return(packet.QosLevel == (byte)0x01 ? MqttMsgState.QueuedQos1 : MqttMsgState.QueuedQos2); };
            MqttMsgState   state   = packet.QosLevel == (byte)0x00 ? MqttMsgState.QueuedQos0 : d();

            context.State   = state;
            context.Message = packet;
            session.InflightMessages.Add(packet.MessageId, context);
        }
示例#13
0
        /// <summary>
        /// Parse bytes for a PINGREQ message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PINGREQ message instance</returns>
        public static MqttMsgPingReq Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel)
        {
            MqttMsgPingReq msg = new MqttMsgPingReq();

            // 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="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);
        }
 private static void HandleQueuedQos0(
     MqttClientConnection clientConnection,
     MqttMsgContext msgContext,
     MqttMsgBase msgInflight)
 {
     // QoS 0, PUBLISH message to send to broker, no state change, no acknowledge
     if (msgContext.Flow == MqttMsgFlow.ToPublish)
     {
         MqttOutgoingMessageManager.Send(clientConnection, msgInflight);
     }
     // QoS 0, no need acknowledge
     else if (msgContext.Flow == MqttMsgFlow.ToAcknowledge)
     {
         var internalEvent = new MsgInternalEvent(msgInflight);
         clientConnection.EnqueueInternalEvent(internalEvent);
     }
 }
示例#16
0
        /// <summary>
        /// Parse bytes for a PINGREQ 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>PINGREQ message instance</returns>
        public static MqttMsgPingReq Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            MqttMsgPingReq msg = new MqttMsgPingReq();

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
            {
                // [v3.1.1] check flag bits
                if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGREQ_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);
        }
示例#17
0
        /// <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);
        }
示例#18
0
        /// <summary>
        /// Parse bytes for a PUBCOMP message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PUBCOMP message instance</returns>
        public static MqttMsgPubcomp Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel)
        {
            byte[]         buffer;
            int            index = 0;
            MqttMsgPubcomp msg   = new MqttMsgPubcomp();

            // 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);
        }
        private int HandleQueuedQos2(
            MqttConnection connection,
            MqttMsgContext msgContext,
            MqttMsgBase msgInflight,
            int timeout)
        {
            // QoS 2, PUBLISH message to send to broker, state change to wait PUBREC
            if (msgContext.Flow == MqttMsgFlow.ToPublish)
            {
                msgContext.Timestamp = Environment.TickCount;
                msgContext.Attempt++;
                msgContext.State = MqttMsgState.WaitForPubrec;

                // retry ? set dup flag
                if (msgContext.Attempt > 1)
                {
                    msgInflight.DupFlag = true;
                }

                outgoingMessageHandler.Send(connection, msgInflight);

                // update timeout : minimum between delay (based on current message sent) or current timeout
                timeout = connection.Settings.DelayOnRetry < timeout ? connection.Settings.DelayOnRetry : timeout;

                // re-enqueue message (I have to re-analyze for receiving PUBREC)
                connection.EnqueueInflight(msgContext);
            }

            // QoS 2, PUBLISH message received from broker to acknowledge, send PUBREC, state change to wait PUBREL
            else if (msgContext.Flow == MqttMsgFlow.ToAcknowledge)
            {
                msgContext.State = MqttMsgState.WaitForPubrel;

                outgoingMessageHandler.Pubrec(connection, msgInflight.MessageId);

                // re-enqueue message (I have to re-analyze for receiving PUBREL)
                connection.EnqueueInflight(msgContext);
            }

            return(timeout);
        }
示例#20
0
        /// <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>
 /// 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>
 /// Constructor
 /// </summary>
 /// <param name="message">Related message</param>
 public InternalEvent(MqttMsgBase message)
 {
     this.Message = message;
 }
        private static MqttMsgBase HandleWaitForPubrec(
            MqttClientConnection clientConnection,
            MqttMsgContext msgContext,
            MqttMsgBase msgInflight,
            ref bool msgReceivedProcessed,
            ref int timeout)
        {
            // QoS 2, waiting for PUBREC of a PUBLISH message sent
            if (msgContext.Flow != MqttMsgFlow.ToPublish)
            {
                return(null);
            }

            MqttMsgBase msgReceived;

            if (!clientConnection.InternalQueue.TryPeek(out msgReceived))
            {
                return(null);
            }

            bool          acknowledge = false;
            InternalEvent internalEvent;

            // it is a PUBREC message
            if (msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBREC_TYPE)
            {
                // PUBREC message for the current PUBLISH message, send PUBREL, wait for PUBCOMP
                if (msgReceived.MessageId == msgInflight.MessageId)
                {
                    // received message processed
                    MqttMsgBase dequeuedMsg;
                    clientConnection.InternalQueue.TryDequeue(out dequeuedMsg);
                    acknowledge          = true;
                    msgReceivedProcessed = true;

                    MqttOutgoingMessageManager.Pubrel(clientConnection, msgInflight.MessageId, false);

                    msgContext.State     = MqttMsgState.WaitForPubcomp;
                    msgContext.Timestamp = Environment.TickCount;
                    msgContext.Attempt   = 1;

                    // update timeout : minimum between delay (based on current message sent) or current timeout
                    timeout = (clientConnection.Settings.DelayOnRetry < timeout)
                                  ? clientConnection.Settings.DelayOnRetry
                                  : timeout;

                    // re-enqueue message
                    clientConnection.EnqueueInflight(msgContext);
                }
            }

            // current message not acknowledged
            if (!acknowledge)
            {
                var delta = Environment.TickCount - msgContext.Timestamp;
                // check timeout for receiving PUBREC since PUBLISH was sent
                if (delta >= clientConnection.Settings.DelayOnRetry)
                {
                    // max retry not reached, resend
                    if (msgContext.Attempt < clientConnection.Settings.AttemptsOnRetry)
                    {
                        msgContext.State = MqttMsgState.QueuedQos2;

                        // re-enqueue message
                        clientConnection.EnqueueInflight(msgContext);

                        // update timeout (0 -> reanalyze queue immediately)
                        timeout = 0;
                    }
                    else
                    {
                        // PUBREC not received in time, PUBLISH retries failed, need to remove from session inflight messages too
                        if ((clientConnection.Session != null) &&
                            (clientConnection.Session.InflightMessages.ContainsKey(msgContext.Key)))
                        {
                            MqttMsgContext contextToBeRemoved;
                            clientConnection.Session.InflightMessages.TryRemove(msgContext.Key, out contextToBeRemoved);
                        }

                        // if PUBREC for a PUBLISH message not received after retries, raise event for not published
                        internalEvent = new MsgPublishedInternalEvent(msgInflight, false);
                        // notify not received acknowledge from broker and message not published
                        clientConnection.EnqueueInternalEvent(internalEvent);
                    }
                }
                else
                {
                    // re-enqueue message
                    clientConnection.EnqueueInflight(msgContext);

                    // update timeout
                    int msgTimeout = (clientConnection.Settings.DelayOnRetry - delta);
                    timeout = (msgTimeout < timeout) ? msgTimeout : timeout;
                }
            }

            return(msgReceived);
        }
示例#24
0
 public void Send(MqttConnection connection, MqttMsgBase msg)
 {
     Send(connection, msg.GetBytes((byte)connection.ProtocolVersion));
 }
        private void RouteControlPacketToMethodHandler(object source, PacketReceivedEventHandler args)
        {
            MqttMsgBase packet            = args.Packet;
            uint        clientIndex       = args.ClientIndex;
            bool        isWebSocketClient = args.IsWebSocketClient;

            try
            {
                switch (packet.Type)
                {
                case MqttMsgBase.MQTT_MSG_CONNECT_TYPE:
                {
                    HandleCONNECTType(clientIndex, (MqttMsgConnect)packet, args.IsWebSocketClient);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_CONNACK_TYPE:
                {
                    CrestronLogger.WriteToLog("MQTTSERVER - ROUTE PACKET -  conack packet to broker is not allowed , Disconnecting client", 8);
                    DisconnectClient(clientIndex, false, isWebSocketClient);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_PUBLISH_TYPE:
                {
                    HandlePUBLISHType(clientIndex, (MqttMsgPublish)packet);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_PUBACK_TYPE:
                {
                    HandlePUBACKType(clientIndex, (MqttMsgPuback)packet);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_PUBREC_TYPE:
                {
                    HandlePUBRECType(clientIndex, (MqttMsgPubrec)packet);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_PUBREL_TYPE:
                {
                    HandlePUBRELType(clientIndex, (MqttMsgPubrel)packet);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_PUBCOMP_TYPE:
                {
                    HandlePUBCOMPType(clientIndex, (MqttMsgPubcomp)packet, isWebSocketClient);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE:
                {
                    HandleSUBSCRIBEType(clientIndex, (MqttMsgSubscribe)packet, isWebSocketClient);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_SUBACK_TYPE:
                {
                    DisconnectClient(clientIndex, false, isWebSocketClient);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE:
                {
                    HandleUNSUBSCRIBEType(clientIndex, (MqttMsgUnsubscribe)packet, isWebSocketClient);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_UNSUBACK_TYPE:
                {
                    DisconnectClient(clientIndex, false, isWebSocketClient);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_PINGREQ_TYPE:
                {
                    HandlePINGREQType(clientIndex, (MqttMsgPingReq)packet, isWebSocketClient);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_PINGRESP_TYPE:
                {
                    HandlePINGRESPType(clientIndex, (MqttMsgPingResp)packet, isWebSocketClient);
                    break;
                }

                case MqttMsgBase.MQTT_MSG_DISCONNECT_TYPE:
                {
                    HandleDISCONNECTType(clientIndex, (MqttMsgDisconnect)packet, isWebSocketClient);
                    break;
                }

                default:
                {
                    throw new MqttCommunicationException(new FormatException("MQTTSERVER -Pacchetto non valido" + packet));
                }
                }
            }
            catch (Exception e)
            {
                CrestronLogger.WriteToLog("MQTTSERVER - RouteControlPacketToMethodHandler - Exception occured trying route packet :  " + e.Message, 8);
                CrestronLogger.WriteToLog("MQTTSERVER - RouteControlPacketToMethodHandler - Stack trace :  " + e.StackTrace, 8);
            }
        }
 public PacketToSendEventArgs(MqttMsgBase packet)
 {
     this.Packet = packet;
 }
 public PacketReceivedEventHandler(uint clientIndex, MqttMsgBase packet, bool isWebSocketClient)
 {
     this.ClientIndex       = clientIndex;
     this.Packet            = packet;
     this.IsWebSocketClient = isWebSocketClient;
 }
        private static MqttMsgBase HandleWaitForPubackSubackUbsuback(
            MqttClientConnection clientConnection,
            MqttMsgContext msgContext,
            MqttMsgBase msgInflight,
            ref bool msgReceivedProcessed,
            ref int timeout)
        {
            // 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)
            {
                return(null);
            }

            MqttMsgBase msgReceived;

            if (!clientConnection.InternalQueue.TryPeek(out msgReceived))
            {
                return(null);
            }

            bool          acknowledge = false;
            InternalEvent internalEvent;

            // PUBACK message or SUBACK/UNSUBACK message for the current message
            if (((msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBACK_TYPE) &&
                 (msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) &&
                 (msgReceived.MessageId == msgInflight.MessageId)) ||
                ((msgReceived.Type == MqttMsgBase.MQTT_MSG_SUBACK_TYPE) &&
                 (msgInflight.Type == MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE) &&
                 (msgReceived.MessageId == msgInflight.MessageId)) ||
                ((msgReceived.Type == MqttMsgBase.MQTT_MSG_UNSUBACK_TYPE) &&
                 (msgInflight.Type == MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE) &&
                 (msgReceived.MessageId == msgInflight.MessageId)))
            {
                // received message processed
                MqttMsgBase dequeuedMsg;
                clientConnection.InternalQueue.TryDequeue(out dequeuedMsg);
                acknowledge          = true;
                msgReceivedProcessed = true;

                // if PUBACK received, confirm published with flag
                if (msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBACK_TYPE)
                {
                    internalEvent = new MsgPublishedInternalEvent(msgReceived, true);
                }
                else
                {
                    internalEvent = new MsgInternalEvent(msgReceived);
                }

                // notify received acknowledge from broker of a published message or subscribe/unsubscribe message
                clientConnection.EnqueueInternalEvent(internalEvent);

                // PUBACK received for PUBLISH message with QoS Level 1, remove from session state
                if ((msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && (clientConnection.Session != null) &&
                    (clientConnection.Session.InflightMessages.ContainsKey(msgContext.Key)))
                {
                    MqttMsgContext contextToBeRemoved;
                    clientConnection.Session.InflightMessages.TryRemove(msgContext.Key, out contextToBeRemoved);
                }
            }

            // current message not acknowledged, no PUBACK or SUBACK/UNSUBACK or not equal messageid
            if (!acknowledge)
            {
                var delta = Environment.TickCount - msgContext.Timestamp;
                // 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 (delta >= clientConnection.Settings.DelayOnRetry)
                {
                    // max retry not reached, resend
                    if (msgContext.Attempt < clientConnection.Settings.AttemptsOnRetry)
                    {
                        msgContext.State = MqttMsgState.QueuedQos1;

                        // re-enqueue message
                        clientConnection.EnqueueInflight(msgContext);

                        // update timeout (0 -> reanalyze queue immediately)
                        timeout = 0;
                    }
                    else
                    {
                        // if PUBACK for a PUBLISH message not received after retries, raise event for not published
                        if (msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE)
                        {
                            // PUBACK not received in time, PUBLISH retries failed, need to remove from session inflight messages too
                            if ((clientConnection.Session != null) &&
                                (clientConnection.Session.InflightMessages.ContainsKey(msgContext.Key)))
                            {
                                MqttMsgContext contextToBeRemoved;
                                clientConnection.Session.InflightMessages.TryRemove(msgContext.Key, out contextToBeRemoved);
                            }

                            internalEvent = new MsgPublishedInternalEvent(msgInflight, false);

                            // notify not received acknowledge from broker and message not published
                            clientConnection.EnqueueInternalEvent(internalEvent);
                        }
                        // NOTE : not raise events for SUBACK or UNSUBACK not received
                        //        for the user no event raised means subscribe/unsubscribe failed
                    }
                }
                else
                {
                    // re-enqueue message (I have to re-analyze for receiving PUBACK, SUBACK or UNSUBACK)
                    clientConnection.EnqueueInflight(msgContext);

                    // update timeout
                    int msgTimeout = (clientConnection.Settings.DelayOnRetry - delta);
                    timeout = (msgTimeout < timeout) ? msgTimeout : timeout;
                }
            }

            return(msgReceived);
        }