Improves the handling of port 0

Usually port 0 means that the OS should pick any free port. After
listen() has been called the picked port can be determined and used
from then on.
This commit is contained in:
Christian Kienle 2013-03-19 18:56:27 +01:00
parent 2264cc9802
commit 9e042c9cb6

View File

@ -186,7 +186,6 @@ static void _SocketCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDat
- (BOOL)startWithRunloop:(NSRunLoop*)runloop port:(NSUInteger)port bonjourName:(NSString*)name {
DCHECK(runloop);
DCHECK(port);
DCHECK(_runLoop == nil);
CFSocketContext context = {0, self, NULL, NULL, NULL};
_socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, _SocketCallBack, &context);
@ -203,10 +202,21 @@ static void _SocketCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDat
if (CFSocketSetAddress(_socket, (CFDataRef)[NSData dataWithBytes:&addr4 length:sizeof(addr4)]) == kCFSocketSuccess) {
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _socket, 0);
CFRunLoopAddSource([runloop getCFRunLoop], source, kCFRunLoopCommonModes);
if (port == 0) {
// determine the actual port we are listening on
CFDataRef addressData = CFSocketCopyAddress(_socket);
NSAssert(addressData, @"Failed to determine address. Aborting...");
struct sockaddr_in* sockaddr = (struct sockaddr_in*)CFDataGetBytePtr(addressData);
_port = ntohs(sockaddr->sin_port);
CFRelease(addressData);
} else {
_port = port;
}
CFRelease(source);
if (name) {
_service = CFNetServiceCreate(kCFAllocatorDefault, CFSTR("local."), CFSTR("_http._tcp"), (CFStringRef)name, port);
_service = CFNetServiceCreate(kCFAllocatorDefault, CFSTR("local."), CFSTR("_http._tcp"), (CFStringRef)name, _port);
if (_service) {
CFNetServiceClientContext context = {0, self, NULL, NULL, NULL};
CFNetServiceSetClient(_service, _NetServiceClientCallBack, &context);
@ -218,9 +228,8 @@ static void _SocketCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDat
}
}
_port = port;
_runLoop = [runloop retain];
LOG_VERBOSE(@"%@ started on port %i", [self class], (int)port);
LOG_VERBOSE(@"%@ started on port %i", [self class], (int)_port);
} else {
LOG_ERROR(@"Failed binding socket");
CFRelease(_socket);