Inheritance: MsMessage
示例#1
0
    private void ParseInPacket(byte[] buf) {
      var msgTyp=(MsMessageType)(buf[0]>1?buf[1]:buf[2]);
      switch(msgTyp) {
      case MsMessageType.WILLTOPIC: {
          var msg=new MsWillTopic(buf) { Addr=this.Addr };
          Stat(false, msgTyp);
          PrintPacket(this, msg, buf);
          if(state==State.WillTopic) {
            _willPath=msg.Path;
            _willRetain=msg.Retain;
            state=State.WillMsg;
            ProccessAcknoledge(msg);
          }
        }
        break;
      case MsMessageType.WILLMSG: {
          Stat(false, msgTyp);
          var msg=new MsWillMsg(buf) { Addr=this.Addr };
          PrintPacket(this, msg, buf);
          if(state==State.WillMsg) {
            _wilMsg=msg.Payload;
            state=State.PreConnect;
            ProccessAcknoledge(msg);
            Send(new MsConnack(MsReturnCode.Accepted));
            Log.Info("{0} connected", Owner.path);
          }
        }
        break;
      case MsMessageType.SUBSCRIBE: {
          var msg=new MsSubscribe(buf) { Addr=this.Addr };
          Stat(false, msgTyp, msg.dup);
          PrintPacket(this, msg, buf);

          SyncMsgId(msg.MessageId);
          Topic.Subscription s=null;
          ushort topicId=msg.topicId;
          if(msg.topicIdType!=TopicIdType.Normal || msg.path.IndexOfAny(new[] { '+', '#' })<0) {
            TopicInfo ti=null;
            if(msg.topicIdType==TopicIdType.Normal) {
              ti=GetTopicInfo(msg.path, false);
            } else {
              ti=GetTopicInfo(msg.topicId, msg.topicIdType);
            }
            topicId=ti.TopicId;
          }
          Send(new MsSuback(msg.qualityOfService, topicId, msg.MessageId, MsReturnCode.Accepted));
          if(state==State.PreConnect) {
            state=State.Connected;
          }
          s=Owner.Subscribe(msg.path, PublishTopic, msg.qualityOfService);
          _subsscriptions.Add(s);
        }
        break;
      case MsMessageType.REGISTER: {
          var msg=new MsRegister(buf) { Addr=this.Addr };
          Stat(false, msgTyp);
          PrintPacket(this, msg, buf);
          ResetTimer();
          try {
            TopicInfo ti = GetTopicInfo(msg.TopicPath, false);
            if(ti.topic!=null && ti.topic.valueType==typeof(SmartTwi)) {
              if(ti.topic.GetValue()==null) {
                ti.topic.SetValue(new SmartTwi(ti.topic), new TopicChanged(TopicChanged.ChangeArt.Value, Owner));
              } else {
                (ti.topic as DVar<SmartTwi>).value.Reset();
              }
            }
            Send(new MsRegAck(ti.TopicId, msg.MessageId, MsReturnCode.Accepted));
          }
          catch(Exception) {
            Send(new MsRegAck(0, msg.MessageId, MsReturnCode.NotSupportes));
            Log.Warning("Unknown variable type by register {0}, {1}", Owner.path, msg.TopicPath);
          }
        }
        break;
      case MsMessageType.REGACK: {
          var msg=new MsRegAck(buf) { Addr=this.Addr };
          Stat(false, msgTyp);
          PrintPacket(this, msg, buf);
          ProccessAcknoledge(msg);
          TopicInfo ti=_topics.FirstOrDefault(z => z.TopicId==msg.TopicId);
          if(ti==null) {
            if(msg.TopicId!=0) {
              Log.Warning("{0} RegAck({1:X4}) for unknown variable", Owner.path, msg.TopicId);
            }
            return;
          }
          if(msg.RetCode==MsReturnCode.Accepted) {
            ti.registred=true;
            if(ti.it!=TopicIdType.PreDefined) {
              Send(new MsPublish(ti.topic, ti.TopicId, QoS.AtLeastOnce));
            }
          } else {
            Log.Warning("{0} registred failed: {1}", ti.path, msg.RetCode.ToString());
            ti.it=TopicIdType.NotUsed;
            //_topics.Remove(ti);
            //ti.topic.Remove();
          }
        }
        break;
      case MsMessageType.PUBLISH: {
          var msg=new MsPublish(buf) { Addr=this.Addr };
          Stat(false, msgTyp, msg.Dup);
          PrintPacket(this, msg, buf);
          TopicInfo ti=_topics.Find(z => z.TopicId==msg.TopicId && z.it==msg.topicIdType);
          if(ti==null && msg.topicIdType!=TopicIdType.Normal) {
            ti=GetTopicInfo(msg.TopicId, msg.topicIdType, false);
          }
          if(msg.qualityOfService==QoS.AtMostOnce) {
            ResetTimer();
          } else if(msg.qualityOfService==QoS.AtLeastOnce) {
            SyncMsgId(msg.MessageId);
            Send(new MsPubAck(msg.TopicId, msg.MessageId, ti!=null?MsReturnCode.Accepted:MsReturnCode.InvalidTopicId));
          } else if(msg.qualityOfService==QoS.ExactlyOnce) {
            SyncMsgId(msg.MessageId);
            // QoS2 not supported, use QoS1
            Send(new MsPubAck(msg.TopicId, msg.MessageId, ti!=null?MsReturnCode.Accepted:MsReturnCode.InvalidTopicId));
          } else {
            throw new NotSupportedException("QoS -1 not supported "+Owner.path);
          }
          if(msg.topicIdType==TopicIdType.PreDefined && msg.TopicId>=LOG_D_ID && msg.TopicId<=LOG_E_ID) {
            string str=string.Format("{0}:{1} msg={2} msgId={3} ", this.Owner.path, BitConverter.ToString(msg.Addr), msg.Data==null?"null":BitConverter.ToString(msg.Data), msg.MessageId);
            switch(msg.TopicId) {
            case LOG_D_ID:
              Log.Debug(str);
              break;
            case LOG_I_ID:
              Log.Info(str);
              break;
            case LOG_W_ID:
              Log.Warning(str);
              break;
            case LOG_E_ID:
              Log.Error(str);
              break;
            }
          } else if(ti!=null) {
            SetValue(ti, msg.Data);
          }
        }
        break;
      case MsMessageType.PUBACK: {
          var msg=new MsPubAck(buf) { Addr=this.Addr };
          Stat(false, msgTyp);
          PrintPacket(this, msg, buf);
          ProccessAcknoledge(msg);
        }
        break;
      case MsMessageType.PINGREQ: {
          var msg=new MsPingReq(buf) { Addr=this.Addr };
          Stat(false, msgTyp);
          PrintPacket(this, msg, buf);
          if(state==State.ASleep) {
            if(string.IsNullOrEmpty(msg.ClientId) || msg.ClientId==Owner.name) {
              //if(++_reconnectCnt>1024) {
              //  _reconnectCnt=0;
              //  Send(new MsDisconnect());
              //  state=State.Disconnected;
              //  Log.Info("{0} refresh connection", Owner.path);
              //} else {
              state=State.AWake;
              ProccessAcknoledge(msg);    // resume send proccess
              //}
            } else {
              Send(new MsDisconnect());
              state=State.Lost;
              Log.Warning("{0} PingReq from unknown device: {1}", Owner.path, msg.ClientId);
            }
          } else {
            ResetTimer();
            if(_gate!=null) {
              _gate.Send(new MsMessage(MsMessageType.PINGRESP) { Addr=this.Addr });
              Stat(true, MsMessageType.PINGRESP, false);
            }
          }
        }
        break;
      case MsMessageType.DISCONNECT: {
          var msg=new MsDisconnect(buf) { Addr=this.Addr };
          Stat(false, msgTyp);
          PrintPacket(this, msg, buf);
          Disconnect(msg.Duration);
        }
        break;
      default:
        Log.Warning("{0} unknown packet: {1}", Owner!=null?Owner.path:"null", BitConverter.ToString(buf));
        break;
      }
    }