Esempio n. 1
0
        /// <summary>
        /// 设置握手结果
        /// </summary>
        /// <param name="inputStream">输入流</param>
        /// <returns></returns>
        public bool TrySetResult(IStreamReader inputStream)
        {
            inputStream.Position = 0;
            var index = inputStream.IndexOf(DoubleCrlf);

            if (index < 0)
            {
                return(false);
            }

            var length = index + DoubleCrlf.Length;
            var header = inputStream.ReadString(Encoding.ASCII, length);

            inputStream.Clear(length);

            const string pattern = @"^HTTP/1.1 101 Switching Protocols\r\n((?<field_name>[^:\r\n]+):\s(?<field_value>[^\r\n]*)\r\n)+\r\n";
            var          match   = Regex.Match(header, pattern, RegexOptions.IgnoreCase);

            if (match.Success == true)
            {
                var httpHeader = HttpHeader.Parse(match.Groups["field_name"].Captures, match.Groups["field_value"].Captures);
                var secAccept  = httpHeader["Sec-WebSocket-Accept"];

                const string guid     = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
                var          bytes    = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(this.secKey + guid));
                var          secValue = Convert.ToBase64String(bytes);

                if (secValue == secAccept)
                {
                    return(this.TrySetResult(SocketError.Success));
                }
            }
            return(this.TrySetResult(SocketError.SocketError));
        }
Esempio n. 2
0
        /// <summary>
        /// 解析请求的数据
        /// 返回请求数据包
        /// </summary>
        /// <param name="stream">所有收到的数据</param>
        /// <param name="requiredMask">是否要求必须Mask</param>
        /// <exception cref="NotSupportedException"></exception>
        /// <returns></returns>
        public unsafe static FrameRequest Parse(IStreamReader stream, bool requiredMask = true)
        {
            if (stream.Length < 2)
            {
                return(null);
            }

            ByteBits byte0     = stream[0];
            var      fin       = byte0[0];
            var      frameCode = (FrameCodes)(byte)byte0.Take(4, 4);

            if (fin == false || frameCode == FrameCodes.Continuation)
            {
                return(null);
            }

            var      rsv   = byte0.Take(1, 3);
            ByteBits byte1 = stream[1];
            var      mask  = byte1[0];

            if (requiredMask && mask == false)
            {
                throw new NotSupportedException("mask is required");
            }

            if (Enum.IsDefined(typeof(FrameCodes), frameCode) == false || rsv != 0)
            {
                throw new NotSupportedException();
            }

            var contentSize   = 0;
            var contentLength = (int)byte1.Take(1, 7);

            stream.Position = 2;

            if (contentLength == 127)
            {
                contentSize   = 8;
                contentLength = (int)stream.ReadUInt64();
            }
            else if (contentLength == 126)
            {
                contentSize   = 2;
                contentLength = (int)stream.ReadUInt16();
            }

            var maskSize     = mask ? 4 : 0;
            var packetLength = 2 + maskSize + contentSize + contentLength;

            if (stream.Length < packetLength)
            {
                return(null);
            }

            var maskingKey = mask ? stream.ReadArray(4) : null;
            var content    = stream.ReadArray(contentLength);

            stream.Clear(packetLength);

            if (mask && contentLength > 0)
            {
                fixed(byte *pcontent = &content[0], pmask = &maskingKey[0])
                {
                    for (var i = 0; i < contentLength; i++)
                    {
                        *(pcontent + i) = (byte)(*(pcontent + i) ^ *(pmask + i % 4));
                    }
                }
            }

            return(new FrameRequest
            {
                Fin = fin,
                Rsv = rsv,
                Mask = mask,
                Frame = frameCode,
                ContentLength = contentLength,
                MaskingKey = maskingKey,
                Content = content
            });
        }
Esempio n. 3
0
        /// <summary>
        /// 解析一个数据包
        /// 不足一个封包时返回null
        /// </summary>
        /// <param name="stream">接收到的历史数据</param>
        /// <param name="packet">数据包</param>
        /// <returns></returns>
        public static bool Parse(IStreamReader stream, out FastPacket packet)
        {
            if (stream.Length < 1 || stream[0] != FastPacket.Mark)
            {
                packet = null;
                return(false);
            }

            if (stream.Length < 5)
            {
                packet = null;
                return(true);
            }

            stream.Position = 1;
            const int packetMinSize = 16;
            var       totalBytes    = stream.ReadInt32();

            if (totalBytes < packetMinSize)
            {
                packet = null;
                return(false);
            }

            // 数据包未接收完整
            if (stream.Length < totalBytes)
            {
                packet = null;
                return(true);
            }

            // api名称数据长度
            var apiNameLength = stream.ReadByte();

            if (totalBytes < apiNameLength + packetMinSize)
            {
                packet = null;
                return(false);
            }

            // api名称数据
            var apiNameBytes = stream.ReadArray(apiNameLength);
            // 标识符
            var id = stream.ReadInt64();
            // 是否为客户端封包
            var isFromClient = stream.ReadBoolean();
            // 是否异常
            var isException = stream.ReadBoolean();
            // 实体数据
            var body = stream.ReadArray(totalBytes - stream.Position);

            // 清空本条数据
            stream.Clear(totalBytes);

            var apiName = Encoding.UTF8.GetString(apiNameBytes);

            packet = new FastPacket(apiName, id, isFromClient)
            {
                TotalBytes    = totalBytes,
                ApiNameLength = apiNameLength,
                IsException   = isException,
                Body          = body
            };
            return(true);
        }