Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -26,10 +26,11 @@ #import "OFDate.h" #import "OFDictionary.h" #import "OFURL.h" #import "OFHTTPRequest.h" #import "OFTCPSocket.h" +#import "OFTimer.h" #import "OFAlreadyConnectedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFNotImplementedException.h" @@ -40,11 +41,10 @@ #import "macros.h" #define BUFFER_SIZE 1024 /* - * FIXME: Currently, connections never time out, which means a DoS is possible. * TODO: Add support for chunked transfer encoding. * FIXME: Key normalization replaces headers like "DNT" with "Dnt". * FIXME: Errors are not reported to the user. */ @@ -168,10 +168,11 @@ @interface OFHTTPServer_Connection: OFObject { OFTCPSocket *sock; OFHTTPServer *server; + OFTimer *timer; enum { AWAITING_PROLOG, PARSING_HEADERS, SEND_REPLY } state; @@ -203,21 +204,36 @@ - initWithSocket: (OFTCPSocket*)sock_ server: (OFHTTPServer*)server_ { self = [super init]; - sock = [sock_ retain]; - server = [server_ retain]; - state = AWAITING_PROLOG; + @try { + sock = [sock_ retain]; + server = [server_ retain]; + timer = [[OFTimer + scheduledTimerWithTimeInterval: 10 + target: sock + selector: @selector( + cancelAsyncRequests) + repeats: NO] retain]; + state = AWAITING_PROLOG; + } @catch (id e) { + [self release]; + @throw e; + } return self; } - (void)dealloc { [sock release]; [server release]; + + [timer invalidate]; + [timer release]; + [host release]; [path release]; [headers release]; [POSTData release]; @@ -338,10 +354,12 @@ length: BUFFER_SIZE target: self selector: @selector(socket: didReadIntoBuffer: length:exception:)]; + [timer setFireDate: + [OFDate dateWithTimeIntervalSinceNow: 5]]; return NO; } return YES; @@ -413,10 +431,12 @@ } return NO; } + [timer setFireDate: [OFDate dateWithTimeIntervalSinceNow: 5]]; + return YES; } - (BOOL)sendErrorAndClose: (short)statusCode { @@ -441,10 +461,14 @@ OFHTTPRequestResult *reply; OFDictionary *replyHeaders; OFDataArray *replyData; OFEnumerator *keyEnumerator, *valueEnumerator; OFString *key, *value; + + [timer invalidate]; + [timer release]; + timer = nil; if (host == nil || port == 0) { if (HTTPMinorVersion > 0) { [self sendErrorAndClose: 400]; return; @@ -614,10 +638,11 @@ return NO; connection = [[[OFHTTPServer_Connection alloc] initWithSocket: clientSocket server: self] autorelease]; + [clientSocket asyncReadLineWithTarget: connection selector: @selector(socket:didReadLine: exception:)]; return YES;