Ejemplo n.º 1
0
        /// <summary>
        /// Accepts the callback from client, also handles parsing the
        /// request, and sending response.
        /// </summary>
        public static void AcceptCallback(IAsyncResult ar)
        {
            // Connection has been made, let's let the main thread continue
            ConnectionStatus.AllowListening();

            int t = Environment.TickCount;

            // Get the socket that handles the client request.
            Socket listener = (Socket)ar.AsyncState;
            Socket handler  = listener.EndAccept(ar);


            // Buffer for receiving data
            byte[] buffer = new byte[bufferSize];


            // Raw request
            StringBuilder rawRequest = new StringBuilder();


            // Fetching data from server
            int receivedCount = 0;
            int requestSize   = 0;

            while (true)
            {
                receivedCount = handler.Receive(
                    buffer,
                    0,
                    bufferSize,
                    SocketFlags.None);

                requestSize += receivedCount;
                if (requestSize > maximumRequestSize)
                {
                    // Exceeded maxiumum request size

                    // TODO: Send a page to client saying that the
                    // request buffer is too large.

                    // For now, just clearing some variables
                    rawRequest.Clear();
                    buffer = null;

                    // Just logging the failed request (IK!! IK!! It's very f*****g long)
                    Console.WriteLine("New request from {0}, but the request was too large.", (cloudflareMode ? string.Format("(CFIP){0}", (handler.RemoteEndPoint as IPEndPoint).ToString()) : (handler.RemoteEndPoint as IPEndPoint).ToString()));

                    return;
                }
                else
                {
                    rawRequest.Append(Encoding.ASCII.GetString(buffer));

                    // Checking if this is the end of the receive
                    // buffer.
                    if (receivedCount < bufferSize)
                    {
                        break;
                    }
                }
            }

            // Getting end point
            IPEndPoint ipep = (handler.RemoteEndPoint as IPEndPoint);


            // Storing request/response in variables for ease access
            WebRequestHandler  request  = default(WebRequestHandler);
            WebResponseHandler response = default(WebResponseHandler);


            try
            {
                // Generating a request
                request = WebRequestHandler.ParseRequest(
                    rawRequest.ToString(), ipep.Address, ipep.Port);


                // Generating a response
                response = new WebResponseHandler(request.path, ref request);


                // Getting a string builder for the response
                StringBuilder responseData = new StringBuilder();


                // Appending main header (not sure if it has a name or what)
                responseData.Append(string.Format("{0} {1} {2}\r\n",
                                                  request.protocolVersion, response.StatusCode.ToString(),
                                                  response.StatusCodeDescriptor));


                // CGI status (Non-standard)
                responseData.Append(string.Format("Status: {0} {1}", response.StatusCode, response.StatusCodeDescriptor));


                // Appending default headers
                foreach (HttpHeader header in defaultHeaders)
                {
                    responseData.Append(string.Format("{0}: {1}\r\n",
                                                      header.name, header.value));
                }


                // Appending essential headers
                responseData.Append(string.Format("Date: {0}\r\n",
                                                  Misc.GetFormattedDate(Misc.time)));


                // Adding all headers
                foreach (HttpHeader header in response.Headers)
                {
                    string value = header.value;

                    // If the value contains a new line, you could
                    // potentially inject extra headers, which is not good.
                    if (value.Contains('\r') || value.Contains('\n') ||
                        header.name.Contains('\r') || header.name.Contains('\n'))
                    {
                        return;
                    }

                    // Writing header to buffer
                    responseData.Append(string.Format("{0}: {1}\r\n", header.name, value));
                }


                // If the content isn't empty, add the required headers
                if (!string.IsNullOrEmpty(response.Content))
                {
                    // TODO: Check if content-length is already set.
                    responseData.Append(string.Format("Content-Length: {0}\r\n",
                                                      response.Content.Length.ToString()));

                    responseData.Append("\r\n");
                    responseData.Append(response.Content);
                }


                // Getting a string to send, we need a reference
                string rawSend = responseData.ToString();


                // Sending the response.
                Send(ref handler, ref rawSend);


                // nullifying variables
                response.Clear();
                rawRequest.Clear();
                responseData.Clear();
                buffer   = null;
                rawSend  = null;
                request  = null;
                response = null;

                Console.WriteLine(Environment.TickCount - t);

                // Collect all this shit, don't want to wait for it
                // to collect them.
                GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
            }
            catch (Exception ex)
            {
                Logs.LogException(ex.ToString());
            }
        }