diff --git a/Limelight/Network/DiscoveryManager.m b/Limelight/Network/DiscoveryManager.m index 0652034..cec4fac 100644 --- a/Limelight/Network/DiscoveryManager.m +++ b/Limelight/Network/DiscoveryManager.m @@ -158,21 +158,19 @@ [_hostQueue removeObject:host]; } -// Override from MDNSCallback +// Override from MDNSCallback - called in a worker thread - (void)updateHost:(TemporaryHost*)host { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - // Discover the hosts before adding to eliminate duplicates - Log(LOG_D, @"Found host through MDNS: %@:", host.name); - // Since this is on a background thread, we do not need to use the opQueue - DiscoveryWorker* worker = (DiscoveryWorker*)[self createWorkerForHost:host]; - [worker discoverHost]; - if ([self addHostToDiscovery:host]) { - Log(LOG_I, @"Found new host through MDNS: %@:", host.name); - [self->_callback updateAllHosts:self->_hostQueue]; - } else { - Log(LOG_D, @"Found existing host through MDNS: %@", host.name); - } - }); + // Discover the hosts before adding to eliminate duplicates + Log(LOG_D, @"Found host through MDNS: %@:", host.name); + // Since this is on a background thread, we do not need to use the opQueue + DiscoveryWorker* worker = (DiscoveryWorker*)[self createWorkerForHost:host]; + [worker discoverHost]; + if ([self addHostToDiscovery:host]) { + Log(LOG_I, @"Found new host through MDNS: %@:", host.name); + [self->_callback updateAllHosts:self->_hostQueue]; + } else { + Log(LOG_D, @"Found existing host through MDNS: %@", host.name); + } } - (TemporaryHost*) getHostInDiscovery:(NSString*)uuidString { diff --git a/Limelight/Network/MDNSManager.m b/Limelight/Network/MDNSManager.m index a855e4b..e71a71e 100644 --- a/Limelight/Network/MDNSManager.m +++ b/Limelight/Network/MDNSManager.m @@ -9,6 +9,10 @@ #import "MDNSManager.h" #import "TemporaryHost.h" +#include + +#include + @implementation MDNSManager { NSNetServiceBrowser* mDNSBrowser; NSMutableArray* services; @@ -60,11 +64,25 @@ static NSString* NV_SERVICE_TYPE = @"_nvstream._tcp"; } - (void)netServiceDidResolveAddress:(NSNetService *)service { - Log(LOG_D, @"Resolved address: %@ -> %@", service, service.hostName); - TemporaryHost* host = [[TemporaryHost alloc] init]; - host.activeAddress = host.localAddress = service.hostName; - host.name = service.hostName; - [self.callback updateHost:host]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + Log(LOG_D, @"Resolved address: %@ -> %@", service, service.hostName); + TemporaryHost* host = [[TemporaryHost alloc] init]; + + // Since we discovered this host over mDNS, we know we're on the same network + // as the PC and we can use our current WAN address as a likely candidate + // for our PC's external address. + struct in_addr wanAddr; + int err = LiFindExternalAddressIP4("stun.stunprotocol.org", 3478, &wanAddr.s_addr); + if (err == 0) { + char addrStr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &wanAddr, addrStr, sizeof(addrStr)); + host.externalAddress = [NSString stringWithFormat: @"%s", addrStr]; + } + + host.activeAddress = host.localAddress = service.hostName; + host.name = service.hostName; + [self.callback updateHost:host]; + }); } - (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict { diff --git a/Limelight/Network/ServerInfoResponse.m b/Limelight/Network/ServerInfoResponse.m index 65f44d4..9f0ac83 100644 --- a/Limelight/Network/ServerInfoResponse.m +++ b/Limelight/Network/ServerInfoResponse.m @@ -19,12 +19,18 @@ - (void) populateHost:(TemporaryHost*)host { host.name = [[self getStringTag:TAG_HOSTNAME] trim]; - host.externalAddress = [[self getStringTag:TAG_EXTERNAL_IP] trim]; host.localAddress = [[self getStringTag:TAG_LOCAL_IP] trim]; host.uuid = [[self getStringTag:TAG_UNIQUE_ID] trim]; host.mac = [[self getStringTag:TAG_MAC_ADDRESS] trim]; host.currentGame = [[self getStringTag:TAG_CURRENT_GAME] trim]; + // Modern GFE versions don't actually give us a WAN address anymore + // so we leave the one that we populated from mDNS discovery via STUN. + NSString *wanAddr = [[self getStringTag:TAG_EXTERNAL_IP] trim]; + if (wanAddr) { + host.externalAddress = wanAddr; + } + NSString *state = [[self getStringTag:TAG_STATE] trim]; if (![state hasSuffix:@"_SERVER_BUSY"]) { // GFE 2.8 started keeping currentgame set to the last game played. As a result, it no longer diff --git a/moonlight-common/moonlight-common-c b/moonlight-common/moonlight-common-c index 558ba48..0eed722 160000 --- a/moonlight-common/moonlight-common-c +++ b/moonlight-common/moonlight-common-c @@ -1 +1 @@ -Subproject commit 558ba488e8eb7a614b6d9a93968c7c69683f942d +Subproject commit 0eed722635f411ebfef662501e35733f6fb24e0c diff --git a/moonlight-common/moonlight-common.xcodeproj/project.pbxproj b/moonlight-common/moonlight-common.xcodeproj/project.pbxproj index 27117d2..f6ae69d 100644 --- a/moonlight-common/moonlight-common.xcodeproj/project.pbxproj +++ b/moonlight-common/moonlight-common.xcodeproj/project.pbxproj @@ -34,6 +34,8 @@ 98AB2E561CAD427A0089BB98 /* protocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E151CAD422B0089BB98 /* protocol.c */; }; 98AB2E571CAD427A0089BB98 /* unix.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E171CAD422B0089BB98 /* unix.c */; }; 98AB2E581CAD427A0089BB98 /* win32.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E181CAD422B0089BB98 /* win32.c */; }; + 98C1FC13218404040023FDDF /* SimpleStun.c in Sources */ = {isa = PBXBuildFile; fileRef = 98C1FC11218404030023FDDF /* SimpleStun.c */; }; + 98C1FC142184124C0023FDDF /* SimpleStun.c in Sources */ = {isa = PBXBuildFile; fileRef = 98C1FC11218404030023FDDF /* SimpleStun.c */; }; FB1A67F821324F4900507771 /* rs.c in Sources */ = {isa = PBXBuildFile; fileRef = 9857AEEE1EBE85E10084F99E /* rs.c */; }; FB1A67F921324F4900507771 /* RtpFecQueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 9857AEE91EBE85A20084F99E /* RtpFecQueue.c */; }; FB1A67FA21324F4900507771 /* AudioStream.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E1A1CAD423B0089BB98 /* AudioStream.c */; }; @@ -144,6 +146,7 @@ 98AB2E3C1CAD423B0089BB98 /* Video.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = ""; }; 98AB2E3D1CAD423B0089BB98 /* VideoDepacketizer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = VideoDepacketizer.c; sourceTree = ""; }; 98AB2E3E1CAD423B0089BB98 /* VideoStream.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = VideoStream.c; sourceTree = ""; }; + 98C1FC11218404030023FDDF /* SimpleStun.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SimpleStun.c; sourceTree = ""; }; FB1A67EF21324EE300507771 /* libmoonlight-common-tv.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libmoonlight-common-tv.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FB290E2E19B37A4E004C83CF /* libmoonlight-common.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libmoonlight-common.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -281,6 +284,7 @@ 98AB2E391CAD423B0089BB98 /* RtspConnection.c */, 98AB2E3A1CAD423B0089BB98 /* RtspParser.c */, 98AB2E3B1CAD423B0089BB98 /* SdpGenerator.c */, + 98C1FC11218404030023FDDF /* SimpleStun.c */, 98AB2E3C1CAD423B0089BB98 /* Video.h */, 98AB2E3D1CAD423B0089BB98 /* VideoDepacketizer.c */, 98AB2E3E1CAD423B0089BB98 /* VideoStream.c */, @@ -403,6 +407,7 @@ FB1A680A21324F4900507771 /* callbacks.c in Sources */, FB1A680B21324F4900507771 /* compress.c in Sources */, FB1A680C21324F4900507771 /* host.c in Sources */, + 98C1FC13218404040023FDDF /* SimpleStun.c in Sources */, FB1A680D21324F4900507771 /* list.c in Sources */, FB1A680E21324F4900507771 /* packet.c in Sources */, FB1A680F21324F4900507771 /* peer.c in Sources */, @@ -416,6 +421,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 98C1FC142184124C0023FDDF /* SimpleStun.c in Sources */, 98AB2E401CAD425A0089BB98 /* AudioStream.c in Sources */, 98AB2E411CAD425A0089BB98 /* ByteBuffer.c in Sources */, 98AB2E421CAD425A0089BB98 /* Connection.c in Sources */,