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); }
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); } }
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); } }