Skip to content

Commit

Permalink
Ensure Simulator publishes mDNS records (flutter#6696)
Browse files Browse the repository at this point in the history
* Ensure Simulator publishes mDNS records on loopback interface.
  • Loading branch information
dnfield authored Oct 31, 2018
1 parent d9c2b21 commit d8672ba
Showing 1 changed file with 68 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@

#define FML_USED_ON_EMBEDDER

#import <TargetConditionals.h>

// NSNetService works fine on physical devices, but doesn't expose the services to regular mDNS
// queries on the Simulator. We can work around this by using the lower level C API, but that's
// only available from iOS 9.3+/macOS 10.11.4+.
#if TARGET_IPHONE_SIMULATOR
#include <dns_sd.h> // nogncheck
#include <net/if.h> // nogncheck
#endif // TARGET_IPHONE_SIMLUATOR

#import "FlutterObservatoryPublisher.h"

#include "flutter/fml/logging.h"
Expand All @@ -26,7 +36,11 @@ @interface FlutterObservatoryPublisher () <NSNetServiceDelegate>
@end

@implementation FlutterObservatoryPublisher {
#if TARGET_IPHONE_SIMULATOR
DNSServiceRef _dnsServiceRef;
#else // TARGET_IPHONE_SIMULATOR
fml::scoped_nsobject<NSNetService> _netService;
#endif // TARGET_IPHONE_SIMULATOR

blink::DartServiceIsolate::CallbackHandle _callbackHandle;
std::unique_ptr<fml::WeakPtrFactory<FlutterObservatoryPublisher>> _weakFactory;
Expand Down Expand Up @@ -54,50 +68,91 @@ - (instancetype)init {
}

- (void)dealloc {
#if TARGET_IPHONE_SIMULATOR
if (_dnsServiceRef) {
DNSServiceRefDeallocate(_dnsServiceRef);
_dnsServiceRef = NULL;
}
#else // TARGET_IPHONE_SIMULATOR
[_netService.get() stop];
#endif // TARGET_IPHONE_SIMULATOR

blink::DartServiceIsolate::RemoveServerStatusCallback(std::move(_callbackHandle));
[super dealloc];
}

- (void)publishServiceProtocolPort:(std::string)uri {
#if TARGET_IPHONE_SIMULATOR
if (_dnsServiceRef) {
DNSServiceRefDeallocate(_dnsServiceRef);
_dnsServiceRef = NULL;
}
#else // TARGET_IPHONE_SIMULATOR
[_netService.get() stop];
#endif // TARGET_IPHONE_SIMULATOR
if (uri.empty()) {
[_netService.get() stop];
return;
}
// uri comes in as something like 'http://127.0.0.1:XXXXX/' where XXXXX is the port
// number.
NSURL* url =
[[[NSURL alloc] initWithString:[NSString stringWithUTF8String:uri.c_str()]] autorelease];

// DNS name has to be a max of 63 bytes. Prefer to cut off the app name rather than
// the device hostName. e.g. 'io.flutter.example@someones-iphone', or
// 'ongAppNameBecauseThisCouldHappenAtSomePoint@somelongname-iphone'
NSString* serviceName = [NSString
stringWithFormat:@"%@@%@",
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"],
[NSProcessInfo processInfo].hostName];
if ([serviceName length] > 63) {
serviceName = [serviceName substringFromIndex:[serviceName length] - 63];
}
NSString* serviceName =
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];

#if TARGET_IPHONE_SIMULATOR
DNSServiceFlags flags = kDNSServiceFlagsDefault;
uint32_t interfaceIndex = if_nametoindex("lo0");
const char* registrationType = "_dartobservatory._tcp";
const char* domain = "local."; // default domain
uint16_t port = [[url port] intValue];

int err = DNSServiceRegister(&_dnsServiceRef, flags, interfaceIndex, [serviceName UTF8String],
registrationType, domain, NULL, htons(port), 0, NULL,
registrationCallback, NULL);

if (err != 0) {
FML_LOG(ERROR) << "Failed to register observatory port with mDNS.";
} else {
DNSServiceProcessResult(_dnsServiceRef);
}
#else // TARGET_IPHONE_SIMULATOR
_netService.reset([[NSNetService alloc] initWithDomain:@"local."
type:@"_dartobservatory._tcp."
name:serviceName
port:[[url port] intValue]]);

[_netService.get() setDelegate:self];
[_netService.get() publish];
#endif // TARGET_IPHONE_SIMULATOR
}

- (void)netServiceDidPublish:(NSNetService*)sender {
FML_DLOG(INFO) << "FlutterObservatoryPublisher is ready!";
FML_LOG(INFO) << "FlutterObservatoryPublisher is ready!";
}

- (void)netService:(NSNetService*)sender didNotPublish:(NSDictionary*)errorDict {
FML_LOG(ERROR) << "Could not register as server for FlutterObservatoryPublisher. Check your "
"network settings and relaunch the application.";
}

#if TARGET_IPHONE_SIMULATOR
static void DNSSD_API registrationCallback(DNSServiceRef sdRef,
DNSServiceFlags flags,
DNSServiceErrorType errorCode,
const char* name,
const char* regType,
const char* domain,
void* context) {
if (errorCode == kDNSServiceErr_NoError) {
FML_LOG(ERROR) << "FlutterObservatoryPublisher is ready!";
} else {
FML_LOG(ERROR) << "Could not register as server for FlutterObservatoryPublisher. Check your "
"network settings and relaunch the application.";
}
}
#endif // TARGET_IPHONE_SIMULATOR

#endif // FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE && FLUTTER_RUNTIME_MODE !=
// FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE

Expand Down

0 comments on commit d8672ba

Please sign in to comment.