From 7b7ec133496db4fef867d9100285a02cd3f1aed6 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 17 Oct 2016 14:44:32 -0700 Subject: Prepare for merging into main ZeroTier repo --- macui/ZeroTier One.xcodeproj/project.pbxproj | 382 ++++++++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 + macui/ZeroTier One/AboutViewController.h | 33 + macui/ZeroTier One/AboutViewController.m | 56 ++ macui/ZeroTier One/AboutViewController.xib | 31 + macui/ZeroTier One/AppDelegate.h | 61 ++ macui/ZeroTier One/AppDelegate.m | 339 ++++++++++ .../AppIcon.appiconset/Contents.json | 59 ++ .../AppIcon.appiconset/ZeroTierIcon512x512.png | Bin 0 -> 51309 bytes macui/ZeroTier One/Assets.xcassets/Contents.json | 6 + .../MenuBarIconMac.imageset/Contents.json | 21 + .../MenuBarIconMac.imageset/MenuBar@2x.png | Bin 0 -> 22973 bytes .../MenuBarIconMac.imageset/Menubar.png | Bin 0 -> 17234 bytes .../MenuBarIconMacWhite.imageset/Contents.json | 21 + .../MenuBarIconMacWhite.imageset/MenubarWhite.png | Bin 0 -> 17234 bytes .../MenubarWhite@2x.png | Bin 0 -> 22973 bytes macui/ZeroTier One/AuthtokenCopy.h | 26 + macui/ZeroTier One/AuthtokenCopy.m | 97 +++ macui/ZeroTier One/Base.lproj/MainMenu.xib | 680 +++++++++++++++++++++ macui/ZeroTier One/Info.plist | 41 ++ macui/ZeroTier One/JoinNetworkViewController.h | 40 ++ macui/ZeroTier One/JoinNetworkViewController.m | 184 ++++++ macui/ZeroTier One/JoinNetworkViewController.xib | 74 +++ macui/ZeroTier One/Network.h | 62 ++ macui/ZeroTier One/Network.m | 278 +++++++++ macui/ZeroTier One/NetworkInfoCell.h | 50 ++ macui/ZeroTier One/NetworkInfoCell.m | 85 +++ macui/ZeroTier One/NetworkMonitor.h | 45 ++ macui/ZeroTier One/NetworkMonitor.m | 253 ++++++++ macui/ZeroTier One/NodeStatus.h | 35 ++ macui/ZeroTier One/NodeStatus.m | 40 ++ macui/ZeroTier One/PreferencesViewController.h | 31 + macui/ZeroTier One/PreferencesViewController.m | 112 ++++ macui/ZeroTier One/PreferencesViewController.xib | 33 + macui/ZeroTier One/ServiceCom.h | 39 ++ macui/ZeroTier One/ServiceCom.m | 464 ++++++++++++++ macui/ZeroTier One/ShowNetworksViewController.h | 36 ++ macui/ZeroTier One/ShowNetworksViewController.m | 119 ++++ macui/ZeroTier One/ShowNetworksViewController.xib | 370 +++++++++++ macui/ZeroTier One/ZeroTierIcon.icns | Bin 0 -> 125598 bytes macui/ZeroTier One/about.html | 65 ++ macui/ZeroTier One/main.m | 23 + 42 files changed, 4298 insertions(+) create mode 100644 macui/ZeroTier One.xcodeproj/project.pbxproj create mode 100644 macui/ZeroTier One.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 macui/ZeroTier One/AboutViewController.h create mode 100644 macui/ZeroTier One/AboutViewController.m create mode 100644 macui/ZeroTier One/AboutViewController.xib create mode 100644 macui/ZeroTier One/AppDelegate.h create mode 100644 macui/ZeroTier One/AppDelegate.m create mode 100644 macui/ZeroTier One/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 macui/ZeroTier One/Assets.xcassets/AppIcon.appiconset/ZeroTierIcon512x512.png create mode 100644 macui/ZeroTier One/Assets.xcassets/Contents.json create mode 100644 macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/Contents.json create mode 100644 macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/MenuBar@2x.png create mode 100644 macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/Menubar.png create mode 100644 macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/Contents.json create mode 100644 macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/MenubarWhite.png create mode 100644 macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/MenubarWhite@2x.png create mode 100644 macui/ZeroTier One/AuthtokenCopy.h create mode 100644 macui/ZeroTier One/AuthtokenCopy.m create mode 100644 macui/ZeroTier One/Base.lproj/MainMenu.xib create mode 100644 macui/ZeroTier One/Info.plist create mode 100644 macui/ZeroTier One/JoinNetworkViewController.h create mode 100644 macui/ZeroTier One/JoinNetworkViewController.m create mode 100644 macui/ZeroTier One/JoinNetworkViewController.xib create mode 100644 macui/ZeroTier One/Network.h create mode 100644 macui/ZeroTier One/Network.m create mode 100644 macui/ZeroTier One/NetworkInfoCell.h create mode 100644 macui/ZeroTier One/NetworkInfoCell.m create mode 100644 macui/ZeroTier One/NetworkMonitor.h create mode 100644 macui/ZeroTier One/NetworkMonitor.m create mode 100644 macui/ZeroTier One/NodeStatus.h create mode 100644 macui/ZeroTier One/NodeStatus.m create mode 100644 macui/ZeroTier One/PreferencesViewController.h create mode 100644 macui/ZeroTier One/PreferencesViewController.m create mode 100644 macui/ZeroTier One/PreferencesViewController.xib create mode 100644 macui/ZeroTier One/ServiceCom.h create mode 100644 macui/ZeroTier One/ServiceCom.m create mode 100644 macui/ZeroTier One/ShowNetworksViewController.h create mode 100644 macui/ZeroTier One/ShowNetworksViewController.m create mode 100644 macui/ZeroTier One/ShowNetworksViewController.xib create mode 100644 macui/ZeroTier One/ZeroTierIcon.icns create mode 100644 macui/ZeroTier One/about.html create mode 100644 macui/ZeroTier One/main.m (limited to 'macui') diff --git a/macui/ZeroTier One.xcodeproj/project.pbxproj b/macui/ZeroTier One.xcodeproj/project.pbxproj new file mode 100644 index 00000000..900daacb --- /dev/null +++ b/macui/ZeroTier One.xcodeproj/project.pbxproj @@ -0,0 +1,382 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 932D472F1D1CD499004BCFE2 /* ZeroTierIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 932D472E1D1CD499004BCFE2 /* ZeroTierIcon.icns */; }; + 932D47331D1CD861004BCFE2 /* PreferencesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 932D47311D1CD861004BCFE2 /* PreferencesViewController.xib */; }; + 932D47371D1CDC9B004BCFE2 /* AboutViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */; }; + 93326BDE1CE7C816005CA2AC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 93326BDD1CE7C816005CA2AC /* Assets.xcassets */; }; + 93326BE11CE7C816005CA2AC /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 93326BDF1CE7C816005CA2AC /* MainMenu.xib */; }; + 93326BEB1CE7D9B9005CA2AC /* JoinNetworkViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 93326BE91CE7D9B9005CA2AC /* JoinNetworkViewController.xib */; }; + 93326BEF1CE7DA30005CA2AC /* ShowNetworksViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 93326BED1CE7DA30005CA2AC /* ShowNetworksViewController.xib */; }; + 93D1675F1D54191C00330C99 /* NodeStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D1675E1D54191C00330C99 /* NodeStatus.m */; }; + 93D167621D541BC200330C99 /* ServiceCom.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167611D541BC200330C99 /* ServiceCom.m */; }; + 93D167661D54308200330C99 /* Network.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167651D54308200330C99 /* Network.m */; }; + 93D167691D57E7EA00330C99 /* AboutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167681D57E7EA00330C99 /* AboutViewController.m */; }; + 93D1676D1D57EB8400330C99 /* PreferencesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D1676C1D57EB8400330C99 /* PreferencesViewController.m */; }; + 93D167701D57FD3800330C99 /* NetworkMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D1676F1D57FD3800330C99 /* NetworkMonitor.m */; }; + 93D167731D58093C00330C99 /* NetworkInfoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167721D58093C00330C99 /* NetworkInfoCell.m */; }; + 93D167761D580C3500330C99 /* ShowNetworksViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167751D580C3500330C99 /* ShowNetworksViewController.m */; }; + 93D167791D5815E600330C99 /* JoinNetworkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167781D5815E600330C99 /* JoinNetworkViewController.m */; }; + 93D1677C1D58228A00330C99 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D1677B1D58228A00330C99 /* AppDelegate.m */; }; + 93D1679B1D58300F00330C99 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D1679A1D58300F00330C99 /* main.m */; }; + 93D1679D1D595F0000330C99 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D1679C1D595F0000330C99 /* WebKit.framework */; }; + 93DAFB271D3F0BEE004D5417 /* about.html in Resources */ = {isa = PBXBuildFile; fileRef = 93DAFB261D3F0BEE004D5417 /* about.html */; }; + 93DAFE4B1CFE53CA00547CC4 /* AuthtokenCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = 93DAFE4A1CFE53CA00547CC4 /* AuthtokenCopy.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 932D472E1D1CD499004BCFE2 /* ZeroTierIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = ZeroTierIcon.icns; sourceTree = ""; }; + 932D47311D1CD861004BCFE2 /* PreferencesViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PreferencesViewController.xib; sourceTree = ""; }; + 932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AboutViewController.xib; sourceTree = ""; }; + 93326BD81CE7C816005CA2AC /* ZeroTier One.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ZeroTier One.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 93326BDD1CE7C816005CA2AC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 93326BE01CE7C816005CA2AC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 93326BE21CE7C816005CA2AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 93326BE91CE7D9B9005CA2AC /* JoinNetworkViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JoinNetworkViewController.xib; sourceTree = ""; }; + 93326BED1CE7DA30005CA2AC /* ShowNetworksViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ShowNetworksViewController.xib; sourceTree = ""; }; + 93D1675D1D54191C00330C99 /* NodeStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeStatus.h; sourceTree = ""; }; + 93D1675E1D54191C00330C99 /* NodeStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NodeStatus.m; sourceTree = ""; }; + 93D167601D541BC200330C99 /* ServiceCom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceCom.h; sourceTree = ""; }; + 93D167611D541BC200330C99 /* ServiceCom.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ServiceCom.m; sourceTree = ""; }; + 93D167641D54308200330C99 /* Network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Network.h; sourceTree = ""; }; + 93D167651D54308200330C99 /* Network.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Network.m; sourceTree = ""; }; + 93D167671D57E7EA00330C99 /* AboutViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutViewController.h; sourceTree = ""; }; + 93D167681D57E7EA00330C99 /* AboutViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutViewController.m; sourceTree = ""; }; + 93D1676B1D57EB8400330C99 /* PreferencesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreferencesViewController.h; sourceTree = ""; }; + 93D1676C1D57EB8400330C99 /* PreferencesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PreferencesViewController.m; sourceTree = ""; }; + 93D1676E1D57FD3800330C99 /* NetworkMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkMonitor.h; sourceTree = ""; }; + 93D1676F1D57FD3800330C99 /* NetworkMonitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NetworkMonitor.m; sourceTree = ""; }; + 93D167711D58093C00330C99 /* NetworkInfoCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkInfoCell.h; sourceTree = ""; }; + 93D167721D58093C00330C99 /* NetworkInfoCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NetworkInfoCell.m; sourceTree = ""; }; + 93D167741D580C3500330C99 /* ShowNetworksViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShowNetworksViewController.h; sourceTree = ""; }; + 93D167751D580C3500330C99 /* ShowNetworksViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShowNetworksViewController.m; sourceTree = ""; }; + 93D167771D5815E600330C99 /* JoinNetworkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JoinNetworkViewController.h; sourceTree = ""; }; + 93D167781D5815E600330C99 /* JoinNetworkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JoinNetworkViewController.m; sourceTree = ""; }; + 93D1677A1D58228A00330C99 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 93D1677B1D58228A00330C99 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 93D1679A1D58300F00330C99 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 93D1679C1D595F0000330C99 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + 93DAFB261D3F0BEE004D5417 /* about.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = about.html; sourceTree = ""; }; + 93DAFE4A1CFE53CA00547CC4 /* AuthtokenCopy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AuthtokenCopy.m; sourceTree = ""; }; + 93DAFE4C1CFE53DA00547CC4 /* AuthtokenCopy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthtokenCopy.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 93326BD51CE7C816005CA2AC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 93D1679D1D595F0000330C99 /* WebKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 93326BCF1CE7C816005CA2AC = { + isa = PBXGroup; + children = ( + 93D1679C1D595F0000330C99 /* WebKit.framework */, + 93326BDA1CE7C816005CA2AC /* ZeroTier One */, + 93326BD91CE7C816005CA2AC /* Products */, + ); + sourceTree = ""; + }; + 93326BD91CE7C816005CA2AC /* Products */ = { + isa = PBXGroup; + children = ( + 93326BD81CE7C816005CA2AC /* ZeroTier One.app */, + ); + name = Products; + sourceTree = ""; + }; + 93326BDA1CE7C816005CA2AC /* ZeroTier One */ = { + isa = PBXGroup; + children = ( + 932D472E1D1CD499004BCFE2 /* ZeroTierIcon.icns */, + 93326BDD1CE7C816005CA2AC /* Assets.xcassets */, + 93326BDF1CE7C816005CA2AC /* MainMenu.xib */, + 93326BE21CE7C816005CA2AC /* Info.plist */, + 93DAFE4A1CFE53CA00547CC4 /* AuthtokenCopy.m */, + 93DAFE4C1CFE53DA00547CC4 /* AuthtokenCopy.h */, + 93D1676E1D57FD3800330C99 /* NetworkMonitor.h */, + 93D1676F1D57FD3800330C99 /* NetworkMonitor.m */, + 93DAFB261D3F0BEE004D5417 /* about.html */, + 93D1675D1D54191C00330C99 /* NodeStatus.h */, + 93D1675E1D54191C00330C99 /* NodeStatus.m */, + 93D167601D541BC200330C99 /* ServiceCom.h */, + 93D167611D541BC200330C99 /* ServiceCom.m */, + 93D167641D54308200330C99 /* Network.h */, + 93D167651D54308200330C99 /* Network.m */, + 93D167671D57E7EA00330C99 /* AboutViewController.h */, + 93D167681D57E7EA00330C99 /* AboutViewController.m */, + 932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */, + 93D1676B1D57EB8400330C99 /* PreferencesViewController.h */, + 93D1676C1D57EB8400330C99 /* PreferencesViewController.m */, + 932D47311D1CD861004BCFE2 /* PreferencesViewController.xib */, + 93D167711D58093C00330C99 /* NetworkInfoCell.h */, + 93D167721D58093C00330C99 /* NetworkInfoCell.m */, + 93D167741D580C3500330C99 /* ShowNetworksViewController.h */, + 93D167751D580C3500330C99 /* ShowNetworksViewController.m */, + 93326BED1CE7DA30005CA2AC /* ShowNetworksViewController.xib */, + 93D167771D5815E600330C99 /* JoinNetworkViewController.h */, + 93D167781D5815E600330C99 /* JoinNetworkViewController.m */, + 93326BE91CE7D9B9005CA2AC /* JoinNetworkViewController.xib */, + 93D1677A1D58228A00330C99 /* AppDelegate.h */, + 93D1677B1D58228A00330C99 /* AppDelegate.m */, + 93D1679A1D58300F00330C99 /* main.m */, + ); + path = "ZeroTier One"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 93326BD71CE7C816005CA2AC /* ZeroTier One */ = { + isa = PBXNativeTarget; + buildConfigurationList = 93326BE51CE7C816005CA2AC /* Build configuration list for PBXNativeTarget "ZeroTier One" */; + buildPhases = ( + 93326BD41CE7C816005CA2AC /* Sources */, + 93326BD51CE7C816005CA2AC /* Frameworks */, + 93326BD61CE7C816005CA2AC /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ZeroTier One"; + productName = "ZeroTier One"; + productReference = 93326BD81CE7C816005CA2AC /* ZeroTier One.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 93326BD01CE7C816005CA2AC /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0800; + ORGANIZATIONNAME = "ZeroTier, Inc"; + TargetAttributes = { + 93326BD71CE7C816005CA2AC = { + CreatedOnToolsVersion = 7.3; + }; + }; + }; + buildConfigurationList = 93326BD31CE7C816005CA2AC /* Build configuration list for PBXProject "ZeroTier One" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 93326BCF1CE7C816005CA2AC; + productRefGroup = 93326BD91CE7C816005CA2AC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 93326BD71CE7C816005CA2AC /* ZeroTier One */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 93326BD61CE7C816005CA2AC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 93DAFB271D3F0BEE004D5417 /* about.html in Resources */, + 93326BEF1CE7DA30005CA2AC /* ShowNetworksViewController.xib in Resources */, + 932D47371D1CDC9B004BCFE2 /* AboutViewController.xib in Resources */, + 93326BEB1CE7D9B9005CA2AC /* JoinNetworkViewController.xib in Resources */, + 93326BDE1CE7C816005CA2AC /* Assets.xcassets in Resources */, + 93326BE11CE7C816005CA2AC /* MainMenu.xib in Resources */, + 932D472F1D1CD499004BCFE2 /* ZeroTierIcon.icns in Resources */, + 932D47331D1CD861004BCFE2 /* PreferencesViewController.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 93326BD41CE7C816005CA2AC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 93D1679B1D58300F00330C99 /* main.m in Sources */, + 93D167621D541BC200330C99 /* ServiceCom.m in Sources */, + 93D167761D580C3500330C99 /* ShowNetworksViewController.m in Sources */, + 93DAFE4B1CFE53CA00547CC4 /* AuthtokenCopy.m in Sources */, + 93D167701D57FD3800330C99 /* NetworkMonitor.m in Sources */, + 93D1675F1D54191C00330C99 /* NodeStatus.m in Sources */, + 93D167691D57E7EA00330C99 /* AboutViewController.m in Sources */, + 93D1676D1D57EB8400330C99 /* PreferencesViewController.m in Sources */, + 93D1677C1D58228A00330C99 /* AppDelegate.m in Sources */, + 93D167731D58093C00330C99 /* NetworkInfoCell.m in Sources */, + 93D167661D54308200330C99 /* Network.m in Sources */, + 93D167791D5815E600330C99 /* JoinNetworkViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 93326BDF1CE7C816005CA2AC /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 93326BE01CE7C816005CA2AC /* Base */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 93326BE31CE7C816005CA2AC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 93326BE41CE7C816005CA2AC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 93326BE61CE7C816005CA2AC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "ZeroTier One/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.ZeroTier-One"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "ZeroTier One/ZeroTier One-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 93326BE71CE7C816005CA2AC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "ZeroTier One/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.ZeroTier-One"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "ZeroTier One/ZeroTier One-Bridging-Header.h"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 93326BD31CE7C816005CA2AC /* Build configuration list for PBXProject "ZeroTier One" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 93326BE31CE7C816005CA2AC /* Debug */, + 93326BE41CE7C816005CA2AC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 93326BE51CE7C816005CA2AC /* Build configuration list for PBXNativeTarget "ZeroTier One" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 93326BE61CE7C816005CA2AC /* Debug */, + 93326BE71CE7C816005CA2AC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 93326BD01CE7C816005CA2AC /* Project object */; +} diff --git a/macui/ZeroTier One.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/macui/ZeroTier One.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..fd60338e --- /dev/null +++ b/macui/ZeroTier One.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/macui/ZeroTier One/AboutViewController.h b/macui/ZeroTier One/AboutViewController.h new file mode 100644 index 00000000..d3d5bc14 --- /dev/null +++ b/macui/ZeroTier One/AboutViewController.h @@ -0,0 +1,33 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import +#import + +@interface AboutViewController : NSViewController + +@property (nonatomic, weak) IBOutlet WebView *webView; + +- (void)viewDidLoad; + +- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation + request:(NSURLRequest *)request + frame:(WebFrame *)frame +decisionListener:(id)listener; + +@end diff --git a/macui/ZeroTier One/AboutViewController.m b/macui/ZeroTier One/AboutViewController.m new file mode 100644 index 00000000..21dceae1 --- /dev/null +++ b/macui/ZeroTier One/AboutViewController.m @@ -0,0 +1,56 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "AboutViewController.h" + +@interface AboutViewController () + +@end + +@implementation AboutViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self.webView setWantsLayer:YES]; + self.webView.layer.borderWidth = 1.0f; + [self.webView.layer setCornerRadius:1.0f]; + self.webView.layer.masksToBounds = YES; + [self.webView.layer setBorderColor:[[NSColor darkGrayColor] CGColor]]; + + NSBundle *bundle = [NSBundle mainBundle]; + NSURL *path = [bundle URLForResource:@"about" withExtension:@"html"]; + if(path) { + [self.webView.mainFrame loadRequest:[NSURLRequest requestWithURL:path]]; + } +} + +- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation + request:(NSURLRequest *)request + frame:(WebFrame *)frame +decisionListener:(id)listener +{ + if(request.URL != nil && request.URL.host != nil) { + [[NSWorkspace sharedWorkspace] openURL:request.URL]; + } + else { + [listener use]; + } +} + +@end diff --git a/macui/ZeroTier One/AboutViewController.xib b/macui/ZeroTier One/AboutViewController.xib new file mode 100644 index 00000000..a0df0fcf --- /dev/null +++ b/macui/ZeroTier One/AboutViewController.xib @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macui/ZeroTier One/AppDelegate.h b/macui/ZeroTier One/AppDelegate.h new file mode 100644 index 00000000..a00cfba9 --- /dev/null +++ b/macui/ZeroTier One/AppDelegate.h @@ -0,0 +1,61 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + +@class NetworkMonitor; +@class Network; +@class NodeStatus; + +@interface AppDelegate : NSObject + +@property (weak, nonatomic) IBOutlet NSWindow *window; + +@property (nonatomic) NSStatusItem *statusItem; + +@property (nonatomic) NSPopover *networkListPopover; +@property (nonatomic) NSPopover *joinNetworkPopover; +@property (nonatomic) NSPopover *preferencesPopover; +@property (nonatomic) NSPopover *aboutPopover; + +@property (nonatomic) id transientMonitor; + +@property (nonatomic) NetworkMonitor *monitor; + +@property (nonatomic) NSMutableArray *networks; + +@property (nonatomic) NodeStatus *status; + +- (void)buildMenu; + +- (void)onNetworkListUpdated:(NSNotification*)note; +- (void)onNodeStatusUpdated:(NSNotification*)note; + +- (void)showNetworks; +- (void)joinNetwork; +- (void)showPreferences; +- (void)showAbout; +- (void)quit; +- (void)toggleNetwork:(NSMenuItem*)sender; +- (void)copyNodeID; + +- (void)closeJoinNetworkPopover; + +- (void)darkModeChanged:(NSNotification*)note; + +@end diff --git a/macui/ZeroTier One/AppDelegate.m b/macui/ZeroTier One/AppDelegate.m new file mode 100644 index 00000000..5da6b354 --- /dev/null +++ b/macui/ZeroTier One/AppDelegate.m @@ -0,0 +1,339 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "AppDelegate.h" +#import "NetworkMonitor.h" +#import "Network.h" +#import "NodeStatus.h" +#import "JoinNetworkViewController.h" +#import "ShowNetworksViewController.h" +#import "PreferencesViewController.h" +#import "AboutViewController.h" +#import "ServiceCom.h" + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:-2.0f]; + self.networkListPopover = [[NSPopover alloc] init]; + self.joinNetworkPopover = [[NSPopover alloc] init]; + self.preferencesPopover = [[NSPopover alloc] init]; + self.aboutPopover = [[NSPopover alloc] init]; + self.transientMonitor = nil; + self.monitor = [[NetworkMonitor alloc] init]; + self.networks = [NSMutableArray array]; + self.status = nil; + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSDictionary *defaultsDict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"firstRun"]; + [defaults registerDefaults:defaultsDict]; + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + + [nc addObserver:self + selector:@selector(onNetworkListUpdated:) + name:NetworkUpdateKey + object:nil]; + [nc addObserver:self + selector:@selector(onNodeStatusUpdated:) + name:StatusUpdateKey + object:nil]; + + NSString *osxMode = [defaults stringForKey:@"AppleInterfaceStyle"]; + + if(osxMode != nil && [osxMode isEqualToString:@"Dark"]) { + self.statusItem.image = [NSImage imageNamed:@"MenuBarIconMacWhite"]; + } + else { + self.statusItem.image = [NSImage imageNamed:@"MenuBarIconMac"]; + } + + [[NSDistributedNotificationCenter defaultCenter] addObserver:self + selector:@selector(darkModeChanged:) + name:@"AppleInterfaceThemeChangedNotification" + object:nil]; + + [self buildMenu]; + JoinNetworkViewController *jnvc = [[JoinNetworkViewController alloc] initWithNibName:@"JoinNetworkViewController" bundle:nil]; + jnvc.appDelegate = self; + self.joinNetworkPopover.contentViewController = jnvc; + self.joinNetworkPopover.behavior = NSPopoverBehaviorTransient; + + ShowNetworksViewController *showNetworksView = [[ShowNetworksViewController alloc] initWithNibName:@"ShowNetworksViewController" bundle:nil]; + showNetworksView.netMonitor = self.monitor; + self.networkListPopover.contentViewController = showNetworksView; + self.networkListPopover.behavior = NSPopoverBehaviorTransient; + + PreferencesViewController *prefsView = [[PreferencesViewController alloc] initWithNibName:@"PreferencesViewController" bundle:nil]; + self.preferencesPopover.contentViewController = prefsView; + self.preferencesPopover.behavior = NSPopoverBehaviorTransient; + + self.aboutPopover.contentViewController = [[AboutViewController alloc] initWithNibName:@"AboutViewController" bundle:nil]; + self.aboutPopover.behavior = NSPopoverBehaviorTransient; + + BOOL firstRun = [defaults boolForKey:@"firstRun"]; + + if(firstRun) { + [defaults setBool:NO forKey:@"firstRun"]; + [defaults synchronize]; + + [prefsView setLaunchAtLoginEnabled:YES]; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + sleep(2); + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [self showAbout]; + }]; + }); + } + + [self.monitor updateNetworkInfo]; + [self.monitor start]; +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [[NSDistributedNotificationCenter defaultCenter] removeObserver:self + name:@"AppleInterfaceThemeChangedNotification" + object:nil]; +} + +- (void)showNetworks { + if(self.statusItem.button != nil) { + NSStatusBarButton *button = self.statusItem.button; + [self.networkListPopover showRelativeToRect:button.bounds + ofView:button + preferredEdge:NSMinYEdge]; + + if(self.transientMonitor == nil) { + self.transientMonitor = + [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDown|NSRightMouseDown|NSOtherMouseDown) + handler:^(NSEvent * _Nonnull e) { + [NSEvent removeMonitor:self.transientMonitor]; + self.transientMonitor = nil; + [self.networkListPopover close]; + }]; + } + } +} + +- (void)joinNetwork { + if(self.statusItem.button != nil) { + NSStatusBarButton *button = self.statusItem.button; + [self.joinNetworkPopover showRelativeToRect:button.bounds + ofView:button + preferredEdge:NSMinYEdge]; + if(self.transientMonitor == nil) { + self.transientMonitor = + [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDown|NSRightMouseDown|NSOtherMouseDown) + handler:^(NSEvent * _Nonnull e) { + [NSEvent removeMonitor:self.transientMonitor]; + self.transientMonitor = nil; + [self.joinNetworkPopover close]; + }]; + } + } +} + +- (void)showPreferences { + if(self.statusItem.button != nil) { + NSStatusBarButton *button = self.statusItem.button; + [self.preferencesPopover showRelativeToRect:button.bounds + ofView:button + preferredEdge:NSMinYEdge]; + if(self.transientMonitor == nil) { + [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDown|NSRightMouseDown|NSOtherMouseDown) + handler:^(NSEvent * _Nonnull e) { + [NSEvent removeMonitor:self.transientMonitor]; + self.transientMonitor = nil; + [self.preferencesPopover close]; + }]; + } + } +} + +- (void)showAbout { + if(self.statusItem.button != nil) { + NSStatusBarButton *button = self.statusItem.button; + [self.aboutPopover showRelativeToRect:button.bounds + ofView:button + preferredEdge:NSMinYEdge]; + if(self.transientMonitor == nil) { + [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDown|NSRightMouseDown|NSOtherMouseDown) + handler:^(NSEvent * _Nonnull e) { + [NSEvent removeMonitor:self.transientMonitor]; + self.transientMonitor = nil; + [self.aboutPopover close]; + }]; + } + } + +} + +- (void)quit { + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; +} + +- (void)onNetworkListUpdated:(NSNotification*)note { + NSArray *netList = [note.userInfo objectForKey:@"networks"]; + [(ShowNetworksViewController*)self.networkListPopover.contentViewController setNetworks:netList]; + self.networks = [netList mutableCopy]; + + [self buildMenu]; +} + +- (void)onNodeStatusUpdated:(NSNotification*)note { + NodeStatus *status = [note.userInfo objectForKey:@"status"]; + self.status = status; + + [self buildMenu]; +} + +- (void)buildMenu { + NSMenu *menu = [[NSMenu alloc] init]; + + if(self.status != nil) { + NSString *nodeId = @"Node ID: "; + nodeId = [nodeId stringByAppendingString:self.status.address]; + [menu addItem:[[NSMenuItem alloc] initWithTitle:nodeId + action:@selector(copyNodeID) + keyEquivalent:@""]]; + [menu addItem:[NSMenuItem separatorItem]]; + } + + [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Network Details..." + action:@selector(showNetworks) + keyEquivalent:@"n"]]; + [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Join Network..." + action:@selector(joinNetwork) + keyEquivalent:@"j"]]; + + [menu addItem:[NSMenuItem separatorItem]]; + + if([self.networks count] > 0) { + for(Network *net in self.networks) { + NSString *nwid = [NSString stringWithFormat:@"%10llx", net.nwid]; + NSString *networkName = @""; + if([net.name lengthOfBytesUsingEncoding:NSUTF8StringEncoding] == 0) { + networkName = nwid; + } + else { + networkName = [NSString stringWithFormat:@"%@ (%@)", nwid, net.name]; + } + + if(net.allowDefault && net.connected) { + networkName = [networkName stringByAppendingString:@" [default]"]; + } + + NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:networkName + action:@selector(toggleNetwork:) + keyEquivalent:@""]; + if(net.connected) { + item.state = NSOnState; + } + else { + item.state = NSOffState; + } + + item.representedObject = net; + + [menu addItem:item]; + } + + [menu addItem:[NSMenuItem separatorItem]]; + } + + [menu addItem:[[NSMenuItem alloc] initWithTitle:@"About ZeroTier One..." + action:@selector(showAbout) + keyEquivalent:@""]]; + [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Preferences..." + action:@selector(showPreferences) + keyEquivalent:@""]]; + + [menu addItem:[NSMenuItem separatorItem]]; + + [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Quit" + action:@selector(quit) + keyEquivalent:@"q"]]; + + self.statusItem.menu = menu; +} + +- (void)toggleNetwork:(NSMenuItem*)sender { + Network *network = sender.representedObject; + NSString *nwid = [NSString stringWithFormat:@"%10llx", network.nwid]; + + if(network.connected) { + NSError *error = nil; + + [[ServiceCom sharedInstance] leaveNetwork:nwid error:&error]; + + if (error) { + NSAlert *alert = [NSAlert alertWithError:error]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Ok"]; + + [alert runModal]; + } + } + else { + NSError *error = nil; + [[ServiceCom sharedInstance] joinNetwork:nwid + allowManaged:network.allowManaged + allowGlobal:network.allowGlobal + allowDefault:(network.allowDefault && ![Network defaultRouteExists:self.networks]) + error:&error]; + + if (error) { + NSAlert *alert = [NSAlert alertWithError:error]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Ok"]; + + [alert runModal]; + } + } +} + +- (void)copyNodeID { + if(self.status != nil) { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil]; + [pasteboard setString:self.status.address forType:NSPasteboardTypeString]; + } +} + +- (void)darkModeChanged:(NSNotification*)note { + NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"]; + + if(osxMode != nil && [osxMode isEqualToString:@"Dark"]) { + self.statusItem.image = [NSImage imageNamed:@"MenuBarIconMacWhite"]; + } + else { + self.statusItem.image = [NSImage imageNamed:@"MenuBarIconMac"]; + } +} + +- (void)closeJoinNetworkPopover { + if (self.transientMonitor) { + [NSEvent removeMonitor:self.transientMonitor]; + self.transientMonitor = nil; + } + [self.joinNetworkPopover close]; +} + +@end diff --git a/macui/ZeroTier One/Assets.xcassets/AppIcon.appiconset/Contents.json b/macui/ZeroTier One/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..24c81d35 --- /dev/null +++ b/macui/ZeroTier One/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,59 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "ZeroTierIcon512x512.png", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/macui/ZeroTier One/Assets.xcassets/AppIcon.appiconset/ZeroTierIcon512x512.png b/macui/ZeroTier One/Assets.xcassets/AppIcon.appiconset/ZeroTierIcon512x512.png new file mode 100644 index 00000000..d225c2e3 Binary files /dev/null and b/macui/ZeroTier One/Assets.xcassets/AppIcon.appiconset/ZeroTierIcon512x512.png differ diff --git a/macui/ZeroTier One/Assets.xcassets/Contents.json b/macui/ZeroTier One/Assets.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/macui/ZeroTier One/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/Contents.json b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/Contents.json new file mode 100644 index 00000000..a680b58b --- /dev/null +++ b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "mac", + "filename" : "Menubar.png", + "scale" : "1x" + }, + { + "idiom" : "mac", + "filename" : "MenuBar@2x.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/MenuBar@2x.png b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/MenuBar@2x.png new file mode 100644 index 00000000..9fd3d3de Binary files /dev/null and b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/MenuBar@2x.png differ diff --git a/macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/Menubar.png b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/Menubar.png new file mode 100644 index 00000000..ee0d7e3f Binary files /dev/null and b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMac.imageset/Menubar.png differ diff --git a/macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/Contents.json b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/Contents.json new file mode 100644 index 00000000..61737760 --- /dev/null +++ b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "mac", + "filename" : "MenubarWhite.png", + "scale" : "1x" + }, + { + "idiom" : "mac", + "filename" : "MenubarWhite@2x.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/MenubarWhite.png b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/MenubarWhite.png new file mode 100644 index 00000000..7049ae55 Binary files /dev/null and b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/MenubarWhite.png differ diff --git a/macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/MenubarWhite@2x.png b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/MenubarWhite@2x.png new file mode 100644 index 00000000..8c20e36f Binary files /dev/null and b/macui/ZeroTier One/Assets.xcassets/MenuBarIconMacWhite.imageset/MenubarWhite@2x.png differ diff --git a/macui/ZeroTier One/AuthtokenCopy.h b/macui/ZeroTier One/AuthtokenCopy.h new file mode 100644 index 00000000..f0497cc6 --- /dev/null +++ b/macui/ZeroTier One/AuthtokenCopy.h @@ -0,0 +1,26 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef AuthtokenCopy_h +#define AuthtokenCopy_h + +#import + +NSString* getAdminAuthToken(AuthorizationRef authRef); + +#endif /* AuthtokenCopy_h */ diff --git a/macui/ZeroTier One/AuthtokenCopy.m b/macui/ZeroTier One/AuthtokenCopy.m new file mode 100644 index 00000000..a10350f7 --- /dev/null +++ b/macui/ZeroTier One/AuthtokenCopy.m @@ -0,0 +1,97 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + +#import "AuthtokenCopy.h" + + +NSString* getAdminAuthToken(AuthorizationRef authRef) { + char *tool = "/bin/cat"; + char *args[] = { "/Library/Application Support/ZeroTier/One/authtoken.secret", NULL}; + FILE *pipe = nil; + char token[25]; + memset(token, 0, sizeof(char)*25); + + + OSStatus status = AuthorizationExecuteWithPrivileges(authRef, tool, kAuthorizationFlagDefaults, args, &pipe); + + if (status != errAuthorizationSuccess) { + NSLog(@"Reading authtoken failed!"); + + + switch(status) { + case errAuthorizationDenied: + NSLog(@"Autorization Denied"); + break; + case errAuthorizationCanceled: + NSLog(@"Authorization Canceled"); + break; + case errAuthorizationInternal: + NSLog(@"Authorization Internal"); + break; + case errAuthorizationBadAddress: + NSLog(@"Bad Address"); + break; + case errAuthorizationInvalidRef: + NSLog(@"Invalid Ref"); + break; + case errAuthorizationInvalidSet: + NSLog(@"Invalid Set"); + break; + case errAuthorizationInvalidTag: + NSLog(@"Invalid Tag"); + break; + case errAuthorizationInvalidFlags: + NSLog(@"Invalid Flags"); + break; + case errAuthorizationInvalidPointer: + NSLog(@"Invalid Pointer"); + break; + case errAuthorizationToolExecuteFailure: + NSLog(@"Tool Execute Failure"); + break; + case errAuthorizationToolEnvironmentError: + NSLog(@"Tool Environment Failure"); + break; + case errAuthorizationExternalizeNotAllowed: + NSLog(@"Externalize Not Allowed"); + break; + case errAuthorizationInteractionNotAllowed: + NSLog(@"Interaction Not Allowed"); + break; + case errAuthorizationInternalizeNotAllowed: + NSLog(@"Internalize Not Allowed"); + break; + default: + NSLog(@"Unknown Error"); + break; + } + + return @""; + } + + if(pipe != nil) { + fread(&token, sizeof(char), 24, pipe); + fclose(pipe); + + return [NSString stringWithUTF8String:token]; + } + + return @""; +} diff --git a/macui/ZeroTier One/Base.lproj/MainMenu.xib b/macui/ZeroTier One/Base.lproj/MainMenu.xib new file mode 100644 index 00000000..6b6da2a6 --- /dev/null +++ b/macui/ZeroTier One/Base.lproj/MainMenu.xib @@ -0,0 +1,680 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macui/ZeroTier One/Info.plist b/macui/ZeroTier One/Info.plist new file mode 100644 index 00000000..e04b5f28 --- /dev/null +++ b/macui/ZeroTier One/Info.plist @@ -0,0 +1,41 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + ZeroTierIcon.icns + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 15 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + LSUIElement + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSHumanReadableCopyright + Copyright © 2016 ZeroTier, Inc. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/macui/ZeroTier One/JoinNetworkViewController.h b/macui/ZeroTier One/JoinNetworkViewController.h new file mode 100644 index 00000000..428959fb --- /dev/null +++ b/macui/ZeroTier One/JoinNetworkViewController.h @@ -0,0 +1,40 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + + +extern NSString * const JoinedNetworksKey; + +@class AppDelegate; + +@interface JoinNetworkViewController : NSViewController + +@property (nonatomic, weak) IBOutlet NSComboBox *network; +@property (nonatomic, weak) IBOutlet NSButton *joinButton; +@property (nonatomic, weak) IBOutlet NSButton *allowManagedCheckBox; +@property (nonatomic, weak) IBOutlet NSButton *allowGlobalCheckBox; +@property (nonatomic, weak) IBOutlet NSButton *allowDefaultCheckBox; +@property (nonatomic, weak) IBOutlet AppDelegate *appDelegate; + +@property (nonatomic) NSMutableArray *values; + +- (IBAction)onJoinClicked:(id)sender; + + +@end diff --git a/macui/ZeroTier One/JoinNetworkViewController.m b/macui/ZeroTier One/JoinNetworkViewController.m new file mode 100644 index 00000000..cae26541 --- /dev/null +++ b/macui/ZeroTier One/JoinNetworkViewController.m @@ -0,0 +1,184 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "JoinNetworkViewController.h" +#import "ServiceCom.h" +#import "AppDelegate.h" + + +NSString * const JoinedNetworksKey = @"com.zerotier.one.joined-networks"; + +@interface NSString (extra) + +- (BOOL)contains:(NSString*)find; + +@end + +@implementation NSString (extra) + +- (BOOL)contains:(NSString*)find { + NSRange range = [self rangeOfString:find]; + return range.location != NSNotFound; +} + +@end + + +@implementation JoinNetworkViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do view setup here. + [self.network setDelegate:self]; + [self.network setDataSource:self]; +} + +- (void)viewWillAppear { + [super viewWillAppear]; + + self.allowManagedCheckBox.state = NSOnState; + self.allowGlobalCheckBox.state = NSOffState; + self.allowDefaultCheckBox.state = NSOffState; + + self.network.stringValue = @""; + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + NSMutableArray *vals = [[defaults stringArrayForKey:JoinedNetworksKey] mutableCopy]; + + if(vals) { + self.values = vals; + } +} + +- (void)viewWillDisappear { + [super viewWillDisappear]; + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + [defaults setObject:self.values forKey:JoinedNetworksKey]; +} + +- (IBAction)onJoinClicked:(id)sender { + NSString *networkId = self.network.stringValue; + + NSError *error = nil; + [[ServiceCom sharedInstance] joinNetwork:networkId + allowManaged:(self.allowManagedCheckBox.state == NSOnState) + allowGlobal:(self.allowGlobalCheckBox.state == NSOnState) + allowDefault:(self.allowDefaultCheckBox.state == NSOnState) + error:&error]; + + if(error) { + NSAlert *alert = [NSAlert alertWithError:error]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Ok"]; + + [alert runModal]; + return; + } + + self.network.stringValue = @""; + + if(![self.values containsObject:networkId]) { + [self.values insertObject:networkId atIndex:0]; + + while([self.values count] > 20) { + [self.values removeLastObject]; + } + } + + [self.appDelegate closeJoinNetworkPopover]; +} + +// NSComboBoxDelegate methods + +- (void)controlTextDidChange:(NSNotification *)obj { + NSComboBox *cb = (NSComboBox*)obj.object; + NSString *value = cb.stringValue; + + NSString *allowedCharacters = @"abcdefABCDEF0123456789"; + + NSString *outValue = @""; + + for(int i = 0; i < [value length]; ++i) { + if(![allowedCharacters contains:[NSString stringWithFormat:@"%C", [value characterAtIndex:i]]]) { + NSBeep(); + } + else { + outValue = [outValue stringByAppendingString:[NSString stringWithFormat:@"%C", [value characterAtIndex:i]]]; + } + } + + if([outValue lengthOfBytesUsingEncoding:NSUTF8StringEncoding] == 16) { + self.joinButton.enabled = YES; + } + else { + if([outValue lengthOfBytesUsingEncoding:NSUTF8StringEncoding] > 16) { + NSRange range = {0, 16}; + range = [outValue rangeOfComposedCharacterSequencesForRange:range]; + outValue = [outValue substringWithRange:range]; + NSBeep(); + self.joinButton.enabled = YES; + } + else { + self.joinButton.enabled = NO; + } + } + + cb.stringValue = outValue; +} + +// end NSComboBoxDelegate methods + +// NSComboBoxDataSource methods + +- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox { + return [self.values count]; +} + +- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index { + return [self.values objectAtIndex:index]; +} + +- (NSUInteger)comboBox:(NSComboBox *)aComboBox indexOfItemWithStringValue:(NSString *)string { + NSUInteger counter = 0; + + for(NSString *val in self.values) { + if([val isEqualToString:string]) { + return counter; + } + + counter += 1; + } + + return NSNotFound; +} + +- (NSString*)comboBox:(NSComboBox *)aComboBox completedString:(NSString *)string { + for(NSString *val in self.values) { + if([val hasPrefix:string]) { + return val; + } + } + return nil; +} + +// end NSComboBoxDataSource methods + +@end diff --git a/macui/ZeroTier One/JoinNetworkViewController.xib b/macui/ZeroTier One/JoinNetworkViewController.xib new file mode 100644 index 00000000..2ef43442 --- /dev/null +++ b/macui/ZeroTier One/JoinNetworkViewController.xib @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macui/ZeroTier One/Network.h b/macui/ZeroTier One/Network.h new file mode 100644 index 00000000..0f3c4964 --- /dev/null +++ b/macui/ZeroTier One/Network.h @@ -0,0 +1,62 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + +enum NetworkStatus { + REQUESTING_CONFIGURATION, + OK, + ACCESS_DENIED, + NOT_FOUND, + PORT_ERROR, + CLIENT_TOO_OLD, +}; + +enum NetworkType { + PUBLIC, + PRIVATE, +}; + +@interface Network : NSObject + +@property (readonly) NSArray *assignedAddresses; +@property (readonly) BOOL bridge; +@property (readonly) BOOL broadcastEnabled; +@property (readonly) BOOL dhcp; +@property (readonly) NSString *mac; +@property (readonly) int mtu; +@property (readonly) int netconfRevision; +@property (readonly) NSString *name; +@property (readonly) UInt64 nwid; +@property (readonly) NSString *portDeviceName; +@property (readonly) int portError; +@property (readonly) enum NetworkStatus status; +@property (readonly) enum NetworkType type; +@property (readonly) BOOL allowManaged; +@property (readonly) BOOL allowGlobal; +@property (readonly) BOOL allowDefault; +@property (readonly) BOOL connected; // not persisted. set to YES if loaded via json + +- (id)initWithJsonData:(NSDictionary*)jsonData; +- (id)initWithCoder:(NSCoder *)aDecoder; +- (void)encodeWithCoder:(NSCoder *)aCoder; ++ (BOOL)defaultRouteExists:(NSArray*)netList; +- (NSString*)statusString; +- (NSString*)typeString; + +@end diff --git a/macui/ZeroTier One/Network.m b/macui/ZeroTier One/Network.m new file mode 100644 index 00000000..16efc6e3 --- /dev/null +++ b/macui/ZeroTier One/Network.m @@ -0,0 +1,278 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "Network.h" + +NSString *NetworkAddressesKey = @"addresses"; +NSString *NetworkBridgeKey = @"bridge"; +NSString *NetworkBroadcastKey = @"broadcast"; +NSString *NetworkDhcpKey = @"dhcp"; +NSString *NetworkMacKey = @"mac"; +NSString *NetworkMtuKey = @"mtu"; +NSString *NetworkMulticastKey = @"multicast"; +NSString *NetworkNameKey = @"name"; +NSString *NetworkNetconfKey = @"netconf"; +NSString *NetworkNwidKey = @"nwid"; +NSString *NetworkPortNameKey = @"port"; +NSString *NetworkPortErrorKey = @"portError"; +NSString *NetworkStatusKey = @"status"; +NSString *NetworkTypeKey = @"type"; +NSString *NetworkAllowManagedKey = @"allowManaged"; +NSString *NetworkAllowGlobalKey = @"allowGlobal"; +NSString *NetworkAllowDefaultKey = @"allowDefault"; + +@implementation Network + +- (id)initWithJsonData:(NSDictionary*)jsonData +{ + self = [super init]; + + if(self) { + if([jsonData objectForKey:@"assignedAddresses"]) { + _assignedAddresses = (NSArray*)[jsonData objectForKey:@"assignedAddresses"]; + } + + if([jsonData objectForKey:@"bridge"]) { + _bridge = [(NSNumber*)[jsonData objectForKey:@"bridge"] boolValue]; + } + + if([jsonData objectForKey:@"broadcastEnabled"]) { + _broadcastEnabled = [(NSNumber*)[jsonData objectForKey:@"broadcastEnabled"] boolValue]; + } + + if([jsonData objectForKey:@"dhcp"]) { + _dhcp = [(NSNumber*)[jsonData objectForKey:@"dhcp"] boolValue]; + } + + if([jsonData objectForKey:@"mac"]) { + _mac = (NSString*)[jsonData objectForKey:@"mac"]; + } + + if([jsonData objectForKey:@"mtu"]) { + _mtu = [(NSNumber*)[jsonData objectForKey:@"mtu"] intValue]; + } + + if([jsonData objectForKey:@"name"]) { + _name = (NSString*)[jsonData objectForKey:@"name"]; + } + + if([jsonData objectForKey:@"netconfRevision"]) { + _netconfRevision = [(NSNumber*)[jsonData objectForKey:@"netconfRevision"] intValue]; + } + + if([jsonData objectForKey:@"nwid"]) { + NSString *networkid = (NSString*)[jsonData objectForKey:@"nwid"]; + + NSScanner *scanner = [NSScanner scannerWithString:networkid]; + [scanner scanHexLongLong:&_nwid]; + } + + if([jsonData objectForKey:@"portDeviceName"]) { + _portDeviceName = (NSString*)[jsonData objectForKey:@"portDeviceName"]; + } + + if([jsonData objectForKey:@"portError"]) { + _portError = [(NSNumber*)[jsonData objectForKey:@"portError"] intValue]; + } + + if([jsonData objectForKey:@"allowManaged"]) { + _allowManaged = [(NSNumber*)[jsonData objectForKey:@"allowManaged"] boolValue]; + } + + if([jsonData objectForKey:@"allowGlobal"]) { + _allowGlobal = [(NSNumber*)[jsonData objectForKey:@"allowGlobal"] boolValue]; + } + + if([jsonData objectForKey:@"allowDefault"]) { + _allowDefault = [(NSNumber*)[jsonData objectForKey:@"allowDefault"] boolValue]; + } + + if([jsonData objectForKey:@"status"]) { + NSString *statusStr = (NSString*)[jsonData objectForKey:@"status"]; + if([statusStr isEqualToString:@"REQUESTING_CONFIGURATION"]) { + _status = REQUESTING_CONFIGURATION; + } + else if([statusStr isEqualToString:@"OK"]) { + _status = OK; + } + else if([statusStr isEqualToString:@"ACCESS_DENIED"]) { + _status = ACCESS_DENIED; + } + else if([statusStr isEqualToString:@"NOT_FOUND"]) { + _status = NOT_FOUND; + } + else if([statusStr isEqualToString:@"PORT_ERROR"]) { + _status = PORT_ERROR; + } + else if([statusStr isEqualToString:@"CLIENT_TOO_OLD"]) { + _status = CLIENT_TOO_OLD; + } + } + + if([jsonData objectForKey:@"type"]) { + NSString *typeStr = (NSString*)[jsonData objectForKey:@"type"]; + if([typeStr isEqualToString:@"PRIVATE"]) { + _type = PRIVATE; + } + else if([typeStr isEqualToString:@"PUBLIC"]) { + _type = PUBLIC; + } + } + + _connected = YES; + } + + return self; +} +- (id)initWithCoder:(NSCoder *)aDecoder +{ + self = [super init]; + + if(self) { + if([aDecoder containsValueForKey:NetworkAddressesKey]) { + _assignedAddresses = (NSArray*)[aDecoder decodeObjectForKey:NetworkAddressesKey]; + } + + if([aDecoder containsValueForKey:NetworkBridgeKey]) { + _bridge = [aDecoder decodeBoolForKey:NetworkBridgeKey]; + } + + if([aDecoder containsValueForKey:NetworkBroadcastKey]) { + _broadcastEnabled = [aDecoder decodeBoolForKey:NetworkBroadcastKey]; + } + + if([aDecoder containsValueForKey:NetworkDhcpKey]) { + _dhcp = [aDecoder decodeBoolForKey:NetworkDhcpKey]; + } + + if([aDecoder containsValueForKey:NetworkMacKey]) { + _mac = (NSString*)[aDecoder decodeObjectForKey:NetworkMacKey]; + } + + if([aDecoder containsValueForKey:NetworkMtuKey]) { + _mtu = (int)[aDecoder decodeIntegerForKey:NetworkMtuKey]; + } + + if([aDecoder containsValueForKey:NetworkNameKey]) { + _name = (NSString*)[aDecoder decodeObjectForKey:NetworkNameKey]; + } + + if([aDecoder containsValueForKey:NetworkNetconfKey]) { + _netconfRevision = (int)[aDecoder decodeIntegerForKey:NetworkNetconfKey]; + } + + if([aDecoder containsValueForKey:NetworkNwidKey]) { + _nwid = [(NSNumber*)[aDecoder decodeObjectForKey:NetworkNwidKey] unsignedLongLongValue]; + } + + if([aDecoder containsValueForKey:NetworkPortNameKey]) { + _portDeviceName = (NSString*)[aDecoder decodeObjectForKey:NetworkPortNameKey]; + } + + if([aDecoder containsValueForKey:NetworkPortErrorKey]) { + _portError = (int)[aDecoder decodeIntegerForKey:NetworkPortErrorKey]; + } + + if([aDecoder containsValueForKey:NetworkStatusKey]) { + _status = (enum NetworkStatus)[aDecoder decodeIntegerForKey:NetworkStatusKey]; + } + + if([aDecoder containsValueForKey:NetworkTypeKey]) { + _type = (enum NetworkType)[aDecoder decodeIntegerForKey:NetworkTypeKey]; + } + + if([aDecoder containsValueForKey:NetworkAllowManagedKey]) { + _allowManaged = [aDecoder decodeBoolForKey:NetworkAllowManagedKey]; + } + + if([aDecoder containsValueForKey:NetworkAllowGlobalKey]) { + _allowGlobal = [aDecoder decodeBoolForKey:NetworkAllowGlobalKey]; + } + + if([aDecoder containsValueForKey:NetworkAllowDefaultKey]) { + _allowDefault = [aDecoder decodeBoolForKey:NetworkAllowDefaultKey]; + } + + _connected = NO; + } + + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder +{ + [aCoder encodeObject:_assignedAddresses forKey:NetworkAddressesKey]; + [aCoder encodeBool:_bridge forKey:NetworkBridgeKey]; + [aCoder encodeBool:_broadcastEnabled forKey:NetworkBroadcastKey]; + [aCoder encodeBool:_dhcp forKey:NetworkDhcpKey]; + [aCoder encodeObject:_mac forKey:NetworkMacKey]; + [aCoder encodeInteger:_mtu forKey:NetworkMtuKey]; + [aCoder encodeObject:_name forKey:NetworkNameKey]; + [aCoder encodeInteger:_netconfRevision forKey:NetworkNetconfKey]; + [aCoder encodeObject:[NSNumber numberWithUnsignedLongLong:_nwid] + forKey:NetworkNwidKey]; + [aCoder encodeObject:_portDeviceName forKey:NetworkPortNameKey]; + [aCoder encodeInteger:_portError forKey:NetworkPortErrorKey]; + [aCoder encodeInteger:_status forKey:NetworkStatusKey]; + [aCoder encodeInteger:_type forKey:NetworkTypeKey]; + [aCoder encodeBool:_allowManaged forKey:NetworkAllowManagedKey]; + [aCoder encodeBool:_allowGlobal forKey:NetworkAllowGlobalKey]; + [aCoder encodeBool:_allowDefault forKey:NetworkAllowDefaultKey]; +} + ++ (BOOL)defaultRouteExists:(NSArray*)netList +{ + for(Network *net in netList) { + if (net.allowDefault && net.connected) { + return YES; + } + } + return NO; +} + +- (NSString*)statusString { + switch(_status) { + case REQUESTING_CONFIGURATION: + return @"REQUESTING_CONFIGURATION"; + case OK: + return @"OK"; + case ACCESS_DENIED: + return @"ACCESS_DENIED"; + case NOT_FOUND: + return @"NOT_FOUND"; + case PORT_ERROR: + return @"PORT_ERROR"; + case CLIENT_TOO_OLD: + return @"CLIENT_TOO_OLD"; + default: + return @""; + } +} + +- (NSString*)typeString { + switch(_type) { + case PUBLIC: + return @"PUBLIC"; + case PRIVATE: + return @"PRIVATE"; + default: + return @""; + } +} + +@end diff --git a/macui/ZeroTier One/NetworkInfoCell.h b/macui/ZeroTier One/NetworkInfoCell.h new file mode 100644 index 00000000..be9345d7 --- /dev/null +++ b/macui/ZeroTier One/NetworkInfoCell.h @@ -0,0 +1,50 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + +@class ShowNetworksViewController; + +@interface NetworkInfoCell : NSTableCellView + +@property (weak, nonatomic) ShowNetworksViewController *parent; + +@property (weak, nonatomic) IBOutlet NSTextField *networkIdField; +@property (weak, nonatomic) IBOutlet NSTextField *networkNameField; +@property (weak, nonatomic) IBOutlet NSTextField *statusField; +@property (weak, nonatomic) IBOutlet NSTextField *typeField; +@property (weak, nonatomic) IBOutlet NSTextField *macField; +@property (weak, nonatomic) IBOutlet NSTextField *mtuField; +@property (weak, nonatomic) IBOutlet NSTextField *broadcastField; +@property (weak, nonatomic) IBOutlet NSTextField *bridgingField; +@property (weak, nonatomic) IBOutlet NSTextField *deviceField; +@property (weak, nonatomic) IBOutlet NSTextField *addressesField; +@property (weak, nonatomic) IBOutlet NSButton *allowManaged; +@property (weak, nonatomic) IBOutlet NSButton *allowGlobal; +@property (weak, nonatomic) IBOutlet NSButton *allowDefault; +@property (weak, nonatomic) IBOutlet NSButton *connectedCheckbox; +@property (weak, nonatomic) IBOutlet NSButton *deleteButton; + +- (IBAction)onConnectCheckStateChanged:(NSButton*)sender; +- (IBAction)deleteNetwork:(NSButton*)sender; +- (IBAction)onAllowStatusChanged:(NSButton*)sender; + +- (void)joinNetwork:(NSString*)nwid; +- (void)leaveNetwork:(NSString*)nwid; + +@end diff --git a/macui/ZeroTier One/NetworkInfoCell.m b/macui/ZeroTier One/NetworkInfoCell.m new file mode 100644 index 00000000..dc75cab3 --- /dev/null +++ b/macui/ZeroTier One/NetworkInfoCell.m @@ -0,0 +1,85 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "NetworkInfoCell.h" +#import "ServiceCom.h" +#import "ShowNetworksViewController.h" +#import "Network.h" + +@implementation NetworkInfoCell + +- (void)drawRect:(NSRect)dirtyRect { + [super drawRect:dirtyRect]; + + // Drawing code here. +} + +- (IBAction)onConnectCheckStateChanged:(NSButton*)sender +{ + if(sender.state == NSOnState) { + [self joinNetwork:self.networkIdField.stringValue]; + } + else { + [self leaveNetwork:self.networkIdField.stringValue]; + } +} + +- (IBAction)deleteNetwork:(NSButton*)sender; +{ + [self leaveNetwork:self.networkIdField.stringValue]; + [self.parent deleteNetworkFromList:self.networkIdField.stringValue]; +} + +- (IBAction)onAllowStatusChanged:(NSButton*)sender +{ + [self joinNetwork:self.networkIdField.stringValue]; +} + +- (void)joinNetwork:(NSString*)nwid +{ + NSError *error = nil; + [[ServiceCom sharedInstance] joinNetwork:nwid + allowManaged:(self.allowManaged.state == NSOnState) + allowGlobal:(self.allowGlobal.state == NSOnState) + allowDefault:![Network defaultRouteExists:_parent.networkList] && (self.allowDefault.state == NSOnState) + error:&error]; + + if (error) { + NSAlert *alert = [NSAlert alertWithError:error]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Ok"]; + + [alert runModal]; + } +} + +- (void)leaveNetwork:(NSString*)nwid +{ + NSError *error = nil; + [[ServiceCom sharedInstance] leaveNetwork:nwid error:&error]; + + if (error) { + NSAlert *alert = [NSAlert alertWithError:error]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Ok"]; + + [alert runModal]; + } +} + +@end diff --git a/macui/ZeroTier One/NetworkMonitor.h b/macui/ZeroTier One/NetworkMonitor.h new file mode 100644 index 00000000..8cdec4ed --- /dev/null +++ b/macui/ZeroTier One/NetworkMonitor.h @@ -0,0 +1,45 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + +extern NSString * const NetworkUpdateKey; +extern NSString * const StatusUpdateKey; + +@class Network; + +@interface NetworkMonitor : NSObject +{ + NSMutableArray *_savedNetworks; + NSArray *_receivedNetworks; + NSMutableArray *_allNetworks; + + NSTimer *_timer; +} + +- (id)init; +- (void)dealloc; + +- (void)start; +- (void)stop; + +- (void)updateNetworkInfo; + +- (void)deleteSavedNetwork:(NSString*)networkId; + +@end diff --git a/macui/ZeroTier One/NetworkMonitor.m b/macui/ZeroTier One/NetworkMonitor.m new file mode 100644 index 00000000..7ed22c4a --- /dev/null +++ b/macui/ZeroTier One/NetworkMonitor.m @@ -0,0 +1,253 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "NetworkMonitor.h" +#import "Network.h" +#import "ServiceCom.h" +#import "NodeStatus.h" + +@import AppKit; + + +NSString * const NetworkUpdateKey = @"com.zerotier.one.network-list"; +NSString * const StatusUpdateKey = @"com.zerotier.one.status"; + +@interface NetworkMonitor (private) + +- (NSString*)dataFile; +- (void)internal_updateNetworkInfo; +- (NSInteger)findNetworkWithID:(UInt64)networkId; +- (NSInteger)findSavedNetworkWithID:(UInt64)networkId; +- (void)saveNetworks; + +@end + +@implementation NetworkMonitor + +- (id)init +{ + self = [super init]; + if(self) + { + _savedNetworks = [NSMutableArray array]; + _receivedNetworks = [NSArray array]; + _allNetworks = [NSMutableArray array]; + _timer = nil; + } + + return self; +} + +- (void)dealloc +{ + [_timer invalidate]; +} + +- (void)start +{ + NSLog(@"ZeroTier monitor started"); + _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f + target:self + selector:@selector(updateNetworkInfo) + userInfo:nil + repeats:YES]; +} + +- (void)stop +{ + NSLog(@"ZeroTier monitor stopped"); + [_timer invalidate]; + _timer = nil; +} + +- (void)updateNetworkInfo +{ + NSString *filePath = [self dataFile]; + + if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { + NSArray *networks = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + if(networks != nil) { + _savedNetworks = [networks mutableCopy]; + } + } + + NSError *error = nil; + + [[ServiceCom sharedInstance] getNetworklist:^(NSArray *networkList) { + _receivedNetworks = networkList; + + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [self internal_updateNetworkInfo]; + } ]; + } error:&error]; + + if(error) { + [self stop]; + + NSAlert *alert = [NSAlert alertWithError:error]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Quit"]; + [alert addButtonWithTitle:@"Retry"]; + + NSModalResponse res = [alert runModal]; + + if(res == NSAlertFirstButtonReturn) { + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; + } + else if(res == NSAlertSecondButtonReturn) { + [self start]; + return; + } + } + + [[ServiceCom sharedInstance] getNodeStatus:^(NodeStatus *status) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:status forKey:@"status"]; + + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [[NSNotificationCenter defaultCenter] postNotificationName:StatusUpdateKey + object:nil + userInfo:userInfo]; + }]; + } error:&error]; + + if (error) { + [self stop]; + + NSAlert *alert = [NSAlert alertWithError:error]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Quit"]; + [alert addButtonWithTitle:@"Retry"]; + + NSModalResponse res = [alert runModal]; + + if(res == NSAlertFirstButtonReturn) { + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; + } + else if(res == NSAlertSecondButtonReturn) { + [self start]; + return; + } + } +} + +- (void)deleteSavedNetwork:(NSString*)networkId +{ + UInt64 nwid = 0; + NSScanner *scanner = [NSScanner scannerWithString:networkId]; + [scanner scanHexLongLong:&nwid]; + + NSInteger index = [self findNetworkWithID:nwid]; + + if(index != NSNotFound) { + [_allNetworks removeObjectAtIndex:index]; + } + + index = [self findSavedNetworkWithID:nwid]; + + if(index != NSNotFound) { + [_savedNetworks removeObjectAtIndex:index]; + } + + [self saveNetworks]; +} + +@end + +@implementation NetworkMonitor (private) +- (NSString*)dataFile +{ + NSURL *appSupport = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory + inDomains:NSUserDomainMask] objectAtIndex:0]; + + appSupport = [[[appSupport URLByAppendingPathComponent:@"ZeroTier"] URLByAppendingPathComponent:@"One"] URLByAppendingPathComponent:@"networkinfo.dat"]; + return appSupport.path; +} + +- (void)internal_updateNetworkInfo +{ + NSMutableArray *networks = [_savedNetworks mutableCopy]; + + for(Network *nw in _receivedNetworks) { + NSInteger index = [self findSavedNetworkWithID:nw.nwid]; + + if(index != NSNotFound) { + [networks setObject:nw atIndexedSubscript:index]; + } + else { + [networks addObject:nw]; + } + } + + [networks sortUsingComparator:^NSComparisonResult(Network *obj1, Network *obj2) { + if(obj1.nwid > obj2.nwid) { + return true; + } + return false; + }]; + + @synchronized(_allNetworks) { + _allNetworks = networks; + } + + [self saveNetworks]; + + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:networks forKey:@"networks"]; + + [[NSNotificationCenter defaultCenter] postNotificationName:NetworkUpdateKey + object:nil + userInfo:userInfo]; +} + +- (NSInteger)findNetworkWithID:(UInt64)networkId +{ + for(int i = 0; i < [_allNetworks count]; ++i) { + Network *nw = [_allNetworks objectAtIndex:i]; + + if(nw.nwid == networkId) { + return i; + } + } + + return NSNotFound; +} + + +- (NSInteger)findSavedNetworkWithID:(UInt64)networkId +{ + for(int i = 0; i < [_savedNetworks count]; ++i) { + Network *nw = [_savedNetworks objectAtIndex:i]; + + if(nw.nwid == networkId) { + return i; + } + } + + return NSNotFound; +} + +- (void)saveNetworks +{ + NSString *filePath = [self dataFile]; + + @synchronized(_allNetworks) { + [NSKeyedArchiver archiveRootObject:_allNetworks toFile:filePath]; + } +} + +@end diff --git a/macui/ZeroTier One/NodeStatus.h b/macui/ZeroTier One/NodeStatus.h new file mode 100644 index 00000000..eab5bfe4 --- /dev/null +++ b/macui/ZeroTier One/NodeStatus.h @@ -0,0 +1,35 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + +@interface NodeStatus : NSObject + +@property (readonly) NSString *address; +@property (readonly) NSString *publicIdentity; +@property (readonly) BOOL online; +@property (readonly) BOOL tcpFallbackActive; +@property (readonly) int versionMajor; +@property (readonly) int versionMinor; +@property (readonly) int versionRev; +@property (readonly) NSString *version; +@property (readonly) UInt64 clock; + +- (id)initWithJsonData:(NSDictionary*)jsonData; + +@end diff --git a/macui/ZeroTier One/NodeStatus.m b/macui/ZeroTier One/NodeStatus.m new file mode 100644 index 00000000..3bae3c7d --- /dev/null +++ b/macui/ZeroTier One/NodeStatus.m @@ -0,0 +1,40 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#import "NodeStatus.h" + +@implementation NodeStatus + +- (id)initWithJsonData:(NSDictionary*)jsonData +{ + self = [super init]; + + if(self) { + _address = (NSString*)[jsonData objectForKey:@"address"]; + _publicIdentity = (NSString*)[jsonData objectForKey:@"publicIdentity"]; + _online = [(NSNumber*)[jsonData objectForKey:@"online"] boolValue]; + _tcpFallbackActive = [(NSNumber*)[jsonData objectForKey:@"tcpFallbackActive"] boolValue]; + _versionMajor = [(NSNumber*)[jsonData objectForKey:@"versionMajor"] intValue]; + _versionMinor = [(NSNumber*)[jsonData objectForKey:@"versionMinor"] intValue]; + _versionRev = [(NSNumber*)[jsonData objectForKey:@"versionRev"] intValue]; + _version = (NSString*)[jsonData objectForKey:@"version"]; + _clock = [(NSNumber*)[jsonData objectForKey:@"clock"] unsignedLongLongValue]; + } + + return self; +} +@end diff --git a/macui/ZeroTier One/PreferencesViewController.h b/macui/ZeroTier One/PreferencesViewController.h new file mode 100644 index 00000000..56d0fdb8 --- /dev/null +++ b/macui/ZeroTier One/PreferencesViewController.h @@ -0,0 +1,31 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + +@interface PreferencesViewController : NSViewController + +@property (nonatomic, weak) IBOutlet NSButton *startupCheckBox; + +- (IBAction)onStartupCheckBoxChanged:(NSButton*)sender; + +- (BOOL)isLaunchAtStartup; +- (LSSharedFileListItemRef)itemRefInLoginItems; +- (void)setLaunchAtLoginEnabled:(BOOL)enabled; + +@end diff --git a/macui/ZeroTier One/PreferencesViewController.m b/macui/ZeroTier One/PreferencesViewController.m new file mode 100644 index 00000000..13927fba --- /dev/null +++ b/macui/ZeroTier One/PreferencesViewController.m @@ -0,0 +1,112 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "PreferencesViewController.h" + +@interface PreferencesViewController () + +@end + +@implementation PreferencesViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + if([self isLaunchAtStartup]) { + self.startupCheckBox.state = NSOnState; + } + else { + self.startupCheckBox.state = NSOffState; + } +} + +- (IBAction)onStartupCheckBoxChanged:(NSButton *)sender +{ + if(sender.state == NSOnState) { + [self setLaunchAtLoginEnabled:YES]; + } + else { + [self setLaunchAtLoginEnabled:NO]; + } + +} + +- (void)setLaunchAtLoginEnabled:(BOOL)enabled +{ + LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + + if (enabled) { + // Add the app to the LoginItems list. + CFURLRef appUrl = (__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; + LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, appUrl, NULL, NULL); + if (itemRef) CFRelease(itemRef); + } + else { + // Remove the app from the LoginItems list. + LSSharedFileListItemRef itemRef = [self itemRefInLoginItems]; + LSSharedFileListItemRemove(loginItemsRef,itemRef); + if (itemRef != nil) CFRelease(itemRef); + } +} + + +- (BOOL)isLaunchAtStartup { + // See if the app is currently in LoginItems. + LSSharedFileListItemRef itemRef = [self itemRefInLoginItems]; + // Store away that boolean. + BOOL isInList = itemRef != nil; + // Release the reference if it exists. + if (itemRef != nil) CFRelease(itemRef); + + return isInList; +} + +- (LSSharedFileListItemRef)itemRefInLoginItems { + LSSharedFileListItemRef itemRef = nil; + + NSString * appPath = [[NSBundle mainBundle] bundlePath]; + + // This will retrieve the path for the application + // For example, /Applications/test.app + CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:appPath]; + + // Create a reference to the shared file list. + LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + + if (loginItems) { + UInt32 seedValue; + //Retrieve the list of Login Items and cast them to + // a NSArray so that it will be easier to iterate. + NSArray *loginItemsArray = (__bridge NSArray *)LSSharedFileListCopySnapshot(loginItems, &seedValue); + for(int i = 0; i< [loginItemsArray count]; i++){ + LSSharedFileListItemRef currentItemRef = (__bridge LSSharedFileListItemRef)[loginItemsArray + objectAtIndex:i]; + //Resolve the item with URL + if (LSSharedFileListItemResolve(currentItemRef, 0, (CFURLRef*) &url, NULL) == noErr) { + NSString * urlPath = [(__bridge NSURL*)url path]; + if ([urlPath compare:appPath] == NSOrderedSame){ + itemRef = currentItemRef; + } + } + } + } + CFRelease(loginItems); + return itemRef; +} + +@end diff --git a/macui/ZeroTier One/PreferencesViewController.xib b/macui/ZeroTier One/PreferencesViewController.xib new file mode 100644 index 00000000..62aef4c0 --- /dev/null +++ b/macui/ZeroTier One/PreferencesViewController.xib @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macui/ZeroTier One/ServiceCom.h b/macui/ZeroTier One/ServiceCom.h new file mode 100644 index 00000000..74ab2b35 --- /dev/null +++ b/macui/ZeroTier One/ServiceCom.h @@ -0,0 +1,39 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + +@class NodeStatus; +@class Network; + +@interface ServiceCom : NSObject +{ + NSString *baseURL; + NSURLSession *session; + BOOL _isQuitting; +} ++ (ServiceCom*)sharedInstance; + +- (id)init; + +- (void)getNetworklist:(void (^)(NSArray*))completionHandler error:(NSError* __autoreleasing *)error; +- (void)getNodeStatus:(void (^)(NodeStatus*))completionHandler error:(NSError*__autoreleasing*)error; +- (void)joinNetwork:(NSString*)networkId allowManaged:(BOOL)allowManaged allowGlobal:(BOOL)allowGlobal allowDefault:(BOOL)allowDefault error:(NSError*__autoreleasing*)error; +- (void)leaveNetwork:(NSString*)networkId error:(NSError*__autoreleasing*)error; + +@end diff --git a/macui/ZeroTier One/ServiceCom.m b/macui/ZeroTier One/ServiceCom.m new file mode 100644 index 00000000..4982d40e --- /dev/null +++ b/macui/ZeroTier One/ServiceCom.m @@ -0,0 +1,464 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "ServiceCom.h" +#import "AuthtokenCopy.h" +#import "Network.h" +#import "NodeStatus.h" +@import AppKit; + +@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]]; + _isQuitting = NO; + } + + return self; +} + +- (NSString*)key:(NSError* __autoreleasing *)err +{ + 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; + *err = error; + return @""; + } + } + else { + NSURL *sysAppSupportDir = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSSystemDomainMask appropriateForURL:nil create:false error:nil]; + + sysAppSupportDir = [[sysAppSupportDir URLByAppendingPathComponent:@"ZeroTier"] URLByAppendingPathComponent:@"One"]; + NSURL *sysAuthtokenURL = [sysAppSupportDir URLByAppendingPathComponent:@"authtoken.secret"]; + + if(![[NSFileManager defaultManager] fileExistsAtPath:[sysAuthtokenURL path]]) { + + } + + [[NSFileManager defaultManager] createDirectoryAtURL:appSupportDir + withIntermediateDirectories:YES + attributes:nil + error:&error]; + + if (error) { + NSLog(@"Error: %@", error); + *err = error; + k = nil; + return @""; + } + + AuthorizationRef authRef; + OSStatus status = AuthorizationCreate(nil, nil, kAuthorizationFlagDefaults, &authRef); + + if (status != errAuthorizationSuccess) { + NSLog(@"Authorization Failed! %d", status); + + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't create AuthorizationRef", nil), + }; + *err = [NSError errorWithDomain:@"com.zerotier.one" code:-1 userInfo:userInfo]; + + 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); + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't copy authorization rights", nil), + }; + *err = [NSError errorWithDomain:@"com.zerotier.one" code:-1 userInfo:userInfo]; + 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); + *err = error; + } + } + } + } + + if (k == nil) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Unknown error finding authorization key", nil), + }; + *err = [NSError errorWithDomain:@"com.zerotier.one" code:-1 userInfo:userInfo]; + + return @""; + } + + return k; +} + +- (void)getNetworklist:(void (^)(NSArray *))completionHandler error:(NSError *__autoreleasing*)error +{ + NSString* key = [self key:error]; + if(*error) { + return; + } + + NSString *urlString = [[baseURL stringByAppendingString:@"/network?auth="] stringByAppendingString:key]; + + NSURL *url = [NSURL URLWithString:urlString]; + NSURLSessionDataTask *task = + [session dataTaskWithURL:url + completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable err) { + + if (err) { + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + NSAlert *alert = [NSAlert alertWithError:err]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Quit"]; + [alert addButtonWithTitle:@"Retry"]; + + NSModalResponse res; + if (!_isQuitting) { + res = [alert runModal]; + } + else { + return; + } + + if(res == NSAlertFirstButtonReturn) { + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; + _isQuitting = YES; + } + }]; + return; + } + + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; + NSInteger status = [httpResponse statusCode]; + + NSError *err2; + + if (status == 200) { + NSArray *json = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&err2]; + if (err) { + NSLog(@"Error fetching network list: %@", err2); + + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + NSAlert *alert = [NSAlert alertWithError:err2]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Quit"]; + [alert addButtonWithTitle:@"Retry"]; + + NSModalResponse res; + if (!_isQuitting) { + res = [alert runModal]; + } + else { + return; + } + + if(res == NSAlertFirstButtonReturn) { + _isQuitting = YES; + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; + } + }]; + 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 error:(NSError*__autoreleasing*)error +{ + NSString *key = [self key:error]; + if(*error) { + return; + } + + NSString *urlString = [[baseURL stringByAppendingString:@"/status?auth="] stringByAppendingString:key]; + + NSURL *url = [NSURL URLWithString:urlString]; + NSURLSessionDataTask *task = + [session dataTaskWithURL:url + completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable err) { + + if(err) { + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + NSAlert *alert = [NSAlert alertWithError:err]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Quit"]; + [alert addButtonWithTitle:@"Retry"]; + + NSModalResponse res; + if (!_isQuitting) { + res = [alert runModal]; + } + else { + return; + } + + if(res == NSAlertFirstButtonReturn) { + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; + _isQuitting = YES; + } + }]; + return; + } + + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; + NSInteger status = [httpResponse statusCode]; + + NSError *err2; + if(status == 200) { + NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&err2]; + + if(err2) { + NSLog(@"Error fetching node status: %@", err2); + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + NSAlert *alert = [NSAlert alertWithError:err2]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Quit"]; + [alert addButtonWithTitle:@"Retry"]; + + NSModalResponse res; + if (!_isQuitting) { + res = [alert runModal]; + } + else { + return; + } + + if(res == NSAlertFirstButtonReturn) { + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; + _isQuitting = YES; + } + }]; + return; + } + + NodeStatus *status = [[NodeStatus alloc] initWithJsonData:json]; + + completionHandler(status); + } + }]; + [task resume]; +} + +- (void)joinNetwork:(NSString*)networkId allowManaged:(BOOL)allowManaged allowGlobal:(BOOL)allowGlobal allowDefault:(BOOL)allowDefault error:(NSError *__autoreleasing*)error +{ + NSString *key = [self key:error]; + if(*error) { + return; + } + + NSString *urlString = [[[[baseURL stringByAppendingString:@"/network/"] + stringByAppendingString:networkId] + stringByAppendingString:@"?auth="] + stringByAppendingString: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); + *error = 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 err) { + if(err) { + NSLog(@"Error posting join request: %@", err); + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + NSAlert *alert = [NSAlert alertWithError:err]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Quit"]; + [alert addButtonWithTitle:@"Retry"]; + + NSModalResponse res; + if (!_isQuitting) { + res = [alert runModal]; + } + else { + return; + } + + if(res == NSAlertFirstButtonReturn) { + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; + _isQuitting = YES; + } + }]; + } + + 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 error:(NSError*__autoreleasing*)error +{ + NSString *key = [self key:error]; + if(*error) { + return; + } + + NSString *urlString = [[[[baseURL stringByAppendingString:@"/network/"] + stringByAppendingString:networkId] + stringByAppendingString:@"?auth="] + stringByAppendingString: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 err) { + if(err) { + NSLog(@"Error posting delete request: %@", err); + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + NSAlert *alert = [NSAlert alertWithError:err]; + alert.alertStyle = NSCriticalAlertStyle; + [alert addButtonWithTitle:@"Quit"]; + [alert addButtonWithTitle:@"Retry"]; + + NSModalResponse res; + if (!_isQuitting) { + res = [alert runModal]; + } + else { + return; + } + + if(res == NSAlertFirstButtonReturn) { + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; + _isQuitting = YES; + } + }]; + 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/macui/ZeroTier One/ShowNetworksViewController.h b/macui/ZeroTier One/ShowNetworksViewController.h new file mode 100644 index 00000000..5c251674 --- /dev/null +++ b/macui/ZeroTier One/ShowNetworksViewController.h @@ -0,0 +1,36 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + +@class NetworkMonitor; +@class Network; + +@interface ShowNetworksViewController : NSViewController + +@property (nonatomic) NSArray *networkList; +@property (nonatomic) NetworkMonitor *netMonitor; +@property (nonatomic) BOOL visible; + +@property (weak, nonatomic) IBOutlet NSTableView *tableView; + +- (void)deleteNetworkFromList:(NSString*)nwid; +- (void)setNetworks:(NSArray*)list; + + +@end diff --git a/macui/ZeroTier One/ShowNetworksViewController.m b/macui/ZeroTier One/ShowNetworksViewController.m new file mode 100644 index 00000000..e3a1e52c --- /dev/null +++ b/macui/ZeroTier One/ShowNetworksViewController.m @@ -0,0 +1,119 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "ShowNetworksViewController.h" +#import "NetworkMonitor.h" +#import "NetworkInfoCell.h" +#import "Network.h" + +@interface ShowNetworksViewController () + +@end + +@implementation ShowNetworksViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self.tableView setDelegate:self]; + [self.tableView setDataSource:self]; + [self.tableView setBackgroundColor:[NSColor clearColor]]; +} + +- (void)viewWillAppear { + [super viewWillAppear]; + self.visible = YES; +} + +- (void)viewWillDisappear { + [super viewWillDisappear]; + self.visible = NO; +} + +- (void)deleteNetworkFromList:(NSString *)nwid { + [self.netMonitor deleteSavedNetwork:nwid]; +} + +- (void)setNetworks:(NSArray *)list { + _networkList = list; + if(_visible) { + [_tableView reloadData]; + } +} + +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { + return [_networkList count]; +} + +- (NSView*)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row +{ + NetworkInfoCell *cell = (NetworkInfoCell*)[tableView makeViewWithIdentifier:@"NetworkInfoCell" + owner:nil]; + Network *network = [_networkList objectAtIndex:row]; + cell.parent = self; + cell.networkIdField.stringValue = [NSString stringWithFormat:@"%10llx", network.nwid]; + cell.networkNameField.stringValue = network.name; + cell.statusField.stringValue = [network statusString]; + cell.typeField.stringValue = [network typeString]; + cell.mtuField.stringValue = [NSString stringWithFormat:@"%d", network.mtu]; + cell.macField.stringValue = network.mac; + cell.broadcastField.stringValue = network.broadcastEnabled ? @"ENABLED" : @"DISABLED"; + cell.bridgingField.stringValue = network.bridge ? @"ENABLED" : @"DISABLED"; + cell.deviceField.stringValue = network.portDeviceName; + + if(network.connected) { + cell.connectedCheckbox.state = NSOnState; + + if(network.allowDefault) { + cell.allowDefault.enabled = YES; + cell.allowDefault.state = NSOnState; + } + else { + cell.allowDefault.state = NSOffState; + + if([Network defaultRouteExists:_networkList]) { + cell.allowDefault.enabled = NO; + } + else { + cell.allowDefault.enabled = YES; + } + } + + cell.allowGlobal.enabled = YES; + cell.allowManaged.enabled = YES; + } + else { + cell.connectedCheckbox.state = NSOffState; + cell.allowDefault.enabled = NO; + cell.allowGlobal.enabled = NO; + cell.allowManaged.enabled = NO; + } + + cell.allowGlobal.state = network.allowGlobal ? NSOnState : NSOffState; + cell.allowManaged.state = network.allowManaged ? NSOnState : NSOffState; + + cell.addressesField.stringValue = @""; + + for(NSString *addr in network.assignedAddresses) { + cell.addressesField.stringValue = [[cell.addressesField.stringValue stringByAppendingString:addr] stringByAppendingString:@"\n"]; + } + + return cell; +} + +@end diff --git a/macui/ZeroTier One/ShowNetworksViewController.xib b/macui/ZeroTier One/ShowNetworksViewController.xib new file mode 100644 index 00000000..f26cb446 --- /dev/null +++ b/macui/ZeroTier One/ShowNetworksViewController.xib @@ -0,0 +1,370 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macui/ZeroTier One/ZeroTierIcon.icns b/macui/ZeroTier One/ZeroTierIcon.icns new file mode 100644 index 00000000..17e60d58 Binary files /dev/null and b/macui/ZeroTier One/ZeroTierIcon.icns differ diff --git a/macui/ZeroTier One/about.html b/macui/ZeroTier One/about.html new file mode 100644 index 00000000..4fa41d7b --- /dev/null +++ b/macui/ZeroTier One/about.html @@ -0,0 +1,65 @@ + + + + + + +
+
+
+
+
+ +
+

Getting Started

+ +

Getting started is simple. Simply click Join Network from the ZeroTier status bar menu. To join the public network "Earth", enter 8056c2e21c000001 and click the Join button. Once connected, you'll be able to navigate to earth.zerotier.net.

+ +

Create a Network

+

Visit my.zerotier.com to create and manage your own virtual networks.

+ +

For more information, visit zerotier.com.

+ +
+ + \ No newline at end of file diff --git a/macui/ZeroTier One/main.m b/macui/ZeroTier One/main.m new file mode 100644 index 00000000..108a6bd1 --- /dev/null +++ b/macui/ZeroTier One/main.m @@ -0,0 +1,23 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} -- cgit v1.2.3