Пример #1
0
        /// <summary>
        /// Sends to the HTTP response asynchronously, then closes the connection if required.
        /// </summary>
        /// <param name="persist">Sets or overrides exiting Connection header unless Unspecified,
        /// in which case observes existing header or default behavior for version</param>
        public void Send(ConnectionPersistence persist)
        {
            // By default, don't do anything with the connection after sending
            EventHandler <SocketAsyncEventArgs> finished = (sender, comp) => { };

            if (persist != ConnectionPersistence.UNSPECIFIED)
            {                   // There's some value for "persist", use it
                headers["Connection"] = Utility.PERSISTENCE[(int)persist];
                if (ConnectionPersistence.CLOSE == persist)
                {                       // Close the connection after send is complete
                    finished = (sender, comp) => { socket.Close(); };
                }
            }
            else if (headers.ContainsKey("Connection"))
            {                   // Figure out what to do with the connection
                String conn = headers["Connection"];
                if (conn.Equals(
                        Utility.PERSISTENCE[(int)ConnectionPersistence.KEEP_ALIVE],
                        StringComparison.OrdinalIgnoreCase))
                {
                    persist = ConnectionPersistence.KEEP_ALIVE;
                }
                else if (
                    conn.Equals(Utility.PERSISTENCE[(int)ConnectionPersistence.CLOSE],
                                StringComparison.OrdinalIgnoreCase))
                {
                    finished = (sender, comp) => { socket.Close(); };
                }
                else if (this.version != HttpVersion.ONE_POINT_ONE)
                {                       // Default to close for pre-1.1
                    finished = (sender, comp) => { socket.Close(); };
                }
            }
            // If that falls through, there's no Connection header
            else if (this.version != HttpVersion.ONE_POINT_ONE)
            {                   // Default to close for pre-1.1
                finished = (sender, comp) => { socket.Close(); };
            }
            byte[] resp = buildResponse();
            SocketAsyncEventArgs args = new SocketAsyncEventArgs();

            args.SetBuffer(resp, 0, resp.Length);
            args.Completed       += finished;
            socket.SendBufferSize = resp.Length;
            if (!socket.SendAsync(args))
            {
                finished(null, null);
            }
        }
Пример #2
0
 /// <summary>
 /// Allows creating an empty HttpRequest object.
 /// Caller must then use Continue to populate the request data.
 /// </summary>
 public HttpRequest()
 {
     method           = HttpMethod.INVALID_METHOD;
     path             = null;
     querystring      = null;
     fragment         = null;
     version          = HttpVersion.INVALID_VERSION;
     urlparams        = null;
     contentlength    = -1L;
     persist          = ConnectionPersistence.UNSPECIFIED;
     headers          = null;
     multipartboundry = null;
     body             = null;
     bodytext         = null;
     bodyparts        = null;
     current          = 0;
     currentLine      = 0;
     bodyIndex        = -1;
 }
Пример #3
0
 private String parseRequest(String request, bool resume)
 {
     String[] lines = request.Split(new String[] { "\r\n", "\n" }, StringSplitOptions.None);
     #region FIRSTLINE
     if (!resume || 0 == currentLine)
     {
         parseFirstLine(lines[0]);
     }               // if (!resume || 0 == currentLine)
     #endregion      // firstline
     // Parse the headers
     if (lines.Length > 2)
     {
         headers = new Dictionary <String, String>(lines.Length - 2);                // Max header count
     }
     else
     {
         headers = new Dictionary <string, string>();
     }
     if (!resume)
     {
         contentlength = -1;
     }
     for (currentLine = (resume) ? currentLine : 1;
          currentLine < lines.Length;
          currentLine++)
     {
         #region ENDREQUEST
         if (String.IsNullOrEmpty(lines[currentLine]))
         {
             // Two carriage returns in a row signals the end of the headers
             int endIndex = request.IndexOf("\r\n\r\n") + 4;
             if (3 == endIndex)
             {
                 endIndex = request.IndexOf("\n\n") + 2;
             }
             if (contentlength > 0)
             {
                 // There is some body to this request
                 int bodyLen = Math.Min((int)contentlength, (request.Length - endIndex));
                 body     = Encoding.UTF8.GetBytes(request.Substring(endIndex, bodyLen));
                 bodytext = request.Substring(endIndex);
                 // Check whether we're done...
                 if (bodyLen < contentlength)
                 {
                     // We need more body
                 }
                 else
                 {
                     #region MULTIPART
                     // End of the headers. If multipart, parse the parts
                     if (multipartboundry != null)
                     {
                         int firstpart = bodytext.IndexOf("--" + multipartboundry);
                         // Find the end of the line
                         firstpart = bodytext.IndexOf('\n', firstpart) + 1;
                         if (-1 == firstpart)
                         {
                             throw new ProtocolViolationException("Incomplete multipart boundary line: " + lines[currentLine + 1]);
                         }
                         String line = bodytext.Substring(firstpart, (bodytext.IndexOf('\n', firstpart) - firstpart)).Trim();
                         while (!String.IsNullOrWhiteSpace(line))
                         {
                             int    partIndex = line.IndexOf(':');
                             String partHeaderName, partHeaderValue;
                             if (partIndex > 0)
                             {
                                 partHeaderName  = line.Substring(0, partIndex).Trim();
                                 partHeaderValue = line.Substring(partIndex + 1).Trim();
                             }
                             else
                             {
                                 partHeaderName  = line;
                                 partHeaderValue = null;
                             }
                         }
                     }
                     #endregion
                     // Note that we're done with this request, return any remnant
                     current     = -1;
                     currentLine = -1;
                     request     = request.Substring(endIndex + (int)contentlength);
                 }
             }
             else
             {
                 // There is no body to this request; we're done
                 current     = -1;
                 currentLine = -1;
                 request     = request.Substring(endIndex);
             }
             // Either way, we're done parsing
             return(request);
         }
         #endregion
         #region HEADERS
         // OK, this should be a header
         int    valueIndex = lines[currentLine].IndexOf(':');
         String headerName, headerValue;
         if (valueIndex > 0)
         {
             headerName  = lines[currentLine].Substring(0, valueIndex).Trim();
             headerValue = lines[currentLine].Substring(valueIndex + 1).Trim();
         }
         else
         {
             headerName  = lines[currentLine];
             headerValue = null;
         }
         if (headerName.Equals("Content-Length", StringComparison.OrdinalIgnoreCase))
         {
             if (!long.TryParse(headerValue, out contentlength) && (currentLine + 1) < lines.Length)
             {
                 // This was supposed to be a complete line. It is broken
                 throw new ProtocolViolationException(
                           "Invalid value for HTTP header (" + lines[currentLine] + ")");
             }
             // Move on to the next header
             continue;
         }
         else if (headerName.Equals("Content-Type", StringComparison.OrdinalIgnoreCase))
         {
             // For now, just look for multipart
             if (headerValue.StartsWith("multipart"))
             {
                 int offset = headerValue.IndexOf("boundary=");
                 if (offset > 0)
                 {
                     multipartboundry = headerValue.Substring(offset + 9);
                 }
                 else
                 {
                     // There is supposed to be a boundary definition here...
                     throw new ProtocolViolationException(
                               "Invalid value for HTTP header (" + lines[currentLine] + ")");
                 }
             }
         }
         else if (headerName.Equals("Connection", StringComparison.OrdinalIgnoreCase))
         {
             for (int i = 0; i < Utility.PERSISTENCE.Length; i++)
             {
                 if (headerValue.Equals(Utility.PERSISTENCE[i], StringComparison.OrdinalIgnoreCase))
                 {
                     persist = (ConnectionPersistence)i;
                     break;
                 }
             }
         }
         // May be some other header that we don't yet recognize
         headers[headerName] = headerValue;
         #endregion
     }
     // If we get here, we didn't find the end of the request...
     return(request);
 }