From b51d68a419374289c3dc9aa60fed999d9f51a21d Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Sat, 6 Aug 2016 19:45:58 -0700 Subject: [PATCH] replace ServiceCom with objc class --- ZeroTier One.xcodeproj/project.pbxproj | 4 - ZeroTier One/AppDelegate.swift | 4 +- ZeroTier One/JoinNetworkViewController.swift | 2 +- ZeroTier One/NetworkInfoCell.swift | 4 +- ZeroTier One/NetworkMonitor.swift | 4 +- ZeroTier One/ServiceCom.h | 28 ++ ZeroTier One/ServiceCom.m | 286 +++++++++++++++++++ ZeroTier One/ServiceCom.swift | 222 -------------- ZeroTier One/ZeroTier One-Bridging-Header.h | 3 +- 9 files changed, 323 insertions(+), 234 deletions(-) create mode 100644 ZeroTier One/ServiceCom.h create mode 100644 ZeroTier One/ServiceCom.m delete mode 100644 ZeroTier One/ServiceCom.swift diff --git a/ZeroTier One.xcodeproj/project.pbxproj b/ZeroTier One.xcodeproj/project.pbxproj index 8f5a8e1a2..a5993315b 100644 --- a/ZeroTier One.xcodeproj/project.pbxproj +++ b/ZeroTier One.xcodeproj/project.pbxproj @@ -14,7 +14,6 @@ 932D47361D1CDC9B004BCFE2 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 932D47341D1CDC9B004BCFE2 /* AboutViewController.swift */; }; 932D47371D1CDC9B004BCFE2 /* AboutViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */; }; 932D473A1D220D63004BCFE2 /* LaunchAtLoginController.m in Sources */ = {isa = PBXBuildFile; fileRef = 932D47391D220D63004BCFE2 /* LaunchAtLoginController.m */; }; - 9330F1351CEAB4C400687EC8 /* ServiceCom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9330F1341CEAB4C400687EC8 /* ServiceCom.swift */; }; 9330F13B1CF534E500687EC8 /* NetworkInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9330F13A1CF534E500687EC8 /* NetworkInfoCell.swift */; }; 93326BDC1CE7C816005CA2AC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93326BDB1CE7C816005CA2AC /* AppDelegate.swift */; }; 93326BDE1CE7C816005CA2AC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 93326BDD1CE7C816005CA2AC /* Assets.xcassets */; }; @@ -39,7 +38,6 @@ 932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AboutViewController.xib; sourceTree = ""; }; 932D47381D220D63004BCFE2 /* LaunchAtLoginController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LaunchAtLoginController.h; sourceTree = ""; }; 932D47391D220D63004BCFE2 /* LaunchAtLoginController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LaunchAtLoginController.m; sourceTree = ""; }; - 9330F1341CEAB4C400687EC8 /* ServiceCom.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceCom.swift; sourceTree = ""; }; 9330F13A1CF534E500687EC8 /* NetworkInfoCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkInfoCell.swift; sourceTree = ""; }; 93326BD81CE7C816005CA2AC /* ZeroTier One.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ZeroTier One.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 93326BDB1CE7C816005CA2AC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -97,7 +95,6 @@ 93326BE81CE7D9B9005CA2AC /* JoinNetworkViewController.swift */, 9330F13A1CF534E500687EC8 /* NetworkInfoCell.swift */, 93326BEC1CE7DA30005CA2AC /* ShowNetworksViewController.swift */, - 9330F1341CEAB4C400687EC8 /* ServiceCom.swift */, 93326BDD1CE7C816005CA2AC /* Assets.xcassets */, 93326BDF1CE7C816005CA2AC /* MainMenu.xib */, 93326BE21CE7C816005CA2AC /* Info.plist */, @@ -212,7 +209,6 @@ 93D1675F1D54191C00330C99 /* NodeStatus.m in Sources */, 932D47361D1CDC9B004BCFE2 /* AboutViewController.swift in Sources */, 93D167661D54308200330C99 /* Network.m in Sources */, - 9330F1351CEAB4C400687EC8 /* ServiceCom.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ZeroTier One/AppDelegate.swift b/ZeroTier One/AppDelegate.swift index 0bcea7415..7fb42c824 100644 --- a/ZeroTier One/AppDelegate.swift +++ b/ZeroTier One/AppDelegate.swift @@ -244,10 +244,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { let id = String(network.nwid, radix: 16) if network.connected { - ServiceCom.sharedInstance.leaveNetwork(id) + ServiceCom.sharedInstance().leaveNetwork(id) } else { - ServiceCom.sharedInstance.joinNetwork(id) + ServiceCom.sharedInstance().joinNetwork(id, allowManaged: true, allowGlobal: false, allowDefault: false) } } diff --git a/ZeroTier One/JoinNetworkViewController.swift b/ZeroTier One/JoinNetworkViewController.swift index 446e87199..0effda595 100644 --- a/ZeroTier One/JoinNetworkViewController.swift +++ b/ZeroTier One/JoinNetworkViewController.swift @@ -69,7 +69,7 @@ class JoinNetworkViewController: NSViewController, NSComboBoxDelegate, NSComboBo @IBAction func onJoinClicked(sender: AnyObject?) { let networkString = network.stringValue - ServiceCom.sharedInstance.joinNetwork(networkString, + ServiceCom.sharedInstance().joinNetwork(networkString, allowManaged: allowManagedCheckBox.state == NSOnState, allowGlobal: allowGlobalCheckBox.state == NSOnState, allowDefault: allowDefaultCheckBox.state == NSOnState) diff --git a/ZeroTier One/NetworkInfoCell.swift b/ZeroTier One/NetworkInfoCell.swift index d04996a64..8c9c54595 100644 --- a/ZeroTier One/NetworkInfoCell.swift +++ b/ZeroTier One/NetworkInfoCell.swift @@ -56,14 +56,14 @@ class NetworkInfoCell: NSTableCellView { } func joinNetwork(nwid: String) { - ServiceCom.sharedInstance.joinNetwork(nwid, + ServiceCom.sharedInstance().joinNetwork(nwid, allowManaged: allowManaged.state == NSOnState, allowGlobal: allowGlobal.state == NSOnState, allowDefault: !Network.defaultRouteExists(parent.networkList) && (allowDefault.state == NSOnState)) } func leaveNetwork(nwid: String) { - ServiceCom.sharedInstance.leaveNetwork(nwid) + ServiceCom.sharedInstance().leaveNetwork(nwid) } @IBAction func onAllowStatusChanged(sender: NSButton) { diff --git a/ZeroTier One/NetworkMonitor.swift b/ZeroTier One/NetworkMonitor.swift index e96d7aac0..fda45ea4b 100644 --- a/ZeroTier One/NetworkMonitor.swift +++ b/ZeroTier One/NetworkMonitor.swift @@ -63,7 +63,7 @@ class NetworkMonitor: NSObject { } } - ServiceCom.sharedInstance.getNetworkList() { (networkList) -> Void in + ServiceCom.sharedInstance().getNetworklist() { (networkList) -> Void in self.receivedNetworks = networkList NSOperationQueue.mainQueue().addOperationWithBlock() { () -> Void in @@ -71,7 +71,7 @@ class NetworkMonitor: NSObject { } } - ServiceCom.sharedInstance.getNodeStatus() { nodeStatus -> Void in + ServiceCom.sharedInstance().getNodeStatus() { nodeStatus -> Void in NSOperationQueue.mainQueue().addOperationWithBlock() { () -> Void in let nc = NSNotificationCenter.defaultCenter() diff --git a/ZeroTier One/ServiceCom.h b/ZeroTier One/ServiceCom.h new file mode 100644 index 000000000..a06650019 --- /dev/null +++ b/ZeroTier One/ServiceCom.h @@ -0,0 +1,28 @@ +// +// ServiceCom.h +// ZeroTier One +// +// Created by Grant Limberg on 8/4/16. +// Copyright © 2016 ZeroTier, Inc. All rights reserved. +// + +#import + +@class NodeStatus; +@class Network; + +@interface ServiceCom : NSObject +{ + NSString *baseURL; + NSURLSession *session; +} ++ (ServiceCom*)sharedInstance; + +- (id)init; + +- (void)getNetworklist:(void (^)(NSArray*))completionHandler; +- (void)getNodeStatus:(void (^)(NodeStatus*))completionHandler; +- (void)joinNetwork:(NSString*)networkId allowManaged:(BOOL)allowManaged allowGlobal:(BOOL)allowGlobal allowDefault:(BOOL)allowDefault; +- (void)leaveNetwork:(NSString*)networkId; + +@end diff --git a/ZeroTier One/ServiceCom.m b/ZeroTier One/ServiceCom.m new file mode 100644 index 000000000..4e23d496d --- /dev/null +++ b/ZeroTier One/ServiceCom.m @@ -0,0 +1,286 @@ +// +// ServiceCom.m +// ZeroTier One +// +// Created by Grant Limberg on 8/4/16. +// Copyright © 2016 ZeroTier, Inc. All rights reserved. +// + +#import "ServiceCom.h" +#import "AuthtokenCopy.h" +#import "Network.h" +#import "NodeStatus.h" + +@interface ServiceCom (Private) + +- (NSString*)key; + +@end + +@implementation ServiceCom + ++ (ServiceCom*)sharedInstance { + static ServiceCom *sc = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sc = [[ServiceCom alloc] init]; + }); + return sc; +} + +- (id)init +{ + self = [super init]; + if(self) { + baseURL = @"http://localhost:9993"; + session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]]; + } + + return self; +} + +- (NSString*)key +{ + static NSString *k = nil; + + if (k == nil) { + NSError *error = nil; + NSURL *appSupportDir = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:false error:&error]; + + if (error) { + NSLog(@"Error: %@", error); + return @""; + } + + appSupportDir = [[appSupportDir URLByAppendingPathComponent:@"ZeroTier"] URLByAppendingPathComponent:@"One"]; + NSURL *authtokenURL = [appSupportDir URLByAppendingPathComponent:@"authtoken.secret"]; + + if ([[NSFileManager defaultManager] fileExistsAtPath:[authtokenURL path]]) { + k = [NSString stringWithContentsOfURL:authtokenURL + encoding:NSUTF8StringEncoding + error:&error]; + + if (error) { + NSLog(@"Error: %@", error); + k = nil; + return @""; + } + } + else { + [[NSFileManager defaultManager] createDirectoryAtURL:appSupportDir + withIntermediateDirectories:YES + attributes:nil + error:&error]; + + if (error) { + NSLog(@"Error: %@", error); + k = nil; + return @""; + } + + AuthorizationRef authRef; + OSStatus status = AuthorizationCreate(nil, nil, kAuthorizationFlagDefaults, &authRef); + + if (status != errAuthorizationSuccess) { + NSLog(@"Authorization Failed! %d", status); + return @""; + } + + AuthorizationItem authItem; + authItem.name = kAuthorizationRightExecute; + authItem.valueLength = 0; + authItem.flags = 0; + + AuthorizationRights authRights; + authRights.count = 1; + authRights.items = &authItem; + + AuthorizationFlags authFlags = kAuthorizationFlagDefaults | + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagPreAuthorize | + kAuthorizationFlagExtendRights; + + status = AuthorizationCopyRights(authRef, &authRights, nil, authFlags, nil); + + if (status != errAuthorizationSuccess) { + NSLog(@"Authorization Failed! %d", status); + return @""; + } + + NSString *localKey = getAdminAuthToken(authRef); + AuthorizationFree(authRef, kAuthorizationFlagDestroyRights); + + if (localKey != nil && [localKey lengthOfBytesUsingEncoding:NSUTF8StringEncoding] > 0) { + k = localKey; + + [localKey writeToURL:authtokenURL + atomically:YES + encoding:NSUTF8StringEncoding + error:&error]; + + if (error) { + NSLog(@"Error writing token to disk: %@", error); + } + } + } + } + + if (k == nil) { + return @""; + } + + return k; +} + +- (void)getNetworklist:(void (^)(NSArray*))completionHandler +{ + NSString *urlString = [[baseURL stringByAppendingString:@"/network?auth="] stringByAppendingString:[self key]]; + + NSURL *url = [NSURL URLWithString:urlString]; + NSURLSessionDataTask *task = + [session dataTaskWithURL:url + completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + + if (error) { + NSLog(@"Error: %@", error); + return; + } + + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; + NSInteger status = [httpResponse statusCode]; + + NSError *err; + + if (status == 200) { + NSArray *json = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&err]; + if (err) { + NSLog(@"Error fetching network list: %@", err); + return; + } + + NSMutableArray *networks = [[NSMutableArray alloc] init]; + for(NSDictionary *dict in json) { + [networks addObject:[[Network alloc] initWithJsonData:dict]]; + } + + completionHandler(networks); + } + }]; + [task resume]; +} + +- (void)getNodeStatus:(void (^)(NodeStatus*))completionHandler +{ + NSString *urlString = [[baseURL stringByAppendingString:@"/status?auth="] stringByAppendingString:[self key]]; + + NSURL *url = [NSURL URLWithString:urlString]; + NSURLSessionDataTask *task = + [session dataTaskWithURL:url + completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + + if(error) { + NSLog(@"Error: %@", error); + return; + } + + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; + NSInteger status = [httpResponse statusCode]; + + NSError *err; + if(status == 200) { + NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&err]; + + if(err) { + NSLog(@"Error fetching node status: %@", err); + return; + } + + NodeStatus *status = [[NodeStatus alloc] initWithJsonData:json]; + + completionHandler(status); + } + }]; + [task resume]; +} + +- (void)joinNetwork:(NSString*)networkId allowManaged:(BOOL)allowManaged allowGlobal:(BOOL)allowGlobal allowDefault:(BOOL)allowDefault +{ + + NSString *urlString = [[[[baseURL stringByAppendingString:@"/network/"] stringByAppendingString:networkId] stringByAppendingString:@"?auth="] stringByAppendingString:[self key]]; + + NSURL *url = [NSURL URLWithString:urlString]; + + NSMutableDictionary *jsonDict = [NSMutableDictionary dictionary]; + [jsonDict setObject:[NSNumber numberWithBool:allowManaged] forKey:@"allowManaged"]; + [jsonDict setObject:[NSNumber numberWithBool:allowGlobal] forKey:@"allowGlobal"]; + [jsonDict setObject:[NSNumber numberWithBool:allowDefault] forKey:@"allowDefault"]; + + NSError *err = nil; + + NSData *json = [NSJSONSerialization dataWithJSONObject:jsonDict + options:0 + error:&err]; + + if(err) { + NSLog(@"Error creating json data: %@", err); + return; + } + + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + request.HTTPMethod = @"POST"; + request.HTTPBody = json; + [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + + NSURLSessionDataTask *task = + [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + if(error) { + NSLog(@"Error posting join request: %@", error); + } + + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; + NSInteger status = [httpResponse statusCode]; + + if(status == 200) { + NSLog(@"join ok"); + } + else { + NSLog(@"join error: %ld", (long)status); + } + }]; + [task resume]; +} + +- (void)leaveNetwork:(NSString*)networkId +{ + NSString *urlString = [[[[baseURL stringByAppendingString:@"/network/"] stringByAppendingString:networkId] stringByAppendingString:@"?auth="] stringByAppendingString:[self key]]; + + NSURL *url = [NSURL URLWithString:urlString]; + + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + request.HTTPMethod = @"DELETE"; + + NSURLSessionDataTask *task = + [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + if(error) { + NSLog(@"Error posting delete request: %@", error); + return; + } + + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; + NSInteger status = httpResponse.statusCode; + + if(status == 200) { + NSLog(@"leave ok"); + } + else { + NSLog(@"leave error: %ld", status); + } + }]; + [task resume]; +} + +@end diff --git a/ZeroTier One/ServiceCom.swift b/ZeroTier One/ServiceCom.swift deleted file mode 100644 index af5fb07a9..000000000 --- a/ZeroTier One/ServiceCom.swift +++ /dev/null @@ -1,222 +0,0 @@ -// -// ServiceCom.swift -// ZeroTier One -// -// Created by Grant Limberg on 5/16/16. -// Copyright © 2016 ZeroTier, Inc. All rights reserved. -// - -import Cocoa - -class ServiceCom: NSObject { - static let sharedInstance = ServiceCom() - - let baseURL = "http://localhost:9993" - let session = NSURLSession(configuration: NSURLSessionConfiguration.ephemeralSessionConfiguration()) - - private override init() { - super.init() - } - - - private func getKey() -> String { - struct Holder { - static var key: String? = nil - } - - if Holder.key == nil { - do { - // Check the user's ZeroTier application support directory. If - // authtoken.secret exists, use it. - - var appSupportDir = try NSFileManager.defaultManager().URLForDirectory(.ApplicationSupportDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false) - appSupportDir = appSupportDir.URLByAppendingPathComponent("ZeroTier") - appSupportDir = appSupportDir.URLByAppendingPathComponent("One") - let authtokenURL = appSupportDir.URLByAppendingPathComponent("authtoken.secret") - - if NSFileManager.defaultManager().fileExistsAtPath(authtokenURL.path!) { - Holder.key = try String(contentsOfURL: authtokenURL) - } - else { - try NSFileManager.defaultManager().createDirectoryAtURL(appSupportDir, withIntermediateDirectories: true, attributes: nil) - - var authRef: AuthorizationRef = nil - var status = AuthorizationCreate(nil, nil, .Defaults, &authRef) - - if status != errAuthorizationSuccess { - NSLog("Authorization Failed! \(status)") - return "" - } - - var authItem = AuthorizationItem(name: kAuthorizationRightExecute, valueLength: 0, value: nil, flags: 0) - var authRights = AuthorizationRights(count: 1, items: &authItem) - let authFlags: AuthorizationFlags = [.Defaults, .InteractionAllowed, .PreAuthorize, .ExtendRights] - - status = AuthorizationCopyRights(authRef, &authRights, nil, authFlags, nil) - - if status != errAuthorizationSuccess { - NSLog("Authorization Failed! \(status)") - return "" - } - - let localKey = getAdminAuthToken(authRef) - AuthorizationFree(authRef, .DestroyRights) - - if localKey != nil && localKey.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) > 0 { - NSLog("\(localKey)") - Holder.key = localKey - - try localKey.writeToURL(authtokenURL, atomically: true, encoding: NSUTF8StringEncoding) - } - } - } - catch { - NSLog("Error getting app support dir: \(error)") - Holder.key = nil - } - - } - - if let k = Holder.key { - return k - } - else { - return "" - } - } - - func getNetworkList(completionHandler: ([Network]) -> Void) { - - let urlString = baseURL + "/network?auth=\(getKey())" - - let url = NSURL(string: urlString) - - if let u = url { - let task = session.dataTaskWithURL(u) { (data, response, error) in - if error != nil{ - NSLog("\(error)") - return - } - - let httpResponse = response as! NSHTTPURLResponse - let status = httpResponse.statusCode - - if status == 200 { - do { - let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions()) as! [[String: AnyObject]] - - var networks = [Network]() - for jobj in json { - networks.append(Network(jsonData: jobj)) - } - - completionHandler(networks) - } - catch { - } - } - } - - task.resume() - } - else { - print("bad URL") - } - } - - func getNodeStatus(completionHandler: (NodeStatus -> Void)) { - let urlString = baseURL + "/status?auth=\(getKey())" - - if let u = NSURL(string: urlString) { - let task = session.dataTaskWithURL(u) { (data, response, error) in - if error != nil{ - NSLog("\(error)") - return - } - - let httpResponse = response as! NSHTTPURLResponse - let status = httpResponse.statusCode - - if status == 200 { - do { - let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions()) as! [String: AnyObject] - - let status = NodeStatus(jsonData: json) - - completionHandler(status) - } - catch { - } - } - } - - task.resume() - } - else { - NSLog("bad URL") - } - } - - func joinNetwork(network: String, allowManaged: Bool = true, allowGlobal: Bool = false, allowDefault: Bool = false) { - let urlString = baseURL + "/network/\(network)?auth=\(getKey())" - let url = NSURL(string: urlString) - - var jsonDict = [String: AnyObject]() - jsonDict["allowManaged"] = NSNumber(bool: allowManaged) - jsonDict["allowGlobal"] = NSNumber(bool: allowGlobal) - jsonDict["allowDefault"] = NSNumber(bool: allowDefault) - - do { - let json = try NSJSONSerialization.dataWithJSONObject(jsonDict, options: NSJSONWritingOptions()) - - if let u = url { - let request = NSMutableURLRequest(URL: u) - request.HTTPMethod = "POST" - request.HTTPBody = json - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - - let task = session.dataTaskWithRequest(request) { (data, response, error) in - let httpResponse = response as! NSHTTPURLResponse - let status = httpResponse.statusCode - - if status == 200 { - NSLog("join ok") - } - else { - NSLog("join error: \(status)") - } - } - - task.resume() - } - } - catch { - NSLog("\(error)") - } - - } - - func leaveNetwork(network: String) { - let urlString = baseURL + "/network/\(network)?auth=\(getKey())" - - if let u = NSURL(string: urlString) { - let request = NSMutableURLRequest(URL: u) - request.HTTPMethod = "DELETE" - - let task = session.dataTaskWithRequest(request) { (data, response, error) in - let httpResponse = response as! NSHTTPURLResponse - let status = httpResponse.statusCode - - if status == 200 { - NSLog("leave ok") - } - else { - NSLog("leave error: \(status)") - } - } - - task.resume() - } - } - -} diff --git a/ZeroTier One/ZeroTier One-Bridging-Header.h b/ZeroTier One/ZeroTier One-Bridging-Header.h index 01023713a..78d5264d5 100644 --- a/ZeroTier One/ZeroTier One-Bridging-Header.h +++ b/ZeroTier One/ZeroTier One-Bridging-Header.h @@ -5,4 +5,5 @@ #import "AuthtokenCopy.h" #import "LaunchAtLoginController.h" #import "NodeStatus.h" -#import "Network.h" \ No newline at end of file +#import "Network.h" +#import "ServiceCom.h" \ No newline at end of file