X13.Periphery.MsDevice.ProcessInPacket C# (CSharp) Method

ProcessInPacket() private method

private ProcessInPacket ( MsMessage msg ) : void
msg MsMessage
return void
    internal void ProcessInPacket(MsMessage msg) {
      if(_statistic.value && msg.MsgTyp!=MsMessageType.EncapsulatedMessage && msg.MsgTyp!=MsMessageType.PUBLISH) {
        Stat(false, msg.MsgTyp);
      }
      switch(msg.MsgTyp) {
      case MsMessageType.WILLTOPIC: {
          var tmp=msg as MsWillTopic;
          if(state==State.WillTopic) {
            _willPath=tmp.Path;
            _willRetain=tmp.Retain;
            state=State.WillMsg;
            ProccessAcknoledge(msg);
          }
        }
        break;
      case MsMessageType.WILLMSG: {
          var tmp=msg as MsWillMsg;
          if(state==State.WillMsg) {
            _wilMsg=tmp.Payload;
            Log.Info("{0}.state {1} => WILLTOPICREQ", Owner.path, state);
            state=State.PreConnect;
            ProccessAcknoledge(msg);
            Send(new MsConnack(MsReturnCode.Accepted));
          }
        }
        break;
      case MsMessageType.SUBSCRIBE: {
          var tmp=msg as MsSubscribe;

          SyncMsgId(msg.MessageId);
          Topic.Subscription s=null;
          ushort topicId=tmp.topicId;
          if(tmp.topicIdType!=TopicIdType.Normal || tmp.path.IndexOfAny(new[] { '+', '#' })<0) {
            TopicInfo ti=null;
            if(tmp.topicIdType==TopicIdType.Normal) {
              ti=GetTopicInfo(tmp.path, false);
            } else {
              ti=GetTopicInfo(tmp.topicId, tmp.topicIdType);
            }
            topicId=ti.TopicId;
          }
          Send(new MsSuback(tmp.qualityOfService, topicId, msg.MessageId, MsReturnCode.Accepted));
          if(state==State.PreConnect) {
            state=State.Connected;
          }
          s=Owner.Subscribe(tmp.path, PublishTopic, tmp.qualityOfService);
          _subsscriptions.Add(s);
        }
        break;
      case MsMessageType.REGISTER: {
          var  tmp=msg as MsRegister;
          ResetTimer();
          try {
            TopicInfo ti = GetTopicInfo(tmp.TopicPath, false);
            if(ti.topic!=null) {
              if(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();
                }
              } else if(ti.topic.valueType==typeof(TWIDriver)) {
                if(ti.topic.GetValue()==null) {
                  ti.topic.SetValue(new TWIDriver(ti.topic), new TopicChanged(TopicChanged.ChangeArt.Value, Owner));
                } else {
                  (ti.topic as DVar<TWIDriver>).value.Reset();
                }
              }
            }
            Send(new MsRegAck(ti.TopicId, tmp.MessageId, MsReturnCode.Accepted));
          }
          catch(Exception) {
            Send(new MsRegAck(0, tmp.MessageId, MsReturnCode.NotSupportes));
            Log.Warning("Unknown variable type by register {0}, {1}", Owner.path, tmp.TopicPath);
          }
        }
        break;
      case MsMessageType.REGACK: {
          var  tmp=msg as MsRegAck;
          ProccessAcknoledge(tmp);
          TopicInfo ti=_topics.FirstOrDefault(z => z.TopicId==tmp.TopicId);
          if(ti==null) {
            if(tmp.TopicId!=0xFFFF) { // 0xFFFF - remove variable
              Log.Warning("{0} RegAck({1:X4}) for unknown variable", Owner.path, tmp.TopicId);
            }
            return;
          }
          if(tmp.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, tmp.RetCode.ToString());
            _topics.Remove(ti);
            ti.topic.Remove();
          }
        }
        break;
      case MsMessageType.PUBLISH: {
          var tmp=msg as MsPublish;
          if(_statistic.value) {
            Stat(false, msg.MsgTyp, tmp.Dup);
          }
          TopicInfo ti=_topics.Find(z => z.TopicId==tmp.TopicId && z.it==tmp.topicIdType);
          if(ti==null && tmp.topicIdType!=TopicIdType.Normal) {
            ti=GetTopicInfo(tmp.TopicId, tmp.topicIdType, false);
          }
          if(tmp.qualityOfService==QoS.AtMostOnce || (tmp.qualityOfService==QoS.MinusOne && (tmp.topicIdType==TopicIdType.PreDefined || tmp.topicIdType==TopicIdType.ShortName))) {
            ResetTimer();
          } else if(tmp.qualityOfService==QoS.AtLeastOnce) {
            SyncMsgId(tmp.MessageId);
            Send(new MsPubAck(tmp.TopicId, tmp.MessageId, ti!=null?MsReturnCode.Accepted:MsReturnCode.InvalidTopicId));
          } else if(tmp.qualityOfService==QoS.ExactlyOnce) {
            SyncMsgId(tmp.MessageId);
            // QoS2 not supported, use QoS1
            Send(new MsPubAck(tmp.TopicId, tmp.MessageId, ti!=null?MsReturnCode.Accepted:MsReturnCode.InvalidTopicId));
          } else {
            throw new NotSupportedException("QoS -1 not supported "+Owner.path);
          }
          if(tmp.topicIdType==TopicIdType.PreDefined && tmp.TopicId>=LOG_D_ID && tmp.TopicId<=LOG_E_ID) {
            string str=string.Format("{0} msgId={2:X4}  msg={1}", this.Owner.name, tmp.Data==null?"null":(BitConverter.ToString(tmp.Data)+"["+ Encoding.ASCII.GetString(tmp.Data.Select(z => (z<0x20 || z>0x7E)?(byte)'.':z).ToArray())+"]"), tmp.MessageId);
            switch(tmp.TopicId) {
            case LOG_D_ID:
              Log.Debug("{0}", str);
              break;
            case LOG_I_ID:
              Log.Info("{0}", str);
              break;
            case LOG_W_ID:
              Log.Warning("{0}", str);
              break;
            case LOG_E_ID:
              Log.Error("{0}", str);
              break;
            }
          } else if(ti!=null) {
            if(tmp.Dup && _lastInPub!=null && tmp.MessageId==_lastInPub.MessageId) {  // arready recieved
            } else {
              SetValue(ti, tmp.Data, tmp.Retained);
            }
            _lastInPub=tmp;
          }
        }
        break;
      case MsMessageType.PUBACK: {
          ProccessAcknoledge(msg);
        }
        break;
      case MsMessageType.PINGREQ: {
          var tmp=msg as MsPingReq;
          if(state==State.ASleep) {
            if(string.IsNullOrEmpty(tmp.ClientId) || tmp.ClientId==Owner.name) {
              state=State.AWake;
              ProccessAcknoledge(msg);    // resume send proccess
            } else {
              SendGw(this, new MsDisconnect());
              state=State.Lost;
              Log.Warning("{0} PingReq from unknown device: {1}", Owner.path, tmp.ClientId);
            }
          } else {
            ResetTimer();
            if(_gate!=null) {
              _gate.SendGw(this, new MsMessage(MsMessageType.PINGRESP));
              if(_statistic.value) {
                Stat(true, MsMessageType.PINGRESP, false);
              }
            }
          }
        }
        break;
      case MsMessageType.DISCONNECT:
        Disconnect((msg as MsDisconnect).Duration);
        break;
      case MsMessageType.CONNECT:
        Connect(msg as MsConnect);
        break;
      case MsMessageType.EncapsulatedMessage: {
          Topic devR=Topic.root.Get("/dev");
          var fm=msg as MsForward;
          if(fm.msg==null) {
            if(_verbose.value) {
              Log.Warning("bad message {0}:{1}", _gate, fm.ToString());
            }
            return;
          }
          if(fm.msg.MsgTyp==MsMessageType.SEARCHGW) {
            _gate.SendGw(this, new MsGwInfo(gwIdx));
          } else if(fm.msg.MsgTyp==MsMessageType.DHCP_REQ) {
            var dr=fm.msg as MsDhcpReq;
            //******************************
            List<byte> ackAddr=new List<byte>();
            byte[] respPrev=null;

            foreach(byte hLen in dr.hLen) {
              if(hLen==0) {
                continue;
              } else if(hLen<=8) {
                byte[] resp;
                if(respPrev!=null && respPrev.Length==hLen) {
                  resp=respPrev;
                } else {
                  resp=new byte[hLen];

                  for(int i=0; i<5; i++) {
                    for(int j=0; j<resp.Length; j++) {
                      resp[j]=(byte)_rand.Next((i<3 && hLen==1)?32:1, (i<3 && hLen==1)?126:(j==0?254:255));
                    }
                    if(devR.children.Select(z => z as DVar<MsDevice>).Where(z => z!=null && z.value!=null).All(z => !z.value.CheckAddr(resp))) {
                      break;
                    } else if(i==4) {
                      for(int j=0; j<resp.Length; j++) {
                        resp[j]=0xFF;
                      }
                    }
                  }
                  respPrev=resp;
                }
                ackAddr.AddRange(resp);
              } else {
                if(_verbose.value) {
                  Log.Warning("{0}:{1} DhcpReq.hLen is too high", BitConverter.ToString(fm.addr), fm.msg.ToString());
                }
                ackAddr=null;
                break;
              }
            }
            if(ackAddr!=null) {
              _gate.SendGw(this, new MsForward(fm.addr, new MsDhcpAck(gwIdx, dr.xId, ackAddr.ToArray())));
            }
            //******************************
          } else {
            if(fm.msg.MsgTyp==MsMessageType.CONNECT) {
              var cm=fm.msg as MsConnect;
              if(fm.addr!=null && fm.addr.Length==2 && fm.addr[1]==0xFF) {    // DHCP V<0.3
                _gate.SendGw(this, new MsForward(fm.addr, new MsConnack(MsReturnCode.Accepted)));

                byte[] nAddr=new byte[1];
                do {
                  nAddr[0]=(byte)(_rand.Next(32, 254));
                } while(!devR.children.Select(z => z as DVar<MsDevice>).Where(z => z!=null && z.value!=null).All(z => !z.value.CheckAddr(nAddr)));
                Log.Info("{0} new addr={1:X2}", cm.ClientId, nAddr[0]);
                _gate.SendGw(this, new MsForward(fm.addr, new MsPublish(null, PredefinedTopics[".cfg/XD_DeviceAddr"], QoS.AtLeastOnce) { MessageId=1, Data=nAddr }));
              } else {
                DVar<MsDevice> dDev=devR.Get<MsDevice>(cm.ClientId);
                if(dDev.value==null) {
                  dDev.value=new MsDevice(this, fm.addr);
                  Thread.Sleep(0);
                  dDev.value.Owner=dDev;
                } else {
                  this.RemoveNode(dDev.value);
                  dDev.value._gate=this;
                  dDev.value.Addr=fm.addr;
                }
                this.AddNode(dDev.value);
                dDev.value.Connect(cm);
                foreach(var dub in devR.children.Select(z => z.GetValue() as MsDevice).Where(z => z!=null && z!=dDev.value && z.Addr!=null && z.Addr.SequenceEqual(fm.addr) && z._gate==this).ToArray()) {
                  dub.Addr=null;
                  dub._gate=null;
                  dub.state=State.Disconnected;
                }
              }
            } else {
              MsDevice dev=devR.children.Select(z => z.GetValue() as MsDevice).FirstOrDefault(z => z!=null && z.Addr!=null && z.Addr.SequenceEqual(fm.addr) && z._gate==this);
              if(dev!=null 
                && ((dev.state!=State.Disconnected && dev.state!=State.Lost) 
                  || fm.msg.MsgTyp==MsMessageType.CONNECT 
                  || (fm.msg.MsgTyp==MsMessageType.PUBLISH && (fm.msg as MsPublish).qualityOfService==QoS.MinusOne))) {
                dev.ProcessInPacket(fm.msg);
              } else if(fm.msg.MsgTyp==MsMessageType.PUBLISH && (fm.msg as MsPublish).qualityOfService==QoS.MinusOne) {
                var tmp=fm.msg as MsPublish;
                if(tmp.topicIdType==TopicIdType.PreDefined && tmp.TopicId>=LOG_D_ID && tmp.TopicId<=LOG_E_ID) {
                  string str=string.Format("{0}: msgId={2:X4} msg={1}", BitConverter.ToString(this.Addr), tmp.Data==null?"null":(BitConverter.ToString(tmp.Data)+"["+ Encoding.ASCII.GetString(tmp.Data.Select(z => (z<0x20 || z>0x7E)?(byte)'.':z).ToArray())+"]"), tmp.MessageId);
                  switch(tmp.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(dev==null || dev.Owner==null) {
                  if(_verbose.value) {
                    Log.Debug("{0} via {1} unknown device", BitConverter.ToString(fm.addr), this.name);
                  }
                } else {
                  if(_verbose.value) {
                    Log.Debug("{0} via {1} inactive", dev.Owner.name, this.name);
                  }
                }
                _gate.SendGw(this, new MsForward(fm.addr, new MsDisconnect()));
              }
            }
          }
        }
        break;
      }
    }

Same methods

MsDevice::ProcessInPacket ( IMsGate gate, byte addr, byte buf, int start, int end ) : void