浏览代码

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.
Christian Kienle 12 年之前
父节点
当前提交
9e042c9cb6
共有 1 个文件被更改,包括 13 次插入4 次删除
  1. 13 4
      CGDWebServer/GCDWebServer.m

+ 13 - 4
CGDWebServer/GCDWebServer.m

@@ -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);