/// <summary> /// Record the fragment at the position. If recorded, then /// must retain the fragment. /// </summary> /// <param name="fragNo"></param> /// <param name="frag"></param> /// <returns>true if the fragment hadn't been previously seen</returns> public bool RecordFragment(uint fragNo, TransportPacket frag) { ResizeIfNecessary(fragNo); if (fragments[fragNo] != null) { return false; } fragments[fragNo] = frag; frag.Retain(); seen++; return true; }
public void SendPacket(ITransport transport, TransportPacket packet) { try { packet.Retain(); SentPackets.Add(packet); transport.SendPacket(packet); } catch (TransportError e) { } }
private void ProcessPacket(PacketMode mode, TransportPacket packet, DelayQueue<TransportPacket> queue) { uint delay = (uint)Math.Max(0, CalculateDelay()); if (Ordering != Ordering.Unordered) { // if this transport is ordered or sequenced, then the packets // must be sent in order, and thus must be delayed in order. // Thus when figuring out the possible delay of a packet, // we must ensure it's at least as delayed as the previous // packet, which must be the most-delayed packet. delay = (uint)Math.Max(delay, lastPacketTime[mode] - timer.TimeInMilliseconds); } if (Reliability != Reliability.Reliable || Ordering != Ordering.Ordered) { double pDropped = PacketLossCorrelation * pLastDropped + (1d - PacketLossCorrelation) * urng.NextDouble(); pLastDropped = pDropped; if(pDropped < PacketLoss) { NotifyPacketDisposition(mode, PacketEffect.Dropped, packet); return; } } // don't include reordering time when recording the scheduled // time for this current packet -- if we reorder by delaying, // then we *don't* want subsequent packets lastPacketTime[mode] = timer.TimeInMilliseconds + delay; // Sequenced and ordered transports cannot have out-of-order packets if (Ordering == Ordering.Unordered && urng.NextDouble() < PacketReordering) { // reorder packets by delaying this current packet delay += queue.MaximumDelay == 0 ? 10u : queue.MaximumDelay / 2; NotifyPacketDisposition(mode, PacketEffect.Reordered, packet); } else if(delay > 0) { NotifyPacketDisposition(mode, PacketEffect.Delayed, packet); } else { NotifyPacketDisposition(mode, PacketEffect.None, packet); } packet.Retain(); // countered in Really{Send,Receive}Packet queue.Enqueue(packet, delay); }
protected void ServerReceivedPacket(TransportPacket packet, ITransport transport) { byte[] received = packet.ToArray(); if (received[0] != (byte)(serverPacketCount + serverMissedOffset)) { Console.WriteLine("server: ERROR: expected packet#" + (serverPacketCount + serverMissedOffset) + " but received packet #" + received[0]); } else { Debug("server: received expected packet#{0}", (byte)(serverPacketCount + serverMissedOffset)); } CheckPacket(received, "server"); Debug("==> server: replying with byte array"); packet.Retain(); // must retain since SendPacket() will dispose server.SendPacket(packet); serverPacketCount++; }
/// <summary> /// Wraps ITransport.SendPacket(byte[],int,int). In addition, writes data to a sink if /// MillipedeTransport initialized with Mode.Record. /// </summary> /// <see cref="ITransport.SendPacket"/> public void SendPacket(TransportPacket packet) { switch (recorder.Mode) { case MillipedeMode.Unconfigured: case MillipedeMode.PassThrough: default: underlyingTransport.SendPacket(packet); // underlyingTransport is responsible for disposing of packet return; case MillipedeMode.Record: try { packet.Retain(); // since underlyingTransport will dispose of packet underlyingTransport.SendPacket(packet); recorder.Record(new MillipedeEvent(milliDescriptor, MillipedeEventType.SentPacket, packet.ToArray())); packet.Dispose(); } catch(GTException ex) { recorder.Record(new MillipedeEvent(milliDescriptor, MillipedeEventType.Exception, ex)); throw; } return; case MillipedeMode.Playback: MillipedeEvent e = recorder.WaitForReplayEvent(milliDescriptor, MillipedeEventType.Exception, MillipedeEventType.SentPacket, MillipedeEventType.Error); if(e.Type == MillipedeEventType.Exception) { throw (Exception)e.Context; } if (e.Type == MillipedeEventType.Error && ErrorEvent != null) { ErrorEvent((ErrorSummary)e.Context); } return; } }