bool HandlePartial(ref NetInboundPacket packet)
        {
            // Read the partials header (6 bytes)
            ushort partialId   = packet.ReadUInt16();
            byte   index       = packet.ReadByte();
            byte   numPartials = packet.ReadByte();
            ushort partialSize = packet.ReadUInt16();

            PartialPacket partial;

            // See if the partial already exists
            if (!packet.Sender.Partials.TryGetValue(partialId, out partial))
            {
                // Since the partial doesn't exist, create one.
                if (!packet.Sender.Partials.TryAdd(partialId,
                                                   partial = new PartialPacket(packet.Sender, partialId, numPartials, partialSize)))
                {
                    //NetLogger.LogError("[Partial:{0}:{1}] Failed to add new partial!", packet.Sender.EndPoint, partialId);
                    //return false;

                    // TODO: See if theres a better way to handle this partial packet concurrency issue

                    // If for some reason, two partials are processed simultaneously,
                    // and it tried adding two packets at once,
                    // we'll just grab the packet created by the other and move on.
                    partial = packet.Sender.Partials[partialId];
                }
                else
                {
                    if (NetLogger.LogPartials)
                    {
                        NetLogger.LogVerbose("[Partial:{0}:{1}] Starting new; NumPackets: {2}; PacketSize: {3}b",
                                             packet.Sender, partialId, numPartials, partialSize);
                    }
                }
            }

            // Add the current partial
            if (partial.AddPacket(index, packet.ReadBytes(partialSize)))
            {
                if (NetLogger.LogPartials)
                {
                    NetLogger.LogVerbose("[Partial:{0}:{1}] Adding index: {2}; PacketsLeft: {3}",
                                         packet.Sender, partialId, index, partial.numPartials - partial.numPartialsReceived);
                }

                // Check if the partial is complete
                if (partial.numPartialsReceived >= partial.numPartials)
                {
                    // Remove the partial from the connections queue
                    if (packet.Sender.Partials.TryRemove(partial.id, out partial))
                    {
                        // Save the old sender
                        NetConnection sender = packet.Sender;
                        // Construct the final packet
                        packet = partial.Construct(packet);
                        // Reset the packets parameters
                        packet.ReadOnly = true;

                        if (NetLogger.LogPartials)
                        {
                            NetLogger.LogVerbose("[Partial:{0}:{1}] Constructed final partial; FullSize: {2}b",
                                                 sender, partialId, packet.Length);
                        }

                        // Process the partial like a physical packet
                        packet.position = 0;
                        if (packet.ReadHeader())
                        {
                            if (packet.isEncrypted)
                            {
                                NetEncryption.DecryptPacket(packet);
                            }
                            if (packet.isCompressed)
                            {
                                NetCompressor.Decompress(packet);
                            }

                            // Update the stats
                            packet.Sender.PartialPacketReceived(numPartials);

                            // Tell the caller this partial is ready!
                            return(true);
                        }
                        else
                        {
                            // Bad stuff happened
                            NetLogger.LogWarning("[Partial:{0}:{1}] Constructed partial packet had invalid header!",
                                                 sender, partialId);
                            return(false);
                        }
                    }
                    else
                    {
                        NetLogger.LogError("[Partial:{0}:{1}] Failed to remove completed partial!",
                                           packet.Sender, partialId);
                    }
                }
            }

            // Tell the caller this partial is not complete
            return(false);
        }
Exemplo n.º 2
0
        internal static void HandleReceivedMessages(int?engineProcessID, ConcurrentQueue <string> receivedMessages, IpiSensorNetConfiguration moduleConfiguration, Action <string> logger)
        {
            if (receivedMessages.Count == 0)
            {
                return;
            }

            logger("HandleReceivedMessages: Start...");

            var arePacketsProcessed = false;

            using (var context = PiSensorNetDbContext.Connect(moduleConfiguration.ConnectionString))
            {
                while (receivedMessages.Count > 0)
                {
                    logger("HandleReceivedMessages: Dequeing...");

                    string text;
                    if (!receivedMessages.TryDequeue(out text))
                    {
                        continue;
                    }

                    logger($"HandleReceivedMessages: Processing '{text}'...");

                    var isFailed = text.StartsWith("FAIL ", StringComparison.InvariantCultureIgnoreCase);
                    var isOk     = text.StartsWith("OK ", StringComparison.InvariantCultureIgnoreCase);

                    if (isFailed || isOk)
                    {
                        if (!_lastMessageSentID.HasValue)
                        {
                            logger($"HandleReceivedMessages: ERROR: Message '{text} was not handled due to lack of {nameof(_lastMessageSentID)}!");
                            continue;
                        }

                        var state = isOk ? MessageStateEnum.Completed : MessageStateEnum.Failed;
                        var error = isFailed ? text.Substring("FAIL ".Length) : null;

                        //context.EnqueueRaw(Message.GenerateUpdate(context,
                        //    new Dictionary<Expression<Func<Message, object>>, string>
                        //    {
                        //        {i => i.State, state.ToSql()},
                        //        {i => i.ResponseReceived, DateTime.Now.ToSql()},
                        //        {i => i.Error, error.ToSql()},
                        //    },
                        //    new Tuple<Expression<Func<Message, object>>, string, string>(i => i.ID, "=", _lastMessageSentID.Value.ToSql())));

                        context.EnqueueUpdate <Message>(
                            i => i.State == state && i.ResponseReceived == DateTime.Now && i.Error == error,
                            i => i.ID == _lastMessageSentID.Value);

                        logger($"HandleReceivedMessages: Updated message #{_lastMessageSentID.Value} to '{state}'!");

                        _lastMessageSentID = null;
                    }
                    else
                    {
                        var partialPacket = new PartialPacket(
                            String.Format(moduleConfiguration.AddressPattern, text.SubstringBetween("@", "#")),
                            Byte.Parse(text.SubstringBetween("#", "(")),
                            Byte.Parse(text.SubstringBetween("(", "/")),
                            Byte.Parse(text.SubstringBetween("/", ")")),
                            text.SubstringAfter("):"),
                            DateTime.Now);

                        context.PartialPackets.Add(partialPacket);

                        arePacketsProcessed = true;

                        logger("HandleReceivedMessages: Processed message to new partial packet!");
                    }
                }

                context.SaveChanges();

                logger("HandleReceivedMessages: Done!"); // ~64ms, 4 messagess
            }

            if (arePacketsProcessed && engineProcessID.HasValue)
            {
                Signal.Send(engineProcessID.Value, SignalTypeEnum.User1);
            }
        }
Exemplo n.º 3
0
 private void WaitForData(Socket socket)
 {
     try
     {
         PartialPacket socketData = new PartialPacket();
         socketData.Socket = socket;
         socket.BeginReceive(socketData.Buffer, 0,
                            socketData.Buffer.Length,
                            SocketFlags.None,
                            dataReceivedCallback,
                            socketData);
     }
     catch (SocketException se)
     {
         OnSocketExceptionCaught(se);
     }
 }