#46 Added "error" argument to -startWithOptions:

This commit is contained in:
Pierre-Olivier Latour
2014-04-27 19:19:55 -07:00
parent dd3f539f74
commit d404112a88
6 changed files with 39 additions and 34 deletions

View File

@ -288,9 +288,9 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
* Starts the server with explicit options. This method is the designated way * Starts the server with explicit options. This method is the designated way
* to start the server. * to start the server.
* *
* Returns NO if the server failed to start. * Returns NO if the server failed to start and sets "error" argument if not NULL.
*/ */
- (BOOL)startWithOptions:(NSDictionary*)options; - (BOOL)startWithOptions:(NSDictionary*)options error:(NSError**)error;
/** /**
* Stops the server and prevents it to accepts new HTTP requests. * Stops the server and prevents it to accepts new HTTP requests.
@ -355,11 +355,11 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
* is received i.e. Ctrl-C. This method is intended to be used by command line * is received i.e. Ctrl-C. This method is intended to be used by command line
* tools. * tools.
* *
* Returns NO if the server failed to start. * Returns NO if the server failed to start and sets "error" argument if not NULL.
* *
* @warning This method must be used from the main thread only. * @warning This method must be used from the main thread only.
*/ */
- (BOOL)runWithOptions:(NSDictionary*)options; - (BOOL)runWithOptions:(NSDictionary*)options error:(NSError**)error;
#endif #endif

View File

@ -367,7 +367,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
return ARC_AUTORELEASE([[NSString alloc] initWithData:[data base64EncodedDataWithOptions:0] encoding:NSASCIIStringEncoding]); return ARC_AUTORELEASE([[NSString alloc] initWithData:[data base64EncodedDataWithOptions:0] encoding:NSASCIIStringEncoding]);
} }
- (BOOL)_start { - (BOOL)_start:(NSError**)error {
DCHECK(_source == NULL); DCHECK(_source == NULL);
NSUInteger port = [_GetOption(_options, GCDWebServerOption_Port, @0) unsignedIntegerValue]; NSUInteger port = [_GetOption(_options, GCDWebServerOption_Port, @0) unsignedIntegerValue];
NSString* name = _GetOption(_options, GCDWebServerOption_BonjourName, @""); NSString* name = _GetOption(_options, GCDWebServerOption_BonjourName, @"");
@ -473,8 +473,8 @@ static inline NSString* _EncodeBase64(NSString* string) {
CFNetServiceClientContext context = {0, (ARC_BRIDGE void*)self, NULL, NULL, NULL}; CFNetServiceClientContext context = {0, (ARC_BRIDGE void*)self, NULL, NULL, NULL};
CFNetServiceSetClient(_service, _NetServiceClientCallBack, &context); CFNetServiceSetClient(_service, _NetServiceClientCallBack, &context);
CFNetServiceScheduleWithRunLoop(_service, CFRunLoopGetMain(), kCFRunLoopCommonModes); CFNetServiceScheduleWithRunLoop(_service, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFStreamError error = {0}; CFStreamError streamError = {0};
CFNetServiceRegisterWithOptions(_service, 0, &error); CFNetServiceRegisterWithOptions(_service, 0, &streamError);
} else { } else {
LOG_ERROR(@"Failed creating CFNetService"); LOG_ERROR(@"Failed creating CFNetService");
} }
@ -488,15 +488,24 @@ static inline NSString* _EncodeBase64(NSString* string) {
}); });
} }
} else { } else {
LOG_ERROR(@"Failed listening on socket: %s (%i)", strerror(errno), errno); LOG_ERROR(@"Failed starting listening socket: %s (%i)", strerror(errno), errno);
if (error) {
*error = GCDWebServerMakePosixError(errno);
}
close(listeningSocket); close(listeningSocket);
} }
} else { } else {
LOG_ERROR(@"Failed binding socket: %s (%i)", strerror(errno), errno); LOG_ERROR(@"Failed binding listening socket: %s (%i)", strerror(errno), errno);
if (error) {
*error = GCDWebServerMakePosixError(errno);
}
close(listeningSocket); close(listeningSocket);
} }
} else { } else {
LOG_ERROR(@"Failed creating socket: %s (%i)", strerror(errno), errno); LOG_ERROR(@"Failed creating listening socket: %s (%i)", strerror(errno), errno);
if (error) {
*error = GCDWebServerMakePosixError(errno);
}
} }
return (_source ? YES : NO); return (_source ? YES : NO);
} }
@ -548,20 +557,20 @@ static inline NSString* _EncodeBase64(NSString* string) {
DCHECK([NSThread isMainThread]); DCHECK([NSThread isMainThread]);
LOG_DEBUG(@"Will enter foreground"); LOG_DEBUG(@"Will enter foreground");
if (!_source) { if (!_source) {
[self _start]; // TODO: There's probably nothing we can do on failure [self _start:NULL]; // TODO: There's probably nothing we can do on failure
} }
} }
#endif #endif
- (BOOL)startWithOptions:(NSDictionary*)options { - (BOOL)startWithOptions:(NSDictionary*)options error:(NSError**)error {
if (_options == nil) { if (_options == nil) {
_options = [options copy]; _options = [options copy];
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
_suspendInBackground = [_GetOption(_options, GCDWebServerOption_AutomaticallySuspendInBackground, @YES) boolValue]; _suspendInBackground = [_GetOption(_options, GCDWebServerOption_AutomaticallySuspendInBackground, @YES) boolValue];
if (((_suspendInBackground == NO) || ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground)) && ![self _start]) if (((_suspendInBackground == NO) || ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground)) && ![self _start:error])
#else #else
if (![self _start]) if (![self _start:error])
#endif #endif
{ {
ARC_RELEASE(_options); ARC_RELEASE(_options);
@ -643,7 +652,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
NSMutableDictionary* options = [NSMutableDictionary dictionary]; NSMutableDictionary* options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithInteger:port] forKey:GCDWebServerOption_Port]; [options setObject:[NSNumber numberWithInteger:port] forKey:GCDWebServerOption_Port];
[options setValue:name forKey:GCDWebServerOption_BonjourName]; [options setValue:name forKey:GCDWebServerOption_BonjourName];
return [self startWithOptions:options]; return [self startWithOptions:options error:NULL];
} }
#if !TARGET_OS_IPHONE #if !TARGET_OS_IPHONE
@ -652,16 +661,16 @@ static inline NSString* _EncodeBase64(NSString* string) {
NSMutableDictionary* options = [NSMutableDictionary dictionary]; NSMutableDictionary* options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithInteger:port] forKey:GCDWebServerOption_Port]; [options setObject:[NSNumber numberWithInteger:port] forKey:GCDWebServerOption_Port];
[options setValue:name forKey:GCDWebServerOption_BonjourName]; [options setValue:name forKey:GCDWebServerOption_BonjourName];
return [self runWithOptions:options]; return [self runWithOptions:options error:NULL];
} }
- (BOOL)runWithOptions:(NSDictionary*)options { - (BOOL)runWithOptions:(NSDictionary*)options error:(NSError**)error {
DCHECK([NSThread isMainThread]); DCHECK([NSThread isMainThread]);
BOOL success = NO; BOOL success = NO;
_run = YES; _run = YES;
void (*handler)(int) = signal(SIGINT, _SignalHandler); void (*handler)(int) = signal(SIGINT, _SignalHandler);
if (handler != SIG_ERR) { if (handler != SIG_ERR) {
if ([self startWithOptions:options]) { if ([self startWithOptions:options error:error]) {
while (_run) { while (_run) {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, true); CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, true);
} }
@ -957,7 +966,7 @@ static void _LogResult(NSString* format, ...) {
- (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)path { - (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)path {
NSArray* ignoredHeaders = @[@"Date", @"Etag"]; // Dates are always different by definition and ETags depend on file system node IDs NSArray* ignoredHeaders = @[@"Date", @"Etag"]; // Dates are always different by definition and ETags depend on file system node IDs
NSInteger result = -1; NSInteger result = -1;
if ([self startWithOptions:options]) { if ([self startWithOptions:options error:NULL]) {
result = 0; result = 0;
NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL]; NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];

View File

@ -114,6 +114,10 @@ static inline BOOL GCDWebServerIsValidByteRange(NSRange range) {
return ((range.location != NSNotFound) || (range.length > 0)); return ((range.location != NSNotFound) || (range.length > 0));
} }
static inline NSError* GCDWebServerMakePosixError(int code) {
return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithUTF8String:strerror(code)]}];
}
extern void GCDWebServerInitializeFunctions(); extern void GCDWebServerInitializeFunctions();
extern NSString* GCDWebServerNormalizeHeaderValue(NSString* value); extern NSString* GCDWebServerNormalizeHeaderValue(NSString* value);
extern NSString* GCDWebServerTruncateHeaderValue(NSString* value); extern NSString* GCDWebServerTruncateHeaderValue(NSString* value);

View File

@ -34,10 +34,6 @@
} }
@end @end
static inline NSError* _MakePosixError(int code) {
return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"%s", strerror(code)]}];
}
@implementation GCDWebServerFileRequest @implementation GCDWebServerFileRequest
@synthesize temporaryPath=_temporaryPath; @synthesize temporaryPath=_temporaryPath;
@ -59,7 +55,7 @@ static inline NSError* _MakePosixError(int code) {
- (BOOL)open:(NSError**)error { - (BOOL)open:(NSError**)error {
_file = open([_temporaryPath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); _file = open([_temporaryPath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (_file <= 0) { if (_file <= 0) {
*error = _MakePosixError(errno); *error = GCDWebServerMakePosixError(errno);
return NO; return NO;
} }
return YES; return YES;
@ -67,7 +63,7 @@ static inline NSError* _MakePosixError(int code) {
- (BOOL)writeData:(NSData*)data error:(NSError**)error { - (BOOL)writeData:(NSData*)data error:(NSError**)error {
if (write(_file, data.bytes, data.length) != (ssize_t)data.length) { if (write(_file, data.bytes, data.length) != (ssize_t)data.length) {
*error = _MakePosixError(errno); *error = GCDWebServerMakePosixError(errno);
return NO; return NO;
} }
return YES; return YES;
@ -75,7 +71,7 @@ static inline NSError* _MakePosixError(int code) {
- (BOOL)close:(NSError**)error { - (BOOL)close:(NSError**)error {
if (close(_file) < 0) { if (close(_file) < 0) {
*error = _MakePosixError(errno); *error = GCDWebServerMakePosixError(errno);
return NO; return NO;
} }
#ifdef __GCDWEBSERVER_ENABLE_TESTING__ #ifdef __GCDWEBSERVER_ENABLE_TESTING__

View File

@ -40,10 +40,6 @@
} }
@end @end
static inline NSError* _MakePosixError(int code) {
return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"%s", strerror(code)]}];
}
@implementation GCDWebServerFileResponse @implementation GCDWebServerFileResponse
+ (instancetype)responseWithFile:(NSString*)path { + (instancetype)responseWithFile:(NSString*)path {
@ -142,11 +138,11 @@ static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
- (BOOL)open:(NSError**)error { - (BOOL)open:(NSError**)error {
_file = open([_path fileSystemRepresentation], O_NOFOLLOW | O_RDONLY); _file = open([_path fileSystemRepresentation], O_NOFOLLOW | O_RDONLY);
if (_file <= 0) { if (_file <= 0) {
*error = _MakePosixError(errno); *error = GCDWebServerMakePosixError(errno);
return NO; return NO;
} }
if (lseek(_file, _offset, SEEK_SET) != (off_t)_offset) { if (lseek(_file, _offset, SEEK_SET) != (off_t)_offset) {
*error = _MakePosixError(errno); *error = GCDWebServerMakePosixError(errno);
close(_file); close(_file);
return NO; return NO;
} }
@ -158,7 +154,7 @@ static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
NSMutableData* data = [[NSMutableData alloc] initWithLength:length]; NSMutableData* data = [[NSMutableData alloc] initWithLength:length];
ssize_t result = read(_file, data.mutableBytes, length); ssize_t result = read(_file, data.mutableBytes, length);
if (result < 0) { if (result < 0) {
*error = _MakePosixError(errno); *error = GCDWebServerMakePosixError(errno);
return nil; return nil;
} }
if (result > 0) { if (result > 0) {

View File

@ -359,7 +359,7 @@ int main(int argc, const char* argv[]) {
[options setObject:GCDWebServerAuthenticationMethod_DigestAccess forKey:GCDWebServerOption_AuthenticationMethod]; [options setObject:GCDWebServerAuthenticationMethod_DigestAccess forKey:GCDWebServerOption_AuthenticationMethod];
} }
} }
if ([webServer runWithOptions:options]) { if ([webServer runWithOptions:options error:NULL]) {
result = 0; result = 0;
} }
} }