public DiscardingSequences(ITransportDeliveryCharacteristics tdc, uint windowSize, uint capacity)
     : base(tdc)
 {
     sw = new SlidingWindowManager(windowSize, capacity);
     sw.FrameExpired += _ExpireFrame;
 }
 public ReliableSequences(ITransportDeliveryCharacteristics tdc)
     : base(tdc)
 {
 }
        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();
        }
 private TransportPacket UnmarshalFragInProgress(byte seqNo, uint fragNo, TransportPacket frag,
     ITransportDeliveryCharacteristics tdc)
 {
     Sequences sequences;
     if (!accumulatedReceived.TryGetValue(tdc, out sequences))
     {
         accumulatedReceived[tdc] = sequences = Sequences.ForTransport(tdc, windowSize, SeqNoCapacity);
     }
     return sequences.ReceivedFrag(seqNo, fragNo, frag);
 }
        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();
            }
        }
 private uint AllocateOutgoingSeqNo(ITransportDeliveryCharacteristics tdc)
 {
     lock (this)
     {
         uint seqNo;
         if (!outgoingSeqNo.TryGetValue(tdc, out seqNo))
         {
             seqNo = 0;
         }
         outgoingSeqNo[tdc] = (seqNo + 1) % SeqNoCapacity;
         return seqNo;
     }
 }
Example #7
0
 public IMarshalledResult Marshal(Message m, ITransportDeliveryCharacteristics tdc)
 {
     return Marshaller.Marshal(0, m, tdc);
 }
Example #8
0
 public virtual void Unmarshal(TransportPacket tp, ITransportDeliveryCharacteristics tdc, EventHandler<MessageEventArgs> messageAvailable)
 {
     Debug.Assert(messageAvailable != null, "callers must provide a messageAvailale handler");
     Stream input = tp.AsReadStream();
     MessageType type;
     byte channelId;
     uint length;
     LWMCFv11.DecodeHeader(out type, out channelId, out length, input);
     Message m = UnmarshalContent(channelId, type, new WrappedStream(input, length), length);
     if (m == null)
     {
         throw new MarshallingException(String.Format(
             "Cannot unmarshal the provided content: channel={0}, type={1}, len={2}",
             channelId, type, length));
     }
     messageAvailable(this, new MessageEventArgs(tdc as ITransport, m));
 }
Example #9
0
 public IMarshalledResult Marshal(int senderIdentity, Message message, ITransportDeliveryCharacteristics tdc)
 {
     IMarshalledResult mr = subMarshaller.Marshal(senderIdentity, message, tdc);
     MarshalledResult result = new MarshalledResult();
     while (mr.HasPackets)
     {
         TransportPacket packet = mr.RemovePacket();
         byte[] encoded = Encode(packet.ToArray());
         // FIXME: this is a bit awkward: if encoded is small, then
         // we're likely better off copying these into a contiguous
         // block of memory.  But if big, then we're probably better
         // off using these byte arrays as the backing store.
         TransportPacket newPacket = new TransportPacket(
             DataConverter.Converter.GetBytes(senderIdentity),
             ByteUtils.EncodeLength((uint)encoded.Length),
             encoded);
         result.AddPacket(newPacket);
     }
     mr.Dispose();
     return result;
 }
Example #10
0
 public void Unmarshal(TransportPacket packet, ITransportDeliveryCharacteristics tdc, EventHandler<MessageEventArgs> messageAvailable)
 {
     Debug.Assert(messageAvailable != null, "callers must provide a messageAvailable handler");
     Stream input = packet.AsReadStream();
     int encoderId = DataConverter.Converter.ToInt32(ByteUtils.Read(input, 4), 0);
     uint length = ByteUtils.DecodeLength(input);
     byte[] decoded = Decode(encoderId, ByteUtils.Read(input, length));
     TransportPacket subPacket = TransportPacket.On(decoded);
     input.Close();
     subMarshaller.Unmarshal(subPacket, tdc,
         (sender, mea) => messageAvailable(this, mea));
 }
Example #11
0
        public override IMarshalledResult Marshal(int senderIdentity, Message msg, ITransportDeliveryCharacteristics tdc)
        {
            // This marshaller doesn't use <see cref="senderIdentity"/>.
            if (msg is RawMessage)
            {
                MarshalledResult mr = new MarshalledResult();
                TransportPacket tp = new TransportPacket();

                // NB: SystemMessages use ChannelId to encode the sysmsg descriptor
                RawMessage rm = (RawMessage)msg;
                tp.Prepend(LWMCFv11.EncodeHeader(msg.MessageType, msg.ChannelId, (uint)rm.Bytes.Length));
                tp.Append(rm.Bytes);
                mr.AddPacket(tp);
                return mr;
            }
            return base.Marshal(senderIdentity, msg, tdc);
        }
Example #12
0
 protected override void MarshalContents(Message m, Stream output, ITransportDeliveryCharacteristics tdc)
 {
     // Individual marshalling methods are **NO LONGER RESPONSIBLE** for encoding
     // the payload length
     switch (m.MessageType)
     {
     case MessageType.Binary:
         MarshalBinary(((BinaryMessage)m).Bytes, output);
         break;
     case MessageType.String:
         MarshalString(((StringMessage)m).Text, output);
         break;
     case MessageType.Object:
         MarshalObject(((ObjectMessage)m).Object, output);
         break;
     case MessageType.Tuple1D:
     case MessageType.Tuple2D:
     case MessageType.Tuple3D:
         MarshalTupleMessage((TupleMessage)m, output);
         break;
     default:
         base.MarshalContents(m, output, tdc);
         break;
     }
 }
Example #13
0
 /// <summary>
 /// Marshal the contents of the message <see cref="m"/> onto the stream <see cref="output"/>.
 /// The channelId and message type have already been placed on <see cref="output"/>.
 /// This method is **not responsible** for encoding the message payload length.
 /// </summary>
 /// <param name="m">the message contents to be marshalled</param>
 /// <param name="output">the destination for the marshalled message payload</param>
 /// <param name="tdc">the characteristics of the transport that is to be used for sending</param>
 protected virtual void MarshalContents(Message m, Stream output, ITransportDeliveryCharacteristics tdc)
 {
     // Individual marshalling methods are **NO LONGER RESPONSIBLE** for encoding
     // the payload length
     switch (m.MessageType)
     {
     case MessageType.Session:
         MarshalSessionAction((SessionMessage)m, output);
         break;
     case MessageType.System:
         // channelId is the system message type
         MarshalSystemMessage((SystemMessage)m, output);
         break;
     default:
         throw new MarshallingException(String.Format("ERROR: {0} cannot handle messages of type {1}",
             this.GetType().Name, m.GetType().Name));
     }
 }
 protected Sequences(ITransportDeliveryCharacteristics tdc)
 {
     this.tdc = tdc;
 }
 public IMarshalledResult Marshal(int senderIdentity, Message message, ITransportDeliveryCharacteristics tdc)
 {
     IMarshalledResult submr = subMarshaller.Marshal(senderIdentity, message, tdc);
     // Hmm, maybe this would be better as a generator, just in case the
     // sub-marshaller returns an infinite message.
     MarshalledResult mr = new MarshalledResult();
     while (submr.HasPackets)
     {
         TransportPacket packet = submr.RemovePacket();
         // Need to account for LWMCFv1.1 header for non-LWMCFv1.1 marshallers
         uint contentLength = (uint)packet.Length -
             (subMarshallerIsLwmcf11 ? LWMCFv11.HeaderSize : 0);
         // If this packet fits within the normal transport packet length
         // then we don't have to fragment it.
         if (LWMCFv11.HeaderSize + contentLength < tdc.MaximumPacketSize)
         {
             // Message fits within the transport packet length, so sent unmodified
             //     <pre>[byte:message-type] [byte:channelId] [uint32:packet-size]
             //         [bytes:content]</pre>
             if (!subMarshallerIsLwmcf11)
             {
                 // need to prefix the LWMCFv1.1 header
                 packet.Prepend(LWMCFv11.EncodeHeader(message.MessageType,
                     message.ChannelId, (uint)packet.Length));
             }
             mr.AddPacket(packet);
         }
         else
         {
             FragmentMessage(message, tdc, packet, mr);
         }
     }
     submr.Dispose();
     return mr;
 }
 internal static Sequences ForTransport(ITransportDeliveryCharacteristics tdc, 
     uint seqWindowSize, uint seqCapacity)
 {
     if(tdc.Reliability == Reliability.Reliable)
     {
         return new ReliableSequences(tdc); // seqWindowSize, seqCapacity
     }
     return new DiscardingSequences(tdc, seqWindowSize, seqCapacity);
 }
Example #17
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;
        }