예제 #1
0
 public void Send(MqMessage msg)
 {
     _stream.Send(msg);
     if (_pl.verbose)
     {
         Log.Debug("S {0} < {1}", this.Signature, msg);
     }
 }
예제 #2
0
        public static MqMessage Parse(byte header, uint len, MemoryStream stream)
        {
            MqMessage msg = null;

            switch ((MessageType)((header & 0xf0) >> 4))
            {
            case MessageType.CONNECT:
                msg = new MqConnect(header, len, stream);
                break;

            case MessageType.CONNACK:
                msg = new MqConnack(header, len, stream);
                break;

            case MessageType.DISCONNECT:
                msg = new MqDisconnect(header, len, stream);
                break;

            case MessageType.PINGREQ:
                msg = new MqPingReq(header, len, stream);
                break;

            case MessageType.PINGRESP:
                msg = new MqPingResp(header, len, stream);
                break;

            case MessageType.PUBLISH:
                msg = new MqPublish(header, len, stream);
                break;

            case MessageType.SUBSCRIBE:
                msg = new MqSubscribe(header, len, stream);
                break;

            case MessageType.SUBACK:
                msg = new MqSuback(header, len, stream);
                break;

            case MessageType.UNSUBSCRIBE:
                msg = new MqUnsubscribe(header, len, stream);
                break;

            case MessageType.UNSUBACK:
                msg = new MqUnsuback(header, len, stream);
                break;

            case MessageType.PUBACK:
            case MessageType.PUBCOMP:
            case MessageType.PUBREC:
            case MessageType.PUBREL:
                msg = new MqMsgAck(header, len, stream);
                break;
            }
            return(msg);
        }
예제 #3
0
        private void SendIntern(MqMessage msg)
        {
            if (msg == null || _waitAck == null)
            {
                return;
            }
            MemoryStream ms = new MemoryStream();

            msg.Serialise(ms);
            try {
                _stream.BeginWrite(ms.GetBuffer(), 0, (int)ms.Length, _sendCB, null);
            }
            catch (IOException) {
                if (this._connected)
                {
                    this.Close();
                }
                return;
            }
            catch (ObjectDisposedException) {
                return;
            }
            catch (Exception ex) {
                string re;
                try{
                    re = Socket.Client.RemoteEndPoint.ToString();
                }
                catch (Exception) {
                    re = "UNK";
                }
                Log.Warning("MqStreamer.SendIntern({0}, {1}) - {2}", msg.ToString(), re, ex.ToString());
            }
            if (msg.QualityOfService != QoS.AtMostOnce && !msg.Duplicate)
            {
                _waitAck.Add(new wMessage(msg));
            }
            msg.Duplicate = true;
            if (msg.MsgType == MessageType.DISCONNECT)
            {
                Thread.Sleep(30); // hack, wait fo buffers flush
                Close(true);
            }
        }
예제 #4
0
 /// <summary> Send Message to broker</summary>
 /// <param name="msg">MQTT message</param>
 /// <remarks>Upon receipt of subscription switches to pause.
 /// Resumes at a pause in the receive of data over 300 ms.
 /// When paused publish are not sent</remarks>
 public void Send(MqMessage msg) {
   if(msg.QualityOfService!=QoS.AtMostOnce && msg.MessageID==0) {
     int tmp=Interlocked.Increment(ref _messageIdGen);
     if((tmp & 0x7FFF)==0) {
       tmp=Interlocked.Increment(ref _messageIdGen);
       _messageIdGen=(ushort)tmp;
     }
     if(Topic.brokerMode) {
       tmp^=0x8000;
     }
     msg.MessageID=(ushort)tmp;
   }
   if((!_sndPaused || msg.MsgType!=MessageType.PUBLISH) && Interlocked.Exchange(ref _sendProcessed, 1)==0) {
     SendIntern(msg);
   } else {
     lock(_sendQ) {
       _sendQ.Enqueue(msg);
     }
   }
 }
예제 #5
0
 /// <summary> Send Message to broker</summary>
 /// <param name="msg">MQTT message</param>
 /// <remarks>Upon receipt of subscription switches to pause.
 /// Resumes at a pause in the receive of data over 300 ms.
 /// When paused publish are not sent</remarks>
 public void Send(MqMessage msg)
 {
     if (msg.QualityOfService != QoS.AtMostOnce && msg.MessageID == 0)
     {
         int tmp = Interlocked.Increment(ref _messageIdGen);
         if ((tmp & 0x7FFF) == 0)
         {
             tmp           = Interlocked.Increment(ref _messageIdGen);
             _messageIdGen = (ushort)tmp;
         }
         tmp          ^= 0x8000;
         msg.MessageID = (ushort)tmp;
     }
     if (Interlocked.Exchange(ref _sendProcessed, 1) == 0)
     {
         SendIntern(msg);
     }
     else
     {
         lock (_sendQ) {
             _sendQ.Enqueue(msg);
         }
     }
 }
예제 #6
0
 private void Send(MqMessage msg) {
   _stream.Send(msg);
   if(_verbose.value) {
     Log.Debug("S {0}", msg);
   }
 }
예제 #7
0
 private void Received(MqMessage msg) {
   if(_verbose.value) {
     Log.Debug("R {0}", msg);
   }
   switch(msg.MsgType) {
   case MessageType.CONNACK: {
       MqConnack cm=msg as MqConnack;
       if(cm.Response!=MqConnack.MqttConnectionResponse.Accepted) {
         Reconnect(true);
         Log.Error("Connection to {0}:{1} failed. error={2}", addr, port, cm.Response.ToString());
       } else {
         _connected=true;
         _subs.Clear();
         Topic_SubscriptionsChg(null, true);
       }
       if(StatusChg!=null) {
         StatusChg(_connected);
       }
     }
     break;
   case MessageType.DISCONNECT:
     Reconnect();
     break;
   case MessageType.PINGRESP:
     _waitPingResp=false;
     break;
   case MessageType.PUBLISH: {
       MqPublish pm=msg as MqPublish;
       if(msg.MessageID!=0) {
         if(msg.QualityOfService==QoS.AtLeastOnce) {
           this.Send(new MqMsgAck(MessageType.PUBACK, msg.MessageID));
         } else if(msg.QualityOfService==QoS.ExactlyOnce) {
           this.Send(new MqMsgAck(MessageType.PUBREC, msg.MessageID));
         }
       }
       ProccessPublishMsg(pm);
     }
     break;
   case MessageType.PUBACK:
     break;
   case MessageType.PUBREC:
     if(msg.MessageID!=0) {
       this.Send(new MqMsgAck(MessageType.PUBREL, msg.MessageID));
     }
     break;
   case MessageType.PUBREL:
     if(msg.MessageID!=0) {
       this.Send(new MqMsgAck(MessageType.PUBCOMP, msg.MessageID));
     }
     break;
   case MessageType.PUBCOMP:
     break;
   default:
     break;
   }
   if(_waitPingResp) {
     _tOut.Change(_keepAliveMS, _keepAliveMS);
   }
 }
예제 #8
0
 public wMessage(MqMessage msg)
 {
     this.msg = msg;
     this.cnt = 0;
 }
예제 #9
0
        private void RcvProcess(IAsyncResult ar)
        {
            bool first = true;
            int  len;

            try {
                len = _stream.EndRead(ar);
            }
            catch (IOException) {
                Close(true);
                return;
            }
            catch (ObjectDisposedException) {
                return;
            }
            if (len > 0)
            {
                try {
                    do
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            _rcvBuf[0] = (byte)_stream.ReadByte();
                        }
                        switch (_rcvState)
                        {
                        case 0: // header
                            _rcvHeader    = _rcvBuf[0];
                            _rcvLengt     = 0;
                            _rcvLengthPos = 0;
                            _rcvState++;
                            break;

                        case 1: {
                            _rcvLengt += (uint)((_rcvBuf[0] & 0x7F) << (7 * _rcvLengthPos));
                            _rcvLengthPos++;
                            if ((_rcvBuf[0] & 0x80) == 0)
                            {
                                _rcvState++;
                                _rcvLengthPos = 0;
                                if (_rcvLengt == 0)
                                {
                                    goto case 2;
                                }
                            }
                        }
                        break;

                        case 2:
                            if (_rcvMemoryStream.Position < _rcvLengt)
                            {
                                _rcvMemoryStream.WriteByte(_rcvBuf[0]);
                            }
                            if (_rcvMemoryStream.Position >= _rcvLengt)
                            {
                                _rcvMemoryStream.Seek(0, SeekOrigin.Begin);
                                MqMessage msg = MqMessage.Parse(_rcvHeader, _rcvLengt, _rcvMemoryStream);
                                if (msg == null)
                                {
                                    Log.Warning("unrecognized message from {0}={1:X2}[{2}]", ((IPEndPoint)Socket.Client.RemoteEndPoint), _rcvHeader, _rcvLengt);
                                    _rcvMemoryStream.Seek(0, SeekOrigin.Begin);
                                    _rcvState = 0;
                                }
                                else
                                {
                                    _rcvMemoryStream.Seek(0, SeekOrigin.Begin);
                                    _rcvMemoryStream.SetLength(0);
                                    _rcvState = 0;

                                    if (msg.MessageID != 0)
                                    {
                                        if (msg.Reason != MessageType.NONE)
                                        {
                                            _waitAck.RemoveAll(wm => wm.msg.MessageID == msg.MessageID && wm.msg.MsgType == msg.Reason);
                                        }
                                        else
                                        {
                                            int nid = msg.MessageID + 1;
                                            if (nid == 0x10000)
                                            {
                                                nid++;
                                            }
                                            if (nid > (int)_messageIdGen || (nid > 0xFF00 && _messageIdGen < 0x0100))
                                            {
                                                _messageIdGen = (ushort)nid; // synchronize messageId
                                            }
                                        }
                                    }
                                    if (_rcvCallback != null)
                                    {
                                        _rcvCallback(msg);
                                    }
                                }

                                if (_waitAck.Count > 0)
                                {
                                    _sendTimer.Change(900, Timeout.Infinite); // connection is busy
                                }
                            }
                            break;

                        default:
                            _rcvState = 0;
                            break;
                        }
                    } while(_stream.DataAvailable);
                    if (_rcvState != 0)
                    {
                        _rcvTimer.Change(100, Timeout.Infinite);
                    }
                    else
                    {
                        _rcvTimer.Change(Timeout.Infinite, Timeout.Infinite);
                    }
                }
                catch (ObjectDisposedException) {
                    return;
                }
                catch (ArgumentException ex) {
                    _rcvMemoryStream.Seek(0, SeekOrigin.Begin);
                    _rcvState = 0;
                    Log.Warning(ex.Message);
                }
                catch (Exception ex) {
                    _rcvMemoryStream.Seek(0, SeekOrigin.Begin);
                    _rcvState = 0;
                    Log.Warning(ex.ToString());
                }
            }
            else
            {
                if (_connected)
                {
                    this.Close(true);
                }
                return;
            }
            try {
                _stream.BeginRead(_rcvBuf, 0, 1, RcvProcess, _stream);
            }
            catch (IOException ex) {
                if (_connected)
                {
                    this.Close(true);
                    Log.Warning("MqStreamer.RcvProcess {0}", ex.Message);
                }
                return;
            }
            catch (ObjectDisposedException ex) {
                Log.Warning("MqStreamer.RcvProcess {0}", ex.Message);
                return;
            }
        }
예제 #10
0
        private void Received(MqMessage msg)
        {
            if (_pl.verbose)
            {
                Log.Debug("R {0} > {1}", this.Signature, msg);
            }
            switch (msg.MsgType)
            {
            case MessageType.CONNACK: {
                MqConnack cm = msg as MqConnack;
                if (cm.Response == MqConnack.MqttConnectionResponse.Accepted)
                {
                    status = Status.Connected;
                    _tOut.Change(KEEP_ALIVE, KEEP_ALIVE);
                    Log.Info("Connected to {0}", Signature);
                    foreach (var site in Sites)
                    {
                        site.Connected();
                    }
                }
                else
                {
                    status = Status.NotAccepted;
                    _tOut.Change(Timeout.Infinite, Timeout.Infinite);
                }
            }
            break;

            case MessageType.DISCONNECT:
                status = Status.Disconnected;
                _tOut.Change(3000, KEEP_ALIVE);
                break;

            case MessageType.PINGRESP:
                _waitPingResp = false;
                break;

            case MessageType.PUBLISH: {
                MqPublish pm = msg as MqPublish;
                if (msg.MessageID != 0)
                {
                    if (msg.QualityOfService == QoS.AtLeastOnce)
                    {
                        this.Send(new MqMsgAck(MessageType.PUBACK, msg.MessageID));
                    }
                    else if (msg.QualityOfService == QoS.ExactlyOnce)
                    {
                        this.Send(new MqMsgAck(MessageType.PUBREC, msg.MessageID));
                    }
                }
                ProccessPublishMsg(pm);
            }
            break;

            case MessageType.PUBACK:
                break;

            case MessageType.PUBREC:
                if (msg.MessageID != 0)
                {
                    this.Send(new MqMsgAck(MessageType.PUBREL, msg.MessageID));
                }
                break;

            case MessageType.PUBREL:
                if (msg.MessageID != 0)
                {
                    this.Send(new MqMsgAck(MessageType.PUBCOMP, msg.MessageID));
                }
                break;
            }
            if (_waitPingResp)
            {
                _tOut.Change(KEEP_ALIVE, KEEP_ALIVE);
            }
        }
예제 #11
0
 public wMessage(MqMessage msg) {
   this.msg=msg;
   this.cnt=0;
 }
예제 #12
0
 private void SendIntern(MqMessage msg) {
   if(msg==null || _waitAck==null) {
     return;
   }
   MemoryStream ms=new MemoryStream();
   msg.Serialise(ms);
   try {
     _stream.BeginWrite(ms.GetBuffer(), 0, (int)ms.Length, _sendCB, null);
   }
   catch(IOException) {
     if(this._connected) {
       this.Close();
     }
     return;
   }
   catch(ObjectDisposedException) {
     return;
   }
   catch(Exception ex) {
     string re;
     try{
       re=Socket.Client.RemoteEndPoint.ToString();
     }catch(Exception){
       re="UNK";
     }
     Log.Warning("MqStreamer.SendIntern({0}, {1}) - {2}", msg.ToString(), re, ex.ToString());
   }
   if(msg.QualityOfService!=QoS.AtMostOnce && !msg.Duplicate) {
     _waitAck.Add(new wMessage(msg));
   }
   msg.Duplicate=true;
   if(msg.MsgType==MessageType.DISCONNECT) {
     Thread.Sleep(30);     // hack, wait fo buffers flush
     Close(true);
   }
 }