internal void Run()
        {
            Resend.Do(() =>
            {
                try
                {
                    List <KeyValuePair <II2NPHeader16, GarlicCreationInfo> > tosend = new List <KeyValuePair <II2NPHeader16, GarlicCreationInfo> >();
                    lock ( Window )
                    {
                        var resend = Window.Where(gci => gci.Value.LastSend.DeltaToNow > GarlicTimeBetweenResends);

                        if (WaitingForEGAck != null && WaitingForEGAck.DeltaToNow > GarlicTimeBetweenResends)
                        {
                            DebugUtils.LogDebug("TagsTransferWindow: Run: ElGamal message needs to be resent. Starting over.");
                            Session.Reset();
                        }

                        foreach (var one in resend.ToArray())
                        {
                            var egmsg = Session.Encrypt(true, one.Value.TrackingId, one.Value.Cloves);
                            var npmsg = new GarlicMessage(egmsg.Garlic).GetHeader16(I2NPHeader.GenerateMessageId());
                            one.Value.LastSend.SetNow();
                            tosend.Add(new KeyValuePair <II2NPHeader16, GarlicCreationInfo>(npmsg, egmsg));

                            if (WaitingForEGAck == null && !one.Value.AckMessageId.HasValue)
                            {
                                // Non explicit ack cloves that should not be retransmitted any more.
                                Window.Remove(one.Key);
                            }
                        }
                    }

                    foreach (var pair in tosend)
                    {
                        DebugUtils.LogDebug(string.Format("TagsTransferWindow: Resend: ({0}) TrackingId: {1}, Ack MessageId: {2}.",
                                                          pair.Value.KeyType, pair.Value.TrackingId, pair.Value.AckMessageId));

                        if (pair.Value.AckMessageId.HasValue)
                        {
                            lock ( OutstandingMessageIds )
                            {
                                OutstandingMessageIds[pair.Value.AckMessageId.Value] = pair.Value;
                            }
                        }

                        TunnelSelector(Session.LatestRemoteLeaseSet, pair.Key, pair.Value);
                    }
                }
                catch (Exception ex)
                {
                    Session.Reset();
                    DebugUtils.Log("TagsTransferWindow Run", ex);
                }
            });
        }
Beispiel #2
0
        void InboundTunnel_DeliveryStatusReceived(DeliveryStatusMessage dstatus)
        {
            var probe = OutstandingProbeIds[dstatus.MessageId];

            if (probe == null)
            {
                return;
            }

            var run = OutstandingTests[probe.Tunnel];

            if (run == null)
            {
                return;
            }

            var testms = (DateTime.UtcNow - (DateTime)dstatus.Timestamp).TotalMilliseconds;

            var limit = PassTestTimePerHop.ToMilliseconds * probe.TotalHops;
            var pass  = testms < limit;

            DebugUtils.LogDebug(string.Format("TunnelTester: DeliveryStatus received. Test with {0} and {1}: {2}. {3:0} vs {4} ms",
                                              run.TunnelUnderTest.TunnelDebugTrace, probe.Partner.TunnelDebugTrace,
                                              (pass ? "Success" : "Fail"),
                                              testms, limit));

            var delta = TickSpan.Milliseconds((int)testms);

            if (probe.Tunnel.MinLatencyMeasured == null || probe.Tunnel.MinLatencyMeasured > delta)
            {
                probe.Tunnel.MinLatencyMeasured = delta;
            }
            if (probe.Partner.MinLatencyMeasured == null || probe.Partner.MinLatencyMeasured > delta)
            {
                probe.Partner.MinLatencyMeasured = delta;
            }

            lock ( ExternalEventSync )
            {
                if (pass)
                {
                    run.SuccessPartners.Add(probe.Partner);
                }
                else
                {
                    run.FailurePartners.Add(probe.Partner);
                }
                run.OutstandingProbes.Remove(probe);
                OutstandingProbeIds.Remove(probe.MessageId);

                HandleTunnelTestResult(run);
            }
        }
        void DeliveryStatusReceived(DeliveryStatusMessage dsmsg)
        {
            GarlicCreationInfo info;

            lock ( OutstandingMessageIds )
            {
                info = OutstandingMessageIds[dsmsg.MessageId];
                if (info == null)
                {
                    /*
                     * DebugUtils.LogDebug( string.Format( "TagsTransferWindow: DeliveryStatusReceived: Non matching status message MsgId: {0}.",
                     *  dsmsg.MessageId ) );
                     */
                    return;
                }
                OutstandingMessageIds.Remove(dsmsg.MessageId);
            }

            lock ( Window )
            {
                Window.Remove(info.TrackingId);
            }

            DebugUtils.LogDebug(string.Format("TagsTransferWindow: DeliveryStatusReceived: Received ACK MsgId: {0} TrackingId: {1}. {2}",
                                              dsmsg.MessageId, info.TrackingId, info.Created.DeltaToNow));

            if (WaitingForEGAck != null && info.KeyType == GarlicCreationInfo.KeyUsed.ElGamal && dsmsg.MessageId == LatestEGMessage.AckMessageId)
            {
                WaitingForEGAck = null;

                // Aes messages sent after this can be decrypted, hopefully.
                // Send them one more time.

                /*
                 * lock ( OutstandingMessageIds )
                 * {
                 *  var remove = OutstandingMessageIds.Where( gci => gci.Value.KeyType == GarlicCreationInfo.KeyUsed.Aes &&
                 *      !gci.Value.AckMessageId.HasValue && gci.Value.EGAckMessageId == dsmsg.MessageId );
                 *  foreach ( var one in remove.ToArray() )
                 *  {
                 *      OutstandingMessageIds.Remove( one.Key );
                 *  }
                 * }
                 *
                 * lock ( Window )
                 * {
                 *  var remove = Window.Where( gci => gci.Value.KeyType == GarlicCreationInfo.KeyUsed.Aes &&
                 *      !gci.Value.AckMessageId.HasValue && gci.Value.EGAckMessageId == dsmsg.MessageId );
                 *  foreach ( var one in remove.ToArray() )
                 *  {
                 *      Window.Remove( one.Key );
                 *  }
                 * }
                 */
            }

            MessageAckEvent(info);
        }