Exemplo n.º 1
0
        /// <summary>
        /// Builds the headers frame.
        /// </summary>
        /// <param name="streamId">The stream id.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="final">if set to <c>true</c> than this frame is final for the stream.</param>
        /// <returns>Headers frame.</returns>
        public ControlFrame BuildHeadersFrame(int streamId, SMHeaders headers, bool final)
        {
            ControlFrame frame = BuildControlFrame(FrameType.Headers, streamId, headers);

            frame.IsFinal = final;
            return(frame);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Builds the SYN_STREAM frame.
        /// </summary>
        /// <param name="streamId">The stream id.</param>
        /// <param name="headers">The headers.</param>
        /// <returns>SYN_STREAM frame.</returns>
        public ControlFrame BuildSynStreamFrame(int streamId, SMHeaders headers)
        {
            ControlFrame frame = BuildControlFrame(FrameType.SynStream, streamId, headers);

            frame.Priority = SYNStreamPriority;

            return(frame);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Builds the SYN_STREAM frame.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="final">Indicates that stream is not going to send any more data.</param>
        /// <returns>SYN_STREAM frame.</returns>
        public ControlFrame BuildSynStreamFrame(SMStream stream, SMHeaders headers, bool final)
        {
            ControlFrame frame = BuildControlFrame(FrameType.SynStream, stream, headers);

            frame.Priority = SYNStreamPriority;
            frame.IsFinal  = final;

            return(frame);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Builds the control frame.
        /// </summary>
        /// <param name="type">The frame type.</param>
        /// <param name="streamId">The SM stream id.</param>
        /// <param name="headers">The headers.</param>
        /// <returns>Returns Control frame object.</returns>
        private static ControlFrame BuildControlFrame(FrameType type, int streamId, SMHeaders headers)
        {
            ControlFrame frame = new ControlFrame(headers);

            frame.StreamId = streamId;
            frame.Type     = type;
            frame.Priority = ControlPriority;

            return(frame);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Builds the RST Frame.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="reason">The reason for RST.</param>
        /// <returns>RST frame.</returns>
        public ControlFrame BuildRSTFrame(SMStream stream, StatusCode reason)
        {
            ControlFrame frame = new ControlFrame();

            frame.StreamId   = stream.StreamId;
            frame.Type       = FrameType.RTS;
            frame.StatusCode = reason;
            frame.Priority   = RSTPriority;

            return(frame);
        }
        /// <summary>
        /// Parses HTTP headers of SM control frame.
        /// </summary>
        /// <param name="frame">The frame.</param>
        /// <param name="data">The data.</param>
        /// <param name="offset">Offset of HTTP headers in the data.</param>
        private static void ParseControlFrameHeaders(ref ControlFrame frame, byte[] data, int offset)
        {
            int headersCount = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, offset, 4));
            offset += 4;

            for (int i = 0; i < headersCount; ++i)
            {
                int nameLength = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, offset, 4));
                offset += 4;
                string name = Encoding.UTF8.GetString(data, offset, nameLength);
                offset += nameLength;

                int valLength = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, offset, 4));
                offset += 4;
                string val = Encoding.UTF8.GetString(data, offset, valLength);
                offset += valLength;

                frame.Headers.Add(name, val);
            }
        }
 /// <summary>
 /// Parses HTTP header of SM control frame.
 /// </summary>
 /// <param name="frame">The frame.</param>
 /// <param name="data">The data.</param>
 private static void ParseControlFrameHeader(ref ControlFrame frame, byte[] data)
 {
     frame.Version = BinaryHelper.Int16FromBytes(data[0], data[1], 1);
     frame.Type = (FrameType)BinaryHelper.Int16FromBytes(data[2], data[3]);
     frame.Flags = data[4];
     frame.Length = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 5, 3));
     frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 8, 4), 1);
     frame.IsFinal = (frame.Flags & 0x01) != 0;
 }
        /// <summary>
        /// Serializes the control frame.
        /// </summary>
        /// <param name="frame">The frame.</param>
        /// <returns>Serialized control frame.</returns>
        private byte[] SerializeControlFrame(ControlFrame frame)
        {
            var byteList = new List<byte>();

            byteList.Add((byte)(((frame.Version & 0xFF00) >> 8) | 0x80));
            byteList.Add((byte)(frame.Version & 0x00FF));

            byteList.Add((byte)(((Int16)frame.Type & 0xFF00) >> 8));
            byteList.Add((byte)((Int16)frame.Type & 0x00FF));

            byteList.AddRange(BinaryHelper.Int32ToBytes(frame.StreamId));

            var headersArray = new byte[0];
            switch (frame.Type)
            {
                    case FrameType.SynStream:
                        byteList.Add(Convert.ToByte(frame.Flags | (frame.IsFinal ? 0x01 : 0x00)));
                        byteList.Add(Convert.ToByte(frame.Priority >> 5));
                        byteList.Add(Unused);
                        byteList.Add(Unused);
                        headersArray = SerializeControlFrameHeaders(frame.Headers);
                        break;
                    case FrameType.RTS:
                        byteList.AddRange(BinaryHelper.Int32ToBytes((int)frame.StatusCode));
                        break;
                    case FrameType.SynReply:
                        byteList.Add(frame.Flags);
                        byteList.Add(Unused);
                        byteList.Add(Unused);
                        byteList.Add(Unused);
                        headersArray = SerializeControlFrameHeaders(frame.Headers);
                        break;
                    case FrameType.CreditUpdate:
                        byteList.AddRange(BinaryHelper.Int64ToBytes(((CreditUpdateFrame)frame).CreditAddition));
                        break;
            }

            if (headersArray.Length > 0)
            {
                ProcessorRun(ref headersArray, DirectionProcessType.Outbound, frame.Flags);
            }

            byteList.AddRange(headersArray);
            return byteList.ToArray();
        }
        /// <summary>
        /// Parses HTTP headers of SM control frame.
        /// </summary>
        /// <param name="frame">The frame.</param>
        /// <param name="data">The data.</param>
        /// <param name="offset">Offset of HTTP headers in the data.</param>
        private void ParseControlFrameHeaders(ref ControlFrame frame, byte[] data, int offset)
        {
            var headers = new byte[data.Length - offset];
            Array.Copy(data, offset, headers, 0, headers.Length);
            if (headers.Length > 0)
                ProcessorRun(ref data, DirectionProcessType.Outbound, frame.Flags);

            for (int i = 0; /*i < headersCount*/ offset < data.Length; ++i)
            {
                int nameLength = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, offset, 4));
                offset += 4;
                string name = Encoding.UTF8.GetString(data, offset, nameLength);
                offset += nameLength;

                int valLength = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, offset, 4));
                offset += 4;
                string val = Encoding.UTF8.GetString(data, offset, valLength);
                offset += valLength;
                // Ensure no duplicates.
                if (frame.Headers.ContainsKey(name))
                {
                    throw new SMProtocolExeption(StatusCode.InternalError);
                }

                frame.Headers.Add(name, val);
            }
        }
        /// <summary>
        /// Deserializes the data into control frame.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <returns>Deserialized frame.</returns>
        private BaseFrame DeserializeControlFrame(byte[] data)
        {
            var frame = new ControlFrame();
            ParseControlFrameHeader(ref frame, data);

            switch (frame.Type)
            {
                case FrameType.RTS:
                    frame.StatusCode = (StatusCode)BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 8, 4));
                    break;
                case FrameType.Headers:
                case FrameType.SynReply:
                    ParseControlFrameHeaders(ref frame, data, 12);
                    break;
                case FrameType.SynStream:
                    frame.Priority = (byte)(data[9] >> 5);
                    ParseControlFrameHeaders(ref frame, data, 12);
                    break;
                case FrameType.CreditUpdate:
                    ((CreditUpdateFrame)frame).CreditAddition = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 8, 4));
                    break;

            }

            return frame;
        }
        /// <summary>
        /// Sends the frame.
        /// </summary>
        /// <param name="frame">The control frame.</param>
        private void SendFrame(ControlFrame frame)
        {
            byte[] frameBinary = this.serializer.Serialize(frame);
            frame.Length = frameBinary.Length;

            this.webSocket.SendMessage(frameBinary);

            if (this.OnFrameSent != null)
            {
                this.OnFrameSent(this, new FrameEventArgs(frame));
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ControlFrameEventArgs"/> class.
 /// </summary>
 /// <param name="frame">The frame.</param>
 public ControlFrameEventArgs(ControlFrame frame)
 {
     this.Frame = frame;
 }
        /// <summary>
        /// Builds the control frame.
        /// </summary>
        /// <param name="type">The frame type.</param>
        /// <param name="streamId">The SM stream id.</param>
        /// <param name="headers">The headers.</param>
        /// <returns>Returns Control frame object.</returns>
        private static ControlFrame BuildControlFrame(FrameType type, int streamId, SMHeaders headers)
        {
            ControlFrame frame = new ControlFrame(headers);
            frame.StreamId = streamId;
            frame.Type = type;
            frame.Priority = ControlPriority;

            return frame;
        }
        /// <summary>
        /// Builds the RST Frame.
        /// </summary>
        /// <param name="streamId">The stream id.</param>
        /// <param name="reason">The reason for RST.</param>
        /// <returns>RST frame.</returns>
        public ControlFrame BuildRSTFrame(int streamId, StatusCode reason)
        {
            ControlFrame frame = new ControlFrame();
            frame.StreamId = streamId;
            frame.Type = FrameType.RTS;
            frame.StatusCode = reason;
            frame.Priority = RSTPriority;

            return frame;
        }
        /// <summary>
        /// Serializes the control frame.
        /// </summary>
        /// <param name="frame">The frame.</param>
        /// <returns>Serialized control frame.</returns>
        private static byte[] SerializeControlFrame(ControlFrame frame)
        {
            frame.Length = 12;
            if (frame.Type == FrameType.RTS)
            {
                frame.Length += 4;
            }
            else
            {
                if (frame.Type == FrameType.SynStream)
                {
                    frame.Length += 8;
                }

                frame.Length += 4;
                foreach (var header in frame.Headers)
                {
                    frame.Length += 4 + header.Key.Length;
                    frame.Length += 4 + frame.Headers[header.Key].Length;
                }
            }

            List<byte> byteList = new List<byte>();

            byteList.Add((byte)(((frame.Version & 0xFF00) >> 8) | 0x80));
            byteList.Add((byte)(frame.Version & 0x00FF));

            byteList.Add((byte)(((Int16)frame.Type & 0xFF00) >> 8));
            byteList.Add((byte)((Int16)frame.Type & 0x00FF));

            byteList.Add(frame.Flags);

            byteList.AddRange(BinaryHelper.Int32ToBytes(frame.Length, 3));
            byteList.AddRange(BinaryHelper.Int32ToBytes(frame.StreamId));

            if (frame.Type == FrameType.SynStream)
            {
                byteList.AddRange(BinaryHelper.Int32ToBytes(frame.AssociatedToStreamId));
                byteList.Add(frame.Priority);
                byteList.Add(frame.Slot);
                byteList.Add(Unused);
                byteList.Add(Unused);
            }

            if (frame.Type == FrameType.RTS)
            {
                byteList.AddRange(BinaryHelper.Int32ToBytes((int)frame.StatusCode));
            }
            else
            {
                byteList.AddRange(BinaryHelper.Int32ToBytes(frame.Headers.Count));

                foreach (KeyValuePair<string, string> pair in frame.Headers)
                {
                    byte[] nameBin = Encoding.UTF8.GetBytes(pair.Key);
                    byteList.AddRange(BinaryHelper.Int32ToBytes(nameBin.Length));

                    byteList.AddRange(nameBin);

                    byte[] valBin = Encoding.UTF8.GetBytes(pair.Value);
                    byteList.AddRange(BinaryHelper.Int32ToBytes(valBin.Length));

                    byteList.AddRange(valBin);
                }
            }

            return byteList.ToArray();
        }
        /// <summary>
        /// Deserializes the data into control frame.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <returns>Deserialized frame.</returns>
        private static BaseFrame DeserializeControlFrame(byte[] data)
        {
            ControlFrame frame = new ControlFrame();
            ParseControlFrameHeader(ref frame, data);

            switch (frame.Type)
            {
                case FrameType.RTS:
                    frame.StatusCode = (StatusCode)BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 12, 4));
                    break;
                case FrameType.Headers:
                case FrameType.SynReply:
                    ParseControlFrameHeaders(ref frame, data, 12);
                    break;
                case FrameType.SynStream:
                    frame.AssociatedToStreamId = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 12, 4), 1);
                    frame.Priority = (byte)(data[16] & 0x7);
                    frame.Slot = data[17];
                    ParseControlFrameHeaders(ref frame, data, 20);
                    break;
            }

            return frame;
        }
        /// <summary>
        /// Process SM control frame.
        /// </summary>
        /// <param name="frame">The control frame.</param>
        private void ProcessControlFrame(ControlFrame frame)
        {
            if (frame.Version != Version)
            {
                throw new SMProtocolExeption(StatusCode.UnsupportedVersion);
            }

            SMStream stream = this.streamsStore.GetStreamById(frame.StreamId);

            // if this is rst frame - don't send error or it will go in rst loop
            if (stream == null && frame.Type != FrameType.RTS)
            {
                this.SendRST(frame.StreamId, StatusCode.InvalidStream);
                return;
            }

            switch (frame.Type)
            {
                case FrameType.SynStream:
                case FrameType.SynReply:
                    this.OnSessionFrame(this, new ControlFrameEventArgs(frame));
                    break;
                case FrameType.Headers:
                    this.OnStreamFrame(this, new HeadersEventArgs(this.streamsStore.GetStreamById(frame.StreamId), frame.Headers));
                    break;
                case FrameType.RTS:
                    this.OnStreamFrame(this, new RSTEventArgs(this.streamsStore.GetStreamById(frame.StreamId), frame.StatusCode));
                    break;
            }
        }