From abf66198719fa08de5009dc79e684c2c47827522 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 5 Jan 2016 12:39:53 +0100 Subject: [PATCH] Basic iOS version (only the watch command) --- README.md | 20 +++++---- package.json | 3 +- plugin.xml | 17 ++++++- src/android/ZeroConf.java | 7 +-- src/ios/CDVZeroConf.mm | 95 +++++++++++++++++++++++++++++++++++++++ www/ZeroConf.js | 4 +- 6 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 src/ios/CDVZeroConf.mm diff --git a/README.md b/README.md index 42e9cb4..595b917 100644 --- a/README.md +++ b/README.md @@ -15,15 +15,17 @@ cordova plugin add cordova-zeroconf-plugin or, for older versions: ```bash -cordova plugin add https://github.com/vstirbu/ZeroConf@1.1.1 +cordova plugin add https://github.com/vstirbu/ZeroConf@1.3.0 ``` ## Using the plugin ## There are six static methods on the ZeroConf object, as follows: -### `watch(type, callback)` -Note that `type` is a fully-qualified service type, including the domain, e.g. `"_http._tcp.local."` +### `watch(service, domain, callback)` +Note that `service` is a fully-qualified service type, e.g. `"_http._tcp."` + +As `domain` consider using `local.` (dot at the end!) `callback` is a function that is called when services are added and removed. The function is passed an object with the following structure: @@ -32,13 +34,13 @@ an object with the following structure: { "service": { "port": 50930, - "protocol": "tcp", - "application": "http", - "urls": ["http://192.168.2.2:50930", "http://fe80::7256:81ff:fe00:99e3:50930"], - "description": "\\00", - "name": "Black iPod", + "protocol": "tcp", #android only + "application": "http", #android only + "urls": ["http://192.168.2.2:50930", "http://fe80::7256:81ff:fe00:99e3:50930"], ##android only + "description": "\\00", ##android only + "name": "Black iPod", "domain": "local", - "server": "", + "server": "", ##android only "addresses": ["192.168.2.2", "fe80::7256:81ff:fe00:99e3"], "type": "_http._tcp.local.", "qualifiedname": "Black iPod._http._tcp.local." diff --git a/package.json b/package.json index fa0bcf3..60be526 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "cordova": { "id": "cordova-zeroconf-plugin", "platforms": [ + "ios", "android" ] }, @@ -22,7 +23,7 @@ "version": ">=3.0.0" } ], - "author": "Vlad Stirbu", + "author": "Vlad Stirbu, Jonas Schnelli", "license": "MIT", "bugs": { "url": "https://github.com/vstirbu/ZeroConf/issues" diff --git a/plugin.xml b/plugin.xml index 9ea4b06..42e5812 100644 --- a/plugin.xml +++ b/plugin.xml @@ -2,14 +2,14 @@ + version="1.3.0"> ZeroConf ZeroConf plugin for Cordova/Phonegap - Vlad Stirbu + Vlad Stirbu, Jonas Schnelli zeroconf MIT @@ -17,6 +17,19 @@ + + + + + + + + + + + + + diff --git a/src/android/ZeroConf.java b/src/android/ZeroConf.java index af7e920..698afdd 100644 --- a/src/android/ZeroConf.java +++ b/src/android/ZeroConf.java @@ -66,11 +66,12 @@ public boolean execute(String action, JSONArray args, this.callback = callbackContext; if (action.equals("watch")) { - final String type = args.optString(0); - if (type != null) { + final String service = args.optString(0); + final String domain = args.optString(1); + if (service != null) { cordova.getThreadPool().execute(new Runnable() { public void run() { - watch(type); // Thread-safe. + watch(service+domain); // Thread-safe. } }); } else { diff --git a/src/ios/CDVZeroConf.mm b/src/ios/CDVZeroConf.mm new file mode 100644 index 0000000..0206832 --- /dev/null +++ b/src/ios/CDVZeroConf.mm @@ -0,0 +1,95 @@ +/** + * ZeroConf plugin for Cordova/Phonegap + * + * Copyright (c) 2016 Jonas Schnelli + * MIT License + * + * @author Jonas Schnelli + * Available under the terms of the MIT License. + * + * TODO currently, only the watch command is supported. + * TODO the iOS implementation should support the same + * TODO features as the android version. + * + */ + +#import +#import +#import + +#import +#import + +@interface CDVZeroConf : CDVPlugin { + NSNetServiceBrowser* _netServiceBrowser; +} +@property NSNetServiceBrowser* netServiceBrowser; +@property NSString* watchCommandCallbackId; +@property (nonatomic, strong) NSMutableArray *services; +- (void)watch:(CDVInvokedUrlCommand*)command; +@end + +@implementation CDVZeroConf + ++ (NSString *) stringFromAddress: (const struct sockaddr *) address +{ + if (address && address->sa_family == AF_INET) + { + const struct sockaddr_in* sin = (struct sockaddr_in *) address; + return [NSString stringWithFormat:@"%@", [NSString stringWithUTF8String:inet_ntoa(sin->sin_addr)]]; + } + + return nil; +} + +- (void)watch:(CDVInvokedUrlCommand*)command +{ + self.services = [[NSMutableArray alloc] init]; + [self.netServiceBrowser stop]; + self.netServiceBrowser = [[NSNetServiceBrowser alloc] init]; + self.netServiceBrowser.delegate = self; + [self.netServiceBrowser searchForServicesOfType:command.arguments[0] inDomain:command.arguments[1]]; + + //store the callback id + self.watchCommandCallbackId = command.callbackId; +} + +- (void)netServiceBrowser:(NSNetServiceBrowser*)netServiceBrowser didFindService:(NSNetService*)service moreComing:(BOOL)moreComing { + + if (!self.services) { + self.services = [[NSMutableArray alloc] init]; + } + [self.services addObject:service]; + [service setDelegate:self]; + [service resolveWithTimeout:5.0]; +} + +// Sent when addresses are resolved +- (void)netServiceDidResolveAddress:(NSNetService *)service +{ + NSMutableArray *addrs = [NSMutableArray array]; + NSLog(@"%@, %@, %@, %ld", service.name, service.domain, service.addresses, service.port); + for (NSData *data in service.addresses) + { + struct sockaddr *adr = (struct sockaddr*)data.bytes; + NSString *ipStr = [CDVZeroConf stringFromAddress:adr]; + if (ipStr) + [addrs addObject:ipStr]; + } + NSDictionary *serviceJson = @{ + @"domain" : service.domain, + @"name" : service.name, + @"type" : service.type, + @"port" : [NSNumber numberWithInteger:service.port], + @"addresses" : addrs}; + NSDictionary *jsonObj = @{@"action" : @"Added", @"service" : serviceJson}; + + CDVPluginResult *pluginResult = [ CDVPluginResult + resultWithStatus : CDVCommandStatus_OK + messageAsDictionary : jsonObj + ]; + + [self.commandDelegate sendPluginResult:pluginResult callbackId:self.watchCommandCallbackId]; +} + +@end diff --git a/www/ZeroConf.js b/www/ZeroConf.js index f46e2ac..eff968a 100644 --- a/www/ZeroConf.js +++ b/www/ZeroConf.js @@ -16,13 +16,13 @@ var exec = require('cordova/exec'); var ZeroConf = { - watch: function (type, callback) { + watch: function (service, domain, callback) { return exec(function (result) { if (callback) { callback(result); } - }, ZeroConf.fail, "ZeroConf", "watch", [type]); + }, ZeroConf.fail, "ZeroConf", "watch", [service, domain]); }, unwatch: function (type) { return exec(null, ZeroConf.fail, "ZeroConf", "unwatch", [type]);