public void Unmarshal(TransportPacket input, ITransportDeliveryCharacteristics tdc, EventHandler<MessageEventArgs> messageAvailable)
        {
            // <item>Message fits within the transport packet length, so sent unmodified
            //     <pre>[byte:message-type] [byte:channelId] [uint32:packet-size]
            //         [bytes:content]</pre>
            // </item>
            // <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>

            // Fastpath: if the message-type doesn't have the high-bit set,
            // then this is a non-fragmented message
            if ((input.ByteAt(0) & 128) == 0)
            {
                // If the submarshaller uses LWMCFv1.1 then we would have just
                // sent the packet as-is; if not, then we'll have prefixed a
                // LWMCFv1.1 header which must be first removed
                if (!subMarshallerIsLwmcf11)
                {
                    input.RemoveBytes(0, (int)LWMCFv11.HeaderSize);
                }
                subMarshaller.Unmarshal(input, tdc, messageAvailable);
                return;
            }

            MessageType type;
            byte channelId;
            uint contentLength;

            Stream s = input.AsReadStream();
            LWMCFv11.DecodeHeader(out type, out channelId, out contentLength, s);
            byte seqNo = (byte)s.ReadByte();
            TransportPacket subPacket;
            if ((seqNo & 128) == 0)
            {
                // This starts a new message
                uint numFrags = (uint)ByteUtils.DecodeLength(s);
                subPacket = UnmarshalFirstFragment(seqNo, numFrags,
                    input.SplitOut((int)(s.Length - s.Position)), tdc);
            }
            else
            {
                // This is a message in progress
                seqNo = (byte)(seqNo & ~128);
                uint fragNo = (uint)ByteUtils.DecodeLength(s);
                subPacket = UnmarshalFragInProgress(seqNo, fragNo,
                    input.SplitOut((int)(s.Length - s.Position)), tdc);
            }
            if (subPacket != null)
            {
                subMarshaller.Unmarshal(subPacket, tdc, messageAvailable);
                subPacket.Dispose();
            }
        }
Esempio n. 2
0
        public void TestSubset()
        {
            byte[] source = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            // We test for various subsets that overlap partially or fully with the different segments
            for (int sourceStart = 0; sourceStart < source.Length / 2; sourceStart++)
            {
                for (int sourceEnd = source.Length - 1; sourceEnd - sourceStart > 0; sourceEnd--)
                {
                    int sourceCount = sourceEnd - sourceStart + 1;
                    TransportPacket packet = new TransportPacket(source, sourceStart, sourceCount);
                    Assert.AreEqual(sourceCount, packet.Length);
                    Assert.AreEqual(1, ((IList<ArraySegment<byte>>)packet).Count);

                    for (int i = 0; i < 10; i++)
                    {
                        packet.Append(source, sourceStart, sourceCount);
                    }
                    Assert.AreEqual(sourceCount * 11, packet.Length);

                    const int subsetStart = 4;
                    int subsetCount = Math.Min(17, packet.Length - 2);

                    TransportPacket subset = packet.Subset(subsetStart, subsetCount);
                    Assert.AreEqual(subsetCount, subset.Length);
                    byte[] result = subset.ToArray();
                    Assert.AreEqual(subsetCount, result.Length);
                    for (int i = 0; i < result.Length; i++)
                    {
                        Assert.AreEqual(source[sourceStart +
                            ((subsetStart + i) % sourceCount)], result[i]);
                        Assert.AreEqual(source[sourceStart +
                            ((subsetStart + i) % sourceCount)], subset.ByteAt(i));
                        Assert.AreEqual(packet.ByteAt(subsetStart + i), subset.ByteAt(i));
                    }

                    // And ensure the subset has the same backing byte array is still referenced
                    // sourceEquivIndex = the equivalent index in source to subset[0]
                    int sourceEquivIndex = sourceStart + (subsetStart % sourceCount);
                    Assert.AreEqual(source[sourceEquivIndex], packet.ByteAt(subsetStart));
                    Assert.AreEqual(source[sourceEquivIndex], subset.ByteAt(0));
                    packet.Replace(subsetStart, new byte[] { 255 }, 0, 1);
                    Assert.AreEqual(255, packet.ByteAt(subsetStart));
                    Assert.AreEqual(255, subset.ByteAt(0));
                    packet.Replace(subsetStart, source, sourceEquivIndex, 1);
                    Assert.AreEqual(source[sourceEquivIndex], packet.ByteAt(subsetStart));
                    Assert.AreEqual(source[sourceEquivIndex], subset.ByteAt(0));

                    CheckNotDisposed(subset);

                    /// Ensure that disposing of the subset doesn't dispose the parent packet
                    for (int i = 0; i < packet.Length; i++)
                    {
                        Assert.AreEqual(source[sourceStart + (i % sourceCount)], packet.ByteAt(i));
                    }
                    CheckDisposed(packet);
                }
            }
            CheckForUndisposedSegments();
        }
Esempio n. 3
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 */ }
 }
Esempio n. 4
0
        public void TestRemoveBytes()
        {
            byte[] bytes = new byte[256];
            for (int i = 0; i < bytes.Length; i++) { bytes[i] = (byte)(i % 256); }
            byte[] reversed = new byte[bytes.Length];
            Buffer.BlockCopy(bytes, 0, reversed, 0, bytes.Length);
            Array.Reverse(reversed);

            TransportPacket tp = new TransportPacket();
            Stream stream = tp.AsWriteStream();
            // we'll make 256 copies of [0,1,...,254,255,255,254,...,1,0]
            for (int i = 0; i < 256; i++)
            {
                stream.Write(bytes, 0, bytes.Length);
                stream.Write(reversed, 0, reversed.Length);
            }
            stream.Flush();
            Assert.AreEqual((bytes.Length + reversed.Length) * 256, tp.Length);

            byte[] copy = tp.ToArray();
            Assert.AreEqual((bytes.Length + reversed.Length) * 256, tp.Length);

            // Now remove successively larger chunks from between the bytes/reversed
            // boundary points
            int nextIndex = 0;  // the start into the next bytes/reverse pair
            for (int i = 0; i < bytes.Length / 2; i++)
            {
                Assert.AreEqual(0, tp.ByteAt(nextIndex));
                Assert.AreEqual(1, tp.ByteAt(nextIndex + 1));
                Assert.AreEqual(bytes.Length - 2, tp.ByteAt(nextIndex + bytes.Length - 2));
                Assert.AreEqual(bytes.Length - 1, tp.ByteAt(nextIndex + bytes.Length - 1));
                Assert.AreEqual(bytes.Length - 1, tp.ByteAt(nextIndex + bytes.Length));
                Assert.AreEqual(bytes.Length - 2, tp.ByteAt(nextIndex + bytes.Length +1));
                Assert.AreEqual(1,
                    tp.ByteAt(nextIndex + bytes.Length + reversed.Length - 2));
                Assert.AreEqual(0,
                    tp.ByteAt(nextIndex + bytes.Length + reversed.Length - 1));

                // remove 2i bytes from the end of the bytes copy extending
                tp.RemoveBytes(nextIndex + bytes.Length - i, 2 * i);
                Assert.AreEqual((bytes.Length + reversed.Length) * 256 - 2 * i * (i+1) / 2, tp.Length);

                Assert.AreEqual(0, tp.ByteAt(nextIndex));
                Assert.AreEqual(bytes.Length - i - 1, tp.ByteAt(nextIndex + bytes.Length - i - 1));
                Assert.AreEqual(bytes.Length - i - 1, tp.ByteAt(nextIndex + bytes.Length - i));
                Assert.AreEqual(0, tp.ByteAt(nextIndex + bytes.Length + reversed.Length - 2*i - 1));

                nextIndex += bytes.Length + reversed.Length - 2 * i;
            }

            CheckDisposed(tp);
            CheckForUndisposedSegments();
        }
Esempio n. 5
0
        public void TestByteAt()
        {
            TransportPacket packet = new TransportPacket();
            packet.Append(new byte[] {0, 1, 2, 3});
            packet.Append(new byte[] {4, 5, 6, 7, 8});
            packet.Append(new byte[] {9});

            for(int i = 0; i < 10; i++)
            {
                Assert.AreEqual(i, packet.ByteAt(i));
                packet.BytesAt(i, 1, (b,offset) => Assert.AreEqual(i, b[offset]));
            }

            packet.BytesAt(0, 10, (bytes, offset) => {
                for(int i = 0; i < 10; i++) { Assert.AreEqual(i, bytes[i]); }
            });

            try
            {
                packet.ByteAt(10);
                Assert.Fail("Should have thrown ArgumentOutOfRange");
            }
            catch (ArgumentOutOfRangeException) { /*ignore*/ }

            try
            {
                packet.BytesAt(10,1, (b,o) => Assert.Fail("should have thrown AOOR"));
                Assert.Fail("Should have thrown ArgumentOutOfRange");
            }
            catch (ArgumentOutOfRangeException) { /*ignore*/ }

            try
            {
                packet.BytesAt(8, 8, (b, o) => Assert.Fail("should have thrown AOOR"));
                Assert.Fail("Should have thrown ArgumentOutOfRange");
            }
            catch (ArgumentOutOfRangeException) { /*ignore*/ }
            CheckDisposed(packet);
            CheckForUndisposedSegments();
        }