/// <summary> /// Exchange data from client and server /// </summary> /// <param name="reader"></param> /// <param name="tcpClient"></param> public async void ExchangeClient(PipeNetworkStream reader, TcpClient tcpClient) { //File.WriteAllBytes("I:\\signalgotext.txt", reader.LastBytesReaded); ClientInfo client = null; try { if (_serverBase.ProviderSetting.IsEnabledToUseTimeout) { tcpClient.GetStream().ReadTimeout = (int)_serverBase.ProviderSetting.ReceiveDataTimeout.TotalMilliseconds; tcpClient.GetStream().WriteTimeout = (int)_serverBase.ProviderSetting.SendDataTimeout.TotalMilliseconds; } string firstLineString = await reader.ReadLineAsync(); if (firstLineString.Contains("SignalGo-Stream/4.0")) { if (!_serverBase.ProviderSetting.IsEnabledToUseTimeout) { tcpClient.GetStream().ReadTimeout = -1; tcpClient.GetStream().WriteTimeout = -1; } client = CreateClientInfo(false, tcpClient, reader); client.ProtocolType = ClientProtocolType.SignalGoStream; client.StreamHelper = SignalGoStreamBase.CurrentBase; SignalGoStreamProvider.StartToReadingClientData(client, _serverBase); } else if (firstLineString.Contains("SignalGo-OneWay/4.0")) { if (!_serverBase.ProviderSetting.IsEnabledToUseTimeout) { tcpClient.GetStream().ReadTimeout = -1; tcpClient.GetStream().WriteTimeout = -1; } client = CreateClientInfo(false, tcpClient, reader); client.ProtocolType = ClientProtocolType.SignalGoOneWay; client.StreamHelper = SignalGoStreamBase.CurrentBase; OneWayServiceProvider.StartToReadingClientData(client, _serverBase); } else if (firstLineString.Contains("SignalGo/4.0")) { client = CreateClientInfo(false, tcpClient, reader); client.ProtocolType = ClientProtocolType.SignalGoDuplex; //"SignalGo/1.0"; client.StreamHelper = SignalGoStreamBase.CurrentBase; if (_serverBase.ProviderSetting.ServerServiceSetting.IsEnabledToUseTimeout) { tcpClient.ReceiveTimeout = (int)_serverBase.ProviderSetting.ServerServiceSetting.ReceiveDataTimeout.TotalMilliseconds; tcpClient.SendTimeout = (int)_serverBase.ProviderSetting.ServerServiceSetting.SendDataTimeout.TotalMilliseconds; } else { tcpClient.GetStream().ReadTimeout = -1; tcpClient.GetStream().WriteTimeout = -1; } await SignalGoDuplexServiceProvider.StartToReadingClientData(client, _serverBase); } else if (firstLineString.Contains("HTTP/")) { if (_serverBase.ProviderSetting.HttpSetting.IsEnabledToUseTimeout) { tcpClient.GetStream().ReadTimeout = (int)_serverBase.ProviderSetting.HttpSetting.ReceiveDataTimeout.TotalMilliseconds; tcpClient.GetStream().WriteTimeout = (int)_serverBase.ProviderSetting.HttpSetting.SendDataTimeout.TotalMilliseconds; } await HttpProvider.StartToReadingClientData(tcpClient, _serverBase, reader, new StringBuilder(firstLineString)); } else { _serverBase.DisposeClient(client, tcpClient, "AddClient header not support"); } } catch (Exception) { _serverBase.DisposeClient(client, tcpClient, "exception"); } finally { _WaitingToReadFirstLineCount--; } }
public async Task <HttpClientResponseBase> PostHeadAsync(string url, ParameterInfo[] parameterInfoes, BaseStreamInfo streamInfo = null) { string newLine = TextHelper.NewLine; Uri uri = new Uri(url); TcpClient tcpClient = new TcpClient(uri.Host, uri.Port); try { if (streamInfo != null && (!streamInfo.Length.HasValue || streamInfo.Length <= 0)) { throw new Exception("Please set streamInfo.Length before upload your stream!"); } string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); string headData = $"POST {uri.AbsolutePath} HTTP/1.1" + newLine + $"Host: {uri.Host}" + newLine + $"Content-Type: multipart/form-data; boundary={boundary}" + newLine; if (RequestHeaders != null && RequestHeaders.Count > 0) { foreach (KeyValuePair <string, string[]> item in RequestHeaders) { if (!item.Key.Equals("host", StringComparison.OrdinalIgnoreCase) && !item.Key.Equals("content-type", StringComparison.OrdinalIgnoreCase) && !item.Key.Equals("content-length", StringComparison.OrdinalIgnoreCase)) { if (item.Value == null || item.Value.Length == 0) { continue; } headData += item.Key + ": " + string.Join(",", item.Value) + newLine; } } } StringBuilder valueData = new StringBuilder(); if (parameterInfoes != null) { string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; string boundaryinsert = TextHelper.NewLine + "--" + boundary + TextHelper.NewLine; foreach (ParameterInfo item in parameterInfoes) { valueData.AppendLine(boundaryinsert); valueData.Append(string.Format(formdataTemplate, item.Name, item.Value)); } } byte[] dataBytes = Encoding.GetBytes(valueData.ToString()); headData += $"Content-Length: {dataBytes.Length}" + newLine + newLine; byte[] headBytes = Encoding.GetBytes(headData); Stream stream = uri.Port == 443 ? (Stream) new SslStream(tcpClient.GetStream()) : tcpClient.GetStream(); if (uri.Port == 443) { SslStream sslStream = (SslStream)stream; await sslStream.AuthenticateAsClientAsync(uri.Host); } stream.Write(headBytes, 0, headBytes.Length); stream.Write(dataBytes, 0, dataBytes.Length); if (streamInfo != null) { int sentBytesCount = 0; int wantReadCount = 1024 * 512; while (streamInfo.Length > sentBytesCount) { if (wantReadCount > streamInfo.Length - sentBytesCount) { wantReadCount = (int)(streamInfo.Length - sentBytesCount); } byte[] result = new byte[wantReadCount]; int readCount = await streamInfo.Stream.ReadAsync(result, wantReadCount); await stream.WriteAsync(result, 0, readCount); sentBytesCount += readCount; } } PipeNetworkStream pipelineReader = new PipeNetworkStream(new NormalStream(stream), 30000); List <string> lines = new List <string>(); string line = null; do { if (line != null) { lines.Add(line.TrimEnd()); } line = await pipelineReader.ReadLineAsync(); }while (line != newLine); HttpClientResponseBase httpClientResponse = new HttpClientResponseBase { Status = (HttpStatusCode)Enum.Parse(typeof(HttpStatusCode), lines[0].Split(' ')[1]), ResponseHeaders = SignalGo.Shared.Http.WebHeaderCollection.GetHttpHeaders(lines.Skip(1).ToArray()), Stream = pipelineReader, TcpClient = tcpClient }; Response = httpClientResponse; return(httpClientResponse); } catch (Exception ex) { throw ex; } }
public static async Task StartToReadingClientData(TcpClient tcpClient, ServerBase serverBase, PipeNetworkStream reader, StringBuilder builder) { //Console.WriteLine($"Http Client Connected: {((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString().Replace("::ffff:", "")}"); ClientInfo client = null; try { while (true) { string line = await reader.ReadLineAsync(); builder.Append(line); if (line == TextHelper.NewLine) { break; } } string requestHeaders = builder.ToString(); if (requestHeaders.Contains("Sec-WebSocket-Key")) { tcpClient.ReceiveTimeout = -1; tcpClient.SendTimeout = -1; client = serverBase.ServerDataProvider.CreateClientInfo(false, tcpClient, reader); client.ProtocolType = ClientProtocolType.WebSocket; client.IsWebSocket = true; string key = requestHeaders.Replace("ey:", "`").Split('`')[1].Replace("\r", "").Split('\n')[0].Trim(); string acceptKey = AcceptKey(ref key); string newLine = TextHelper.NewLine; //var response = "HTTP/1.1 101 Switching Protocols" + newLine string response = "HTTP/1.0 101 Switching Protocols" + newLine + "Upgrade: websocket" + newLine + "Connection: Upgrade" + newLine + "Sec-WebSocket-Accept: " + acceptKey + newLine + newLine; byte[] bytes = System.Text.Encoding.UTF8.GetBytes(response); await client.ClientStream.WriteAsync(bytes, 0, bytes.Length); client.StreamHelper = SignalGoStreamBase.CurrentBase; client.ClientStream = new PipeNetworkStream(new WebSocketStream(client.TcpClient.GetStream())); if (requestHeaders.Contains("SignalgoDuplexWebSocket")) { await SignalGoDuplexServiceProvider.StartToReadingClientData(client, serverBase); } else { //client.StreamHelper = SignalGoStreamWebSocketLlight.CurrentWebSocket; //client.ClientStream = new PipeNetworkStream(new WebSocketStream(client.TcpClient.GetStream())); //await WebSocketProvider.StartToReadingClientData(client, serverBase); await HttpProvider.AddWebSocketHttpClient(client, serverBase); } } else if (requestHeaders.Contains("SignalGoHttpDuplex")) { client = serverBase.ServerDataProvider.CreateClientInfo(false, tcpClient, reader); client.ProtocolType = ClientProtocolType.HttpDuplex; client.StreamHelper = SignalGoStreamBase.CurrentBase; await SignalGoDuplexServiceProvider.StartToReadingClientData(client, serverBase); } else { try { //serverBase.TaskOfClientInfoes client = (HttpClientInfo)serverBase.ServerDataProvider.CreateClientInfo(true, tcpClient, reader); client.ProtocolType = ClientProtocolType.Http; client.StreamHelper = SignalGoStreamBase.CurrentBase; string[] lines = null; if (requestHeaders.Contains(TextHelper.NewLine + TextHelper.NewLine)) { lines = requestHeaders.Substring(0, requestHeaders.IndexOf(TextHelper.NewLine + TextHelper.NewLine)).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); } else { lines = requestHeaders.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); } if (lines.Length > 0) { string methodName = GetHttpMethodName(lines[0]); string address = GetHttpAddress(lines[0]); if (requestHeaders != null) { ((HttpClientInfo)client).RequestHeaders = SignalGo.Shared.Http.WebHeaderCollection.GetHttpHeaders(lines.Skip(1).ToArray()); } await HandleHttpRequest(methodName, address, serverBase, (HttpClientInfo)client); } else { serverBase.DisposeClient(client, tcpClient, "HttpProvider StartToReadingClientData no line detected"); } } catch { serverBase.DisposeClient(client, tcpClient, "HttpProvider StartToReadingClientData exception"); } } } catch (Exception ex) { //if (client != null) //serverBase.AutoLogger.LogError(ex, $"{client.IPAddress} {client.ClientId} ServerBase HttpProvider StartToReadingClientData"); serverBase.DisposeClient(client, tcpClient, "HttpProvider StartToReadingClientData exception 2"); } }