示例#1
0
        public void TestWriteStream()
        {
            /// This tests ReplaceBytes too.
            byte[] bytes = new byte[271];	// so it doesn't align with a segment size
            for (int i = 0; i < bytes.Length; i++) { bytes[i] = (byte)(i % 256); }

            TransportPacket tp = new TransportPacket();
            Stream stream = tp.AsWriteStream();
            long initialPosition = stream.Position;
            Assert.AreEqual(0, initialPosition);
            for (int i = 0; i < 255; i++)
            {
                stream.Write(bytes, i, bytes.Length - i);
                stream.Write(bytes, 0, i);
            }
            stream.Flush();

            Assert.AreEqual(bytes.Length * 255, tp.Length);
            byte[] copy = tp.ToArray();
            Assert.AreEqual(bytes.Length * 255, copy.Length);
            stream.Position = initialPosition;
            for (int i = 0; i < 255; i++)
            {
                for (int j = 0; j < bytes.Length; j++)
                {
                    Assert.AreEqual(bytes[(i + j) % bytes.Length], copy[i * bytes.Length + j]);
                    Assert.AreEqual(bytes[(i + j) % bytes.Length], stream.ReadByte());
                }
            }
            Assert.AreEqual(stream.Length, stream.Position);
            stream.Position = initialPosition;
            stream.Position = stream.Length;

            CheckDisposed(tp);
            CheckForUndisposedSegments();
        }
示例#2
0
        public void TestWriteStreamLargeWrite()
        {
            byte[] bytes = new byte[TransportPacket.MaxSegmentSize * 3 + 13];
                for (int i = 0; i < bytes.Length; i++)
                {
                        bytes[i] = (byte) (i%256);
                }

                TransportPacket tp = new TransportPacket();
                Stream stream = tp.AsWriteStream();
                Assert.AreEqual(0, stream.Position);
                stream.Write(bytes, 0, bytes.Length);
                stream.Flush();

                Assert.AreEqual(bytes.Length, tp.Length);
                Assert.AreEqual(bytes, tp.ToArray());
        }
示例#3
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();
        }
示例#4
0
        public void TestToArray()
        {
            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 });

            byte[] original = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            Assert.AreEqual(original, packet.ToArray());

            for (int i = 0; i < packet.Length; i++)
            {
                for (int count = 0; count < packet.Length - i; count++)
                {
                    byte[] sub = packet.ToArray(i, count);
                    for (int j = 0; j < count; j++)
                    {
                        Assert.AreEqual(original[i + j], sub[j]);
                    }
                }
            }
            CheckDisposed(packet);
            CheckForUndisposedSegments();
        }
示例#5
0
        public void TestNewTransportPacket()
        {
            TransportPacket.MaxSegmentSize = TransportPacket.MinSegmentSize;

            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 });

            // Ensure that new TransportPacket() properly copies out
            TransportPacket copy = new TransportPacket(packet, 1, 8);
            Assert.AreEqual(packet.ToArray(1, 8), copy.ToArray());
            CheckDisposed(packet, copy);
            CheckForUndisposedSegments();
        }
示例#6
0
        public void TestPrepending()
        {
            // Ensure small packets
            TransportPacket.ReservedInitialBytes = 0;
            TransportPacket.MaxSegmentSize = TransportPacket.MinSegmentSize;

            TransportPacket packet = new TransportPacket(new byte[] { 9 });
            packet.Prepend(new byte[] { 4, 5, 6, 7, 8 });
            packet.Prepend(new byte[] { 0, 1, 2, 3 });

            Assert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, packet.ToArray());
            CheckDisposed(packet);
            CheckForUndisposedSegments();
        }
示例#7
0
        public void TestInplacePrepending()
        {
            TransportPacket.ReservedInitialBytes = 10;

            TransportPacket packet = new TransportPacket(new byte[] { 9 });
            packet.Prepend(new byte[] { 4, 5, 6, 7, 8 });
            packet.Prepend(new byte[] { 0, 1, 2, 3 });

            Assert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, packet.ToArray());
            Assert.AreEqual(1, ((IList<ArraySegment<byte>>)packet).Count);
            CheckDisposed(packet);
            CheckForUndisposedSegments();
        }
示例#8
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;
            }
        }
示例#9
0
        public void TestBasics()
        {
            byte[] source = new byte[] { 0, 1, 2, 3, 4 };
            TransportPacket p = new TransportPacket(source, 1, 4);
            Assert.AreEqual(4, p.Length);
            Assert.AreEqual(1, ((IList<ArraySegment<byte>>)p).Count);
            Assert.AreEqual(4, ((IList<ArraySegment<byte>>)p)[0].Count);

            byte[] result = p.ToArray();
            Assert.AreEqual(4, result.Length);
            for (int i = 0; i < 4; i++)
            {
                Assert.AreEqual(source[1 + i], result[i]);
            }

            CheckDisposed(p);
            CheckForUndisposedSegments();
        }
示例#10
0
        public void TestConsolidate()
        {
            // Ensure result wilbe distributed across multiple packets
            TransportPacket.ReservedInitialBytes = 0;

            TransportPacket packet = new TransportPacket(new byte[] { 9 });
            packet.Prepend(new byte[] { 4, 5, 6, 7, 8 });
            packet.Prepend(new byte[] { 0, 1, 2, 3 });
            Assert.IsTrue(((IList<ArraySegment<byte>>)packet).Count > 1);

            packet.Consolidate();
            Assert.AreEqual(1, ((IList<ArraySegment<byte>>)packet).Count);
            Assert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, packet.ToArray());
            CheckDisposed(packet);
            CheckForUndisposedSegments();
        }
示例#11
0
 public override void SendPacket(TransportPacket packet)
 {
     ContractViolation.Assert(packet.Length > 0, "cannot send 0-byte packets");
     ContractViolation.Assert(packet.Length <= MaximumPacketSize,
         String.Format("packet exceeds maximum packet size: {0} > {1}", packet.Length, MaximumPacketSize));
     handle.Put(packet.ToArray());
     NotifyPacketSent(packet);
 }
示例#12
0
 /// <summary>
 /// Send a packet on the UDP socket.
 /// </summary>
 /// <exception cref="SocketException">thrown if there is a socket error</exception>
 public int Send(TransportPacket packet, EndPoint remote)
 {
     // Is our throwing a SocketException considered out of line?
     if (!Active) { throw new SocketException((int)SocketError.Shutdown); }
     // Sadly SentTo does not support being provided a IList<ArraySegment<byte>>
     packet.Consolidate();   // try to reduce to a single segment
     IList<ArraySegment<byte>> bytes = packet;
     if (bytes.Count == 1)
     {
         return udpClient.Client.SendTo(bytes[0].Array, bytes[0].Offset, bytes[0].Count,
             SocketFlags.None, remote);
     }
     // hopefully this won't happen often; we could maintain our own bytearray pool
     return udpClient.Client.SendTo(packet.ToArray(), SocketFlags.None, remote);
 }
示例#13
0
        /// <summary>
        /// Handle incoming packets from previously-unknown remote endpoints.
        /// We check if the packet indicates a handshake and, if so, negotiate.
        /// Otherwise we send a GT error message and disregard the packet.
        /// </summary>
        /// <param name="ep">the remote endpoint</param>
        /// <param name="packet">the first packet</param>
        protected void PreviouslyUnseenUdpEndpoint(EndPoint ep, TransportPacket packet)
        {
            TransportPacket response;
            Stream ms;

            // This is the GT (UDP) protocol 1.0:
            //   bytes 0 - 3: the protocol version (the result from ProtocolDescriptor)
            //   bytes 4 - n: the number of bytes in the capability dictionary (see ByteUtils.EncodeLength)
            //   bytes n+1 - end: the capability dictionary
            // The # bytes in the dictionary isn't actually necessary in UDP, but oh well
            foreach(TransportFactory<UdpHandle> factory in factories)
            {
                if(packet.Length >= factory.ProtocolDescriptor.Length &&
                    ByteUtils.Compare(packet.ToArray(0, factory.ProtocolDescriptor.Length),
                        factory.ProtocolDescriptor))
                {
                    packet.RemoveBytes(0, factory.ProtocolDescriptor.Length);
                    ms = packet.AsReadStream();
                    Dictionary<string, string> dict = null;
                    try
                    {
                        uint count = ByteUtils.DecodeLength(ms); // we don't use it
                        dict = ByteUtils.DecodeDictionary(ms);
                        if(ms.Position != ms.Length)
                        {
                            byte[] rest = packet.ToArray();
                            log.Info(String.Format(
                                "{0} bytes still left at end of UDP handshake packet: {1} ({2})",
                                rest.Length, ByteUtils.DumpBytes(rest, 0, rest.Length),
                                ByteUtils.AsPrintable(rest, 0, rest.Length)));
                        }

                        ITransport result = factory.CreateTransport(UdpHandle.Bind(udpMultiplexer, ep));
                        if (ShouldAcceptTransport(result, dict))
                        {
                            // Send confirmation
                            // NB: following uses the format specified by LWMCF v1.1
                            response = new TransportPacket(LWMCFv11.EncodeHeader(MessageType.System,
                                (byte)SystemMessageType.Acknowledged,
                                (uint)factory.ProtocolDescriptor.Length));
                            response.Append(factory.ProtocolDescriptor);
                            udpMultiplexer.Send(response, ep);

                            NotifyNewTransport(result, dict);
                        }
                        else
                        {
                            // NB: following follows the format specified by LWMCF v1.1
                            response = new TransportPacket(LWMCFv11.EncodeHeader(MessageType.System,
                                (byte)SystemMessageType.IncompatibleVersion, 0));
                            udpMultiplexer.Send(response, ep);
                            result.Dispose();
                        }
                        return;
                    }
                    catch(Exception e)
                    {
                        log.Warn(String.Format("Error decoding handshake from remote {0}", ep), e);
                    }
                }
            }

            // If we can figure out some way to say: the packet is an invalid form:
            //  response = new TransportPacket();
            //  ms = response.AsWriteStream();
            //  log.Info("Undecipherable packet (ignored)");
            //  // NB: following follows the format specified by LWMCF v1.1
            //  LWMCFv11.EncodeHeader(MessageType.System, (byte)SystemMessageType.UnknownConnexion,
            //    (uint)ProtocolDescriptor.Length, ms);
            //  ms.Write(ProtocolDescriptor, 0, ProtocolDescriptor.Length);
            //  ms.Flush();
            //  udpMultiplexer.Send(response, ep);

            response = new TransportPacket();
            ms = response.AsWriteStream();
            log.Info("Unknown protocol version: "
                + ByteUtils.DumpBytes(packet.ToArray(), 0, 4) + " ["
                + ByteUtils.AsPrintable(packet.ToArray(), 0, 4) + "]");
            // NB: following follows the format specified by LWMCF v1.1
            LWMCFv11.EncodeHeader(MessageType.System, (byte)SystemMessageType.IncompatibleVersion,
                0, ms);
            ms.Flush();
            udpMultiplexer.Send(response, ep);
        }
示例#14
0
 protected void ClientReceivedPacket(TransportPacket packet, ITransport transport)
 {
     byte[] received = packet.ToArray();
     bool ok = true;
     if (received[0] != (byte)(clientPacketCount + clientMissedOffset))
     {
         Console.WriteLine("client: ERROR: expected packet#" + (clientPacketCount + clientMissedOffset)
             + " but received packet #" + received[0]);
         ok = false;
     }
     else
     {
         Debug("client: received expected packet#{0}",
             (byte)(clientPacketCount + clientMissedOffset));
     }
     if (!CheckPacket(received, "client")) { ok = false; }
     Console.Write(ok ? '+' : '!');
     clientPacketCount++;
 }
示例#15
0
        public void TestMultiSegments()
        {
            byte[] source = new byte[] { 0, 1, 2, 3, 4 };
            TransportPacket p = new TransportPacket(source, 1, 4);
            Assert.AreEqual(4, p.Length);
            Assert.AreEqual(1, ((IList<ArraySegment<byte>>)p).Count);

            for (int i = 0; i < 10; i++)
            {
                p.Append(source, 1, 4);
            }
            Assert.AreEqual(4 * 11, p.Length);

            byte[] result = p.ToArray();
            Assert.AreEqual(4 * 11, result.Length);
            for (int j = 0; j < 11; j++)
            {
                for (int i = 0; i < 4; i++)
                {
                    Assert.AreEqual(source[1 + i], result[4 * j + i]);
                }
            }

            CheckDisposed(p);
            CheckForUndisposedSegments();
        }
示例#16
0
 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++;
 }
示例#17
0
 /// <summary>
 /// ITransports use a observer-pattern (implemented with events and callbacks) to notify
 /// other GT2 components. Since these other componets register to the MillipedeTransport,
 /// there must be a mechanism to forward notifications from the ITransport to other GT2
 /// components.
 /// </summary>
 /// <see cref="ITransport.PacketReceived"/>
 private void _underlyingTransports_PacketReceivedEvent(TransportPacket packet, ITransport transport)
 {
     recorder.Record(new MillipedeEvent(milliDescriptor, MillipedeEventType.PacketReceived,
         packet.ToArray()));
     if (PacketReceived == null) { return; }
     PacketReceived(packet, this);
 }