public void Store(SNMessage message)
        {
            Boolean isConnect = false;

            if (message.getType() == SNType.CONNECT)
            {
                isConnect = true;
            }

            MessageResendTimer <SNMessage> timer = new MessageResendTimer <SNMessage>(message, _listener, this, isConnect);
            Boolean added = false;

            if (!((CountableMessage)message).MessageID.HasValue)
            {
                Int32 packetID = _packetIDCounter;
                while (!added)
                {
                    packetID = Interlocked.Increment(ref _packetIDCounter) % MAX_VALUE;
                    try
                    {
                        _timersMap.Add(packetID, timer);
                        added = true;
                    }
                    catch (ArgumentException)
                    {
                        //already exists
                    }
                }


                CountableMessage countable = (CountableMessage)message;
                countable.MessageID = packetID;
            }
            else
            {
                _timersMap.Add(((CountableMessage)message).MessageID.Value, timer);
            }

            timer.Execute(_resendPeriod);
        }
        public static IByteBuffer encode(SNMessage message)
        {
            int         length = message.getLength();
            IByteBuffer buf    = Unpooled.Buffer(length);

            if (length <= 255)
            {
                buf.WriteByte(length);
            }
            else
            {
                buf.WriteByte(THREE_OCTET_LENGTH_SUFFIX);
                buf.WriteShort(length);
            }
            SNType type = message.getType();

            buf.WriteByte((byte)(int)type);

            switch (type)
            {
            case SNType.ADVERTISE:
                Advertise advertise = (Advertise)message;
                buf.WriteByte(advertise.gwID);
                buf.WriteShort(advertise.duration);
                break;

            case SNType.SEARCHGW:
                SearchGW searchGw = (SearchGW)message;
                buf.WriteByte((byte)(int)searchGw.Radius);
                break;

            case SNType.GWINFO:
                GWInfo gwInfo = (GWInfo)message;
                buf.WriteByte(gwInfo.gwID);
                if (gwInfo.gwAddress != null)
                {
                    buf.WriteBytes(Encoding.UTF8.GetBytes(gwInfo.gwAddress));
                }
                break;

            case SNType.CONNECT:
                SNConnect connect          = (SNConnect)message;
                byte      connectFlagsByte = Flags.encode(false, null, false, connect.WillPresent, connect.CleanSession, null);
                buf.WriteByte(connectFlagsByte);
                buf.WriteByte(connect.ProtocolID);
                buf.WriteShort(connect.Duration);
                buf.WriteBytes(Encoding.UTF8.GetBytes(connect.ClientID));
                break;

            case SNType.CONNACK:
            case SNType.WILL_TOPIC_RESP:
            case SNType.WILL_MSG_RESP:
                ResponseMessage responseMessage = (ResponseMessage)message;
                buf.WriteByte((byte)(int)responseMessage.ReturnCode);
                break;

            case SNType.WILL_TOPIC:
                WillTopic willTopic = (WillTopic)message;
                if (willTopic.Topic != null)
                {
                    byte willTopicFlagsByte = Flags.encode(false, willTopic.Topic.getQos(), willTopic.Retain, false, false, willTopic.Topic.getType());
                    buf.WriteByte(willTopicFlagsByte);
                    buf.WriteBytes(Encoding.UTF8.GetBytes(willTopic.Topic.Value));
                }
                break;

            case SNType.WILL_MSG:
                WillMsg willMsg = (WillMsg)message;
                buf.WriteBytes(willMsg.Content);
                break;

            case SNType.REGISTER:
                Register register = (Register)message;
                buf.WriteShort(register.topicID);
                buf.WriteShort(register.MessageID.Value);
                buf.WriteBytes(Encoding.UTF8.GetBytes(register.TopicName));
                break;

            case SNType.REGACK:
                Regack regack = (Regack)message;
                buf.WriteShort(regack.topicID);
                buf.WriteShort(regack.MessageID.Value);
                buf.WriteByte((byte)(int)regack.code);
                break;

            case SNType.PUBLISH:
                SNPublish publish          = (SNPublish)message;
                byte      publishFlagsByte = Flags.encode(publish.Dup, publish.SnTopic.getQos(), publish.Retain, false, false, publish.SnTopic.getType());
                buf.WriteByte(publishFlagsByte);
                buf.WriteBytes(publish.SnTopic.encode());
                if (publish.MessageID.HasValue)
                {
                    buf.WriteShort(publish.MessageID.Value);
                }
                else
                {
                    buf.WriteShort(0);
                }
                buf.WriteBytes(publish.Content);
                break;

            case SNType.PUBACK:
                SNPuback puback = (SNPuback)message;
                buf.WriteShort(puback.topicID);
                buf.WriteShort(puback.MessageID.Value);
                buf.WriteByte((byte)(int)puback.ReturnCode);
                break;

            case SNType.PUBREC:
            case SNType.PUBREL:
            case SNType.PUBCOMP:
            case SNType.UNSUBACK:
                CountableMessage contableMessage = (CountableMessage)message;
                buf.WriteShort(contableMessage.MessageID.Value);
                break;

            case SNType.SUBSCRIBE:
                SNSubscribe subscribe      = (SNSubscribe)message;
                byte        subscribeFlags = Flags.encode(subscribe.Dup, subscribe.SnTopic.getQos(), false, false, false, subscribe.SnTopic.getType());
                buf.WriteByte(subscribeFlags);
                buf.WriteShort(subscribe.MessageID.Value);
                buf.WriteBytes(subscribe.SnTopic.encode());
                break;

            case SNType.SUBACK:
                SNSuback suback     = (SNSuback)message;
                byte     subackByte = Flags.encode(false, suback.AllowedQos, false, false, false, null);
                buf.WriteByte(subackByte);
                buf.WriteShort(suback.topicID);
                buf.WriteShort(suback.MessageID.Value);
                buf.WriteByte((byte)(int)suback.ReturnCode);
                break;

            case SNType.UNSUBSCRIBE:
                SNUnsubscribe unsubscribe      = (SNUnsubscribe)message;
                byte          unsubscribeFlags = Flags.encode(false, null, false, false, false, unsubscribe.SnTopic.getType());
                buf.WriteByte(unsubscribeFlags);
                buf.WriteShort(unsubscribe.MessageID.Value);
                buf.WriteBytes(unsubscribe.SnTopic.encode());
                break;

            case SNType.PINGREQ:
                if (length > 2)
                {
                    SNPingreq pingreq = (SNPingreq)message;
                    buf.WriteBytes(Encoding.UTF8.GetBytes(pingreq.ClientID));
                }
                break;

            case SNType.DISCONNECT:
                if (length > 2)
                {
                    SNDisconnect disconnect = (SNDisconnect)message;
                    buf.WriteShort(disconnect.Duration);
                }
                break;

            case SNType.WILL_TOPIC_UPD:
                WillTopicUpd willTopicUpd = (WillTopicUpd)message;
                if (willTopicUpd.Topic != null)
                {
                    byte willTopicUpdByte = Flags.encode(false, willTopicUpd.Topic.getQos(), willTopicUpd.Retain, false, false, null);
                    buf.WriteByte(willTopicUpdByte);
                    buf.WriteBytes(Encoding.UTF8.GetBytes(willTopicUpd.Topic.Value));
                }
                break;

            case SNType.WILL_MSG_UPD:
                WillMsgUpd willMsgUpd = (WillMsgUpd)message;
                buf.WriteBytes(willMsgUpd.Content);
                break;

            case SNType.WILL_TOPIC_REQ:
            case SNType.WILL_MSG_REQ:
            case SNType.PINGRESP:
                break;

            case SNType.ENCAPSULATED:
                Encapsulated encapsulated = (Encapsulated)message;

                buf.WriteByte(Controls.encode(encapsulated.radius));
                buf.WriteBytes(Encoding.UTF8.GetBytes(encapsulated.wirelessNodeID));
                buf.WriteBytes(SNParser.encode(encapsulated.message));
                break;

            default:
                break;
            }

            if (type != SNType.ENCAPSULATED && message.getLength() != buf.ReadableBytes)
            {
                throw new MalformedMessageException("invalid message encoding: expected length-" + message.getLength() + ",actual-" + buf.ReadableBytes);
            }

            return(buf);
        }