private async Task ProcessClientAsync(TcpClient tcpClient)
        {
            try
            {
                using (NetworkStream stream = tcpClient.GetStream())
                {
                    //we set the position of the red data (offset)
                    var position = 0;
                    //This is assumed to be the standard size of a buffer - 4kb
                    var buffer = new byte[HTTPConstants.BufferSize];

                    //TODO Check if there is faster way to proceed with array of bytes
                    var data = new List <byte>();

                    while (true)
                    {
                        var count = await stream.ReadAsync(buffer, position, buffer.Length);

                        position += count;

                        //We want to remove the empty bytes when adding to the data - if the last buffer is less than 4096b, then take only the non-empty data.
                        //We could use LINQ (data.AddRange(buffer.Take(count));) but will be slower...
                        if (count < buffer.Length)
                        {
                            var lastPartialBuffer = new byte[count];
                            Array.Copy(buffer, lastPartialBuffer, count);
                            data.AddRange(lastPartialBuffer);
                            break;
                        }
                        else
                        {
                            data.AddRange(buffer);
                        }
                    }

                    //Finally, byte[] => string(text)
                    var requestAsString = Encoding.UTF8.GetString(data.ToArray());
                    //Console.WriteLine(requestAsString);

                    var request = new HttpRequest(requestAsString);
                    //Console.WriteLine($"{request.Method} {request.Path} => ");

                    HttpResponse response;
                    var          route = this.routeTable.FirstOrDefault(
                        x => string.Compare(x.Path, request.Path, true) == 0 &&
                        x.Method == request.Method);

                    if (route != null)
                    {
                        response = route.Action(request);
                    }
                    else
                    {
                        // Not Found 404
                        response = new HttpResponse("text/html", new byte[0], Enums.HttpStatusCode.NotFound);
                    }

                    //We add this headers/cookies to each response

                    response.Headers.Add(new Header("Server", "SUS Custom Server 1.69"));
                    //Set-Cookie: Gosho's Cookie=fc0c3724-c519-4722-abd6-d39eb5522536; Path=/;Max-Age=2073600; HttpOnly;
                    //response.Cookies.Add(new ResponseCookie("Gosho's Cookie", Guid.NewGuid().ToString()) { HttpOnly = "true", MaxAge = 60 * 24 * 24 * 60 });

                    //This is where we add every session cookie from request to the response
                    var sessionCookie = request.Cookies.FirstOrDefault(x => x.Name == HTTPConstants.SessionCookieName);
                    if (sessionCookie != null)
                    {
                        var responseSessionCookie = new ResponseCookie(sessionCookie.Name, sessionCookie.Value);
                        responseSessionCookie.Path = "/";
                        response.Cookies.Add(responseSessionCookie);
                    }

                    //HttpResponse .ToString() is overriden
                    var responseHeaderBytes = Encoding.UTF8.GetBytes(response.ToString());

                    await stream.WriteAsync(responseHeaderBytes, 0, responseHeaderBytes.Length);

                    if (response.Body != null)
                    {
                        await stream.WriteAsync(response.Body, 0, response.Body.Length);
                    }
                }

                //To make sure it's close after we finish working with the current client (we do not trust "using" :) )
                tcpClient.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + " **************** ERRRRRRRRRRRRRRRRROR");
                //Console.WriteLine(ex.Message);
                //Console.WriteLine(ex.StackTrace);
                //Console.WriteLine(ex.Source);
                //Console.WriteLine(ex.InnerException);
            }
        }
Exemple #2
0
        private async Task ProcessClientAsync(TcpClient tcpClient)
        {
            try
            {
                using NetworkStream stream = tcpClient.GetStream();

                var data     = new List <byte>();
                int position = 0;

                byte[] buffer = new byte[HttpConstants.BufferSize]; //chunk

                while (true)
                {
                    int count =
                        await stream.ReadAsync(buffer, position, buffer.Length);

                    position += count;

                    if (count < buffer.Length)
                    {
                        var partialBuffer = new byte[count];
                        Array.Copy(buffer, partialBuffer, count);

                        data.AddRange(partialBuffer);
                        break;
                    }
                    else
                    {
                        data.AddRange(buffer);
                    }
                }

                // byte[] => string (text)
                var requestAsString = Encoding.UTF8.GetString(data.ToArray());
                var request         = new HttpRequest(requestAsString);

                Console.WriteLine($"{request.Method} {request.Path} => {request.Headers.Count} headers");

                HttpResponse response;

                var route = this.routeTable.FirstOrDefault(
                    x => string.Compare(x.Path, request.Path, true) == 0 &&
                    x.Method == request.Method);

                if (route != null)
                {
                    response = route.Action(request);
                }
                else
                {
                    //Not found
                    response = new HttpResponse("text/html", new byte[0], HttpStatusCode.NotFound);
                }

                response.Headers.Add(new Header("Server", "SUS Server 1.0"));

                var sessionCookie = request.Cookies.FirstOrDefault(x => x.Name == HttpConstants.SessionCookieName);
                if (sessionCookie != null)
                {
                    var responseSessionCookie = new ResponseCookie(sessionCookie.Name, sessionCookie.Value);
                    responseSessionCookie.Path = "/";
                    response.Cookies.Add(responseSessionCookie);
                }

                var responseHeaderBytes = Encoding.UTF8.GetBytes(response.ToString());
                await stream.WriteAsync(responseHeaderBytes, 0, responseHeaderBytes.Length);

                if (response.Body != null)
                {
                    await stream.WriteAsync(response.Body, 0, response.Body.Length);
                }

                tcpClient.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
        private async Task ProcessClientAsync(TcpClient tcpClient)
        {
            try
            {
                using (NetworkStream stream = tcpClient.GetStream())
                {
                    //TOOD: research if there is faster data structure
                    List <byte> data     = new List <byte>();
                    int         position = 0;
                    byte[]      buffer   = new byte[HttpConstants.BufferSize]; //also called chunk
                    while (true)
                    {
                        int count = await stream.ReadAsync(buffer, position, buffer.Length);

                        position = +count;

                        if (count < buffer.Length)
                        {
                            var partialBuffer = new byte[count];
                            Array.Copy(buffer, partialBuffer, count);
                            data.AddRange(partialBuffer);
                            break; //no data left
                        }
                        else
                        {
                            data.AddRange(data);
                        }
                    }

                    //Request
                    //byte[] => string (text)
                    var requestString = Encoding.UTF8.GetString(data.ToArray());
                    var request       = new HttpRequest(requestString);
                    //Console.WriteLine(requestString);
                    Console.WriteLine($"{request.Method} {request.Path} => {request.Headers.Count} Headers");

                    //let's go to the route table now and connect the request with the response
                    //Response
                    HttpResponse response;

                    //if (this.routeTable.ContainsKey(request.Path))
                    //{
                    //    var action = this.routeTable[request.Path];
                    //    response = action(request);
                    //}

                    //var route = this.routeTable.FirstOrDefault(x => x.Path == request.Path);
                    //to ignore the casing i use string.Compare():
                    var route = this.routeTable.FirstOrDefault(x => string.Compare(x.Path, request.Path, ignoreCase: true) == 0 &&
                                                               x.Method == request.Method);

                    if (route != null)
                    {
                        var action = route.Action;
                        response = action(request);
                    }
                    else
                    {
                        //404 Not Found
                        response = new HttpResponse("text/html", new byte[0], HttpStatusCode.NotFound);
                    }

                    response.Headers.Add(new Header("Server", "SUS Server 1.0"));
                    //response.Cookies.Add(new ResponseCookie("sid", Guid.NewGuid().ToString()) { HttpOnly = true, MaxAge = 60 * 24 * 60 * 60 });
                    var sessionCookie = request.Cookies.FirstOrDefault(x => x.Name == HttpConstants.SessionCookieName);
                    if (sessionCookie != null)
                    {
                        //pravq si response cookie, zashtoto ako e samo cookie, to shte mi se razmqta po edno novo session cookie
                        //za vseki request, dori za js i css fajlovete, a towa ne mi e nujno!!! Trqbwa mi 1 session cookie za 1 user!!!
                        var responseSessionCookie = new ResponseCookie(sessionCookie.Name, sessionCookie.Value);
                        //responseSessionCookie.Path = "/"; //toj si mi defaultno takyv path-a za towa sessionCookie!!!!
                        response.Cookies.Add(responseSessionCookie); //mestq tazi cookie ot requesta v responsa!!!
                    }

                    var responseHeaderBytes = Encoding.UTF8.GetBytes(response.ToString());

                    await stream.WriteAsync(responseHeaderBytes, 0, responseHeaderBytes.Length);

                    if (response.Body != null)
                    {
                        await stream.WriteAsync(response.Body, 0, response.Body.Length);
                    }
                }

                tcpClient.Close();
            }
            catch (Exception e)
            {
                //throw e;
                Console.WriteLine(e);
            }
        }