private async Task <HttpRequest> ReadByteFromClientSocketAndBuildRequest(Socket socketAccepted)
        {
            byte[] bufferReceive = new byte[_bufferLength];

            using (var received = new MemoryStream())
            {
                while (true)
                {
                    int receiveLength = socketAccepted.Receive(bufferReceive);
                    if (receiveLength <= 0)
                    {
                        break;
                    }

                    received.Write(bufferReceive, 0, receiveLength);

                    if (receiveLength <= _bufferLength)
                    {
                        break;
                    }
                }

                string data = Encoding.UTF8.GetString(received.ToArray());

                var tempReq = await HttpTransform.BuildHttpRequest(data);

                return(tempReq);
            }
        }
Exemple #2
0
        internal static async Task <HttpRequest> DoHandShaking(TcpClient clientWssAccepted, NetworkStream clientStream, byte[] wssReceivedBytes)
        {
            string      wss1stData   = Encoding.UTF8.GetString(wssReceivedBytes);
            HttpRequest firstRequest = null;

            if (Regex.IsMatch(wss1stData, "^GET", RegexOptions.IgnoreCase))
            {
                firstRequest = await HttpTransform.BuildHttpRequest(wss1stData);

                WebsocketServerHub.Register(firstRequest.UrlRelative, clientWssAccepted, clientStream);

                //do handshaking
                string swk            = Regex.Match(wss1stData, "Sec-WebSocket-Key: (.*)").Groups[1].Value.Trim();
                string swka           = swk + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
                byte[] swkaSha1       = System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(swka));
                string swkaSha1Base64 = Convert.ToBase64String(swkaSha1);
                byte[] response       = Encoding.UTF8.GetBytes(
                    "HTTP/1.1 101 Switching Protocols\r\n" +
                    "Connection: Upgrade\r\n" +
                    "Upgrade: websocket\r\n" +
                    "Sec-WebSocket-Accept: " + swkaSha1Base64 + "\r\n\r\n");

                await clientStream.WriteAsync(response, 0, response.Length);

                return(firstRequest);
            }

            return(firstRequest);
        }
        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);
                }
            }
        }