public KeyValue <DataType, CompressMode> ReadFirstData(PipeNetworkStream stream, int maximumReceiveStreamHeaderBlock) { DataType responseType = (DataType)SignalGoStreamBase.CurrentBase.ReadOneByte(stream); CompressMode compressMode = (CompressMode)SignalGoStreamBase.CurrentBase.ReadOneByte(stream); return(new KeyValue <DataType, CompressMode>(responseType, compressMode)); }
public static async void StartToReadingClientData(ClientInfo client, ServerBase serverBase) { try { Console.WriteLine($"Stream Client Connected: {client.IPAddress}"); PipeNetworkStream stream = client.ClientStream; byte firstByte = await client.StreamHelper.ReadOneByteAsync(stream); if (firstByte == 0) { await DownloadStreamFromClient(client, serverBase); } //download from server and upload from client else { await UploadStreamToClient(client, serverBase); } serverBase.DisposeClient(client, null, "StartToReadingClientData finished"); } catch (Exception ex) { serverBase.AutoLogger.LogError(ex, $"{client.IPAddress} {client.ClientId} ServerBase SignalGoStreamProvider StartToReadingClientData"); serverBase.DisposeClient(client, null, "SignalGoStreamProvider StartToReadingClientData exception"); } }
/// <summary> /// initialzie and read client /// </summary> /// <param name="tcpClient"></param> public void InitializeClient(TcpClient tcpClient) { Task.Run(async() => { try { tcpClient.GetStream().ReadTimeout = 5000; tcpClient.GetStream().WriteTimeout = 5000; PipeNetworkStream stream = new PipeNetworkStream(new NormalStream(await tcpClient.GetTcpStream(_serverBase)), (int)_serverBase.ProviderSetting.ReceiveDataTimeout.TotalMilliseconds); ExchangeClient(stream, tcpClient); } catch (Exception) { #if (NETSTANDARD) tcpClient.Dispose(); #else tcpClient.Close(); #endif } }); }
/// <summary> /// create client information /// </summary> /// <param name="isHttp"></param> /// <param name="tcpClient"></param> /// <param name="stream"></param> /// <returns></returns> public ClientInfo CreateClientInfo(bool isHttp, TcpClient tcpClient, PipeNetworkStream stream) { ClientInfo client = null; if (isHttp) { client = new HttpClientInfo(_serverBase); } else { client = new ClientInfo(_serverBase); } client.ConnectedDateTime = DateTime.Now; client.TcpClient = tcpClient; //client.IPAddressBytes = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString().Replace("::ffff:", ""); client.IPAddressBytes = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.GetAddressBytes(); client.ClientId = Guid.NewGuid().ToString(); _serverBase.Clients.TryAdd(client.ClientId, client); client.ClientStream = stream; _serverBase.OnClientConnectedAction?.Invoke(client); return(client); }
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; } }
/// <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 StreamInfo(PipeNetworkStream stream) { Stream = stream; }
public StreamGo(PipeNetworkStream currentStream) { CurrentStream = currentStream; }
public static async Task StartToReadingClientData(ClientInfo client, ServerBase serverBase) { try { Console.WriteLine($"Duplex Client Connected: {client.IPAddress}"); PipeNetworkStream stream = client.ClientStream; while (true) { byte oneByteOfDataType = await client.StreamHelper.ReadOneByteAsync(stream); //type of data DataType dataType = (DataType)oneByteOfDataType; if (dataType == DataType.PingPong) { await client.StreamHelper.WriteToStreamAsync(client.ClientStream, new byte[] { 5 }); continue; } //compress mode of data CompressMode compressMode = (CompressMode)await client.StreamHelper.ReadOneByteAsync(stream); //a server service method called from client if (dataType == DataType.CallMethod) { byte[] bytes = await client.StreamHelper.ReadBlockToEndAsync(stream, compressMode, serverBase.ProviderSetting.MaximumReceiveDataBlock); //if (ClientsSettings.ContainsKey(client)) // bytes = DecryptBytes(bytes, client); string json = Encoding.UTF8.GetString(bytes); MethodCallInfo callInfo = ServerSerializationHelper.Deserialize <MethodCallInfo>(json, serverBase); if (callInfo.PartNumber != 0) { SegmentManager segmentManager = new SegmentManager(); ISegment result = segmentManager.GenerateAndMixSegments(callInfo); if (result != null) { callInfo = (MethodCallInfo)result; } else { continue; } } Task <MethodCallbackInfo> callbackResult = CallMethod(callInfo, client, json, serverBase); SendCallbackDataAsync(callbackResult, client, serverBase); } //reponse of client method that server called to client else if (dataType == DataType.ResponseCallMethod) { byte[] bytes = await client.StreamHelper.ReadBlockToEndAsync(stream, compressMode, serverBase.ProviderSetting.MaximumReceiveDataBlock); //if (ClientsSettings.ContainsKey(client)) // bytes = DecryptBytes(bytes, client); string json = Encoding.UTF8.GetString(bytes); MethodCallbackInfo callback = ServerSerializationHelper.Deserialize <MethodCallbackInfo>(json, serverBase); if (callback == null) { serverBase.AutoLogger.LogText($"{client.IPAddress} {client.ClientId} callback is null:" + json); } if (callback.PartNumber != 0) { SegmentManager segmentManager = new SegmentManager(); ISegment result = segmentManager.GenerateAndMixSegments(callback); if (result != null) { callback = (MethodCallbackInfo)result; } else { continue; } } if (serverBase.ClientServiceCallMethodsResult.TryGetValue(callback.Guid, out KeyValue <Type, object> resultTask)) { if (callback.IsException) { resultTask.Value.GetType().FindMethod("SetException").Invoke(resultTask.Value, new object[] { new Exception(callback.Data) }); } else { resultTask.Value.GetType().FindMethod("SetResult").Invoke(resultTask.Value, new object[] { ServerSerializationHelper.Deserialize(callback.Data, resultTask.Key, serverBase) }); } } } else if (dataType == DataType.GetServiceDetails) { byte[] bytes = await client.StreamHelper.ReadBlockToEndAsync(stream, compressMode, serverBase.ProviderSetting.MaximumReceiveDataBlock); //if (ClientsSettings.ContainsKey(client)) // bytes = DecryptBytes(bytes, client); string json = Encoding.UTF8.GetString(bytes); string hostUrl = ServerSerializationHelper.Deserialize <string>(json, serverBase); ServerServicesManager serverServicesManager = new ServerServicesManager(); ProviderDetailsInfo detail = serverServicesManager.SendServiceDetail(hostUrl, serverBase); json = ServerSerializationHelper.SerializeObject(detail, serverBase); List <byte> resultBytes = new List <byte> { (byte)DataType.GetServiceDetails, (byte)CompressMode.None }; byte[] jsonBytes = Encoding.UTF8.GetBytes(json); byte[] dataLen = BitConverter.GetBytes(jsonBytes.Length); resultBytes.AddRange(dataLen); resultBytes.AddRange(jsonBytes); await client.StreamHelper.WriteToStreamAsync(client.ClientStream, resultBytes.ToArray()); } else if (dataType == DataType.GetMethodParameterDetails) { byte[] bytes = await client.StreamHelper.ReadBlockToEndAsync(stream, compressMode, serverBase.ProviderSetting.MaximumReceiveDataBlock); //if (ClientsSettings.ContainsKey(client)) // bytes = DecryptBytes(bytes, client); string json = Encoding.UTF8.GetString(bytes); MethodParameterDetails detail = ServerSerializationHelper.Deserialize <MethodParameterDetails>(json, serverBase); if (!serverBase.RegisteredServiceTypes.TryGetValue(detail.ServiceName, out Type serviceType)) { throw new Exception($"{client.IPAddress} {client.ClientId} Service {detail.ServiceName} not found"); } if (serviceType == null) { throw new Exception($"{client.IPAddress} {client.ClientId} serviceType {detail.ServiceName} not found"); } ServerServicesManager serverServicesManager = new ServerServicesManager(); json = serverServicesManager.SendMethodParameterDetail(serviceType, detail, serverBase); List <byte> resultBytes = new List <byte> { (byte)DataType.GetMethodParameterDetails, (byte)CompressMode.None }; byte[] jsonBytes = Encoding.UTF8.GetBytes(json); byte[] dataLen = BitConverter.GetBytes(jsonBytes.Length); resultBytes.AddRange(dataLen); resultBytes.AddRange(jsonBytes); await client.StreamHelper.WriteToStreamAsync(client.ClientStream, resultBytes.ToArray()); } else if (dataType == DataType.GetClientId) { byte[] bytes = Encoding.UTF8.GetBytes(client.ClientId); //if (ClientsSettings.ContainsKey(client)) // bytes = EncryptBytes(bytes, client); byte[] len = BitConverter.GetBytes(bytes.Length); List <byte> data = new List <byte> { (byte)DataType.GetClientId, (byte)CompressMode.None }; data.AddRange(len); data.AddRange(bytes); if (data.Count > serverBase.ProviderSetting.MaximumSendDataBlock) { throw new Exception($"{client.IPAddress} {client.ClientId} GetClientId data length exceeds MaximumSendDataBlock"); } await client.StreamHelper.WriteToStreamAsync(client.ClientStream, data.ToArray()); } else { //throw new Exception($"Correct DataType Data {dataType}"); serverBase.AutoLogger.LogText($"Correct DataType Data {oneByteOfDataType} {client.ClientId} {client.IPAddress}"); break; } } serverBase.DisposeClient(client, null, "StartToReadingClientData while break"); } catch (Exception ex) { serverBase.AutoLogger.LogError(ex, $"{client.IPAddress} {client.ClientId} ServerBase SignalGoDuplexServiceProvider StartToReadingClientData"); serverBase.DisposeClient(client, null, "SignalGoDuplexServiceProvider StartToReadingClientData exception"); } }
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"); } }
/// <summary> /// this method calll when client want to download file or stream from your server /// </summary> /// <param name="stream">client stream</param> /// <param name="client">client</param> private static async Task UploadStreamToClient(ClientInfo client, ServerBase serverBase) { MethodCallbackInfo callback = null; IStreamInfo streamInfo = null; PipeNetworkStream userStream = null; PipeNetworkStream stream = client.ClientStream; bool isCallbackSended = false; try { byte[] bytes = await client.StreamHelper.ReadBlockToEndAsync(client.ClientStream, CompressMode.None, serverBase.ProviderSetting.MaximumReceiveStreamHeaderBlock); string json = Encoding.UTF8.GetString(bytes); MethodCallInfo callInfo = ServerSerializationHelper.Deserialize <MethodCallInfo>(json, serverBase); CallMethodResultInfo <OperationContext> result = await CallMethod(callInfo.ServiceName, callInfo.Guid, callInfo.MethodName, callInfo.Parameters, null, client, null, serverBase, null, null); callback = result.CallbackInfo; streamInfo = result.StreamInfo; userStream = streamInfo.Stream; long len = streamInfo.Length.GetValueOrDefault(); await SendCallbackData(callback, client, serverBase); isCallbackSended = true; long writeLen = 0; while (writeLen < len) { bytes = new byte[1024 * 100]; int readCount = await userStream.ReadAsync(bytes, bytes.Length); byte[] sendBytes = bytes.Take(readCount).ToArray(); await stream.WriteAsync(sendBytes, 0, sendBytes.Length); writeLen += readCount; } userStream.Dispose(); Console.WriteLine("user stream finished"); stream.Dispose(); } catch (Exception ex) { if (streamInfo != null) { streamInfo.Dispose(); } stream.Dispose(); if (userStream != null) { userStream.Dispose(); Console.WriteLine("user stream disposed"); } if (!isCallbackSended && !client.ClientStream.IsClosed) { if (callback == null) { callback = new MethodCallbackInfo(); } callback.IsException = true; callback.Data = ServerSerializationHelper.SerializeObject(ex); await SendCallbackData(callback, client, serverBase); } } finally { //MethodsCallHandler.EndStreamCallAction?.Invoke(client, guid, serviceName, methodName, values, jsonResult, exception); } }