IOS Streaming Browser 1.0
An IOS streaming browser to stream the display to others or to a projector

HTTPConnection Class Reference

#import <HTTPConnection.h>

Collaboration diagram for HTTPConnection:

Public Member Functions

(id) - initWithAsyncSocket:configuration:
(void) - start
(void) - stop
(void) - startConnection
(BOOL) - supportsMethod:atPath:
(BOOL) - expectsRequestBodyFromMethod:atPath:
(BOOL) - isSecureServer
(NSArray *) - sslIdentityAndCertificates
(BOOL) - isPasswordProtected:
(BOOL) - useDigestAccessAuthentication
(NSString *) - realm
(NSString *) - passwordForUser:
(NSDictionary *) - parseParams:
(NSDictionary *) - parseGetParams
(NSString *) - requestURI
(NSArray *) - directoryIndexFileNames
(NSString *) - filePathForURI:
(NSObject< HTTPResponse > *) - httpResponseForMethod:URI:
(WebSocket *) - webSocketForURI:
(void) - prepareForBodyWithSize:
(void) - processDataChunk:
(void) - handleVersionNotSupported:
(void) - handleAuthenticationFailed
(void) - handleResourceNotFound
(void) - handleInvalidRequest:
(void) - handleUnknownMethod:
(NSData *) - preprocessResponse:
(NSData *) - preprocessErrorResponse:
(BOOL) - shouldDie
(void) - die
(void) - responseHasAvailableData:
(void) - responseDidAbort:
(void) - startReadingRequest
(void) - sendResponseHeadersAndBody

Protected Attributes

dispatch_queue_t connectionQueue
GCDAsyncSocketasyncSocket
HTTPConfigconfig
BOOL started
HTTPMessagerequest
unsigned int numHeaderLines
BOOL sentResponseHeaders
NSString * nonce
long lastNC
NSObject< HTTPResponse > * httpResponse
NSMutableArray * ranges
NSMutableArray * ranges_headers
NSString * ranges_boundry
int rangeIndex
UInt64 requestContentLength
UInt64 requestContentLengthReceived
NSMutableArray * responseDataSizes

Detailed Description

Definition at line 66 of file HTTPConnection.h.


Member Function Documentation

- (void) die

Closes the connection

Definition at line 3223 of file HTTPConnection.m.

{
        DDLogError(@"die");
    
        // Override me if you want to perform any custom actions when a connection is closed.
        // Then call [super die] when you're done.
        // 
        // Important: There is a rare timing condition where this method might get invoked twice.
        // If you override this method, you should be prepared for this situation.
        
        // Inform the http response that we're done
        if ([httpResponse respondsToSelector:@selector(connectionDidClose)])
        {
        //This method is called from the HTTPConnection class when the connection is closed, or when the connection is finished with the response.
                [httpResponse connectionDidClose];
        }
        
        // Release the http response so we don't call it's connectionDidClose method again in our dealloc method
        [httpResponse release];
        httpResponse = nil;
        
        // Post notification of dead connection
        // This will allow our server to release us from its array of connections
        [[NSNotificationCenter defaultCenter] postNotificationName:HTTPConnectionDidDieNotification object:self];
}
- (NSArray *) directoryIndexFileNames

Returns an array of possible index pages. For example: {"index.html", "index.htm"}

Returns an array of possible index pages. For example: {"index.html", "index.htm"} returns NSArray

Definition at line 2102 of file HTTPConnection.m.

{
        DDLogError(@"directoryIndexFileNames");
    
        // Override me to support other index pages.
        
        return [NSArray arrayWithObjects:@"index.html", @"index.htm", nil];
}
- (BOOL) expectsRequestBodyFromMethod: (NSString *)  method
atPath: (NSString *)  path 

Returns whether or not the server expects a body from the given method.

In other words, should the server expect a content-length header and associated body from this method. This would be true in the case of a POST, where the client is sending data, or for something like PUT where the client is supposed to be uploading a file.

param NSString param NSString returns BOOL

Definition at line 276 of file HTTPConnection.m.

                                    :(NSString *)method atPath:(NSString *)path
{
    DDLogError(@"expectsRequestBodyFromMethod: method: %@, path: %@",method,path);
        
        // Override me to add support for other methods that expect the client
        // to send a body along with the request header.
        // 
        // You should fall through with a call to [super expectsRequestBodyFromMethod:method atPath:path]
        // 
        // See also: supportsMethod:atPath:
        
    
    // We accept POST methods
        if ([method isEqualToString:@"POST"])
    {
                return YES;
        }
    
    // We accept PUT methods
        if ([method isEqualToString:@"PUT"])
    {
                return YES;
        }
    
    // We don't accept any other methods
        return NO;
}
- (NSString *) filePathForURI: (NSString *)  path

Converts relative URI path into full file-system path. param NSString returns NSString

Definition at line 2116 of file HTTPConnection.m.

                            :(NSString *)path
{
        DDLogError(@"filePathForURI: %@",path);
        // Override me to perform custom path mapping.
        // For example you may want to use a default file other than index.html, or perhaps support multiple types.
        
        NSString *documentRoot = [config documentRoot];
    
        // Part 0: Validate document root setting.
        // 
        // If there is no configured documentRoot,
        // then it makes no sense to try to return anything.
        
        if (documentRoot == nil)
        {
                return nil;
        }
        
        // Part 1: Strip parameters from the url
        // 
        // E.g.: /page.html?q=22&var=abc -> /page.html
        
        NSURL *docRoot = [NSURL fileURLWithPath:documentRoot isDirectory:YES];
    
    // If there is no document root set
        if (docRoot == nil)
        {
                return nil;
        }
        
    // There is a document root
    
    // Get the string representation of the URL for the document root
        NSString *relativePath = [[NSURL URLWithString:path relativeToURL:docRoot] relativePath];
        
        // Part 2: Append relative path to document root (base path)
        // 
        // E.g.: relativePath="/images/icon.png"
        //       documentRoot="/Users/robbie/Sites"
        //           fullPath="/Users/robbie/Sites/images/icon.png"
        // 
        // We also standardize the path.
        // 
        // E.g.: "Users/robbie/Sites/images/../index.html" -> "/Users/robbie/Sites/index.html"
    
    
    
        NSString *fullPath = [[documentRoot stringByAppendingPathComponent:relativePath] stringByStandardizingPath];
        
    
        if ([relativePath isEqualToString:@"/"])
        {
                fullPath = [fullPath stringByAppendingString:@"/"];
        }
        
        // Part 3: Prevent serving files outside the document root.
        // 
        // Sneaky requests may include ".." in the path.
        // 
        // E.g.: relativePath="../Documents/TopSecret.doc"
        //       documentRoot="/Users/robbie/Sites"
        //           fullPath="/Users/robbie/Documents/TopSecret.doc"
        // 
        // E.g.: relativePath="../Sites_Secret/TopSecret.doc"
        //       documentRoot="/Users/robbie/Sites"
        //           fullPath="/Users/robbie/Sites_Secret/TopSecret"
    
    // If the document root does NOT have a forward slash as a suffix
        if (![documentRoot hasSuffix:@"/"])
        {
                documentRoot = [documentRoot stringByAppendingString:@"/"];
        }
        
    
        if (![fullPath hasPrefix:documentRoot])
        {
                return nil;
        }
        
        // Part 4: Search for index page if path is pointing to a directory
        
        BOOL isDir = NO;

        // if the file exists at the path and it is not a directory
        if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDir] && isDir)
        {
        
        // Get an array of possible index pages
                NSArray *indexFileNames = [self directoryIndexFileNames];
                
        
        
        // Loop through the array of possible index pages
                for (NSString *indexFileName in indexFileNames)
                {
            // Appends the file name to the full path
                        NSString *indexFilePath = [fullPath stringByAppendingPathComponent:indexFileName];
                        
            // If the file exists at the path and is a directory
                        if ([[NSFileManager defaultManager] fileExistsAtPath:indexFilePath isDirectory:&isDir] && !isDir)
                        {
                                return indexFilePath;
                        }
                }
                
                // No matching index files found in directory
                return nil;
        }
        else // If file does not exist at the path
        {
                return fullPath;
        }
}
- (void) handleAuthenticationFailed

Called if the authentication information was required and absent, or if authentication failed.

Definition at line 2394 of file HTTPConnection.m.

{
    DDLogError(@"handleAuthenticationFailed");
    
        // Override me for custom handling of authentication challenges
        // If you simply want to add a few extra header fields, see the preprocessErrorResponse: method.
        // You can also use preprocessErrorResponse: to add an optional HTML body.
        
                
        // Status Code 401 - Unauthorized
        HTTPMessage *response = [[HTTPMessage alloc] initResponseWithStatusCode:401 description:nil version:HTTPVersion1_1];
    
    // Set the HTTPMessage "Content-Length" header field to a value of zero
        [response setHeaderField:@"Content-Length" value:@"0"];
        
    
    // Test if using digest authentication
        if ([self useDigestAccessAuthentication])
        {
        // Adds a digest authentication challenge to the http response
                [self addDigestAuthChallenge:response];
        }
        else // if using basic authentication
        {
        // Adds a basic authentication challenge to the http response
                [self addBasicAuthChallenge:response];
        }
        
    // This method is called immediately prior to sending the response headers (for an error).
    // This method adds standard header fields, and then converts the response to an NSData object.
        NSData *responseData = [self preprocessErrorResponse:response];
    
    
    
    // Writes the response to the socket.  Keeps the connection alive so that we can read more request from the host.  We only kill this connection if the user responsds incorrectly
        [asyncSocket writeData:responseData withTimeout:TIMEOUT_WRITE_ERROR tag:HTTP_RESPONSE];
        
    
        [response release];
}
- (void) handleInvalidRequest: (NSData *)  data

Called if we receive some sort of malformed HTTP request. The data parameter is the invalid HTTP header line, including CRLF, as read from GCDAsyncSocket. The data parameter may also be nil if the request as a whole was invalid, such as a POST with no Content-Length.

Definition at line 2440 of file HTTPConnection.m.

                            :(NSData *)data
{
    DDLogError(@"handleInvalidRequest");
        // Override me for custom error handling of invalid HTTP requests
        // If you simply want to add a few extra header fields, see the preprocessErrorResponse: method.
        // You can also use preprocessErrorResponse: to add an optional HTML body.
        
        // Status Code 400 - Bad Request
    
    // Create the response with a status code of 400 for a bad request
        HTTPMessage *response = [[HTTPMessage alloc] initResponseWithStatusCode:400 description:nil version:HTTPVersion1_1];
    
    // Set the content length to zero
        [response setHeaderField:@"Content-Length" value:@"0"];
    
    // Set the header field so the connection is closed
        [response setHeaderField:@"Connection" value:@"close"];
        
    // This method is called immediately prior to sending the response headers (for an error).
    // This method adds standard header fields, and then converts the response to an NSData object.
        NSData *responseData = [self preprocessErrorResponse:response];
    
    // Write the data to the socket with a tag the all data has been completely written to the socket
        [asyncSocket writeData:responseData withTimeout:TIMEOUT_WRITE_ERROR tag:HTTP_FINAL_RESPONSE];
        
        [response release];
        
        // Note: We used the HTTP_FINAL_RESPONSE tag to disconnect after the response is sent.
        // We do this because we couldn't parse the request,
        // so we won't be able to recover and move on to another request afterwards.
        // In other words, we wouldn't know where the first request ends and the second request begins.
}
- (void) handleResourceNotFound

Called if we're unable to find the requested resource.

Definition at line 2518 of file HTTPConnection.m.

{
    DDLogError(@"handleResourceNotFound");
        // Override me for custom error handling of 404 not found responses
        // If you simply want to add a few extra header fields, see the preprocessErrorResponse: method.
        // You can also use preprocessErrorResponse: to add an optional HTML body.
        
        // Status Code 404 - Not Found
    
    // Creates the response
        HTTPMessage *response = [[HTTPMessage alloc] initResponseWithStatusCode:404 description:nil version:HTTPVersion1_1];
    
    // Sets content length to close
        [response setHeaderField:@"Content-Length" value:@"0"];
        
    // Note:  We are not setting the header field to close the connection.  The client just requested a resource which is not found so give them another chance to request the resource
    
    
    // Preprocess the response
        NSData *responseData = [self preprocessErrorResponse:response];
    
    // Write the response to the socket
        [asyncSocket writeData:responseData withTimeout:TIMEOUT_WRITE_ERROR tag:HTTP_RESPONSE];
        
        [response release];
}
- (void) handleUnknownMethod: (NSString *)  method

Called if we receive a HTTP request with a method other than GET or HEAD.

Called if we receive a HTTP request with a method other than GET or HEAD. param NSString

Definition at line 2479 of file HTTPConnection.m.

                           :(NSString *)method
{
    DDLogError(@"handleUnknownMethod");
        // Override me for custom error handling of 405 method not allowed responses.
        // If you simply want to add a few extra header fields, see the preprocessErrorResponse: method.
        // You can also use preprocessErrorResponse: to add an optional HTML body.
        // 
        // See also: supportsMethod:atPath:
        
        // Status code 405 - Method Not Allowed
    
    // Creates the response
        HTTPMessage *response = [[HTTPMessage alloc] initResponseWithStatusCode:405 description:nil version:HTTPVersion1_1];
    
    // Sets the content length to zero
        [response setHeaderField:@"Content-Length" value:@"0"];
    
    // Sets the connection to be closed
        [response setHeaderField:@"Connection" value:@"close"];
        
    
    // Preprocess teh response
        NSData *responseData = [self preprocessErrorResponse:response];
    
    // Write the data to the socket with the tag that all data has been completely written to the socket.  It also terminates the connection because this is the final response
        [asyncSocket writeData:responseData withTimeout:TIMEOUT_WRITE_ERROR tag:HTTP_FINAL_RESPONSE];
    
        [response release];
        
        // Note: We used the HTTP_FINAL_RESPONSE tag to disconnect after the response is sent.
        // We do this because the method may include an http body.
        // Since we can't be sure, we should close the connection.
}
- (void) handleVersionNotSupported: (NSString *)  version

Called if the HTML version is other than what is supported param NSString

Definition at line 2368 of file HTTPConnection.m.

                                 :(NSString *)version
{
    DDLogError(@"handleVersionNotSupported: %@",version);
    
        // Override me for custom error handling of unsupported http version responses
        // If you simply want to add a few extra header fields, see the preprocessErrorResponse: method.
        // You can also use preprocessErrorResponse: to add an optional HTML body.
        
        // Create a response and initialize with because the HTTP version is not supported
        HTTPMessage *response = [[HTTPMessage alloc] initResponseWithStatusCode:505 description:nil version:HTTPVersion1_1];
    
    // Set the content length to zero
        [response setHeaderField:@"Content-Length" value:@"0"];
    
    // The response which will be sent to the host
        NSData *responseData = [self preprocessErrorResponse:response];
    
    // Write the reponse to the socket by creating a writePacket and sending the packet to the socket queue 
        [asyncSocket writeData:responseData withTimeout:TIMEOUT_WRITE_ERROR tag:HTTP_RESPONSE];
        
        [response release];
}
- (NSObject< HTTPResponse > *) httpResponseForMethod: (NSString *)  method
URI: (NSString *)  path 

This method is called to get a response for a request. You may return any object that adopts the HTTPResponse protocol. The HTTPServer comes with two such classes: HTTPFileResponse and HTTPDataResponse. HTTPFileResponse is a wrapper for an NSFileHandle object, and is the preferred way to send a file response. HTTPDataResponse is a wrapper for an NSData object, and may be used to send a custom response.

This method is called to get a response for a request. You may return any object that adopts the HTTPResponse protocol. The HTTPServer comes with two such classes: HTTPFileResponse and HTTPDataResponse. HTTPFileResponse is a wrapper for an NSFileHandle object, and is the preferred way to send a file response. HTTPDataResponse is a wrapper for an NSData object, and may be used to send a custom response. param NSString param NSString returns NSObject <HTTPResponse>

Definition at line 2248 of file HTTPConnection.m.

                                                 :(NSString *)method URI:(NSString *)path
{
        DDLogError(@"httpResponseForMethod: %@ %@",method,path);
        // Override me to provide custom responses.
        
        NSString *filePath = [self filePathForURI:path];
        
        BOOL isDir = NO;
        
    // If the file exists at a path and  is not a directory
        if (filePath && [[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDir] && !isDir)
        {
        
                return [[[HTTPFileResponse alloc] initWithFilePath:filePath forConnection:self] autorelease];
        
                // Use me instead for asynchronous file IO.
                // Generally better for larger files.
                
        //      return [[[HTTPAsyncFileResponse alloc] initWithFilePath:filePath forConnection:self] autorelease];
        
        }else  // If file path is a directory
    {
        if ([path isEqualToString:@"/"]) {
            DDLogError(@"path is a slash");
            DDLogError(@"config documentRoot is: %@",[config documentRoot]);
        }else{
            DDLogError(@"path is not just a slash");
        }
        
        // Create a mutable string to hold the data being sent to the host
        NSMutableString *outdata = [NSMutableString new];
        
        [outdata appendString:@"<html>\n"];
        [outdata appendString:@"<head>\n"];
        [outdata appendString:@"<script language=\"JavaScript\"><!--\n"];
        [outdata appendString:@"function refreshIt() {\n"];
        [outdata appendString:@"if (!document.images) return;\n"];
        [outdata appendString:@"document.images['myImage'].src = '1.png?' + Math.random();\n"];
        [outdata appendString:@"setTimeout('refreshIt()',1000);\n"];
        [outdata appendString:@"}\n"];
        [outdata appendString:@"//--></script>\n"];
        [outdata appendString:@"</head>\n"];
        [outdata appendString:@"<body onLoad=\" setTimeout('refreshIt()',1000)\">\n"];
        [outdata appendString:@"<img src=\"1.png\" name=\"myImage\">\n"];
        [outdata appendString:@"</body>\n"];
        [outdata appendString:@"</html>\n"];

        // Encodes the mutable string 
        NSData *browseData = [outdata dataUsingEncoding:NSUTF8StringEncoding];
        
        // Creates a data response
        return [[[HTTPDataResponse alloc] initWithData:browseData] autorelease];
 
    }
        
        return nil;
}
- (id) initWithAsyncSocket: (GCDAsyncSocket *)  newSocket
configuration: (HTTPConfig *)  aConfig 

Returns HTTPConnection param GCDAsyncSocket param HTTPConfig returns id

Sole Constructor. Associates this new HTTP connection with the given AsyncSocket. This HTTP connection object will become the socket's delegate and take over responsibility for the socket. param GCDAsyncSocket param HTTPConfig returns self

Definition at line 140 of file HTTPConnection.m.

                         :(GCDAsyncSocket *)newSocket configuration:(HTTPConfig *)aConfig
{
    DDLogError(@"initWithAsyncSocket");
    
        if ((self = [super init]))
        {
                // if there is a dispatch queue for requests
                if (aConfig.queue)
                {
            // Get the HTTPConfig dispatch queue
                        connectionQueue = aConfig.queue;
            
            // Increments the reference count on the connection queue
                        dispatch_retain(connectionQueue);
                }
                else  // if there is not a dispatch queue for requests then create one
                {
            // Create the HTTPConnection queue
                        connectionQueue = dispatch_queue_create("HTTPConnection", NULL);
                }
                
                // Take over ownership of the socket
                asyncSocket = [newSocket retain];
        
        // Set the connection queue as the asyncSocket's delegate
                [asyncSocket setDelegate:self delegateQueue:connectionQueue];
                
                // Store configuration
                config = [aConfig retain];
                
                // Initialize lastNC (last nonce count).
                // Used with digest access authentication.
                // These must increment for each request from the client.
                lastNC = 0;
                
                // Create a new HTTP message
                request = [[HTTPMessage alloc] initEmptyRequest];
                
        // Sets the number of header lines to zero
                numHeaderLines = 0;
                
        // Creates a mutable array for the HTTPResponse sizes
                responseDataSizes = [[NSMutableArray alloc] initWithCapacity:5];
        }
        return self;
}
- (BOOL) isPasswordProtected: (NSString *)  path

Returns whether or not the requested resource is password protected. In this generic implementation, nothing is password protected. param NSString returns BOOL

Definition at line 348 of file HTTPConnection.m.

                           :(NSString *)path
{
        
        // Override me to provide password protection...
        // You can configure it for the entire server, or based on the current request
        
        return NO;
}
- (BOOL) isSecureServer

Returns whether or not the server is configured to be a secure server. In other words, all connections to this server are immediately secured, thus only secure connections are allowed. This is the equivalent of having an https server, where it is assumed that all connections must be secure. If this is the case, then unsecure connections will not be allowed on this server, and a separate unsecure server would need to be run on a separate port in order to support unsecure connections.

Note: In order to support secure connections, the sslIdentityAndCertificates method must be implemented.

Definition at line 317 of file HTTPConnection.m.

{
        
        // Override me to create an https server...
        
        return NO;
}
- (NSDictionary *) parseGetParams

Parses the query variables in the request URI.

For example, if the request URI was "/search.html?q=John%20Mayer%20Trio&num=50" then this method would return the following dictionary: { q = "John Mayer Trio" num = "50" }

Definition at line 894 of file HTTPConnection.m.

{
    DDLogError(@"parseGetParams");
    
    // If the request header is not complete
        if(![request isHeaderComplete]) 
    {
        return nil;
        }
    
    // A disctionary for holding the keys and values from the parameters
        NSDictionary *result = nil;
        
    // Gets the request url
        NSURL *url = [request url];
    
    // If there is a url
        if(url)
        {
        // Gets the query for the url
                NSString *query = [url query];
        
        // If there is a query string
                if (query)
                {
            // Parses the given query string
                        result = [self parseParams:query];
                }
        }
        
        return result; 
}
- (NSDictionary *) parseParams: (NSString *)  query

Parses the given query string.

For example, if the query is "q=John%20Mayer%20Trio&num=50" then this method would return the following dictionary: { q = "John Mayer Trio" num = "50" }

Parses the given query string.

For example, if the query is "q=John%20Mayer%20Trio&num=50" then this method would return the following dictionary: { q = "John Mayer Trio" num = "50" } param NSString returns NSDictionary

Definition at line 799 of file HTTPConnection.m.

                             :(NSString *)query
{
    DDLogError(@"parseParams: %@",query);
    
    // Separates the compones which are separated by the '&' symbol
        NSArray *components = [query componentsSeparatedByString:@"&"];

    // Creates a mutable dictionary for the parameters key- value pairs
        NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:[components count]];
        
    
        NSUInteger i;
    
    // Loop through each of the components in the array
        for (i = 0; i < [components count]; i++)
        { 
        
        // Gets the component at a specific index
                NSString *component = [components objectAtIndex:i];
        
        // If the component has length
                if ([component length] > 0)
                {
            // Gets the range (location and length) of the equal sign
                        NSRange range = [component rangeOfString:@"="];
            
            // If there is an equal sign in the range
                        if (range.location != NSNotFound)
                        { 
                // returns substring up to but not including index 
                                NSString *escapedKey = [component substringToIndex:(range.location + 0)]; 
                
                // returns substring up to but not including index (start counting at 0)
                                NSString *escapedValue = [component substringFromIndex:(range.location + 1)];
                                
                // If there is an escape key in the parameters
                                if ([escapedKey length] > 0)
                                {
                                        CFStringRef k;  // The key
                    CFStringRef v;  // The value
                                        
                    // The key
                    // Returns a string with any percent escape sequences that do NOT correspond to characters in charactersToLeaveEscaped with their equivalent. 
                                        k = CFURLCreateStringByReplacingPercentEscapes(NULL, (CFStringRef)escapedKey, CFSTR(""));
                    
                    
                    
                    // The value
                    // Returns a string with any percent escape sequences that do NOT correspond to characters in charactersToLeaveEscaped with their equivalent. 
                                        v = CFURLCreateStringByReplacingPercentEscapes(NULL, (CFStringRef)escapedValue, CFSTR(""));
                                        
                                        NSString *key;
                    NSString *value;
                                        
                    // Makes the key eligible for collection.
                                        key   = [NSMakeCollectable(k) autorelease];
                    
                    // Makes the value eligible for collection.
                                        value = [NSMakeCollectable(v) autorelease];
        
                    
                    // If there is a key
                                        if (key)
                                        {
                        // If there is a value
                                                if (value)
                        {
                            // Adds the value and key to the dictionary
                                                        [result setObject:value forKey:key]; 
                            
                                                }else{
                            
                            // Adds the key to the dictionary with a null value
                                                        [result setObject:[NSNull null] forKey:key];
                            
                        }
                                        }
                                }
                        }
                }
        }
        
        return result;
}
- (NSString *) passwordForUser: (NSString *)  username

Returns the password for the given username. param NSString returns NSString

Definition at line 393 of file HTTPConnection.m.

                             :(NSString *)username
{
        
        // Override me to provide proper password authentication
        // You can configure a password for the entire server, or custom passwords for users and/or resources
        
        // Security Note:
        // A nil password means no access at all. (Such as for user doesn't exist)
        // An empty string password is allowed, and will be treated as any other password. (To support anonymous access)
        
        return nil;
}
- (void) prepareForBodyWithSize: (UInt64)  contentLength

This method is called after receiving all HTTP headers, but before reading any of the request body. param UInt64

Definition at line 2339 of file HTTPConnection.m.

                              :(UInt64)contentLength
{
        // Override me to allocate buffers, file handles, etc.
}
- (NSData *) preprocessErrorResponse: (HTTPMessage *)  response

This method is called immediately prior to sending the response headers (for an error). This method adds standard header fields, and then converts the response to an NSData object.

Definition at line 2647 of file HTTPConnection.m.

                                   :(HTTPMessage *)response;
{
        DDLogError(@"preprocessErrorResponse");
        // Override me to customize the error response headers
        // You'll likely want to add your own custom headers, and then return [super preprocessErrorResponse:response]
        // 
        // Notes:
        // You can use [response statusCode] to get the type of error.
        // You can use [response setBody:data] to add an optional HTML body.
        // If you add a body, don't forget to update the Content-Length.
        // 
        // if ([response statusCode] == 404)
        // {
        //     NSString *msg = @"<html><body>Error 404 - Not Found</body></html>";
        //     NSData *msgData = [msg dataUsingEncoding:NSUTF8StringEncoding];
        //     
        //     [response setBody:msgData];
        //     
        //     NSString *contentLengthStr = [NSString stringWithFormat:@"%lu", (unsigned long)[msgData length]];
        //     [response setHeaderField:@"Content-Length" value:contentLengthStr];
        // }
        
        // Add standard headers
    
    // Gets the current date as a string
        NSString *now = [self dateAsString:[NSDate date]];
    
    // Set the  response header date value
        [response setHeaderField:@"Date" value:now];
        
        // Add server capability headers
        [response setHeaderField:@"Accept-Ranges" value:@"bytes"];
        
        // Add optional response headers
        if ([httpResponse respondsToSelector:@selector(httpHeaders)])
        {
        
        // Dictionary for the response headers
                NSDictionary *responseHeaders = [httpResponse httpHeaders];
                
        // Gets an enumerator object for enumerating the response headers dictionary
                NSEnumerator *keyEnumerator = [responseHeaders keyEnumerator];

                NSString *key;
                
        // Loops through each key in the header
                while((key = [keyEnumerator nextObject]))
                {
            // Gets the value for a specific key
                        NSString *value = [responseHeaders objectForKey:key];
                        
            // Sets the response header field
                        [response setHeaderField:key value:value];
                }
        }
        
        return [response messageData];
}
- (NSData *) preprocessResponse: (HTTPMessage *)  response

This method is called immediately prior to sending the response headers. This method adds standard header fields, and then converts the response to an NSData object. param HTTPMessage returns NSData

This method is called immediately prior to sending the response headers. This method adds standard header fields, and then converts the response to an NSData object.

Definition at line 2600 of file HTTPConnection.m.

                              :(HTTPMessage *)response
{
        DDLogError(@"preprocessResponse");
    
        // Override me to customize the response headers
        // You'll likely want to add your own custom headers, and then return [super preprocessResponse:response]
        
        // Add standard headers
        NSString *now = [self dateAsString:[NSDate date]];
    
    // Sets the date field in the response header
        [response setHeaderField:@"Date" value:now];
        
        // Add server capability headers
        [response setHeaderField:@"Accept-Ranges" value:@"bytes"];
        
        // Add optional response headers
        if ([httpResponse respondsToSelector:@selector(httpHeaders)])
        {
        // Creates a dictionary for the response headers
                NSDictionary *responseHeaders = [httpResponse httpHeaders];
                
        // Enumerates the responseHeaders dictionary
        // Gets an enumerator object that lets you access each key in the dictionary.
                NSEnumerator *keyEnumerator = [responseHeaders keyEnumerator];

        
                NSString *key;
                
        // enumerate through the keys in the response header
                while ((key = [keyEnumerator nextObject]))
                {
            // Gets the value for a certain key in the response headers
                        NSString *value = [responseHeaders objectForKey:key];
                        
            // Sets the response header field
                        [response setHeaderField:key value:value];
                }
        }
        
        return [response messageData];
}
- (void) processDataChunk: (NSData *)  postDataChunk

This method is called to handle data read from a POST / PUT. The given data is part of the request body. param NSData

This method is called to handle data read from a POST / PUT. The given data is part of the request body.

Definition at line 2348 of file HTTPConnection.m.

                        :(NSData *)postDataChunk
{
        // Override me to do something useful with a POST / PUT.
        // If the post is small, such as a simple form, you may want to simply append the data to the request.
        // If the post is big, such as a file upload, you may want to store the file to disk.
        // 
        // Remember: In order to support LARGE POST uploads, the data is read in chunks.
        // This prevents a 50 MB upload from being stored in RAM.
        // The size of the chunks are limited by the POST_CHUNKSIZE definition.
        // Therefore, this method may be called multiple times for the same POST request.
}
- (NSString *) realm

Returns the authentication realm. In this generic implmentation, a default realm is used for the entire server. returns NSString

Definition at line 379 of file HTTPConnection.m.

{
        
        // Override me to provide a custom realm...
        // You can configure it for the entire server, or based on the current request
        
        return @"defaultRealm@host.com";
}
- (NSString *) requestURI

Returns the URL as a string for the HTTPMessage

Gets the URL as a string for the request HTTPMessage returns NSSTring

Definition at line 1182 of file HTTPConnection.m.

{
    DDLogError(@"requestURI");
    
    // If the request HTTPMessage is nil
        if(request == nil) 
    {
        return nil;
        }
    
    // Returns the request message url as a readable string
        return [[request url] relativeString];
}
- (void) responseDidAbort: (NSObject< HTTPResponse > *)  sender

param NSObject with HTTPResponse protocl

- (void) responseHasAvailableData: (NSObject< HTTPResponse > *)  sender

param NSObject with HTTPResponse protocol

- (void) sendResponseHeadersAndBody

Send response headers and body

- (BOOL) shouldDie

Returns whether the HTTPConnection should die returns BOOL

This method is called after each response has been fully sent. Since a single connection may handle multiple request/responses, this method may be called multiple times. That is, it will be called after completion of each response.

Definition at line 3169 of file HTTPConnection.m.

{
        DDLogError(@"shouldDie");
        // Override me if you want to perform any custom actions after a response has been fully sent.
        // You may also force close the connection by returning YES.
        // 
        // If you override this method, you should take care to fall through with [super shouldDie]
        // instead of returning NO.
        
        
        BOOL shouldDie = NO; // flag for whether the connection should die
        
    // Get the http request version
        NSString *version = [request version];
    
    // If the http request version is using 1.1
        if ([version isEqualToString:HTTPVersion1_1])
        {
                // HTTP version 1.1
                // Connection should only be closed if request included "Connection: close" header
                
                NSString *connection = [request headerField:@"Connection"];
                
        // Close the connection
                shouldDie = (connection && ([connection caseInsensitiveCompare:@"close"] == NSOrderedSame));
        }
    // If HTTP version 1.0
        else if ([version isEqualToString:HTTPVersion1_0])
        {
                // HTTP version 1.0
                // Connection should be closed unless request included "Connection: Keep-Alive" header
                
                NSString *connection = [request headerField:@"Connection"];
                
        // If there is not a connection
                if (connection == nil)
        {
            // Flag the connection to die
                        shouldDie = YES;
            
                }else{ // If there is a connection
            
            // Keep the connection alive
                        shouldDie = [connection caseInsensitiveCompare:@"Keep-Alive"] != NSOrderedSame;
        }
        }
        
    // if not HTTP version 1.0 or 1.1
        return shouldDie;
}
- (NSArray *) sslIdentityAndCertificates

This method is expected to returns an array appropriate for use in kCFStreamSSLCertificates SSL Settings. It should be an array of SecCertificateRefs except for the first element in the array, which is a SecIdentityRef.

This method is expected to returns an array appropriate for use in kCFStreamSSLCertificates SSL Settings. It should be an array of SecCertificateRefs except for the first element in the array, which is a SecIdentityRef. returns NSArray

Definition at line 330 of file HTTPConnection.m.

{
        
        // Override me to provide the proper required SSL identity.
        
        return nil;
}
- (void) start

Starting point for the HTTP connection after it has been fully initialized (including subclasses). This method is called by the HTTP server.

Definition at line 676 of file HTTPConnection.m.

{
    DDLogError(@"start");
    
    //  Submits a block for asynchronous execution on the connectionQueue
        dispatch_async(connectionQueue, ^{
        
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
                
        // Check if the connection is already started
                if (started)
        {
            return;
        }
        
        // If not started the set the flag that the connection is started and start the connection
                started = YES;
                
        // Starts the connection
                [self startConnection];
                
                [pool release];
        });  // END OF BLOCK
}
- (void) startConnection

Starting point for the HTTP connection.

Definition at line 726 of file HTTPConnection.m.

{
    DDLogError(@"startConnection");
    
        // Override me to do any custom work before the connection starts.
        // 
        // Be sure to invoke [super startConnection] when you're done.
        
        
        if ([self isSecureServer])
        {
                // We are configured to be an HTTPS server.
                // That is, we secure via SSL/TLS the connection prior to any communication.
                
                NSArray *certificates = [self sslIdentityAndCertificates];
                
        // if there are certificates in the array
                if ([certificates count] > 0)
                {
                        // All connections are assumed to be secure. Only secure connections are allowed on this server.
            // The objects for the dictionary are:
            //      is server
            //      certificates
            //      authentication level
                        NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3];
                        
                        // Configure this connection as the server
                        [settings setObject:[NSNumber numberWithBool:YES]
                                                 forKey:(NSString *)kCFStreamSSLIsServer];
                        
            // Set the SSL certificate
                        [settings setObject:certificates
                                                 forKey:(NSString *)kCFStreamSSLCertificates];
                        
                        // Configure this connection to use the highest possible SSL level
                        [settings setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL
                                                 forKey:(NSString *)kCFStreamSSLLevel];
                        
            // Start transport layer security with specific settings
                        [asyncSocket startTLS:settings];
                }
        }
        
    // Starts reading an HTTP request
        [self startReadingRequest];
}
- (void) startReadingRequest

Start reading the request

- (void) stop

This method is called by the HTTPServer if it is asked to stop. The server, in turn, invokes stop on each HTTPConnection instance.

Definition at line 705 of file HTTPConnection.m.

{
    DDLogError(@"stop");
    
    // Submits a block for asynchronous execution on the connectionQueue
        dispatch_async(connectionQueue, ^{
        
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
                
                // Disconnect the socket.
                // The socketDidDisconnect delegate method will handle everything else.
                [asyncSocket disconnect];
                
                [pool release];
        
        }); // END OF BLOCK
}
- (BOOL) supportsMethod: (NSString *)  method
atPath: (NSString *)  path 

Returns whether or not the server will accept messages of a given method at a particular URI. param NSString param NSString returns BOOL

Returns whether or not the server will accept messages of a given method at a particular URI. param NSString param NSString return BOOL

Definition at line 232 of file HTTPConnection.m.

                      :(NSString *)method 
                atPath:(NSString *)path
{
        DDLogError(@"supportsMethod: method: %@, path: %@",method,path);
    
        // Override me to support methods such as POST.
        // 
        // Things you may want to consider:
        // - Does the given path represent a resource that is designed to accept this method?
        // - If accepting an upload, is the size of the data being uploaded too big?
        //   To do this you can check the requestContentLength variable.
        // 
        // For more information, you can always access the HTTPMessage request variable.
        // 
        // You should fall through with a call to [super supportsMethod:method atPath:path]
        // 
        // See also: expectsRequestBodyFromMethod:atPath:
        
    
    // We with accept GET methods
        if ([method isEqualToString:@"GET"])
    {
                return YES;
        }
    
    // We will accept HEAD methods
        if ([method isEqualToString:@"HEAD"])
    {
                return YES;
        }
        
    // We will not accept any other methods
        return NO;
}
- (BOOL) useDigestAccessAuthentication

Returns whether or not the authentication challenge should use digest access authentication. The alternative is basic authentication.

If at all possible, digest access authentication should be used because it's more secure. Basic authentication sends passwords in the clear and should be avoided unless using SSL/TLS.

Returns whether or not the authentication challenge should use digest access authentication. The alternative is basic authentication.

If at all possible, digest access authentication should be used because it's more secure. Basic authentication sends passwords in the clear and should be avoided unless using SSL/TLS. returns BOOL

Definition at line 365 of file HTTPConnection.m.

{
        
        // Override me to customize the authentication scheme
        // Make sure you understand the security risks of using the weaker basic authentication
        
        return NO;
}
- (WebSocket *) webSocketForURI: (NSString *)  path

param NSString returns WebSocket

Gets the webSocket for a specific URI param NSString return WebSocket

Definition at line 2312 of file HTTPConnection.m.

                              :(NSString *)path
{
        DDLogError(@"webSocketForURI: %@",path);
        // Override me to provide custom WebSocket responses.
        // To do so, simply override the base WebSocket implementation, and add your custom functionality.
        // Then return an instance of your custom WebSocket here.
        // 
        // For example:
        // 
        // if ([path isEqualToString:@"/myAwesomeWebSocketStream"])
        // {
        //     return [[[MyWebSocket alloc] initWithRequest:request socket:asyncSocket] autorelease];
        // }
        // 
        // return [super webSocketForURI:path];
        
        return nil;
}

Field Documentation

- (GCDAsyncSocket*) asyncSocket [protected]

Handles each request one at a time in order

Definition at line 77 of file HTTPConnection.h.

- (HTTPConfig*) config [protected]

HTTP server configuration

Definition at line 82 of file HTTPConnection.h.

- (dispatch_queue_t) connectionQueue [protected]

queue with all the connections

Definition at line 72 of file HTTPConnection.h.

- (NSObject<HTTPResponse>*) httpResponse [protected]

The http response sent to the host

Definition at line 118 of file HTTPConnection.h.

- (long) lastNC [protected]

The last nonce

Definition at line 113 of file HTTPConnection.h.

- (NSString*) nonce [protected]

A nonce is a server-specified string uniquely generated for each 401 response.

Definition at line 108 of file HTTPConnection.h.

- (unsigned int) numHeaderLines [protected]

number of header lines

Definition at line 97 of file HTTPConnection.h.

- (int) rangeIndex [protected]

Definition at line 139 of file HTTPConnection.h.

- (NSMutableArray*) ranges [protected]

Mutable array for the response ranges

Definition at line 123 of file HTTPConnection.h.

- (NSString*) ranges_boundry [protected]

The response ranges boundary

Definition at line 134 of file HTTPConnection.h.

- (NSMutableArray*) ranges_headers [protected]

Mutable array for the response range headers

Definition at line 128 of file HTTPConnection.h.

- (HTTPMessage*) request [protected]

The http request from the host

Definition at line 92 of file HTTPConnection.h.

- (UInt64) requestContentLength [protected]

The length of the http request from the host

Definition at line 144 of file HTTPConnection.h.

- (UInt64) requestContentLengthReceived [protected]

The number of bytes received from the host

Definition at line 149 of file HTTPConnection.h.

- (NSMutableArray*) responseDataSizes [protected]

HTTP response data sizes

Definition at line 154 of file HTTPConnection.h.

- (BOOL) sentResponseHeaders [protected]

Flag for whether sent response headers to the host

Definition at line 102 of file HTTPConnection.h.

- (BOOL) started [protected]

Flag for whether the connection started

Definition at line 87 of file HTTPConnection.h.


The documentation for this class was generated from the following files:
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Properties Defines