Exemplo n.º 1
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());
        }
Exemplo n.º 2
0
        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();
        }
Exemplo n.º 3
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();
        }
Exemplo n.º 4
0
        public void TestStreams()
        {
            byte[] source = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
            TransportPacket packet = new TransportPacket(source);
            Stream rs = packet.AsReadStream();
            Assert.AreEqual(source[0], rs.ReadByte());
            Assert.AreEqual(source[1], rs.ReadByte());
            Assert.AreEqual(source.Length - 2, rs.Length - rs.Position);
            Assert.AreEqual(source.Length - 2, packet.Length);	// causes stream changes to be committed
            Assert.AreEqual(0, rs.Position);
            Assert.AreEqual(packet.Length, rs.Length);

            Assert.AreEqual(source[2], rs.ReadByte());
            Assert.AreEqual(source[3], rs.ReadByte());
            Assert.IsTrue(rs == packet.AsReadStream());

            Stream ws = packet.AsWriteStream();
            try
            {
                rs.ReadByte();
                Assert.Fail("read stream should have been automatically closed");
            }
            catch (ObjectDisposedException) { /* expected */ }

            rs = packet.AsReadStream();
            try
            {
                ws.ReadByte();
                Assert.Fail("read stream should have been automatically closed");
            }
            catch (ObjectDisposedException) { /* expected */ }
            CheckDisposed(packet);
            CheckForUndisposedSegments();
        }
Exemplo n.º 5
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();
        }
Exemplo n.º 6
0
        /// <summary>
        /// Marshal the given message to the provided stream in a form suitable to
        /// be sent out on the provided transport.
        /// </summary>
        /// <param name="senderIdentity">the identity of the sender</param>
        /// <param name="msg">the message being sent, that is to be marshalled</param>
        /// <param name="tdc">the characteristics of the transport that will send the marshalled form</param>
        /// <returns>the marshalled representation</returns>
        public virtual IMarshalledResult Marshal(int senderIdentity, Message msg, ITransportDeliveryCharacteristics tdc)
        {
            // This marshaller doesn't use <see cref="senderIdentity"/>.
            MarshalledResult mr = new MarshalledResult();
            TransportPacket tp = new TransportPacket();

            // We use TransportPacket.Prepend to add the marshalling header in-place
            // after the marshalling.
            Stream output = tp.AsWriteStream();
            Debug.Assert(output.CanSeek);
            MarshalContents(msg, output, tdc);
            output.Flush();
            // System messages don't have a channelId -- we encode their system message
            // type as the channelId instead
            tp.Prepend(LWMCFv11.EncodeHeader(msg.MessageType,
                msg.MessageType == MessageType.System
                    ? (byte)((SystemMessage)msg).Descriptor : msg.ChannelId,
                (uint)output.Position));
            mr.AddPacket(tp);
            return mr;
        }
Exemplo n.º 7
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);
        }