Beispiel #1
0
        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();
            }
        }
Beispiel #2
0
        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");
            }
        }
Beispiel #3
0
        public WebHostBuilder WithWebSocketHandle(string urlRelative, Func <HttpRequest, Task <IResponse> > action)
        {
            RoutingHandler.RegisterWss(urlRelative, action);

            return(this);
        }
Beispiel #4
0
        public WebHostBuilder WithRoutingHandleDefault(Func <HttpRequest, Task <IResponse> > action)
        {
            RoutingHandler.RegisterDefaultResponse(action);

            return(this);
        }
Beispiel #5
0
        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);
                }
            }
        }