Example #1
0
        public void EndGeneration(int endedGeneration)
        {
            var current = incomingMessages;

            if (current.Generation > endedGeneration)
            {
                return;
            }
            lock (this)
            {
                Log.Message("Inserting message generation " + current.Generation + "->" + (endedGeneration + 1));
                //if (!generations.IsEmpty && !generations.ContainsKey(current.Generation - 1))
                //throw new IntegrityViolation("Trying to insert generation " + current.Generation + ", but generation " + (current.Generation - 1) + " does not locally exist");

                if (generations.TryAdd(current.Generation, current))
                {
                    DB.PutNow(new SerialCCS(new SDS.ID(Simulation.ID.XYZ, current.Generation), current.Export(true)), true);
                }
                for (int i = current.Generation + 1; i <= endedGeneration; i++)
                {
                    Log.Message("Skipping empty message generation " + i);
                    var m = new IncomingMessages(i, MessagePack.CompleteBlank);
                    generations.TryAdd(i, m);
                    DB.PutNow(new SerialCCS(new SDS.ID(Simulation.ID.XYZ, i), m.Export(true)), true);
                }
                incomingMessages = new IncomingMessages(endedGeneration + 1);
            }
        }
Example #2
0
 public void TrimGenerations(int generationOrOlder)
 {
     lock (this)
     {
         LazyList <int> eraseGenerations;
         foreach (var p in generations)
         {
             if (p.Key <= generationOrOlder)
             {
                 eraseGenerations.Add(p.Key);
             }
         }
         foreach (var g in eraseGenerations)
         {
             IncomingMessages m;
             generations.ForceRemove(g, out m);
             //if (!m.WasCollected)
             //throw new IntegrityViolation("Dumping uncollected messages");
         }
         if (incomingMessages.Generation <= generationOrOlder)
         {
             incomingMessages = new IncomingMessages(generationOrOlder + 1);
         }
     }
 }
Example #3
0
        /// <summary>
        /// Асинхронное пакетное чтение множества преременных.
        /// </summary>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <param name="target">Адрес устойства.</param>
        /// <param name="ids">Список идентификаторов переменных.</param>
        /// <returns>
        /// Аснихронная задача
        /// </returns>
        /// <seealso cref="ReadProgressInfo"/>
        public async Task ReadManyValuesAsync(NibusOptions options, Address target, params int[] ids)
        {
            //Contract.Requires(options != null);
            //Contract.Requires(options.Progress != null);
            //Contract.Requires(target != null);
            //Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            foreach (var splitIds in ids.Split(NmsMessage.NmsMaxDataLength / 3).Select(splitIds => splitIds.ToArray()))
            {
                NmsMessage lastMessage;
                IncomingMessages.TryReceive(null, out lastMessage);
                await OutgoingMessages.SendAsync(new NmsReadMany(target, splitIds));

                var tasks = from id in splitIds
                            select GetNmsReadResponseAsync(lastMessage, target, id, options)
                            .ContinueWith(
                    task =>
                {
                    var rp = new ReadProgressInfo(target, id, task);
                    if (Logger.IsTraceEnabled)
                    {
                        Logger.Trace("Received id={0}, Exc = {1}", rp.Id, rp.Exception);
                    }
                    options.Progress.Report(rp);
                });

                try
                {
                    await Task.WhenAll(tasks.ToArray());
                }
                catch (Exception e)
                {
                    Logger.Error(e, "Read failed");
                }
            }
        }
Example #4
0
        public string Subscribe(string uid, string topicFilter, Action <MqttApplicationMessageReceivedEventArgs> callback)
        {
            if (topicFilter == null)
            {
                throw new ArgumentNullException(nameof(topicFilter));
            }
            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            if (string.IsNullOrEmpty(uid))
            {
                uid = Guid.NewGuid().ToString("D");
            }

            lock (Subscribers)
            {
                Subscribers[uid] = new MqttSubscriber(uid, topicFilter, callback);
            }

            // Enqueue all retained messages to match the expected MQTT behavior.
            // Here we have no client per subscription. So we need to adopt some
            // features here manually.
            foreach (var retainedMessage in _serverEx.GetRetainedApplicationMessagesAsync().GetAwaiter().GetResult())
            {
                IncomingMessages.Add(new MqttApplicationMessageReceivedEventArgs(null, retainedMessage));
            }

            return(uid);
        }
Example #5
0
 public void ProcessIncomingQueue()
 {
     foreach (RawMessage m in IncomingMessages)
     {
         ProcessIncomingMessage(m);
     }
     IncomingMessages.Clear();
 }
Example #6
0
        protected override void Run()
        {
            Log.Debug("Started sender");

            var persistence = new PersistenceManager();

            while (true)
            {
                if (Token.IsCancellationRequested)
                {
                    Log.Debug("Received request to stop");
                    return;
                }

                if (IncomingMessages.Count == 0)
                {
                    continue;
                }

                using (var file = File.Open(Path.Combine(FileInfo.LocalPath, FileInfo.FileName), FileMode.Open))
                    using (var stream = new BinaryReader(file))
                    {
                        while (IncomingMessages.Count > 0)
                        {
                            Message mesg;
                            if (IncomingMessages.TryDequeue(out mesg))
                            {
                                if (mesg.MessageId == MessageType.CHUNK_REQUEST)
                                {
                                    var chunkReq = (ChunkRequest)mesg;

                                    stream.BaseStream.Seek(chunkReq.Size * chunkReq.Index, SeekOrigin.Begin);
                                    var bytes = stream.ReadBytes(chunkReq.Size);

                                    var provider = new RSACryptoServiceProvider();
                                    provider.ImportCspBlob(persistence.ReadContent().KeyInfo);

                                    Log.DebugFormat("Building ChunkReply message for index {0}", chunkReq.Index);
                                    var outMessage = new ChunkReply(Guid.NewGuid(),
                                                                    chunkReq.ConversationId,
                                                                    chunkReq.MessageCount + 1,
                                                                    bytes,
                                                                    chunkReq.Index,
                                                                    MessageVerifier.CreateSignature(bytes, provider.ExportParameters(true)));
                                    RaiseSendMessageEvent(outMessage);
                                }
                                else if (mesg.MessageId == MessageType.ACKNOWLEDGE)
                                {
                                    Log.Info("Client acknowledged that it has received all the data");
                                    CancelSource.Cancel();
                                    RaiseEndConversationEvent();
                                }
                            }
                        }
                    }
            }
        }
Example #7
0
        public MessageHistory(int startGeneration, IEnumerable <MessagePack> generations)
        {
            int g = startGeneration;

            foreach (var m in generations)
            {
                this.generations.ForceAdd(g, new IncomingMessages(g, m));
                g++;
            }
            incomingMessages = new IncomingMessages(g);
        }
Example #8
0
            public void ProcessMessageString(string message, long senderId, bool isglobal)
            {
                RawMessage rawMessage = new RawMessage();

                rawMessage.isGlobal       = isglobal;
                rawMessage.SenderReceiver = senderId;

                rawMessage.Type = (MessageType)BitConverter.ToInt32(Convert.FromBase64String(message.Substring(0, 8)), 0);
                rawMessage.Args = Convert.FromBase64String(message.Substring(8));
                IncomingMessages.Add(rawMessage);
            }
Example #9
0
        public NetworkMessage <T> GetLatestMessage()
        {
            NetworkMessage <T> msg;
            bool success = IncomingMessages.TryDequeue(out msg);

            if (success)
            {
                return(msg);
            }
            throw new Exception("No Message Queued! Used HaveIncomingMessage() to check!");
        }
Example #10
0
        /// <summary>
        /// Отправляет NMS-сообщение <paramref name="query"/> и ожидает ответа.
        /// Асинхронная операция.
        /// </summary>
        /// <typeparam name="TMessage">Тип сообщения, потомок NmsMessage.</typeparam>
        /// <param name="query">Сообщение-запрос.</param>
        /// <param name="options">Параметры асинхронной операции.</param>
        /// <returns>
        ///  <see cref="Task{TResult}"/> асинхронная операция - ответное сообщение.
        /// </returns>
        /// <exception cref="AggregateException">Призошла ошибка в асинхронном коде. См. <see cref="Exception.InnerException"/></exception>
        /// <exception cref="TimeoutException">Ошибка по таймауту.</exception>
        /// <exception cref="TaskCanceledException">Операция прервана пользователем.</exception>
        /// <exception cref="NibusResponseException">Ошибка NiBUS.</exception>
        public async Task <TMessage> WaitForNmsResponseAsync <TMessage>(TMessage query, NibusOptions options = null)
            where TMessage : NmsMessage
        {
            //Contract.Requires(!IsDisposed);
            //Contract.Requires(
            //    query.Datagram.Destanation.Type == AddressType.Hardware
            //    || query.Datagram.Destanation.Type == AddressType.Net);

            options = GetDefaultOrClone(options);

            // Последнее сообщение в BroadcastBlock всегда остается! Незабываем его фильтровать.
            NmsMessage lastMessage;

            IncomingMessages.TryReceive(null, out lastMessage);

            var wob = new WriteOnceBlock <NmsMessage>(m => m);

            using (IncomingMessages.LinkTo(
                       wob,
                       m => !ReferenceEquals(lastMessage, m) && m.IsResponse && m.ServiceType == query.ServiceType &&
                       (query.Id == 0 || m.Id == query.Id) && (query.Datagram.Destanation == Address.Empty || m.Datagram.Source == query.Datagram.Destanation)))
            {
                for (var i = 0; i < options.Attempts; i++)
                {
                    await OutgoingMessages.SendAsync(query);

                    try
                    {
                        var response =
                            (TMessage)await wob.ReceiveAsync(options.Timeout, options.Token).ConfigureAwait(false);

                        if (response.ErrorCode != 0)
                        {
                            throw new NibusResponseException(response.ErrorCode);
                        }

                        return(response);
                    }
                    catch (TimeoutException)
                    {
                        Logger.Debug("Timeout {0}", i + 1);
                        if (i < options.Attempts - 1)
                        {
                            continue;
                        }
                        throw;
                    }
                }
            }

            // Эта точка недостижима при attempts > 0!
            throw new InvalidOperationException();
        }
Example #11
0
        private async ValueTask <IMessage <T> > FetchSingleMessageFromBroker()
        {
            // Just being cautious
            if (IncomingMessages.Count > 0)
            {
                _log.Error("The incoming message queue should never be greater than 0 when Queue size is 0");
                IncomingMessages.Empty();
            }

            IMessage <T> message;

            try
            {
                // if cnx is null or if the connection breaks the connectionOpened function will send the flow again
                _waitingOnReceiveForZeroQueueSize = true;
                if (Connected())
                {
                    IncreaseAvailablePermits(_clientCnx);
                }
                do
                {
                    message = await IncomingMessages.ReceiveAsync();

                    _lastDequeuedMessageId = message.MessageId;
                    var msgCnx = ((Message <T>)message).Cnx();
                    // synchronized need to prevent race between connectionOpened and the check "msgCnx == cnx()"
                    // if message received due to an old flow - discard it and wait for the message from the
                    // latest flow command
                    if (msgCnx == _clientCnx)
                    {
                        _waitingOnReceiveForZeroQueueSize = false;
                        break;
                    }
                } while(true);

                Stats.UpdateNumMsgsReceived(message);
                return(message);
            }
            catch (Exception e)
            {
                Stats.IncrementNumReceiveFailed();
                throw PulsarClientException.Unwrap(e);
            }
            finally
            {
                // Finally blocked is invoked in case the block on incomingMessages is interrupted
                _waitingOnReceiveForZeroQueueSize = false;
                // Clearing the queue in case there was a race with messageReceived
                IncomingMessages.Empty();
            }
        }
        protected override void Run()
        {
            Log.Debug("Started receiver");

            var persistence = new PersistenceManager();

            for (var i = 0; i < 3; i++)
            {
                if (Token.IsCancellationRequested)
                {
                    Log.Debug("Received request to stop");
                    break;
                }

                while (IncomingMessages.Count > 0)
                {
                    Message mesg;
                    if (IncomingMessages.TryDequeue(out mesg))
                    {
                        if (mesg.MessageId == MessageType.REGISTER_CONTENT_REQUEST)
                        {
                            var req = (RegisterContentRequest)mesg;

                            Log.Info(string.Format("Registering {0} with host {1} and port {2}", req.Name, req.Host, req.Port));
                            var content = new Content()
                            {
                                ContentHash   = req.Hash,
                                ByteSize      = req.FileSize,
                                FileName      = req.Name,
                                Description   = req.Description,
                                Host          = req.Host,
                                Port          = req.Port,
                                LocalPath     = ".",
                                PublicKeyInfo = req.PublicKeyInfo
                            };
                            persistence.WriteContent(content, PersistenceManager.StorageType.Local);

                            var ack = new Acknowledge(Guid.NewGuid(), ConversationId, req.MessageCount + 1, "Accepted register content request");
                            CancelSource.Cancel();
                            RaiseSendMessageEvent(ack);
                            break;
                        }
                    }
                }
            }

            RaiseEndConversationEvent();
        }
Example #13
0
        protected override void Run()
        {
            Log.Debug("Started sender");

            var persistence = new PersistenceManager();

            // Only try three times
            for (var i = 0; i < 3; i++)
            {
                if (Token.IsCancellationRequested)
                {
                    Log.Debug("Received request to stop");
                    break;
                }

                var req = new ContentListRequest(Guid.NewGuid(), ConversationId, 0, Query);
                RaiseSendMessageEvent(req);

                Thread.Sleep(500);

                while (IncomingMessages.Count > 0)
                {
                    Message mesg;
                    if (IncomingMessages.TryDequeue(out mesg))
                    {
                        if (mesg.MessageId == MessageType.CONTENT_LIST_REPLY)
                        {
                            var reply = (ContentListReply)mesg;

                            foreach (var content in reply.ContentList)
                            {
                                // TODO This is read the file on every call
                                persistence.WriteContent(content, PersistenceManager.StorageType.Remote);
                            }

                            OnSearchResults?.Invoke(reply.ContentList);

                            CancelSource.Cancel();
                            break;
                        }
                    }
                }
            }

            RaiseEndConversationEvent();
        }
Example #14
0
        protected override void Run()
        {
            Log.Debug("Started sender");
            var persistence = new PersistenceManager();

            while (true)
            {
                if (Token.IsCancellationRequested)
                {
                    Log.Debug("Received request to stop");
                    return;
                }

                // Slow down busy loop
                Thread.Sleep(100);

                while (IncomingMessages.Count > 0)
                {
                    Message mesg;
                    if (IncomingMessages.TryDequeue(out mesg))
                    {
                        if (mesg.MessageId == MessageType.CONTENT_LIST_REQUEST)
                        {
                            var req = (ContentListRequest)mesg;
                            var availableContent = persistence.ReadContent();
                            var reply            = new ContentListReply(Guid.NewGuid(), ConversationId, req.MessageCount + 1, availableContent.LocalContent);

                            if (req.ContentQuery != "")
                            {
                                // String match the filenames and descriptions for searching content
                                reply.ContentList = availableContent.LocalContent.Where(content =>
                                                                                        content.Description.ToLower().Contains(req.ContentQuery) ||
                                                                                        content.FileName.ToLower().Contains(req.ContentQuery)).ToList();
                            }

                            Log.Info(string.Format("Sending list of {0} content items", reply.ContentList.Count()));
                            RaiseSendMessageEvent(reply);
                            RaiseEndConversationEvent();
                            break;
                        }
                    }
                }
            }
        }
        protected override void Run()
        {
            Log.Debug("Started sender");

            // Only try three times
            for (var i = 0; i < 3; i++)
            {
                if (Token.IsCancellationRequested)
                {
                    Log.Debug("Received request to stop");
                    break;
                }

                RaiseSendMessageEvent(Request);
                MessageCount++;

                for (int times = 0; times < 10; times++)
                {
                    if (IncomingMessages.Count < 1)
                    {
                        Thread.Sleep(250);
                    }
                }

                while (IncomingMessages.Count > 0)
                {
                    Message mesg;
                    if (IncomingMessages.TryDequeue(out mesg))
                    {
                        if (mesg.MessageId == MessageType.ACKNOWLEDGE)
                        {
                            var ack = (Acknowledge)mesg;

                            Log.Info(string.Format("Recevied acknowledge with status: {0}", ack.StatusInformation));
                            CancelSource.Cancel();
                            break;
                        }
                    }
                }
            }

            RaiseEndConversationEvent();
        }
Example #16
0
        public void Process()
        {
            CancellationToken cancellationToken = new CancellationToken(false);

            while (true)
            {
                Message <CMD> message = IncomingMessages.Take(cancellationToken);
                Console.WriteLine(message.Header.Size);
                switch (message.Header.Id)
                {
                case CMD.Chat:
                    Console.WriteLine("Chat: " + message.Extract <UTF8String>());
                    break;

                default:
                    Console.WriteLine($"Unknown command: {message.Header.Id}");
                    break;
                }
            }
        }
Example #17
0
        private async Task <NmsRead> GetNmsReadResponseAsync(
            NmsMessage lastMessage, Address target, int id, NibusOptions options)
        {
            var wob = new WriteOnceBlock <NmsMessage>(m => m);

            using (IncomingMessages.LinkTo(
                       wob,
                       m => !ReferenceEquals(lastMessage, m) && m.IsResponse && m.ServiceType == NmsServiceType.Read &&
                       m.Id == id && (target == Address.Empty || m.Datagram.Source == target)))
            {
                var response = (NmsRead)await wob.ReceiveAsync(options.Timeout, options.Token).ConfigureAwait(false);

                if (response.ErrorCode != 0)
                {
                    throw new NibusResponseException(response.ErrorCode);
                }

                return(response);
            }
        }
Example #18
0
        protected virtual void ReadIncomingPackets()
        {
            bool canRead = UdpSocket.Available > 0;

            if (canRead)
            {
                IPEndPoint ep   = new IPEndPoint(IPAddress.Any, 0);
                byte[]     data = UdpSocket.Receive(ref ep);

                NetworkMessage <T> nm = new NetworkMessage <T>();
                nm.Sender      = ep;
                nm.Packet      = new BytePacket <T>(data);
                nm.ReceiveTime = DateTime.Now;

                IncomingMessages.Enqueue(nm);
                PacketsReceived++;
                TotalBytesReceived    += nm.Packet.Payload.Length;
                InternalReceiveCount  += nm.Packet.Payload.Length;
                LatestReceiveTimestamp = DateTime.Now;
            }
        }
Example #19
0
        private void ProcessBuffer(byte[] buffer)
        {
            if (_currentIncomingMessage == null)
            {
                _currentIncomingMessage = new mBlockIncomingMessage();
            }

            foreach (var value in buffer)
            {
                /* Received message format
                 *  0xFF - Header Byte 1
                 *  0x55 - Header Byte 2
                 *  0xXX - Message index corresponding to request
                 *  0x0X - Payload Type - 1 byte 2 float 3 short 4 len+string 5 double
                 *  [0xXX....0xXX] Payload matcing size
                 *  0x0D
                 *  0x0A
                 */

                _currentIncomingMessage.AddByte(value);
                if (_currentIncomingMessage.EndsWithCRLF())
                {
                    IncomingMessages.Add(_currentIncomingMessage);

                    if (_currentIncomingMessage.BufferSize > 4)
                    {
                        _currentIncomingMessage.MessageSerialNumber = _currentIncomingMessage.Buffer[2];
                        _logger.NotifyUserInfo("mBlock", $"<<< {_currentIncomingMessage.MessageSerialNumber:X2}. " + _currentIncomingMessage.MessageHexString);

                        ProcessMessage(_currentIncomingMessage);
                    }
                    else
                    {
                        _logger.NotifyUserInfo("mBlock", $"<<< XXXXX. " + _currentIncomingMessage.MessageHexString);
                    }

                    _currentIncomingMessage = new mBlockIncomingMessage();
                }
            }
        }
Example #20
0
        private void WebSocketOnMessageReceived(object sender, MessageReceivedEventArgs e)
        {
            Debug.Print("Websocket message received:\n" + e.Message + "\n");

            try
            {
                var message = JsonConvert.DeserializeObject <SinricMessage>(e.Message);

                if (!HmacSignature.ValidateMessageSignature(message, SecretKey))
                {
                    throw new Exception(
                              "Computed signature for the payload does not match the signature supplied in the message. Message may have been tampered with.");
                }

                // add to the incoming message queue. caller will retrieve the messages on their own thread
                IncomingMessages.Enqueue(message);
            }
            catch (Exception ex)
            {
                Debug.Print("Error processing message from Sinric:\n" + ex + "\n");
            }
        }
Example #21
0
        private void ProcessBuffer(byte[] buffer)
        {
            if (_currentIncomingMessage == null)
            {
                _currentIncomingMessage = new mBlockIncomingMessage();
            }

            foreach (var value in buffer)
            {
                /* Received message format
                 *  0xFF - Header Byte 1
                 *  0x55 - Header Byte 2
                 *  0xXX - Message index corresponding to request
                 *  0x0X - Payload Type - 1 byte 2 float 3 short 4 len+string 5 double
                 *  [0xXX....0xXX] Payload matcing size
                 *  0x0D
                 *  0x0A
                 */

                _currentIncomingMessage.AddByte(value);
                if (_currentIncomingMessage.EndsWithCRLF())
                {
                    IncomingMessages.Add(_currentIncomingMessage);
                    //     Debug.WriteLine(String.Format("{0:000000} <<<", (DateTime.Now - _start).TotalMilliseconds) + _currentIncomingMessage.MessageHexString);
                    _logger.NotifyUserInfo("mBlock", "<<< " + _currentIncomingMessage.MessageHexString);

                    if (_currentIncomingMessage.BufferSize > 4)
                    {
                        _currentIncomingMessage.MessageSerialNumber = _currentIncomingMessage.Buffer[2];
                        ProcessMessage(_currentIncomingMessage);
                    }

                    _currentIncomingMessage = new mBlockIncomingMessage();
                }
            }
        }
 public Task <Message> ReceiveMessageAsync(CancellationToken cancellationToken)
 {
     return(IncomingMessages.ReceiveAsync(cancellationToken));
 }
Example #23
0
 public virtual void HandleMessage(Message mesg)
 {
     IncomingMessages.Enqueue(mesg);
 }
Example #24
0
        protected override void Run()
        {
            Log.Debug("Started receiver");

            // Only request all packets five times
            while (true)
            {
                if (Token.IsCancellationRequested)
                {
                    Log.Debug("Received request to stop");
                    break;
                }

                foreach (var data in NeededData)
                {
                    var chunkReq = new ChunkRequest(Guid.NewGuid(), ConversationId, MessageCount, data, FileInfo.ContentHash, ChunkSize);
                    RaiseSendMessageEvent(chunkReq);
                    MessageCount++;
                }

                Thread.Sleep(250);

                while (IncomingMessages.Count > 0)
                {
                    Message mesg;
                    if (IncomingMessages.TryDequeue(out mesg))
                    {
                        if (mesg.MessageId == MessageType.CHUNK_REPLY)
                        {
                            var chunkReply = (ChunkReply)mesg;

                            if (NeededData.Contains(chunkReply.Index))
                            {
                                var provider = new RSACryptoServiceProvider();
                                provider.ImportCspBlob(FileInfo.PublicKeyInfo);

                                if (MessageVerifier.CheckSignature(chunkReply.ChunkData, chunkReply.Signature, provider.ExportParameters(false)))
                                {
                                    DataStore[chunkReply.Index] = chunkReply.ChunkData;

                                    NeededData.Remove(chunkReply.Index);
                                    ReceivedData.Add(chunkReply.Index);

                                    if (NeededData.Count == 0)
                                    {
                                        Log.Info(string.Format("Conversation complete; Downloaded {0} packets", DataStore.Count));
                                        var ack = new Acknowledge(Guid.NewGuid(), ConversationId, mesg.MessageCount + 1, "Download complete");

                                        CancelSource.Cancel();
                                        RaiseSendMessageEvent(ack);
                                        break;
                                    }
                                }
                                else
                                {
                                    Log.Warn("Message signature is NOT verfied");
                                }
                            }
                        }
                    }
                }

                Thread.Sleep(250);
            }

            RaiseEndConversationEvent();
        }
Example #25
0
 internal void Server_ApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs e)
 {
     InboundCounter.Increment();
     IncomingMessages.Add(e);
     if (string.IsNullOrEmpty(e.ClientId))
     {
         _logger.LogInformation($"Message: Topic=[{e.ApplicationMessage.Topic }]");
     }
     else
     {
         _logger.LogInformation($"Server received {e.ClientId}'s message: Topic=[{e.ApplicationMessage.Topic }],Retain=[{e.ApplicationMessage.Retain}],QualityOfServiceLevel=[{e.ApplicationMessage.QualityOfServiceLevel}]");
         if (!lstTopics.ContainsKey(e.ApplicationMessage.Topic))
         {
             lstTopics.Add(e.ApplicationMessage.Topic, 1);
             Task.Run(() => _serverEx.PublishAsync("$SYS/broker/subscriptions/count", lstTopics.Count.ToString()));
         }
         else
         {
             lstTopics[e.ApplicationMessage.Topic]++;
         }
         if (e.ApplicationMessage.Payload != null)
         {
             received += e.ApplicationMessage.Payload.Length;
         }
         string topic = e.ApplicationMessage.Topic;
         var    tpary = topic.Split('/', StringSplitOptions.RemoveEmptyEntries);
         if (tpary.Length >= 3 && tpary[0] == "devices" && Devices.ContainsKey(e.ClientId))
         {
             Device device = JudgeOrCreateNewDevice(tpary, Devices[e.ClientId]);
             if (device != null)
             {
                 Dictionary <string, object> keyValues = new Dictionary <string, object>();
                 if (tpary.Length >= 4)
                 {
                     string keyname = tpary.Length >= 5 ? tpary[4] : tpary[3];
                     if (tpary[3].ToLower() == "xml")
                     {
                         try
                         {
                             var xml = new System.Xml.XmlDocument();
                             xml.LoadXml(e.ApplicationMessage.ConvertPayloadToString());
                             keyValues.Add(keyname, xml);
                         }
                         catch (Exception ex)
                         {
                             _logger.LogWarning(ex, $"xml data error {topic},{ex.Message}");
                         }
                     }
                     else if (tpary[3].ToLower() == "binary")
                     {
                         keyValues.Add(keyname, e.ApplicationMessage.Payload);
                     }
                 }
                 else
                 {
                     try
                     {
                         keyValues = e.ApplicationMessage.ConvertPayloadToDictionary();
                     }
                     catch (Exception ex)
                     {
                         _logger.LogWarning(ex, $"ConvertPayloadToDictionary   Error {topic},{ex.Message}");
                     }
                 }
                 if (tpary[2] == "telemetry")
                 {
                     Task.Run(async() =>
                     {
                         try
                         {
                             var result = await _dbContext.SaveAsync <TelemetryLatest, TelemetryData>(keyValues, device, DataSide.ClientSide);
                         }
                         catch (Exception ex)
                         {
                             _logger.LogError(ex, $"Can't upload telemetry to device {device.Name}({device.Id}).the payload is {e.ApplicationMessage.ConvertPayloadToString()}");
                         }
                     });
                 }
                 else if (tpary[2] == "attributes")
                 {
                     if (tpary.Length > 3 && tpary[3] == "request")
                     {
                         Task.Run(async() =>
                         {
                             await RequestAttributes(tpary, e.ApplicationMessage.ConvertPayloadToDictionary(), device);
                         });
                     }
                     else
                     {
                         Task.Run(async() =>
                         {
                             try
                             {
                                 var result = await _dbContext.SaveAsync <AttributeLatest, AttributeData>(keyValues, device, DataSide.ClientSide);
                             }
                             catch (Exception ex)
                             {
                                 _logger.LogError(ex, $"Can't upload attributes to device {device.Name}({device.Id}).the payload is \"{e.ApplicationMessage.ConvertPayloadToString()}\"");
                             }
                         });
                     }
                 }
             }
         }
     }
 }