示例#1
0
 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();
        }
示例#3
0
 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();
 }
示例#4
0
 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();
 }
示例#5
0
 // 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));
     }
 }
示例#6
0
        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();
        }
示例#7
0
 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 */ }
 }
示例#8
0
 private void ReallySendPacket(TransportPacket p)
 {
     Wrapped.SendPacket(p);
     p.Dispose();    // counter the Retain in ProcessPacket
 }
示例#9
0
 private void ReallyReceivePacket(TransportPacket p)
 {
     NotifyPacketReceived(p, this);
     p.Dispose();    // counter the Retain in ProcessPacket
 }
示例#10
0
        /// <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;
            }
        }
示例#11
0
        /// <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;
            }
        }