public void Start() { Console.WriteLine($"BaseDirectory: {AppDomain.CurrentDomain.BaseDirectory}"); Console.WriteLine($"WebHostBuilder start at: {_domainOrId}:{_port}"); for (var i = 0; i < _numberOfWorker; i++) { WebHostWorker httpWorker = new WebHostWorker(_domainOrId, _port, _socketPoolSize, _socketBufferLength, async() => { await RoutingHandler.Ping(_domainOrId, _port); }, false); _listWorker.Add(httpWorker); if (_wssPort != null) { WebHostWorker wssWorker = new WebHostWorker(_domainOrId, _wssPort.Value, _socketPoolSize, _socketBufferLength, async() => { await Task.Delay(100); }, true); _listWorker.Add(wssWorker); } } foreach (var w in _listWorker) { w.Start(); } }
internal static async Task ReceiveAndReplyClientMessage(TcpClient clientWssAccepted, NetworkStream clientStream, byte[] wssReceivedBytes, HttpRequest firstRequestOfHandShake) { bool fin = (wssReceivedBytes[0] & 0b10000000) != 0; bool mask = (wssReceivedBytes[1] & 0b10000000) != 0; // must be true, "All messages from the client to the server have this bit set" int opcode = wssReceivedBytes[0] & 0b00001111, // expecting 1 - text message msglen = wssReceivedBytes[1] - 128, // & 0111 1111 offset = 2; if (msglen == 126) { // was ToUInt16(bytes, offset) but the result is incorrect msglen = BitConverter.ToUInt16(new byte[] { wssReceivedBytes[3], wssReceivedBytes[2] }, 0); offset = 4; } else if (msglen == 127) { Console.WriteLine("TODO: msglen == 127, needs qword to store msglen"); // i don't really know the byte order, please edit this // msglen = BitConverter.ToUInt64(new byte[] { bytes[5], bytes[4], bytes[3], bytes[2], bytes[9], bytes[8], bytes[7], bytes[6] }, 0); // offset = 10; } if (msglen == 0) { Console.WriteLine("msglen == 0"); } else if (mask) { byte[] decoded = new byte[msglen]; byte[] masks = new byte[4] { wssReceivedBytes[offset], wssReceivedBytes[offset + 1], wssReceivedBytes[offset + 2], wssReceivedBytes[offset + 3] }; offset += 4; for (int i = 0; i < msglen; ++i) { decoded[i] = (byte)(wssReceivedBytes[offset + i] ^ masks[i % 4]); } string receivedFromClient = Encoding.UTF8.GetString(decoded); var wssResponse = await RoutingHandler.HandleWss(new HttpRequest() { UrlRelative = firstRequestOfHandShake.UrlRelative, Method = "wss", CreatedAt = DateTime.Now, Body = receivedFromClient, RemoteEndPoint = clientWssAccepted.Client.RemoteEndPoint.ToString() }); WebsocketServerHub.Send(clientWssAccepted, clientStream, wssResponse); } else { Console.WriteLine("mask bit not set"); } }
public WebHostBuilder WithWebSocketHandle(string urlRelative, Func <HttpRequest, Task <IResponse> > action) { RoutingHandler.RegisterWss(urlRelative, action); return(this); }
public WebHostBuilder WithRoutingHandleDefault(Func <HttpRequest, Task <IResponse> > action) { RoutingHandler.RegisterDefaultResponse(action); return(this); }
public WebHostBuilder WithRoutingHandle(HttpMethod method, string urlRelative, Func <HttpRequest, Task <IResponse> > action) { RoutingHandler.Register(method, urlRelative, action); return(this); }
async Task InternalStartAcceptIncommingAsync(TcpListener tcpListener) { //you may want to do with ssl //https://docs.microsoft.com/en-us/dotnet/api/system.net.security.sslstream?redirectedfrom=MSDN&view=netcore-3.1 while (!_isStop) { try { if (_isWss) { //https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_server TcpClient clientWssAccepted = await tcpListener.AcceptTcpClientAsync(); NetworkStream clientStream = clientWssAccepted.GetStream(); HttpRequest wss1stRequestOfHandShake = null; Task twss = Task.Run(async() => { while (!_isStop) { if (!clientWssAccepted.Client.Connected) { if (wss1stRequestOfHandShake != null) { WebsocketServerHub.Remove(wss1stRequestOfHandShake.UrlRelative); } await Shutdown(clientWssAccepted.Client, wss1stRequestOfHandShake); break; } while (!clientStream.DataAvailable) { ; } while (clientWssAccepted.Available < 3) { ; // match against "get" } byte[] wssReceivedBytes = new byte[clientWssAccepted.Available]; await clientStream.ReadAsync(wssReceivedBytes, 0, clientWssAccepted.Available); var handShakeRequest = await WebsocketServerHub.DoHandShaking(clientWssAccepted, clientStream, wssReceivedBytes); if (handShakeRequest != null) { wss1stRequestOfHandShake = handShakeRequest; } await WebsocketServerHub.ReceiveAndReplyClientMessage(clientWssAccepted, clientStream, wssReceivedBytes, wss1stRequestOfHandShake); } }); continue; } //WebHostWorker will try accept its job Socket clientSocket = await tcpListener.AcceptSocketAsync(); //parse request then dispatched by RoutingHandler var t = Task.Run(async() => { Task <HttpRequest> tRequest = ReadByteFromClientSocketAndBuildRequest(clientSocket); HttpRequest request = new HttpRequest(); request.CreatedAt = DateTime.Now; request.RemoteEndPoint = clientSocket.RemoteEndPoint.ToString(); var tempRequest = await tRequest; request.Body = tempRequest.Body; request.Error = tempRequest.Error; request.Header = tempRequest.Header; request.HeadlerCollection = tempRequest.HeadlerCollection; request.HttpVersion = tempRequest.HttpVersion; request.Method = tempRequest.Method; request.QueryParamCollection = tempRequest.QueryParamCollection; request.Url = tempRequest.Url; request.UrlRelative = tempRequest.UrlRelative; request.UrlQueryString = tempRequest.UrlQueryString; //dispatched routing here var processedResult = await RoutingHandler.Handle(request); HttpResponse response = await HttpTransform.BuildHttpResponse(processedResult, request); await SendResponseToClientSocket(clientSocket, request, response); await Shutdown(clientSocket, request); HttpLogger.Log(request); Console.WriteLine($"{request.RemoteEndPoint}@{request.CreatedAt}=>{request.Method}:{request.Url}"); }); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(JsonConvert.SerializeObject(ex)); } finally { await Task.Delay(0); } } }