public void ProcessAcknowledgement(AcknowledgementDto ack) { Signal signal; if (signalsByAckId.TryRemove(ack.MessageId, out signal)) { #if DEBUG Interlocked.Increment(ref DebugRuntimeStats.out_rs_acked); #endif signal.Set(); } }
public async Task SendAcknowledgementAsync(Guid destination, AcknowledgementDto acknowledgement) { var ms = outboundAcknowledgementMemoryStreamPool.TakeObject(); ms.SetLength(0); await AsyncSerialize.ToAsync(ms, acknowledgement).ConfigureAwait(false); unhandledSendRequestQueue.Enqueue( new SendRequest { Data = ms, DataOffset = 0, DataLength = (int)ms.Position, DataBufferPool = outboundAcknowledgementMemoryStreamPool, IsReliable = false }); workSignal.Set(); }
/// <summary> /// Processes an inbound data event. /// This is assumed to be invoked on an IOCP thread so a goal is to do as little as possible. /// </summary> public void HandleInboundDataEvent(InboundDataEvent e, Action <InboundDataEvent> returnInboundDataEvent) { #if DEBUG Interlocked.Increment(ref DebugRuntimeStats.in_de); #endif // Deserialize inbound payloads SCG.List <object> payloads = new SCG.List <object>(); try { using (var ms = new MemoryStream(e.Data, e.DataOffset, e.DataLength, false, true)) { while (ms.Position < ms.Length) { payloads.Add(Deserialize.From(ms)); } } } catch (Exception ex) { if (!isShutdown) { logger.Warn("Error at payload deserialize", ex); } return; } returnInboundDataEvent(e); #if DEBUG Interlocked.Add(ref DebugRuntimeStats.in_payload, payloads.Count); #endif // Categorize inbound payloads var acknowledgements = new SCG.List <AcknowledgementDto>(); var announcements = new SCG.List <AnnouncementDto>(); var reliablePackets = new SCG.List <PacketDto>(); var unreliablePackets = new SCG.List <PacketDto>(); foreach (var payload in payloads) { if (payload is AcknowledgementDto) { acknowledgements.Add((AcknowledgementDto)payload); } else if (payload is AnnouncementDto) { announcements.Add((AnnouncementDto)payload); } else if (payload is PacketDto) { // Filter packets not destined to us. var packet = (PacketDto)payload; if (!identity.Matches(packet.ReceiverId, IdentityMatchingScope.Broadcast)) { tossedCounter.Increment(); continue; } // Bin into reliable vs unreliable. if (packet.IsReliable()) { reliablePackets.Add(packet); } else { unreliablePackets.Add(packet); } } } // Process acks to prevent resends. foreach (var ack in acknowledgements) { #if DEBUG Interlocked.Increment(ref DebugRuntimeStats.in_ack); #endif acknowledgementCoordinator.ProcessAcknowledgement(ack); #if DEBUG Interlocked.Increment(ref DebugRuntimeStats.in_ack_done); #endif } // Process announcements as they are necessary for routing. foreach (var announcement in announcements) { #if DEBUG Interlocked.Increment(ref DebugRuntimeStats.in_ann); #endif HandleAnnouncement(e.RemoteInfo, announcement); } // Ack inbound reliable messages to prevent resends. foreach (var packet in reliablePackets) { #if DEBUG Interlocked.Increment(ref DebugRuntimeStats.in_out_ack); #endif var ack = AcknowledgementDto.Create(packet.Id); RoutingContext routingContext; if (routingContextsByPeerId.TryGetValue(packet.SenderId, out routingContext)) { routingContext.SendAcknowledgementAsync(packet.SenderId, ack).Forget(); } else { payloadSender.BroadcastAsync(ack).Forget(); } #if DEBUG Interlocked.Increment(ref DebugRuntimeStats.in_out_ack_done); #endif } // Test reliable packets' guids against bloom filter. var isNewByPacketId = duplicateFilter.TestPacketIdsAreNew(new HashSet <Guid>(reliablePackets.Select(p => p.Id))); var standalonePacketsToProcess = new SCG.List <PacketDto>(unreliablePackets); var chunksToProcess = new SCG.List <MultiPartChunkDto>(); foreach (var packet in reliablePackets) { // Toss out duplicate packets if (!isNewByPacketId[packet.Id]) { duplicateReceivesCounter.Increment(); continue; } // Bin into multipart chunk vs not var multiPartChunk = packet.Message.Body as MultiPartChunkDto; if (multiPartChunk != null) { multiPartChunksBytesReceivedAggregator.Put(multiPartChunk.BodyLength); chunksToProcess.Add(multiPartChunk); } else { standalonePacketsToProcess.Add(packet); } } // Kick off async stanadalone packet process on thread pool. foreach (var packet in standalonePacketsToProcess) { inboundMessageDispatcher.DispatchAsync(packet.Message).Forget(); } // Synchronously handle multipart chunk processing. foreach (var chunk in chunksToProcess) { multiPartPacketReassembler.HandleInboundMultiPartChunk(chunk); } }
public Task SendAcknowledgementAsync(Guid destination, AcknowledgementDto acknowledgement) { return(unicaster.SendAcknowledgementAsync(destination, acknowledgement)); }