Exemple #1
0
        public static HTTPHeader GenerateResponse()
        {
            HTTPHeader header = new HTTPHeader();

            header.SetField("Content-Type", "text/html");
            header.Version = 1.1;
            return(header);
        }
        private void PullRequest()
        {
            // Just cache this value in case it randomly decides to change
            int bufSize = this.BufferSize;
            // Shove the message in here, so we can peek around freely
            MemoryStream fullMessage = new MemoryStream();

            byte[] readBuffer = new byte[bufSize]; // Reserve a bit of memory we can receive data in
            while (true)
            {
                int readCount = 0;
                try
                {
                    readCount = this.inputStream.Read(readBuffer, 0, bufSize); // Read data from the TCP stream
                }
                catch (Exception ex)
                {
                    Log.e("Could not read from TCP stream: {0}", ex.Message);
                    this.QuitProcessor();
                    return;
                }

                if (readCount == 0)
                {
                    break;
                }                                            // When we get zero bytes, we can assume it is the end of the stream
                fullMessage.Write(readBuffer, 0, readCount); // Take the data we got, and put it in our own stream object
                if (readCount < bufSize)
                {
                    break;
                }                                  // If the received data length is smaller then the buffer, assume end of stream
            }
            fullMessage.Seek(0, SeekOrigin.Begin); // Set the cursor of our own stream to the start

            if (fullMessage.Length <= 0)           // We can't do anything with empty requests, kill the stream
            {
                if (this.handlingServer.Settings.ChargenOnEmptyStream)
                {
                    Log.m("Got an empty stream, shoving through a load of characters before quitting");
                    Random aRandom = new Random((int)DateTime.Now.Ticks);
                    try
                    {
                        for (int i = 0; i < this.handlingServer.Settings.ChargenLength; i++)
                        {
                            this.outputStream.WriteByte((byte)aRandom.Next(0, 254));
                        }

                        this.outputStream.Flush();
                    }
                    catch (Exception ex)
                    {
                        Log.e("Failed to shove a bunch of characters", ex.Message);
                    }
                }
                else
                {
                    Log.e("Got an empty message from a remote client, aborting processing stream");
                }
                this.QuitProcessor();
                return;
            }

            StringBuilder requestString = new StringBuilder(); // StringBuilers are faster than just appending strings or chars ^^
            int           lastByte      = -1;

            while (fullMessage.CanRead)
            {
                int readByte = fullMessage.ReadByte(); // Get one byte from the received message
                if (readByte == 13)
                {                                      // We're going to ignore carriage returns
                    continue;
                }

                if (lastByte == readByte && readByte == 10)
                { // We've got two newlines, end of request!
                    break;
                }
                requestString.Append((char)(byte)readByte); // Just throw the received byte onto the end of our string

                lastByte = readByte;
            }

            int        contentLength = 0;
            HTTPHeader requestHeader = HTTPHeader.ParseRequest(requestString.ToString()); // Turn our request string into a header object, so we can do stuff

            Log.d("Connection mode is {0}", requestHeader.Connection[0]);
            this.KeepAlive       = requestHeader.Connection.Contains("keep-alive"); // We have to keep pulling requests until specified otherwise
            this.closeConnection = requestHeader.Connection.Contains("close");      // Have a license to kill
            if (requestHeader.HTTPFields.ContainsKey("Content-Length"))
            {
                contentLength = requestHeader.ContentLength;
            }
            Log.d("Got request:\n{0}", requestHeader.ToString());

            // Read the http message content from the stream
            // If we get no content, we're wasting some resources
            // cri
            ContentStream requestContent = new ContentStream();

            if (requestContent.Length > 0)
            {
                while (fullMessage.CanRead)
                {
                    requestContent.WriteByte((byte)fullMessage.ReadByte());
                    if (requestContent.Length >= contentLength)
                    {
                        break;
                    }
                }
            }

            // Finish the stream boogaloo for this request
            fullMessage.Dispose(); // We've got from the stream what we needed, get rid of it
            fullMessage = null;
            // this.inputStream.Seek(0, SeekOrigin.End); // Skip the buffered stream to the end

            // Set up the data containers for the response
            HTTPHeader responseHeader = HTTPHeader.GenerateResponse();

            responseHeader.SetField("Server", this.handlingServer.Settings.Server);
            ContentStream responseContent = new ContentStream();

            // Shove all of our junk in one neat little strucht
            Handlers.HandlePackage handlePackage = new Handlers.HandlePackage(requestHeader, responseHeader, requestContent, responseContent, this.handlingServer);
            if (this.handlingServer.Settings.AutoProxy && !MachineData.HostNames.ContainsName(requestHeader.Host))
            {
                Log.m("Autoproxying for {0}", requestHeader.Host);
                if (!this.handlingServer.AutoProxyHandler.HandleRequest(handlePackage))
                {
                    responseContent.Write("wah");
                }
            }
            else
            {
                if (!this.handlingServer.CoreHandler.HandleRequest(handlePackage)) // Allow the core handler a try first
                {
                    bool notExecuted = true;
                    foreach (IHTTPHandler handler in this.handlingServer.HTTPHandlers)
                    {
                        notExecuted = !handler.HandleRequest(handlePackage);
                        // Might have to put a break in here some day
                    }

                    if (notExecuted)
                    { // Nothing handled our request, shove it through the default handler
                        this.handlingServer.DefaultHTTPHandler.HandleRequest(handlePackage);
                    }
                }
            }

            responseHeader.SetField("Content-Length", responseContent.Length.ToString()); // We have to set the content length on the response header
            responseHeader.SetField("Connection", "closed");

            string statusString = string.Format("HTTP/{2} {0} {1}\r\n", responseHeader.StatusCode, responseHeader.StatusMessage, responseHeader.Version);

            byte[] statusStringBytes = Encoding.UTF8.GetBytes(statusString);
            this.outputStream.Write(statusStringBytes, 0, statusStringBytes.Length);

            Log.d("Response header: {0}\n", responseHeader.ToString());
            responseHeader.DumpFields(this.outputStream);
            this.outputStream.WriteByte(13); // CRLF the really stupid way
            this.outputStream.WriteByte(10);

            if (requestHeader.Method == HTTP_Method.HEAD)
            {
                // WELL OK
            }
            else
            {
                // Copy the content generated by our other stuff into the TCP stream
                byte[] contentBytes = new byte[responseContent.Length];
                if (responseContent.Length > 0)
                {
                    responseContent.Seek(0, SeekOrigin.Begin);
                    responseContent.Read(contentBytes, 0, (int)responseContent.Length);
                }
                try
                {
                    this.outputStream.Write(contentBytes, 0, contentBytes.Length);
                }
                catch (Exception ex)
                {
                    Log.e(ex.Message);
                }
            }

            this.KeepAlive = false; // heh...
            // this.outputStream.Flush();
        }
Exemple #3
0
        public static HTTPHeader ParseRequest(string requestString)
        {
            HTTP_Method method  = HTTP_Method.UNSUPPORTED;
            string      url     = "/";
            double      version = 0;
            Dictionary <string, string> httpFields = new Dictionary <string, string>();
            Dictionary <string, string> getFields  = new Dictionary <string, string>();

            string[] lines        = requestString.Split('\n'); // Take the HTTP request and split it into the seperate lines
            string[] requestParts = lines[0].Split(' ');       // Take line 0 (the request string) and split it into its components
            int      partCounter  = 0;

            for (int i = 0; i < requestParts.Count(); i++)
            {
                string part = requestParts[i];
                if (part == string.Empty)
                {
                    continue;
                }                                       // No place for empty strings

                switch (partCounter)
                {
                case 0:     // Request method
                    try
                    {
                        // Some top kek method selecting
                        method = (HTTP_Method)System.Enum.Parse(typeof(HTTP_Method), part.ToUpper());
                    }
                    catch (Exception ex)
                    {
                        Log.d("Got an unsupported HTTP Request method: {0}", ex.Message);
                    }

                    break;

                case 1:     // Request URL
                    url = HTTPHeader.ExtractURL(part);
                    if (url != part)
                    {
                        getFields = HTTPHeader.ParseGetFields(part);
                    }
                    break;

                case 2:     // Request HTTP Version
                    string part_lower = part.ToLower();
                    if (part_lower.StartsWith("http/") && part.Length >= 5)
                    {
                        try
                        {
                            version = double.Parse(part_lower.Substring(5));
                        }
                        catch (Exception ex)
                        {
                            Log.d("Could not parse HTTP Version: {0}", ex.Message);
                        }
                    }

                    break;

                default:
                    // Well that was awkward
                    break;
                }

                partCounter++;
            }

            if (lines.Length > 1)
            { // We've got ourselves some fields, lets parse those <3
                for (int i = 1; i < lines.Length; i++)
                {
                    string line = lines[i];
                    if (line == string.Empty || line.Length < 3)
                    {
                        continue;
                    }
                    string key         = "";              // Fields aren't that long, so whatever
                    int    keyPosition = 0;
                    for (int c = 0; c < line.Length; c++) // C++, hue hue hue
                    {
                        string chr = line.Substring(c, 1);
                        if (chr == ":")
                        {
                            keyPosition = c; break;
                        }
                    }

                    key = line.Substring(0, keyPosition);
                    if (httpFields.ContainsKey(key))
                    {
                        Log.d("HTTP header contains duplicate field: {0}", key);
                    }
                    else
                    {
                        httpFields[key] = line.Substring(keyPosition + 1);
                    }
                }
            }

            HTTPHeader newHeader = new HTTPHeader(method, url, httpFields, getFields);

            newHeader.Version = version;

            return(newHeader);
        }