protected virtual void NotifyPacketSent(TransportPacket packet) { if (PacketSent != null) { PacketSent(packet, this); } packet.Dispose(); }
private void FragmentMessage(Message message, ITransportDeliveryCharacteristics tdc, TransportPacket packet, MarshalledResult mr) { // <item> if the message is the first fragment, then the high-bit is // set on the message-type; the number of fragments is encoded using // the adaptive <see cref="ByteUtils.EncodeLength(int)"/> format. // <pre>[byte:message-type'] [byte:channelId] [uint32:packet-size] // [byte:seqno] [bytes:encoded-#-fragments] [bytes:frag]</pre> // </item> // <item> for all subsequent fragments; seqno' = seqno | 128; // the number of fragments is encoded using the adaptive // <see cref="ByteUtils.EncodeLength(int)"/> format. // <pre>[byte:message-type'] [byte:channelId] [uint32:packet-size] // [byte:seqno'] [bytes:encoded-fragment-#] [bytes:frag]</pre> // Although we use an adaptive scheme for encoding the number, // we assume a maximum of 4 bytes for encoding # frags // for a total of 4 extra bytes bytes; we determine the frag // size from the message size - MaxHeaderSize const uint maxFragHeaderSize = 1 /*seqno*/ + 4; const uint maxHeaderSize = LWMCFv11.HeaderSize + maxFragHeaderSize; uint maxPacketSize = Math.Max(maxHeaderSize, tdc.MaximumPacketSize - maxHeaderSize); // round up the number of possible fragments uint numFragments = (uint)(packet.Length + maxPacketSize - 1) / maxPacketSize; Debug.Assert(numFragments > 1); uint seqNo = AllocateOutgoingSeqNo(tdc); for (uint fragNo = 0; fragNo < numFragments; fragNo++) { TransportPacket newPacket = new TransportPacket(); Stream s = newPacket.AsWriteStream(); uint fragSize = (uint)Math.Min(maxPacketSize, packet.Length - (fragNo * maxPacketSize)); if (fragNo == 0) { s.WriteByte((byte)seqNo); ByteUtils.EncodeLength(numFragments, s); } else { s.WriteByte((byte)(seqNo | 128)); ByteUtils.EncodeLength(fragNo, s); } newPacket.Prepend(LWMCFv11.EncodeHeader((MessageType)((byte)message.MessageType | 128), message.ChannelId, (uint)(fragSize + s.Length))); newPacket.Append(packet, (int)(fragNo * maxPacketSize), (int)fragSize); mr.AddPacket(newPacket); } packet.Dispose(); }
public void SendPacket(TransportPacket packet) { Debug.Assert(packet.Length != 0, "Shouldn't send zero-length packets!"); bytesSent += (uint)packet.Length; if (PacketSent != null) { PacketSent(packet, this); } packet.Dispose(); }
protected virtual void NotifyPacketReceived(TransportPacket packet) { // DebugUtils.DumpMessage(this.ToString() + " notifying of received message", buffer, offset, count); if (PacketReceived == null) { NotifyError(new ErrorSummary(Severity.Warning, SummaryErrorCode.Configuration, "transport has no listeners for receiving incoming messages!", this, null)); } else { PacketReceived(packet, this); } // event listeners are responsible for calling Retain() if they // want to use it for longer. packet.Dispose(); }
// This packet is a subset of another, and so none of the segments should be disposed private void CheckNotDisposed(TransportPacket subset) { List<ArraySegment<byte>> segs = new List<ArraySegment<byte>>(subset); foreach (ArraySegment<byte> seg in segs) { Assert.IsTrue(TransportPacket.IsManagedSegment(seg)); } subset.Dispose(); foreach (ArraySegment<byte> seg in segs) { Assert.IsTrue(TransportPacket.IsManagedSegment(seg)); } }
public void TestAllocation() { /// This test is specific to the TransportPacket pool allocation scheme /// We go up in power-of-2 checking that allocating just before and /// on the boundary return the proper size, and that allocating just /// after the boundary allocates the next up. TransportPacket.ReservedInitialBytes = 0; int numBits = BitUtils.HighestBitSet(TransportPacket.MaxSegmentSize) - BitUtils.HighestBitSet(TransportPacket.MinSegmentSize); for (int i = 0; i <= numBits; i++) { uint size = TransportPacket.MinSegmentSize * (1u << i); TransportPacket p; ArraySegment<byte> segment; p = new TransportPacket(size-1); Assert.AreEqual(size-1, p.Length); Assert.AreEqual(1, ((IList<ArraySegment<byte>>)p).Count); segment = ((IList<ArraySegment<byte>>)p)[0]; Assert.AreEqual(size - 1, segment.Count); Assert.AreEqual(size, segment.Array.Length - segment.Offset); p.Dispose(); p = new TransportPacket(size); Assert.AreEqual(size, p.Length); Assert.AreEqual(1, ((IList<ArraySegment<byte>>)p).Count); segment = ((IList<ArraySegment<byte>>)p)[0]; Assert.AreEqual(size, segment.Count); Assert.AreEqual(size, segment.Array.Length - segment.Offset); p.Dispose(); p = new TransportPacket(size+1); Assert.AreEqual(size + 1, p.Length); if (i < numBits) { Assert.AreEqual(1, ((IList<ArraySegment<byte>>)p).Count); segment = ((IList<ArraySegment<byte>>)p)[0]; Assert.AreEqual(size + 1, segment.Count); Assert.IsTrue(size < segment.Array.Length - segment.Offset, "Should have been in the next bin size"); } else { // we're outside of the maximum allocation size, and so // the allocation should be split across multiple segments! Assert.AreEqual(2, ((IList<ArraySegment<byte>>)p).Count); segment = ((IList<ArraySegment<byte>>)p)[0]; Assert.AreEqual(size, segment.Count, "Should have been this bin size"); Assert.AreEqual(size, segment.Array.Length - segment.Offset, "Should have been in this last bin size"); } p.Dispose(); } CheckForUndisposedSegments(); }
public void TestDisposal() { TransportPacket packet = new TransportPacket(10); packet.Dispose(); try { packet.Grow(20); Assert.Fail("should have thrown ObjectDisposedException"); } catch(ObjectDisposedException) { /* expected */ } try { packet.RemoveBytes(0,2); Assert.Fail("should have thrown ObjectDisposedException"); } catch(ObjectDisposedException) { /* expected */ } try { packet.ByteAt(0); Assert.Fail("should have thrown ObjectDisposedException"); } catch(ObjectDisposedException) { /* expected */ } try { packet.Consolidate(); Assert.Fail("should have thrown ObjectDisposedException"); } catch(ObjectDisposedException) { /* expected */ } try { packet.Prepend(new byte[0]); Assert.Fail("should have thrown ObjectDisposedException"); } catch (ObjectDisposedException) { /* expected */ } try { packet.Append(new byte[0]); Assert.Fail("should have thrown ObjectDisposedException"); } catch (ObjectDisposedException) { /* expected */ } try { Console.WriteLine(packet.Length); Assert.Fail("should have thrown ObjectDisposedException"); } catch (ObjectDisposedException) { /* expected */ } }
private void ReallySendPacket(TransportPacket p) { Wrapped.SendPacket(p); p.Dispose(); // counter the Retain in ProcessPacket }
private void ReallyReceivePacket(TransportPacket p) { NotifyPacketReceived(p, this); p.Dispose(); // counter the Retain in ProcessPacket }
/// <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; } }
/// <summary> /// Wraps ITransport.Update. /// </summary> /// <see cref="ITransport.Update"/> public void Update() { switch (recorder.Mode) { case MillipedeMode.PassThrough: case MillipedeMode.Unconfigured: default: underlyingTransport.Update(); return; case MillipedeMode.Record: try { underlyingTransport.Update(); } catch(GTException ex) { recorder.Record(new MillipedeEvent(milliDescriptor, MillipedeEventType.Exception, ex)); throw; } return; case MillipedeMode.Playback: MillipedeEvent e = recorder.CheckReplayEvent(milliDescriptor, MillipedeEventType.PacketReceived, MillipedeEventType.Exception, MillipedeEventType.Disposed, MillipedeEventType.Error); if(e == null) { return; } if(e.Type == MillipedeEventType.Disposed) { running = false; } else if(e.Type == MillipedeEventType.PacketReceived && PacketReceived != null) { TransportPacket tp = new TransportPacket(e.Message); PacketReceived(tp, this); tp.Dispose(); } else if (e.Type == MillipedeEventType.Error && ErrorEvent != null) { ErrorEvent((ErrorSummary)e.Context); } else if (e.Type == MillipedeEventType.Exception) { throw (Exception)e.Context; } return; } }