/// <summary> /// 设置握手结果 /// </summary> /// <param name="streamReader">数据读取器</param> /// <returns></returns> public bool TrySetResult(ISessionStreamReader streamReader) { streamReader.Position = 0; var index = streamReader.IndexOf(DoubleCrlf); if (index < 0) { return(false); } var length = index + DoubleCrlf.Length; var header = streamReader.ReadString(Encoding.ASCII, length); streamReader.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)); }
/// <summary> /// 设置握手结果 /// </summary> /// <param name="streamReader">数据读取器</param> /// <returns></returns> public bool TrySetResult(ISessionStreamReader streamReader) { var result = HttpResponseParser.Parse(streamReader); if (result.IsHttp == false) { return(false); } else { streamReader.Clear(); } if (result.Status == 101) { const string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; var bytes = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(this.secKey + guid)); var secValue = Convert.ToBase64String(bytes); var secAccept = result.Header["Sec-WebSocket-Accept"]; if (secValue == secAccept) { return(this.TrySetResult(SocketError.Success)); } } return(this.TrySetResult(SocketError.SocketError)); }
/// <summary> /// 生成表单和文件 /// </summary> /// <param name="request">请求</param> /// <param name="streamReader">数据读取器</param> /// <param name="boundary">边界</param> private static void GenerateMultipartFormAndFiles(HttpRequest request, ISessionStreamReader streamReader, string boundary) { var boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary); var maxPosition = streamReader.Length - Encoding.ASCII.GetBytes("--\r\n").Length; var files = new List <HttpFile>(); var form = new HttpNameValueCollection(); streamReader.Position = streamReader.Position + boundaryBytes.Length; while (streamReader.Position < maxPosition) { var headLength = streamReader.IndexOf(DoubleCRLF) + DoubleCRLF.Length; if (headLength < DoubleCRLF.Length) { break; } var head = streamReader.ReadString(Encoding.UTF8, headLength); var bodyLength = streamReader.IndexOf(boundaryBytes); if (bodyLength < 0) { break; } var mHead = new MultipartHead(head); if (mHead.TryGetFileName(out string fileName) == true) { var bytes = streamReader.ReadArray(bodyLength); var file = new HttpFile(mHead.Name, fileName, bytes); files.Add(file); }
/// <summary> /// 生成Post得到的表单和文件 /// </summary> /// <param name="request">请求</param> /// <param name="streamReader">数据读取器</param> private static void GeneratePostFormAndFiles(HttpRequest request, ISessionStreamReader streamReader) { var boundary = default(string); if (request.IsApplicationFormRequest() == true) { HttpRequestParser.GenerateApplicationForm(request); } else if (request.IsMultipartFormRequest(out boundary) == true) { if (request.Body.Length >= boundary.Length) { HttpRequestParser.GenerateMultipartFormAndFiles(request, streamReader, boundary); } } if (request.Form == null) { request.Form = new HttpNameValueCollection(); } if (request.Files == null) { request.Files = new HttpFile[0]; } }
/// <summary> /// 解析一个数据包 /// 不足一个封包时返回null /// </summary> /// <param name="streamReader">数据读取器</param> /// <param name="packet">数据包</param> /// <returns></returns> public static bool Parse(ISessionStreamReader streamReader, out FastPacket packet) { packet = null; const int packetMinSize = 16; if (streamReader.Length < packetMinSize || streamReader[0] != FastPacket.Mark) { return(false); } streamReader.Position = 1; var totalBytes = streamReader.ReadInt32(); if (totalBytes < packetMinSize) { return(false); } // 数据包未接收完整 if (streamReader.Length < totalBytes) { return(true); } // api名称数据长度 var apiNameLength = streamReader.ReadByte(); if (totalBytes < apiNameLength + packetMinSize) { return(false); } // api名称数据 var apiNameBytes = streamReader.ReadArray(apiNameLength); // 标识符 var id = streamReader.ReadInt64(); // 是否为客户端封包 var isFromClient = streamReader.ReadBoolean(); // 是否异常 var isException = streamReader.ReadBoolean(); // 实体数据 var body = streamReader.ReadArray(totalBytes - streamReader.Position); // 清空本条数据 streamReader.Clear(totalBytes); var apiName = Encoding.UTF8.GetString(apiNameBytes); packet = new FastPacket(apiName, id, isFromClient) { TotalBytes = totalBytes, ApiNameLength = apiNameLength, IsException = isException, Body = body }; return(true); }
/// <summary> /// 收到请求数据 /// </summary> /// <param name="streamReader">数据读取器</param> /// <returns></returns> private Task OnWebSocketRequestAsync(ISessionStreamReader streamReader) { var frames = this.GenerateWebSocketFrame(streamReader); foreach (var frame in frames) { this.OnFrameRequest(frame); } return(TaskExtend.CompletedTask); }
/// <summary> /// 当接收到远程端的数据时,将触发此方法 /// </summary> /// <param name="streamReader">数据读取器</param> /// <returns></returns> protected sealed override Task OnReceiveAsync(ISessionStreamReader streamReader) { var packages = this.GenerateFastPackets(streamReader); foreach (var package in packages) { this.ProcessPacketAsync(package); } return(TaskExtend.CompletedTask); }
/// <summary> /// 收到数据时 /// </summary> /// <param name="streamReader">数据读取器</param> /// <returns></returns> protected override sealed async Task OnReceiveAsync(ISessionStreamReader streamReader) { if (this.handshake.IsWaitting == true) { this.handshake.TrySetResult(streamReader); } else { await this.OnWebSocketRequestAsync(streamReader); } }
/// <summary> /// 获取当前的http方法长度 /// </summary> /// <param name="streamReader">数据读取器</param> /// <returns></returns> private static int GetMthodLength(ISessionStreamReader streamReader) { var maxLength = Math.Min(streamReader.Length, HttpRequestParser.MedthodMaxLength + 1); for (var i = 0; i < maxLength; i++) { if (streamReader[i] == HttpRequestParser.Space) { return(i); } } return(maxLength); }
/// <summary> /// 生成数据包 /// </summary> /// <param name="streamReader">数据流</param> /// <returns></returns> private IList <FastPacket> GenerateFastPackets(ISessionStreamReader streamReader) { var list = new List <FastPacket>(); while (true) { if (FastPacket.Parse(streamReader, out FastPacket packet) == false) { return(list); } if (packet == null) { return(list); } list.Add(packet); } }
/// <summary> /// 生成表单和文件 /// </summary> /// <param name="request">请求</param> /// <param name="streamReader">数据读取器</param> /// <param name="boundary">边界</param> private static void GenerateMultipartFormAndFiles(HttpRequest request, ISessionStreamReader streamReader, string boundary) { var boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary); var maxPosition = streamReader.Length - Encoding.ASCII.GetBytes("--\r\n").Length; var files = new List <HttpFile>(); var form = new HttpNameValueCollection(); streamReader.Position = streamReader.Position + boundaryBytes.Length; while (streamReader.Position < maxPosition) { var headLength = streamReader.IndexOf(DoubleCRLF) + DoubleCRLF.Length; if (headLength < DoubleCRLF.Length) { break; } var head = streamReader.ReadString(Encoding.UTF8, headLength); var bodyLength = streamReader.IndexOf(boundaryBytes); if (bodyLength < 0) { break; } string fileName = null; var partItem = new MultipartItem(head); if (partItem.TryGetFileName(out fileName) == true) { var bytes = streamReader.ReadArray(bodyLength); var file = new HttpFile(partItem.Name, fileName, bytes); files.Add(file); } else { var byes = streamReader.ReadArray(bodyLength); var value = HttpUtility.UrlDecode(byes, Encoding.UTF8); form.Add(partItem.Name, value); } streamReader.Position = streamReader.Position + boundaryBytes.Length; } request.Form = form; request.Files = files.ToArray(); }
/// <summary> /// 解析生成请求帧 /// </summary> /// <param name="streamReader">数据读取器</param> /// <returns></returns> private IList <FrameRequest> GenerateWebSocketFrame(ISessionStreamReader streamReader) { var list = new List <FrameRequest>(); while (true) { try { var request = FrameRequest.Parse(streamReader, false); if (request == null) { return(list); } list.Add(request); } catch (NotSupportedException ex) { this.Close(StatusCodes.ProtocolError, ex.Message); return(list); } } }
/// <summary> /// 解析一个数据包 /// 不足一个封包时packet返回null /// 中间件不符合则返回false /// </summary> /// <param name="session">会话</param> /// <param name="packet">数据包</param> /// <returns></returns> public virtual bool Parse(ISessionStreamReader streamReader, ISession session, out string packet) { packet = null; try { int required = 28; int remain = session.RemainDataLength;//剩余长度 while (remain >= required) { // 实体数据 packet = Encoding.UTF8.GetString(streamReader.ReadArray(required)); // 清空本条数据 streamReader.Clear(required); return(true); } return(true); } catch (Exception) { return(false); } }
/// <summary> /// 是否为http协议 /// </summary> /// <param name="streamReader">数据读取器</param> /// <param name="headerLength">头数据长度,包括双换行</param> /// <returns></returns> private static bool IsHttp(ISessionStreamReader streamReader, out int headerLength) { var methodLength = HttpRequestParser.GetMthodLength(streamReader); var methodName = streamReader.ReadString(Encoding.ASCII, methodLength); if (HttpRequestParser.MethodNames.Any(m => m.StartsWith(methodName, StringComparison.OrdinalIgnoreCase)) == false) { headerLength = 0; return(false); } streamReader.Position = 0; var headerIndex = streamReader.IndexOf(HttpRequestParser.DoubleCrlf); if (headerIndex < 0) { headerLength = 0; return(true); } headerLength = headerIndex + HttpRequestParser.DoubleCrlf.Length; return(true); }
/// <summary> /// 当接收到远程端的数据时,将触发此方法 /// </summary> /// <param name="streamReader">接收到的数据读取器</param> /// <returns></returns> protected abstract Task OnReceiveAsync(ISessionStreamReader streamReader);
/// <summary> /// 解析回复头信息 /// </summary> /// <param name="streamReader">数据读取器</param> /// <returns></returns> public static HttpResponseParseResult Parse(ISessionStreamReader streamReader) { var result = new HttpResponseParseResult(); streamReader.Position = 0; if (streamReader.StartWith(HttpVersion11) == false) { return(result); } var endIndex = streamReader.IndexOf(DoubleCRLF); if (endIndex < 0) { return(result); } streamReader.Position += HttpVersion11.Length + 1; var statusLength = streamReader.IndexOf(Space); if (statusLength < 0) { return(result); } var status = streamReader.ReadString(Encoding.ASCII, statusLength); streamReader.Position += 1; var descriptionLenth = streamReader.IndexOf(CRLF); if (descriptionLenth < 0) { return(result); } var description = streamReader.ReadString(Encoding.ASCII, descriptionLenth); streamReader.Position += CRLF.Length; var httpHeader = new HttpHeader(); var headerLength = endIndex + DoubleCRLF.Length; while (streamReader.Position < headerLength) { var keyLength = streamReader.IndexOf(KvSpliter); if (keyLength <= 0) { break; } var key = streamReader.ReadString(Encoding.ASCII, keyLength); streamReader.Position += KvSpliter.Length; var valueLength = streamReader.IndexOf(CRLF); if (valueLength < 0) { break; } var value = streamReader.ReadString(Encoding.ASCII, valueLength); if (streamReader.StartWith(CRLF) == false) { break; } streamReader.Position += CRLF.Length; httpHeader.Add(key, value); } result.Description = description; result.Status = int.Parse(status); result.IsHttp = true; result.Header = httpHeader; return(result); }
/// <summary> /// 解析请求的数据 /// 返回请求数据包 /// </summary> /// <param name="streamReader">数据读取器</param> /// <param name="requiredMask">是否要求必须Mask</param> /// <exception cref="NotSupportedException"></exception> /// <returns></returns> public unsafe static FrameRequest Parse(ISessionStreamReader streamReader, bool requiredMask = true) { if (streamReader.Length < 2) { return(null); } ByteBits byte0 = streamReader[0]; var fin = byte0[0]; var rsv = byte0.Take(1, 3); var frameCode = (FrameCodes)(byte)byte0.Take(4, 4); ByteBits byte1 = streamReader[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); streamReader.Position = 2; if (contentLength == 127) { contentSize = 8; contentLength = (int)streamReader.ReadUInt64(); } else if (contentLength == 126) { contentSize = 2; contentLength = (int)streamReader.ReadUInt16(); } var maskSize = mask ? 4 : 0; var packetLength = 2 + maskSize + contentSize + contentLength; if (streamReader.Length < packetLength) { return(null); } var maskingKey = mask ? streamReader.ReadArray(4) : null; var content = streamReader.ReadArray(contentLength); streamReader.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 }); }