mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-07 04:53:44 +02:00
Merge branch 'dev' into systemtray
This commit is contained in:
commit
b4bacd50a1
36 changed files with 1781 additions and 1139 deletions
File diff suppressed because it is too large
Load diff
|
@ -37,11 +37,15 @@
|
||||||
|
|
||||||
#include "../osdep/OSUtils.hpp"
|
#include "../osdep/OSUtils.hpp"
|
||||||
#include "../osdep/Thread.hpp"
|
#include "../osdep/Thread.hpp"
|
||||||
|
#include "../osdep/BlockingQueue.hpp"
|
||||||
|
|
||||||
#include "../ext/json/json.hpp"
|
#include "../ext/json/json.hpp"
|
||||||
|
|
||||||
#include "JSONDB.hpp"
|
#include "JSONDB.hpp"
|
||||||
|
|
||||||
|
// Number of background threads to start -- not actually started until needed
|
||||||
|
#define ZT_EMBEDDEDNETWORKCONTROLLER_BACKGROUND_THREAD_COUNT 2
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class Node;
|
class Node;
|
||||||
|
@ -52,13 +56,14 @@ public:
|
||||||
EmbeddedNetworkController(Node *node,const char *dbPath);
|
EmbeddedNetworkController(Node *node,const char *dbPath);
|
||||||
virtual ~EmbeddedNetworkController();
|
virtual ~EmbeddedNetworkController();
|
||||||
|
|
||||||
virtual NetworkController::ResultCode doNetworkConfigRequest(
|
virtual void init(const Identity &signingId,Sender *sender);
|
||||||
const InetAddress &fromAddr,
|
|
||||||
const Identity &signingId,
|
virtual void request(
|
||||||
const Identity &identity,
|
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData,
|
const InetAddress &fromAddr,
|
||||||
NetworkConfig &nc);
|
uint64_t requestPacketId,
|
||||||
|
const Identity &identity,
|
||||||
|
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
|
||||||
|
|
||||||
unsigned int handleControlPlaneHttpGET(
|
unsigned int handleControlPlaneHttpGET(
|
||||||
const std::vector<std::string> &path,
|
const std::vector<std::string> &path,
|
||||||
|
@ -82,8 +87,31 @@ public:
|
||||||
std::string &responseBody,
|
std::string &responseBody,
|
||||||
std::string &responseContentType);
|
std::string &responseContentType);
|
||||||
|
|
||||||
|
void threadMain()
|
||||||
|
throw();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void _circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report);
|
static void _circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report);
|
||||||
|
void _request(
|
||||||
|
uint64_t nwid,
|
||||||
|
const InetAddress &fromAddr,
|
||||||
|
uint64_t requestPacketId,
|
||||||
|
const Identity &identity,
|
||||||
|
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
|
||||||
|
|
||||||
|
struct _RQEntry
|
||||||
|
{
|
||||||
|
uint64_t nwid;
|
||||||
|
uint64_t requestPacketId;
|
||||||
|
InetAddress fromAddr;
|
||||||
|
Identity identity;
|
||||||
|
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData;
|
||||||
|
};
|
||||||
|
BlockingQueue<_RQEntry *> _queue;
|
||||||
|
|
||||||
|
Thread _threads[ZT_EMBEDDEDNETWORKCONTROLLER_BACKGROUND_THREAD_COUNT];
|
||||||
|
bool _threadsStarted;
|
||||||
|
Mutex _threads_m;
|
||||||
|
|
||||||
// Gathers a bunch of statistics about members of a network, IP assignments, etc. that we need in various places
|
// Gathers a bunch of statistics about members of a network, IP assignments, etc. that we need in various places
|
||||||
// This does lock _networkMemberCache_m
|
// This does lock _networkMemberCache_m
|
||||||
|
@ -96,9 +124,14 @@ private:
|
||||||
unsigned long activeMemberCount;
|
unsigned long activeMemberCount;
|
||||||
unsigned long totalMemberCount;
|
unsigned long totalMemberCount;
|
||||||
uint64_t mostRecentDeauthTime;
|
uint64_t mostRecentDeauthTime;
|
||||||
|
uint64_t nmiTimestamp; // time this NMI structure was computed
|
||||||
};
|
};
|
||||||
|
std::map<uint64_t,_NetworkMemberInfo> _nmiCache;
|
||||||
|
Mutex _nmiCache_m;
|
||||||
void _getNetworkMemberInfo(uint64_t now,uint64_t nwid,_NetworkMemberInfo &nmi);
|
void _getNetworkMemberInfo(uint64_t now,uint64_t nwid,_NetworkMemberInfo &nmi);
|
||||||
|
|
||||||
|
void _pushMemberUpdate(uint64_t now,uint64_t nwid,const nlohmann::json &member);
|
||||||
|
|
||||||
// These init objects with default and static/informational fields
|
// These init objects with default and static/informational fields
|
||||||
inline void _initMember(nlohmann::json &member)
|
inline void _initMember(nlohmann::json &member)
|
||||||
{
|
{
|
||||||
|
@ -112,7 +145,8 @@ private:
|
||||||
if (!member.count("creationTime")) member["creationTime"] = OSUtils::now();
|
if (!member.count("creationTime")) member["creationTime"] = OSUtils::now();
|
||||||
if (!member.count("noAutoAssignIps")) member["noAutoAssignIps"] = false;
|
if (!member.count("noAutoAssignIps")) member["noAutoAssignIps"] = false;
|
||||||
if (!member.count("revision")) member["revision"] = 0ULL;
|
if (!member.count("revision")) member["revision"] = 0ULL;
|
||||||
if (!member.count("enableBroadcast")) member["enableBroadcast"] = true;
|
if (!member.count("lastDeauthorizedTime")) member["lastDeauthorizedTime"] = 0ULL;
|
||||||
|
if (!member.count("lastAuthorizedTime")) member["lastAuthorizedTime"] = 0ULL;
|
||||||
member["objtype"] = "member";
|
member["objtype"] = "member";
|
||||||
}
|
}
|
||||||
inline void _initNetwork(nlohmann::json &network)
|
inline void _initNetwork(nlohmann::json &network)
|
||||||
|
@ -121,6 +155,7 @@ private:
|
||||||
if (!network.count("creationTime")) network["creationTime"] = OSUtils::now();
|
if (!network.count("creationTime")) network["creationTime"] = OSUtils::now();
|
||||||
if (!network.count("name")) network["name"] = "";
|
if (!network.count("name")) network["name"] = "";
|
||||||
if (!network.count("multicastLimit")) network["multicastLimit"] = (uint64_t)32;
|
if (!network.count("multicastLimit")) network["multicastLimit"] = (uint64_t)32;
|
||||||
|
if (!network.count("enableBroadcast")) network["enableBroadcast"] = true;
|
||||||
if (!network.count("v4AssignMode")) network["v4AssignMode"] = {{"zt",false}};
|
if (!network.count("v4AssignMode")) network["v4AssignMode"] = {{"zt",false}};
|
||||||
if (!network.count("v6AssignMode")) network["v6AssignMode"] = {{"rfc4193",false},{"zt",false},{"6plane",false}};
|
if (!network.count("v6AssignMode")) network["v6AssignMode"] = {{"rfc4193",false},{"zt",false},{"6plane",false}};
|
||||||
if (!network.count("authTokens")) network["authTokens"] = nlohmann::json::array();
|
if (!network.count("authTokens")) network["authTokens"] = nlohmann::json::array();
|
||||||
|
@ -154,6 +189,9 @@ private:
|
||||||
Node *const _node;
|
Node *const _node;
|
||||||
std::string _path;
|
std::string _path;
|
||||||
|
|
||||||
|
NetworkController::Sender *_sender;
|
||||||
|
Identity _signingId;
|
||||||
|
|
||||||
struct _CircuitTestEntry
|
struct _CircuitTestEntry
|
||||||
{
|
{
|
||||||
ZT_CircuitTest *test;
|
ZT_CircuitTest *test;
|
||||||
|
|
|
@ -79,7 +79,7 @@ public:
|
||||||
{
|
{
|
||||||
for(std::map<std::string,_E>::iterator i(_db.lower_bound(prefix));i!=_db.end();) {
|
for(std::map<std::string,_E>::iterator i(_db.lower_bound(prefix));i!=_db.end();) {
|
||||||
if ((i->first.length() >= prefix.length())&&(!memcmp(i->first.data(),prefix.data(),prefix.length()))) {
|
if ((i->first.length() >= prefix.length())&&(!memcmp(i->first.data(),prefix.data(),prefix.length()))) {
|
||||||
if (!func(i->first,get(i->second.obj,maxSinceCheck))) {
|
if (!func(i->first,get(i->first,maxSinceCheck))) {
|
||||||
std::map<std::string,_E>::iterator i2(i); ++i2;
|
std::map<std::string,_E>::iterator i2(i); ++i2;
|
||||||
this->erase(i->first);
|
this->erase(i->first);
|
||||||
i = i2;
|
i = i2;
|
||||||
|
|
|
@ -1018,16 +1018,6 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
uint64_t address;
|
uint64_t address;
|
||||||
|
|
||||||
/**
|
|
||||||
* Time we last received a unicast frame from this peer
|
|
||||||
*/
|
|
||||||
uint64_t lastUnicastFrame;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Time we last received a multicast rame from this peer
|
|
||||||
*/
|
|
||||||
uint64_t lastMulticastFrame;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote major version or -1 if not known
|
* Remote major version or -1 if not known
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -475,8 +475,6 @@ jobject newPeer(JNIEnv *env, const ZT_Peer &peer)
|
||||||
jclass peerClass = NULL;
|
jclass peerClass = NULL;
|
||||||
|
|
||||||
jfieldID addressField = NULL;
|
jfieldID addressField = NULL;
|
||||||
jfieldID lastUnicastFrameField = NULL;
|
|
||||||
jfieldID lastMulticastFrameField = NULL;
|
|
||||||
jfieldID versionMajorField = NULL;
|
jfieldID versionMajorField = NULL;
|
||||||
jfieldID versionMinorField = NULL;
|
jfieldID versionMinorField = NULL;
|
||||||
jfieldID versionRevField = NULL;
|
jfieldID versionRevField = NULL;
|
||||||
|
@ -500,20 +498,6 @@ jobject newPeer(JNIEnv *env, const ZT_Peer &peer)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastUnicastFrameField = lookup.findField(peerClass, "lastUnicastFrame", "J");
|
|
||||||
if(env->ExceptionCheck() || lastUnicastFrameField == NULL)
|
|
||||||
{
|
|
||||||
LOGE("Error finding lastUnicastFrame field of Peer object");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastMulticastFrameField = lookup.findField(peerClass, "lastMulticastFrame", "J");
|
|
||||||
if(env->ExceptionCheck() || lastMulticastFrameField == NULL)
|
|
||||||
{
|
|
||||||
LOGE("Error finding lastMulticastFrame field of Peer object");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
versionMajorField = lookup.findField(peerClass, "versionMajor", "I");
|
versionMajorField = lookup.findField(peerClass, "versionMajor", "I");
|
||||||
if(env->ExceptionCheck() || versionMajorField == NULL)
|
if(env->ExceptionCheck() || versionMajorField == NULL)
|
||||||
{
|
{
|
||||||
|
@ -571,8 +555,6 @@ jobject newPeer(JNIEnv *env, const ZT_Peer &peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
env->SetLongField(peerObject, addressField, (jlong)peer.address);
|
env->SetLongField(peerObject, addressField, (jlong)peer.address);
|
||||||
env->SetLongField(peerObject, lastUnicastFrameField, (jlong)peer.lastUnicastFrame);
|
|
||||||
env->SetLongField(peerObject, lastMulticastFrameField, (jlong)peer.lastMulticastFrame);
|
|
||||||
env->SetIntField(peerObject, versionMajorField, peer.versionMajor);
|
env->SetIntField(peerObject, versionMajorField, peer.versionMajor);
|
||||||
env->SetIntField(peerObject, versionMinorField, peer.versionMinor);
|
env->SetIntField(peerObject, versionMinorField, peer.versionMinor);
|
||||||
env->SetIntField(peerObject, versionRevField, peer.versionRev);
|
env->SetIntField(peerObject, versionRevField, peer.versionRev);
|
||||||
|
|
|
@ -34,8 +34,6 @@ import java.util.ArrayList;
|
||||||
*/
|
*/
|
||||||
public final class Peer {
|
public final class Peer {
|
||||||
private long address;
|
private long address;
|
||||||
private long lastUnicastFrame;
|
|
||||||
private long lastMulticastFrame;
|
|
||||||
private int versionMajor;
|
private int versionMajor;
|
||||||
private int versionMinor;
|
private int versionMinor;
|
||||||
private int versionRev;
|
private int versionRev;
|
||||||
|
@ -52,20 +50,6 @@ public final class Peer {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Time we last received a unicast frame from this peer
|
|
||||||
*/
|
|
||||||
public final long lastUnicastFrame() {
|
|
||||||
return lastUnicastFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Time we last received a multicast rame from this peer
|
|
||||||
*/
|
|
||||||
public final long lastMulticastFrame() {
|
|
||||||
return lastMulticastFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote major version or -1 if not known
|
* Remote major version or -1 if not known
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -59,4 +59,10 @@ enum NetworkType {
|
||||||
- (NSString*)statusString;
|
- (NSString*)statusString;
|
||||||
- (NSString*)typeString;
|
- (NSString*)typeString;
|
||||||
|
|
||||||
|
- (BOOL)hasSameNetworkId:(UInt64)networkId;
|
||||||
|
|
||||||
|
- (BOOL)isEqualToNetwork:(Network*)network;
|
||||||
|
- (BOOL)isEqual:(id)object;
|
||||||
|
- (NSUInteger)hash;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -275,4 +275,63 @@ NSString *NetworkAllowDefaultKey = @"allowDefault";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasSameNetworkId:(UInt64)networkId
|
||||||
|
{
|
||||||
|
return self.nwid == networkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqualToNetwork:(Network*)network
|
||||||
|
{
|
||||||
|
return [self.assignedAddresses isEqualToArray:network.assignedAddresses] &&
|
||||||
|
self.bridge == network.bridge &&
|
||||||
|
self.broadcastEnabled == network.broadcastEnabled &&
|
||||||
|
self.dhcp == network.dhcp &&
|
||||||
|
[self.mac isEqualToString:network.mac] &&
|
||||||
|
self.mtu == network.mtu &&
|
||||||
|
self.netconfRevision == network.netconfRevision &&
|
||||||
|
[self.name isEqualToString:network.name] &&
|
||||||
|
self.nwid == network.nwid &&
|
||||||
|
[self.portDeviceName isEqualToString:network.portDeviceName] &&
|
||||||
|
self.status == network.status &&
|
||||||
|
self.type == network.type &&
|
||||||
|
self.allowManaged == network.allowManaged &&
|
||||||
|
self.allowGlobal == network.allowGlobal &&
|
||||||
|
self.allowDefault == network.allowDefault &&
|
||||||
|
self.connected == network.connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqual:(id)object
|
||||||
|
{
|
||||||
|
if (self == object) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![object isKindOfClass:[Network class]]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [self isEqualToNetwork:object];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)hash
|
||||||
|
{
|
||||||
|
return [self.assignedAddresses hash] ^
|
||||||
|
self.bridge ^
|
||||||
|
self.broadcastEnabled ^
|
||||||
|
self.dhcp ^
|
||||||
|
[self.mac hash] ^
|
||||||
|
self.mtu ^
|
||||||
|
self.netconfRevision ^
|
||||||
|
[self.name hash] ^
|
||||||
|
self.nwid ^
|
||||||
|
[self.portDeviceName hash] ^
|
||||||
|
self.portError ^
|
||||||
|
self.status ^
|
||||||
|
self.type ^
|
||||||
|
self.allowManaged ^
|
||||||
|
self.allowGlobal ^
|
||||||
|
self.allowDefault ^
|
||||||
|
self.connected;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
@interface ShowNetworksViewController : NSViewController<NSTableViewDelegate, NSTableViewDataSource>
|
@interface ShowNetworksViewController : NSViewController<NSTableViewDelegate, NSTableViewDataSource>
|
||||||
|
|
||||||
@property (nonatomic) NSArray<Network*> *networkList;
|
@property (nonatomic) NSMutableArray<Network*> *networkList;
|
||||||
@property (nonatomic) NetworkMonitor *netMonitor;
|
@property (nonatomic) NetworkMonitor *netMonitor;
|
||||||
@property (nonatomic) BOOL visible;
|
@property (nonatomic) BOOL visible;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,17 @@
|
||||||
#import "NetworkInfoCell.h"
|
#import "NetworkInfoCell.h"
|
||||||
#import "Network.h"
|
#import "Network.h"
|
||||||
|
|
||||||
|
BOOL hasNetworkWithID(NSArray<Network*> *list, UInt64 nwid)
|
||||||
|
{
|
||||||
|
for(Network *n in list) {
|
||||||
|
if(n.nwid == nwid) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
@interface ShowNetworksViewController ()
|
@interface ShowNetworksViewController ()
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -30,6 +41,8 @@
|
||||||
- (void)viewDidLoad {
|
- (void)viewDidLoad {
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
|
|
||||||
|
self.networkList = [NSMutableArray array];
|
||||||
|
|
||||||
[self.tableView setDelegate:self];
|
[self.tableView setDelegate:self];
|
||||||
[self.tableView setDataSource:self];
|
[self.tableView setDataSource:self];
|
||||||
[self.tableView setBackgroundColor:[NSColor clearColor]];
|
[self.tableView setBackgroundColor:[NSColor clearColor]];
|
||||||
|
@ -50,9 +63,30 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setNetworks:(NSArray<Network *> *)list {
|
- (void)setNetworks:(NSArray<Network *> *)list {
|
||||||
_networkList = list;
|
for (Network *n in list) {
|
||||||
if(_visible) {
|
if ([_networkList containsObject:n]) {
|
||||||
[_tableView reloadData];
|
// don't need to do anything here. Already an identical object in the list
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// network not in the list based on equality. Did an object change? or is it a new item?
|
||||||
|
if (hasNetworkWithID(_networkList, n.nwid)) {
|
||||||
|
|
||||||
|
for (int i = 0; i < [_networkList count]; ++i) {
|
||||||
|
Network *n2 = [_networkList objectAtIndex:i];
|
||||||
|
if (n.nwid == n2.nwid)
|
||||||
|
{
|
||||||
|
[_networkList replaceObjectAtIndex:i withObject:n];
|
||||||
|
[_tableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:i]
|
||||||
|
columnIndexes:[NSIndexSet indexSetWithIndex:0]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[_networkList addObject:n];
|
||||||
|
[_tableView reloadData];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10116" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11542" systemVersion="16B2555" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10116"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11542"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="ShowNetworksViewController" customModule="ZeroTier_One" customModuleProvider="target">
|
<customObject id="-2" userLabel="File's Owner" customClass="ShowNetworksViewController" customModule="ZeroTier_One" customModuleProvider="target">
|
||||||
|
@ -24,7 +25,7 @@
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" columnReordering="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="386" rowSizeStyle="automatic" viewBased="YES" id="w5O-vn-cYB">
|
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" columnReordering="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="386" rowSizeStyle="automatic" viewBased="YES" id="w5O-vn-cYB">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="530" height="0.0"/>
|
<rect key="frame" x="0.0" y="0.0" width="530" height="481"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<size key="intercellSpacing" width="3" height="2"/>
|
<size key="intercellSpacing" width="3" height="2"/>
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.59999999999999998" colorSpace="calibratedRGB"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.59999999999999998" colorSpace="calibratedRGB"/>
|
||||||
|
@ -50,7 +51,7 @@
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="EUT-1A-lgY">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="EUT-1A-lgY">
|
||||||
<rect key="frame" x="480" y="364" width="44" height="19"/>
|
<rect key="frame" x="480" y="364" width="44" height="19"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="bf8-gi-tpp">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Label" id="bf8-gi-tpp">
|
||||||
<font key="font" size="13" name="AndaleMono"/>
|
<font key="font" size="13" name="AndaleMono"/>
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
@ -242,7 +243,7 @@
|
||||||
</textField>
|
</textField>
|
||||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="GEJ-6D-gWU">
|
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="GEJ-6D-gWU">
|
||||||
<rect key="frame" x="102" y="86" width="424" height="19"/>
|
<rect key="frame" x="102" y="86" width="424" height="19"/>
|
||||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Multiline Label" id="A3M-ZZ-6h7">
|
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="right" title="Multiline Label" id="A3M-ZZ-6h7">
|
||||||
<font key="font" size="13" name="AndaleMono"/>
|
<font key="font" size="13" name="AndaleMono"/>
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
@ -250,7 +251,7 @@
|
||||||
</textField>
|
</textField>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lO9-Jg-9f8">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lO9-Jg-9f8">
|
||||||
<rect key="frame" x="1" y="364" width="44" height="19"/>
|
<rect key="frame" x="1" y="364" width="44" height="19"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="p7O-rs-RvR">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Label" id="p7O-rs-RvR">
|
||||||
<font key="font" size="13" name="AndaleMono"/>
|
<font key="font" size="13" name="AndaleMono"/>
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
|
|
@ -84,6 +84,10 @@ ifeq ($(ZT_TRACE),1)
|
||||||
DEFS+=-DZT_TRACE
|
DEFS+=-DZT_TRACE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ZT_RULES_ENGINE_DEBUGGING),1)
|
||||||
|
DEFS+=-DZT_RULES_ENGINE_DEBUGGING
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(ZT_DEBUG),1)
|
ifeq ($(ZT_DEBUG),1)
|
||||||
DEFS+=-DZT_TRACE
|
DEFS+=-DZT_TRACE
|
||||||
override CFLAGS+=-Wall -g -O -pthread $(INCLUDES) $(DEFS)
|
override CFLAGS+=-Wall -g -O -pthread $(INCLUDES) $(DEFS)
|
||||||
|
|
|
@ -256,12 +256,12 @@
|
||||||
/**
|
/**
|
||||||
* How frequently to send heartbeats over in-use paths
|
* How frequently to send heartbeats over in-use paths
|
||||||
*/
|
*/
|
||||||
#define ZT_PATH_HEARTBEAT_PERIOD 10000
|
#define ZT_PATH_HEARTBEAT_PERIOD 14000
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paths are considered inactive if they have not received traffic in this long
|
* Paths are considered inactive if they have not received traffic in this long
|
||||||
*/
|
*/
|
||||||
#define ZT_PATH_ALIVE_TIMEOUT 25000
|
#define ZT_PATH_ALIVE_TIMEOUT 45000
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimum time between attempts to check dead paths to see if they can be re-awakened
|
* Minimum time between attempts to check dead paths to see if they can be re-awakened
|
||||||
|
|
|
@ -865,92 +865,12 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
|
||||||
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
|
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
|
||||||
const unsigned int hopCount = hops();
|
const unsigned int hopCount = hops();
|
||||||
const uint64_t requestPacketId = packetId();
|
const uint64_t requestPacketId = packetId();
|
||||||
bool trustEstablished = false;
|
|
||||||
|
|
||||||
if (RR->localNetworkController) {
|
if (RR->localNetworkController) {
|
||||||
const unsigned int metaDataLength = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN);
|
const unsigned int metaDataLength = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN);
|
||||||
const char *metaDataBytes = (const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength);
|
const char *metaDataBytes = (const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength);
|
||||||
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData(metaDataBytes,metaDataLength);
|
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData(metaDataBytes,metaDataLength);
|
||||||
|
RR->localNetworkController->request(nwid,(hopCount > 0) ? InetAddress() : _path->address(),requestPacketId,peer->identity(),metaData);
|
||||||
NetworkConfig *netconf = new NetworkConfig();
|
|
||||||
try {
|
|
||||||
switch(RR->localNetworkController->doNetworkConfigRequest((hopCount > 0) ? InetAddress() : _path->address(),RR->identity,peer->identity(),nwid,metaData,*netconf)) {
|
|
||||||
|
|
||||||
case NetworkController::NETCONF_QUERY_OK: {
|
|
||||||
trustEstablished = true;
|
|
||||||
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
|
||||||
try {
|
|
||||||
if (netconf->toDictionary(*dconf,metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,0) < 6)) {
|
|
||||||
uint64_t configUpdateId = RR->node->prng();
|
|
||||||
if (!configUpdateId) ++configUpdateId;
|
|
||||||
const unsigned int totalSize = dconf->sizeBytes();
|
|
||||||
unsigned int chunkIndex = 0;
|
|
||||||
while (chunkIndex < totalSize) {
|
|
||||||
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_UDP_DEFAULT_PAYLOAD_MTU - (ZT_PACKET_IDX_PAYLOAD + 256)));
|
|
||||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
|
|
||||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
|
||||||
outp.append(requestPacketId);
|
|
||||||
|
|
||||||
const unsigned int sigStart = outp.size();
|
|
||||||
outp.append(nwid);
|
|
||||||
outp.append((uint16_t)chunkLen);
|
|
||||||
outp.append((const void *)(dconf->data() + chunkIndex),chunkLen);
|
|
||||||
|
|
||||||
outp.append((uint8_t)0); // no flags
|
|
||||||
outp.append((uint64_t)configUpdateId);
|
|
||||||
outp.append((uint32_t)totalSize);
|
|
||||||
outp.append((uint32_t)chunkIndex);
|
|
||||||
|
|
||||||
C25519::Signature sig(RR->identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) + sigStart,outp.size() - sigStart));
|
|
||||||
outp.append((uint8_t)1);
|
|
||||||
outp.append((uint16_t)ZT_C25519_SIGNATURE_LEN);
|
|
||||||
outp.append(sig.data,ZT_C25519_SIGNATURE_LEN);
|
|
||||||
|
|
||||||
outp.compress();
|
|
||||||
RR->sw->send(outp,true);
|
|
||||||
chunkIndex += chunkLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete dconf;
|
|
||||||
} catch ( ... ) {
|
|
||||||
delete dconf;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: {
|
|
||||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
|
|
||||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
|
||||||
outp.append(requestPacketId);
|
|
||||||
outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
|
|
||||||
outp.append(nwid);
|
|
||||||
outp.armor(peer->key(),true);
|
|
||||||
_path->send(RR,outp.data(),outp.size(),RR->node->now());
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NetworkController::NETCONF_QUERY_ACCESS_DENIED: {
|
|
||||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
|
|
||||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
|
||||||
outp.append(requestPacketId);
|
|
||||||
outp.append((unsigned char)Packet::ERROR_NETWORK_ACCESS_DENIED_);
|
|
||||||
outp.append(nwid);
|
|
||||||
outp.armor(peer->key(),true);
|
|
||||||
_path->send(RR,outp.data(),outp.size(),RR->node->now());
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR:
|
|
||||||
break;
|
|
||||||
case NetworkController::NETCONF_QUERY_IGNORE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
TRACE("NETWORK_CONFIG_REQUEST failed: invalid return value from NetworkController::doNetworkConfigRequest()");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
delete netconf;
|
|
||||||
} catch ( ... ) {
|
|
||||||
delete netconf;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
|
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
|
||||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||||
|
@ -961,7 +881,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
|
||||||
_path->send(RR,outp.data(),outp.size(),RR->node->now());
|
_path->send(RR,outp.data(),outp.size(),RR->node->now());
|
||||||
}
|
}
|
||||||
|
|
||||||
peer->received(_path,hopCount,requestPacketId,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,trustEstablished);
|
peer->received(_path,hopCount,requestPacketId,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,false);
|
||||||
} catch (std::exception &exc) {
|
} catch (std::exception &exc) {
|
||||||
fprintf(stderr,"WARNING: network config request failed with exception: %s" ZT_EOL_S,exc.what());
|
fprintf(stderr,"WARNING: network config request failed with exception: %s" ZT_EOL_S,exc.what());
|
||||||
TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): %s",source().toString().c_str(),_path->address().toString().c_str(),exc.what());
|
TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): %s",source().toString().c_str(),_path->address().toString().c_str(),exc.what());
|
||||||
|
|
105
node/Network.cpp
105
node/Network.cpp
|
@ -599,7 +599,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
|
||||||
if (conf.length()) {
|
if (conf.length()) {
|
||||||
dconf->load(conf.c_str());
|
dconf->load(conf.c_str());
|
||||||
if (nconf->fromDictionary(*dconf)) {
|
if (nconf->fromDictionary(*dconf)) {
|
||||||
this->_setConfiguration(*nconf,false);
|
this->setConfiguration(*nconf,false);
|
||||||
_lastConfigUpdate = 0; // we still want to re-request a new config from the network
|
_lastConfigUpdate = 0; // we still want to re-request a new config from the network
|
||||||
gotConf = true;
|
gotConf = true;
|
||||||
}
|
}
|
||||||
|
@ -1015,7 +1015,7 @@ uint64_t Network::handleConfigChunk(const Packet &chunk,unsigned int ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nc) {
|
if (nc) {
|
||||||
this->_setConfiguration(*nc,true);
|
this->setConfiguration(*nc,true);
|
||||||
delete nc;
|
delete nc;
|
||||||
return configUpdateId;
|
return configUpdateId;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1025,6 +1025,46 @@ uint64_t Network::handleConfigChunk(const Packet &chunk,unsigned int ptr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
|
||||||
|
{
|
||||||
|
// _lock is NOT locked when this is called
|
||||||
|
try {
|
||||||
|
if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != _id))
|
||||||
|
return 0;
|
||||||
|
if (_config == nconf)
|
||||||
|
return 1; // OK config, but duplicate of what we already have
|
||||||
|
|
||||||
|
ZT_VirtualNetworkConfig ctmp;
|
||||||
|
bool oldPortInitialized;
|
||||||
|
{
|
||||||
|
Mutex::Lock _l(_lock);
|
||||||
|
_config = nconf;
|
||||||
|
_lastConfigUpdate = RR->node->now();
|
||||||
|
_netconfFailure = NETCONF_FAILURE_NONE;
|
||||||
|
oldPortInitialized = _portInitialized;
|
||||||
|
_portInitialized = true;
|
||||||
|
_externalConfig(&ctmp);
|
||||||
|
}
|
||||||
|
_portError = RR->node->configureVirtualNetworkPort(_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
|
||||||
|
|
||||||
|
if (saveToDisk) {
|
||||||
|
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *d = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
||||||
|
try {
|
||||||
|
char n[64];
|
||||||
|
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
|
||||||
|
if (nconf.toDictionary(*d,false))
|
||||||
|
RR->node->dataStorePut(n,(const void *)d->data(),d->sizeBytes(),true);
|
||||||
|
} catch ( ... ) {}
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2; // OK and configuration has changed
|
||||||
|
} catch ( ... ) {
|
||||||
|
TRACE("ignored invalid configuration for network %.16llx",(unsigned long long)_id);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Network::requestConfiguration()
|
void Network::requestConfiguration()
|
||||||
{
|
{
|
||||||
const Address ctrl(controller());
|
const Address ctrl(controller());
|
||||||
|
@ -1046,26 +1086,7 @@ void Network::requestConfiguration()
|
||||||
|
|
||||||
if (ctrl == RR->identity.address()) {
|
if (ctrl == RR->identity.address()) {
|
||||||
if (RR->localNetworkController) {
|
if (RR->localNetworkController) {
|
||||||
NetworkConfig *nconf = new NetworkConfig();
|
RR->localNetworkController->request(_id,InetAddress(),0xffffffffffffffffULL,RR->identity,rmd);
|
||||||
try {
|
|
||||||
switch(RR->localNetworkController->doNetworkConfigRequest(InetAddress(),RR->identity,RR->identity,_id,rmd,*nconf)) {
|
|
||||||
case NetworkController::NETCONF_QUERY_OK:
|
|
||||||
this->_setConfiguration(*nconf,true);
|
|
||||||
break;
|
|
||||||
case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND:
|
|
||||||
this->setNotFound();
|
|
||||||
break;
|
|
||||||
case NetworkController::NETCONF_QUERY_ACCESS_DENIED:
|
|
||||||
this->setAccessDenied();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this->setNotFound();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch ( ... ) {
|
|
||||||
this->setNotFound();
|
|
||||||
}
|
|
||||||
delete nconf;
|
|
||||||
} else {
|
} else {
|
||||||
this->setNotFound();
|
this->setNotFound();
|
||||||
}
|
}
|
||||||
|
@ -1257,46 +1278,6 @@ ZT_VirtualNetworkStatus Network::_status() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Network::_setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
|
|
||||||
{
|
|
||||||
// _lock is NOT locked when this is called
|
|
||||||
try {
|
|
||||||
if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != _id))
|
|
||||||
return 0;
|
|
||||||
if (_config == nconf)
|
|
||||||
return 1; // OK config, but duplicate of what we already have
|
|
||||||
|
|
||||||
ZT_VirtualNetworkConfig ctmp;
|
|
||||||
bool oldPortInitialized;
|
|
||||||
{
|
|
||||||
Mutex::Lock _l(_lock);
|
|
||||||
_config = nconf;
|
|
||||||
_lastConfigUpdate = RR->node->now();
|
|
||||||
_netconfFailure = NETCONF_FAILURE_NONE;
|
|
||||||
oldPortInitialized = _portInitialized;
|
|
||||||
_portInitialized = true;
|
|
||||||
_externalConfig(&ctmp);
|
|
||||||
}
|
|
||||||
_portError = RR->node->configureVirtualNetworkPort(_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
|
|
||||||
|
|
||||||
if (saveToDisk) {
|
|
||||||
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *d = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
|
||||||
try {
|
|
||||||
char n[64];
|
|
||||||
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
|
|
||||||
if (nconf.toDictionary(*d,false))
|
|
||||||
RR->node->dataStorePut(n,(const void *)d->data(),d->sizeBytes(),true);
|
|
||||||
} catch ( ... ) {}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 2; // OK and configuration has changed
|
|
||||||
} catch ( ... ) {
|
|
||||||
TRACE("ignored invalid configuration for network %.16llx",(unsigned long long)_id);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
||||||
{
|
{
|
||||||
// assumes _lock is locked
|
// assumes _lock is locked
|
||||||
|
|
|
@ -187,6 +187,15 @@ public:
|
||||||
*/
|
*/
|
||||||
uint64_t handleConfigChunk(const Packet &chunk,unsigned int ptr);
|
uint64_t handleConfigChunk(const Packet &chunk,unsigned int ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set network configuration
|
||||||
|
*
|
||||||
|
* @param nconf Network configuration
|
||||||
|
* @param saveToDisk Save to disk? Used during loading, should usually be true otherwise.
|
||||||
|
* @return 0 == bad, 1 == accepted but duplicate/unchanged, 2 == accepted and new
|
||||||
|
*/
|
||||||
|
int setConfiguration(const NetworkConfig &nconf,bool saveToDisk);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this
|
* Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this
|
||||||
*/
|
*/
|
||||||
|
@ -328,7 +337,6 @@ public:
|
||||||
inline void **userPtr() throw() { return &_uPtr; }
|
inline void **userPtr() throw() { return &_uPtr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _setConfiguration(const NetworkConfig &nconf,bool saveToDisk);
|
|
||||||
ZT_VirtualNetworkStatus _status() const;
|
ZT_VirtualNetworkStatus _status() const;
|
||||||
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
||||||
bool _gate(const SharedPtr<Peer> &peer);
|
bool _gate(const SharedPtr<Peer> &peer);
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class RuntimeEnvironment;
|
|
||||||
class Identity;
|
class Identity;
|
||||||
class Address;
|
class Address;
|
||||||
struct InetAddress;
|
struct InetAddress;
|
||||||
|
@ -38,45 +37,69 @@ struct InetAddress;
|
||||||
class NetworkController
|
class NetworkController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
enum ErrorCode
|
||||||
* Return value of doNetworkConfigRequest
|
|
||||||
*/
|
|
||||||
enum ResultCode
|
|
||||||
{
|
{
|
||||||
NETCONF_QUERY_OK = 0,
|
NC_ERROR_NONE = 0,
|
||||||
NETCONF_QUERY_OBJECT_NOT_FOUND = 1,
|
NC_ERROR_OBJECT_NOT_FOUND = 1,
|
||||||
NETCONF_QUERY_ACCESS_DENIED = 2,
|
NC_ERROR_ACCESS_DENIED = 2,
|
||||||
NETCONF_QUERY_INTERNAL_SERVER_ERROR = 3,
|
NC_ERROR_INTERNAL_SERVER_ERROR = 3
|
||||||
NETCONF_QUERY_IGNORE = 4
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for sender used to send pushes and replies
|
||||||
|
*/
|
||||||
|
class Sender
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Send a configuration to a remote peer
|
||||||
|
*
|
||||||
|
* @param nwid Network ID
|
||||||
|
* @param requestPacketId Request packet ID to send OK(NETWORK_CONFIG_REQUEST) or 0 to send NETWORK_CONFIG (push)
|
||||||
|
* @param destination Destination peer Address
|
||||||
|
* @param nc Network configuration to send
|
||||||
|
* @param sendLegacyFormatConfig If true, send an old-format network config
|
||||||
|
*/
|
||||||
|
virtual void ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a network configuration request error
|
||||||
|
*
|
||||||
|
* @param nwid Network ID
|
||||||
|
* @param requestPacketId Request packet ID or 0 if none
|
||||||
|
* @param destination Destination peer Address
|
||||||
|
* @param errorCode Error code
|
||||||
|
*/
|
||||||
|
virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
NetworkController() {}
|
NetworkController() {}
|
||||||
virtual ~NetworkController() {}
|
virtual ~NetworkController() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a network config request, sending replies if necessary
|
* Called when this is added to a Node to initialize and supply info
|
||||||
*
|
*
|
||||||
* This call is permitted to block, and may be called concurrently from more
|
* @param signingId Identity for signing of network configurations, certs, etc.
|
||||||
* than one thread. Implementations must use locks if needed.
|
* @param sender Sender implementation for sending replies or config pushes
|
||||||
|
*/
|
||||||
|
virtual void init(const Identity &signingId,Sender *sender) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a network configuration request
|
||||||
*
|
*
|
||||||
* On internal server errors, the 'error' field in result can be filled in
|
|
||||||
* to indicate the error.
|
|
||||||
*
|
|
||||||
* @param fromAddr Originating wire address or null address if packet is not direct (or from self)
|
|
||||||
* @param signingId Identity that should be used to sign results -- must include private key
|
|
||||||
* @param identity Originating peer ZeroTier identity
|
|
||||||
* @param nwid 64-bit network ID
|
* @param nwid 64-bit network ID
|
||||||
|
* @param fromAddr Originating wire address or null address if packet is not direct (or from self)
|
||||||
|
* @param requestPacketId Packet ID of request packet or 0 if not initiated by remote request
|
||||||
|
* @param identity ZeroTier identity of originating peer
|
||||||
* @param metaData Meta-data bundled with request (if any)
|
* @param metaData Meta-data bundled with request (if any)
|
||||||
* @param nc NetworkConfig to fill with results
|
|
||||||
* @return Returns NETCONF_QUERY_OK if result 'nc' is valid, or an error code on error
|
* @return Returns NETCONF_QUERY_OK if result 'nc' is valid, or an error code on error
|
||||||
*/
|
*/
|
||||||
virtual NetworkController::ResultCode doNetworkConfigRequest(
|
virtual void request(
|
||||||
const InetAddress &fromAddr,
|
|
||||||
const Identity &signingId,
|
|
||||||
const Identity &identity,
|
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData,
|
const InetAddress &fromAddr,
|
||||||
NetworkConfig &nc) = 0;
|
uint64_t requestPacketId,
|
||||||
|
const Identity &identity,
|
||||||
|
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -405,8 +405,6 @@ ZT_PeerList *Node::peers() const
|
||||||
for(std::vector< std::pair< Address,SharedPtr<Peer> > >::iterator pi(peers.begin());pi!=peers.end();++pi) {
|
for(std::vector< std::pair< Address,SharedPtr<Peer> > >::iterator pi(peers.begin());pi!=peers.end();++pi) {
|
||||||
ZT_Peer *p = &(pl->peers[pl->peerCount++]);
|
ZT_Peer *p = &(pl->peers[pl->peerCount++]);
|
||||||
p->address = pi->second->address().toInt();
|
p->address = pi->second->address().toInt();
|
||||||
p->lastUnicastFrame = pi->second->lastUnicastFrame();
|
|
||||||
p->lastMulticastFrame = pi->second->lastMulticastFrame();
|
|
||||||
if (pi->second->remoteVersionKnown()) {
|
if (pi->second->remoteVersionKnown()) {
|
||||||
p->versionMajor = pi->second->remoteVersionMajor();
|
p->versionMajor = pi->second->remoteVersionMajor();
|
||||||
p->versionMinor = pi->second->remoteVersionMinor();
|
p->versionMinor = pi->second->remoteVersionMinor();
|
||||||
|
@ -492,6 +490,7 @@ void Node::clearLocalInterfaceAddresses()
|
||||||
void Node::setNetconfMaster(void *networkControllerInstance)
|
void Node::setNetconfMaster(void *networkControllerInstance)
|
||||||
{
|
{
|
||||||
RR->localNetworkController = reinterpret_cast<NetworkController *>(networkControllerInstance);
|
RR->localNetworkController = reinterpret_cast<NetworkController *>(networkControllerInstance);
|
||||||
|
RR->localNetworkController->init(RR->identity,this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_ResultCode Node::circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
|
ZT_ResultCode Node::circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
|
||||||
|
@ -720,6 +719,92 @@ void Node::setTrustedPaths(const struct sockaddr_storage *networks,const uint64_
|
||||||
RR->topology->setTrustedPaths(reinterpret_cast<const InetAddress *>(networks),ids,count);
|
RR->topology->setTrustedPaths(reinterpret_cast<const InetAddress *>(networks),ids,count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig)
|
||||||
|
{
|
||||||
|
if (destination == RR->identity.address()) {
|
||||||
|
SharedPtr<Network> n(network(nwid));
|
||||||
|
if (!n) return;
|
||||||
|
n->setConfiguration(nc,true);
|
||||||
|
} else {
|
||||||
|
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
||||||
|
try {
|
||||||
|
if (nc.toDictionary(*dconf,sendLegacyFormatConfig)) {
|
||||||
|
uint64_t configUpdateId = prng();
|
||||||
|
if (!configUpdateId) ++configUpdateId;
|
||||||
|
|
||||||
|
const unsigned int totalSize = dconf->sizeBytes();
|
||||||
|
unsigned int chunkIndex = 0;
|
||||||
|
while (chunkIndex < totalSize) {
|
||||||
|
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_UDP_DEFAULT_PAYLOAD_MTU - (ZT_PACKET_IDX_PAYLOAD + 256)));
|
||||||
|
Packet outp(destination,RR->identity.address(),(requestPacketId) ? Packet::VERB_OK : Packet::VERB_NETWORK_CONFIG);
|
||||||
|
if (requestPacketId) {
|
||||||
|
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||||
|
outp.append(requestPacketId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned int sigStart = outp.size();
|
||||||
|
outp.append(nwid);
|
||||||
|
outp.append((uint16_t)chunkLen);
|
||||||
|
outp.append((const void *)(dconf->data() + chunkIndex),chunkLen);
|
||||||
|
|
||||||
|
outp.append((uint8_t)0); // no flags
|
||||||
|
outp.append((uint64_t)configUpdateId);
|
||||||
|
outp.append((uint32_t)totalSize);
|
||||||
|
outp.append((uint32_t)chunkIndex);
|
||||||
|
|
||||||
|
C25519::Signature sig(RR->identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) + sigStart,outp.size() - sigStart));
|
||||||
|
outp.append((uint8_t)1);
|
||||||
|
outp.append((uint16_t)ZT_C25519_SIGNATURE_LEN);
|
||||||
|
outp.append(sig.data,ZT_C25519_SIGNATURE_LEN);
|
||||||
|
|
||||||
|
outp.compress();
|
||||||
|
RR->sw->send(outp,true);
|
||||||
|
chunkIndex += chunkLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete dconf;
|
||||||
|
} catch ( ... ) {
|
||||||
|
delete dconf;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode)
|
||||||
|
{
|
||||||
|
if (destination == RR->identity.address()) {
|
||||||
|
SharedPtr<Network> n(network(nwid));
|
||||||
|
if (!n) return;
|
||||||
|
switch(errorCode) {
|
||||||
|
case NetworkController::NC_ERROR_OBJECT_NOT_FOUND:
|
||||||
|
case NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR:
|
||||||
|
n->setNotFound();
|
||||||
|
break;
|
||||||
|
case NetworkController::NC_ERROR_ACCESS_DENIED:
|
||||||
|
n->setAccessDenied();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
} else if (requestPacketId) {
|
||||||
|
Packet outp(destination,RR->identity.address(),Packet::VERB_ERROR);
|
||||||
|
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||||
|
outp.append(requestPacketId);
|
||||||
|
switch(errorCode) {
|
||||||
|
//case NetworkController::NC_ERROR_OBJECT_NOT_FOUND:
|
||||||
|
//case NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR:
|
||||||
|
default:
|
||||||
|
outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
|
||||||
|
break;
|
||||||
|
case NetworkController::NC_ERROR_ACCESS_DENIED:
|
||||||
|
outp.append((unsigned char)Packet::ERROR_NETWORK_ACCESS_DENIED_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
outp.append(nwid);
|
||||||
|
RR->sw->send(outp,true);
|
||||||
|
} // else we can't send an ERROR() in response to nothing, so discard
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "Network.hpp"
|
#include "Network.hpp"
|
||||||
#include "Path.hpp"
|
#include "Path.hpp"
|
||||||
#include "Salsa20.hpp"
|
#include "Salsa20.hpp"
|
||||||
|
#include "NetworkController.hpp"
|
||||||
|
|
||||||
#undef TRACE
|
#undef TRACE
|
||||||
#ifdef ZT_TRACE
|
#ifdef ZT_TRACE
|
||||||
|
@ -55,7 +56,7 @@ namespace ZeroTier {
|
||||||
*
|
*
|
||||||
* The pointer returned by ZT_Node_new() is an instance of this class.
|
* The pointer returned by ZT_Node_new() is an instance of this class.
|
||||||
*/
|
*/
|
||||||
class Node
|
class Node : public NetworkController::Sender
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Node(
|
Node(
|
||||||
|
@ -69,7 +70,7 @@ public:
|
||||||
ZT_PathCheckFunction pathCheckFunction,
|
ZT_PathCheckFunction pathCheckFunction,
|
||||||
ZT_EventCallback eventCallback);
|
ZT_EventCallback eventCallback);
|
||||||
|
|
||||||
~Node();
|
virtual ~Node();
|
||||||
|
|
||||||
// Public API Functions ----------------------------------------------------
|
// Public API Functions ----------------------------------------------------
|
||||||
|
|
||||||
|
@ -282,6 +283,9 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig);
|
||||||
|
virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline SharedPtr<Network> _network(uint64_t nwid) const
|
inline SharedPtr<Network> _network(uint64_t nwid) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,8 +42,7 @@ static uint32_t _natKeepaliveBuf = 0;
|
||||||
|
|
||||||
Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) :
|
Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) :
|
||||||
_lastReceive(0),
|
_lastReceive(0),
|
||||||
_lastUnicastFrame(0),
|
_lastNontrivialReceive(0),
|
||||||
_lastMulticastFrame(0),
|
|
||||||
_lastDirectPathPushSent(0),
|
_lastDirectPathPushSent(0),
|
||||||
_lastDirectPathPushReceive(0),
|
_lastDirectPathPushReceive(0),
|
||||||
_lastCredentialRequestSent(0),
|
_lastCredentialRequestSent(0),
|
||||||
|
@ -128,10 +127,16 @@ void Peer::received(
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_lastReceive = now;
|
_lastReceive = now;
|
||||||
if ((verb == Packet::VERB_FRAME)||(verb == Packet::VERB_EXT_FRAME))
|
switch (verb) {
|
||||||
_lastUnicastFrame = now;
|
case Packet::VERB_FRAME:
|
||||||
else if (verb == Packet::VERB_MULTICAST_FRAME)
|
case Packet::VERB_EXT_FRAME:
|
||||||
_lastMulticastFrame = now;
|
case Packet::VERB_NETWORK_CONFIG_REQUEST:
|
||||||
|
case Packet::VERB_NETWORK_CONFIG:
|
||||||
|
case Packet::VERB_MULTICAST_FRAME:
|
||||||
|
_lastNontrivialReceive = now;
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
if (trustEstablished) {
|
if (trustEstablished) {
|
||||||
_lastTrustEstablishedPacketReceived = now;
|
_lastTrustEstablishedPacketReceived = now;
|
||||||
|
|
|
@ -226,25 +226,10 @@ public:
|
||||||
*/
|
*/
|
||||||
inline bool isAlive(const uint64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
inline bool isAlive(const uint64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Time of most recent unicast frame received
|
|
||||||
*/
|
|
||||||
inline uint64_t lastUnicastFrame() const { return _lastUnicastFrame; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Time of most recent multicast frame received
|
|
||||||
*/
|
|
||||||
inline uint64_t lastMulticastFrame() const { return _lastMulticastFrame; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Time of most recent frame of any kind (unicast or multicast)
|
|
||||||
*/
|
|
||||||
inline uint64_t lastFrame() const { return std::max(_lastUnicastFrame,_lastMulticastFrame); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if this peer has sent us real network traffic recently
|
* @return True if this peer has sent us real network traffic recently
|
||||||
*/
|
*/
|
||||||
inline uint64_t isActive(uint64_t now) const { return ((now - lastFrame()) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
inline uint64_t isActive(uint64_t now) const { return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Latency in milliseconds or 0 if unknown
|
* @return Latency in milliseconds or 0 if unknown
|
||||||
|
@ -469,8 +454,7 @@ private:
|
||||||
uint8_t _key[ZT_PEER_SECRET_KEY_LENGTH];
|
uint8_t _key[ZT_PEER_SECRET_KEY_LENGTH];
|
||||||
uint8_t _remoteClusterOptimal6[16];
|
uint8_t _remoteClusterOptimal6[16];
|
||||||
uint64_t _lastReceive; // direct or indirect
|
uint64_t _lastReceive; // direct or indirect
|
||||||
uint64_t _lastUnicastFrame;
|
uint64_t _lastNontrivialReceive; // frames, things like netconf, etc.
|
||||||
uint64_t _lastMulticastFrame;
|
|
||||||
uint64_t _lastDirectPathPushSent;
|
uint64_t _lastDirectPathPushSent;
|
||||||
uint64_t _lastDirectPathPushReceive;
|
uint64_t _lastDirectPathPushReceive;
|
||||||
uint64_t _lastCredentialRequestSent;
|
uint64_t _lastCredentialRequestSent;
|
||||||
|
|
11
one.cpp
11
one.cpp
|
@ -973,6 +973,7 @@ int main(int argc,char **argv)
|
||||||
std::string homeDir;
|
std::string homeDir;
|
||||||
unsigned int port = ZT_DEFAULT_PORT;
|
unsigned int port = ZT_DEFAULT_PORT;
|
||||||
bool skipRootCheck = false;
|
bool skipRootCheck = false;
|
||||||
|
const char *allowManagementFrom = (const char *)0;
|
||||||
|
|
||||||
for(int i=1;i<argc;++i) {
|
for(int i=1;i<argc;++i) {
|
||||||
if (argv[i][0] == '-') {
|
if (argv[i][0] == '-') {
|
||||||
|
@ -986,6 +987,14 @@ int main(int argc,char **argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'M': // allow management from this IP/bits network
|
||||||
|
allowManagementFrom = argv[i] + 2;
|
||||||
|
if (!strlen(allowManagementFrom)) {
|
||||||
|
printHelp(argv[0],stdout);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
#ifdef __UNIX_LIKE__
|
#ifdef __UNIX_LIKE__
|
||||||
case 'd': // Run in background as daemon
|
case 'd': // Run in background as daemon
|
||||||
runAsDaemon = true;
|
runAsDaemon = true;
|
||||||
|
@ -1167,7 +1176,7 @@ int main(int argc,char **argv)
|
||||||
unsigned int returnValue = 0;
|
unsigned int returnValue = 0;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
zt1Service = OneService::newInstance(homeDir.c_str(),port);
|
zt1Service = OneService::newInstance(homeDir.c_str(),port,allowManagementFrom);
|
||||||
switch(zt1Service->run()) {
|
switch(zt1Service->run()) {
|
||||||
case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
|
case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
|
||||||
case OneService::ONE_NORMAL_TERMINATION:
|
case OneService::ONE_NORMAL_TERMINATION:
|
||||||
|
|
64
osdep/BlockingQueue.hpp
Normal file
64
osdep/BlockingQueue.hpp
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZT_BLOCKINGQUEUE_HPP
|
||||||
|
#define ZT_BLOCKINGQUEUE_HPP
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple C++11 thread-safe queue
|
||||||
|
*
|
||||||
|
* Do not use in node/ since we have not gone C++11 there yet.
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
class BlockingQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BlockingQueue(void) {}
|
||||||
|
|
||||||
|
inline void post(T t)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m);
|
||||||
|
q.push(t);
|
||||||
|
c.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline T get(void)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m);
|
||||||
|
while(q.empty())
|
||||||
|
c.wait(lock);
|
||||||
|
T val = q.front();
|
||||||
|
q.pop();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::queue<T> q;
|
||||||
|
mutable std::mutex m;
|
||||||
|
std::condition_variable c;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ZeroTier
|
||||||
|
|
||||||
|
#endif
|
|
@ -102,6 +102,8 @@ void dropPrivileges(std::string homeDir) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createOwnedHomedir(homeDir, targetUser);
|
||||||
|
|
||||||
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_RAW, 0, 0) < 0) {
|
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_RAW, 0, 0) < 0) {
|
||||||
// Kernel has no support for ambient capabilities.
|
// Kernel has no support for ambient capabilities.
|
||||||
notDropping(homeDir);
|
notDropping(homeDir);
|
||||||
|
@ -113,8 +115,6 @@ void dropPrivileges(std::string homeDir) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
createOwnedHomedir(homeDir, targetUser);
|
|
||||||
|
|
||||||
if (setCapabilities((1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID) | (1 << CAP_SETGID)) < 0) {
|
if (setCapabilities((1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID) | (1 << CAP_SETGID)) < 0) {
|
||||||
fprintf(stderr, "ERROR: failed to set capabilities (not running as real root?)\n");
|
fprintf(stderr, "ERROR: failed to set capabilities (not running as real root?)\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -222,8 +222,6 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_Peer *peer)
|
||||||
Utils::snprintf(json,sizeof(json),
|
Utils::snprintf(json,sizeof(json),
|
||||||
"%s{\n"
|
"%s{\n"
|
||||||
"%s\t\"address\": \"%.10llx\",\n"
|
"%s\t\"address\": \"%.10llx\",\n"
|
||||||
"%s\t\"lastUnicastFrame\": %llu,\n"
|
|
||||||
"%s\t\"lastMulticastFrame\": %llu,\n"
|
|
||||||
"%s\t\"versionMajor\": %d,\n"
|
"%s\t\"versionMajor\": %d,\n"
|
||||||
"%s\t\"versionMinor\": %d,\n"
|
"%s\t\"versionMinor\": %d,\n"
|
||||||
"%s\t\"versionRev\": %d,\n"
|
"%s\t\"versionRev\": %d,\n"
|
||||||
|
@ -234,8 +232,6 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_Peer *peer)
|
||||||
"%s}",
|
"%s}",
|
||||||
prefix,
|
prefix,
|
||||||
prefix,peer->address,
|
prefix,peer->address,
|
||||||
prefix,peer->lastUnicastFrame,
|
|
||||||
prefix,peer->lastMulticastFrame,
|
|
||||||
prefix,peer->versionMajor,
|
prefix,peer->versionMajor,
|
||||||
prefix,peer->versionMinor,
|
prefix,peer->versionMinor,
|
||||||
prefix,peer->versionRev,
|
prefix,peer->versionRev,
|
||||||
|
@ -274,9 +270,6 @@ unsigned int ControlPlane::handleRequest(
|
||||||
std::map<std::string,std::string> urlArgs;
|
std::map<std::string,std::string> urlArgs;
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
|
|
||||||
if (!((fromAddress.ipsEqual(InetAddress::LO4))||(fromAddress.ipsEqual(InetAddress::LO6))))
|
|
||||||
return 403; // Forbidden: we only allow access from localhost right now
|
|
||||||
|
|
||||||
/* Note: this is kind of restricted in what it'll take. It does not support
|
/* Note: this is kind of restricted in what it'll take. It does not support
|
||||||
* URL encoding, and /'s in URL args will screw it up. But the only URL args
|
* URL encoding, and /'s in URL args will screw it up. But the only URL args
|
||||||
* it really uses in ?jsonp=funcionName, and otherwise it just takes simple
|
* it really uses in ?jsonp=funcionName, and otherwise it just takes simple
|
||||||
|
|
|
@ -483,6 +483,7 @@ public:
|
||||||
|
|
||||||
const std::string _homePath;
|
const std::string _homePath;
|
||||||
BackgroundResolver _tcpFallbackResolver;
|
BackgroundResolver _tcpFallbackResolver;
|
||||||
|
InetAddress _allowManagementFrom;
|
||||||
EmbeddedNetworkController *_controller;
|
EmbeddedNetworkController *_controller;
|
||||||
Phy<OneServiceImpl *> _phy;
|
Phy<OneServiceImpl *> _phy;
|
||||||
Node *_node;
|
Node *_node;
|
||||||
|
@ -570,7 +571,7 @@ public:
|
||||||
|
|
||||||
// end member variables ----------------------------------------------------
|
// end member variables ----------------------------------------------------
|
||||||
|
|
||||||
OneServiceImpl(const char *hp,unsigned int port) :
|
OneServiceImpl(const char *hp,unsigned int port,const char *allowManagementFrom) :
|
||||||
_homePath((hp) ? hp : ".")
|
_homePath((hp) ? hp : ".")
|
||||||
,_tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY)
|
,_tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY)
|
||||||
,_controller((EmbeddedNetworkController *)0)
|
,_controller((EmbeddedNetworkController *)0)
|
||||||
|
@ -595,6 +596,9 @@ public:
|
||||||
#endif
|
#endif
|
||||||
,_run(true)
|
,_run(true)
|
||||||
{
|
{
|
||||||
|
if (allowManagementFrom)
|
||||||
|
_allowManagementFrom.fromString(allowManagementFrom);
|
||||||
|
|
||||||
_ports[0] = 0;
|
_ports[0] = 0;
|
||||||
_ports[1] = 0;
|
_ports[1] = 0;
|
||||||
_ports[2] = 0;
|
_ports[2] = 0;
|
||||||
|
@ -614,7 +618,7 @@ public:
|
||||||
struct sockaddr_in in4;
|
struct sockaddr_in in4;
|
||||||
memset(&in4,0,sizeof(in4));
|
memset(&in4,0,sizeof(in4));
|
||||||
in4.sin_family = AF_INET;
|
in4.sin_family = AF_INET;
|
||||||
in4.sin_addr.s_addr = Utils::hton((uint32_t)0x7f000001); // right now we just listen for TCP @127.0.0.1
|
in4.sin_addr.s_addr = Utils::hton((uint32_t)((allowManagementFrom) ? 0 : 0x7f000001)); // right now we just listen for TCP @127.0.0.1
|
||||||
in4.sin_port = Utils::hton((uint16_t)port);
|
in4.sin_port = Utils::hton((uint16_t)port);
|
||||||
_v4TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in4,this);
|
_v4TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in4,this);
|
||||||
|
|
||||||
|
@ -622,7 +626,8 @@ public:
|
||||||
memset((void *)&in6,0,sizeof(in6));
|
memset((void *)&in6,0,sizeof(in6));
|
||||||
in6.sin6_family = AF_INET6;
|
in6.sin6_family = AF_INET6;
|
||||||
in6.sin6_port = in4.sin_port;
|
in6.sin6_port = in4.sin_port;
|
||||||
in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1
|
if (!allowManagementFrom)
|
||||||
|
in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1
|
||||||
_v6TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in6,this);
|
_v6TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in6,this);
|
||||||
|
|
||||||
// We must bind one of IPv4 or IPv6 -- support either failing to support hosts that
|
// We must bind one of IPv4 or IPv6 -- support either failing to support hosts that
|
||||||
|
@ -1259,12 +1264,10 @@ public:
|
||||||
|
|
||||||
inline void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from)
|
inline void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from)
|
||||||
{
|
{
|
||||||
if ((!from)||(reinterpret_cast<const InetAddress *>(from)->ipScope() != InetAddress::IP_SCOPE_LOOPBACK)) {
|
if (!from) {
|
||||||
// Non-Loopback: deny (for now)
|
|
||||||
_phy.close(sockN,false);
|
_phy.close(sockN,false);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// Loopback == HTTP JSON API request
|
|
||||||
TcpConnection *tc = new TcpConnection();
|
TcpConnection *tc = new TcpConnection();
|
||||||
_tcpConnections.insert(tc);
|
_tcpConnections.insert(tc);
|
||||||
tc->type = TcpConnection::TCP_HTTP_INCOMING;
|
tc->type = TcpConnection::TCP_HTTP_INCOMING;
|
||||||
|
@ -1701,16 +1704,20 @@ public:
|
||||||
std::string contentType("text/plain"); // default if not changed in handleRequest()
|
std::string contentType("text/plain"); // default if not changed in handleRequest()
|
||||||
unsigned int scode = 404;
|
unsigned int scode = 404;
|
||||||
|
|
||||||
try {
|
if ( ((!_allowManagementFrom)&&(tc->from.ipScope() == InetAddress::IP_SCOPE_LOOPBACK)) || (_allowManagementFrom.containsAddress(tc->from)) ) {
|
||||||
if (_controlPlane)
|
try {
|
||||||
scode = _controlPlane->handleRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType);
|
if (_controlPlane)
|
||||||
else scode = 500;
|
scode = _controlPlane->handleRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType);
|
||||||
} catch (std::exception &exc) {
|
else scode = 500;
|
||||||
fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what());
|
} catch (std::exception &exc) {
|
||||||
scode = 500;
|
fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what());
|
||||||
} catch ( ... ) {
|
scode = 500;
|
||||||
fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exceptino" ZT_EOL_S);
|
} catch ( ... ) {
|
||||||
scode = 500;
|
fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exceptino" ZT_EOL_S);
|
||||||
|
scode = 500;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scode = 401;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *scodestr;
|
const char *scodestr;
|
||||||
|
@ -1975,7 +1982,7 @@ std::string OneService::autoUpdateUrl()
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
OneService *OneService::newInstance(const char *hp,unsigned int port) { return new OneServiceImpl(hp,port); }
|
OneService *OneService::newInstance(const char *hp,unsigned int port,const char *allowManagementFrom) { return new OneServiceImpl(hp,port,allowManagementFrom); }
|
||||||
OneService::~OneService() {}
|
OneService::~OneService() {}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -98,10 +98,12 @@ public:
|
||||||
*
|
*
|
||||||
* @param hp Home path
|
* @param hp Home path
|
||||||
* @param port TCP and UDP port for packets and HTTP control (if 0, pick random port)
|
* @param port TCP and UDP port for packets and HTTP control (if 0, pick random port)
|
||||||
|
* @param allowManagementFrom If non-NULL, allow control from supplied IP/netmask
|
||||||
*/
|
*/
|
||||||
static OneService *newInstance(
|
static OneService *newInstance(
|
||||||
const char *hp,
|
const char *hp,
|
||||||
unsigned int port);
|
unsigned int port,
|
||||||
|
const char *allowManagementFrom = (const char *)0);
|
||||||
|
|
||||||
virtual ~OneService();
|
virtual ~OneService();
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@ A *jsonp* URL argument may be supplied to request JSONP encapsulation. A JSONP r
|
||||||
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Writable</b></td></tr>
|
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Writable</b></td></tr>
|
||||||
<tr><td>address</td><td>string</td><td>10-digit hexadecimal ZeroTier address of this node</td><td>no</td></tr>
|
<tr><td>address</td><td>string</td><td>10-digit hexadecimal ZeroTier address of this node</td><td>no</td></tr>
|
||||||
<tr><td>publicIdentity</td><td>string</td><td>Full public ZeroTier identity of this node</td><td>no</td></tr>
|
<tr><td>publicIdentity</td><td>string</td><td>Full public ZeroTier identity of this node</td><td>no</td></tr>
|
||||||
|
<tr><td>worldId</td><td>integer</td><td>Fixed value representing the virtual data center of Earth.</td><td>no</td></tr>
|
||||||
|
<tr><td>worldTimestamp</td><td>integer</td><td>Timestamp of the last root server topology change.</td><td>no</td></tr>
|
||||||
<tr><td>online</td><td>boolean</td><td>Does this node appear to have upstream network access?</td><td>no</td></tr>
|
<tr><td>online</td><td>boolean</td><td>Does this node appear to have upstream network access?</td><td>no</td></tr>
|
||||||
<tr><td>tcpFallbackActive</td><td>boolean</td><td>Is TCP fallback mode active?</td><td>no</td></tr>
|
<tr><td>tcpFallbackActive</td><td>boolean</td><td>Is TCP fallback mode active?</td><td>no</td></tr>
|
||||||
<tr><td>versionMajor</td><td>integer</td><td>ZeroTier major version</td><td>no</td></tr>
|
<tr><td>versionMajor</td><td>integer</td><td>ZeroTier major version</td><td>no</td></tr>
|
||||||
|
@ -77,9 +79,22 @@ Most network settings are not writable, as they are defined by the network contr
|
||||||
<tr><td>broadcastEnabled</td><td>boolean</td><td>Is Ethernet broadcast (ff:ff:ff:ff:ff:ff) allowed?</td><td>no</td></tr>
|
<tr><td>broadcastEnabled</td><td>boolean</td><td>Is Ethernet broadcast (ff:ff:ff:ff:ff:ff) allowed?</td><td>no</td></tr>
|
||||||
<tr><td>portError</td><td>integer</td><td>Error code (if any) returned by underlying OS "tap" driver</td><td>no</td></tr>
|
<tr><td>portError</td><td>integer</td><td>Error code (if any) returned by underlying OS "tap" driver</td><td>no</td></tr>
|
||||||
<tr><td>netconfRevision</td><td>integer</td><td>Network configuration revision ID</td><td>no</td></tr>
|
<tr><td>netconfRevision</td><td>integer</td><td>Network configuration revision ID</td><td>no</td></tr>
|
||||||
<tr><td>multicastSubscriptions</td><td>[string]</td><td>Multicast memberships as array of MAC/ADI tuples</td><td>no</td></tr>
|
|
||||||
<tr><td>assignedAddresses</td><td>[string]</td><td>ZeroTier-managed IP address assignments as array of IP/netmask bits tuples</td><td>no</td></tr>
|
<tr><td>assignedAddresses</td><td>[string]</td><td>ZeroTier-managed IP address assignments as array of IP/netmask bits tuples</td><td>no</td></tr>
|
||||||
|
<tr><td>routes</td><td>[route]</td><td>ZeroTier-managed route assignments for a network. See below for a description of the route object.</td><td>no</td></tr>
|
||||||
<tr><td>portDeviceName</td><td>string</td><td>OS-specific network device name (if available)</td><td>no</td></tr>
|
<tr><td>portDeviceName</td><td>string</td><td>OS-specific network device name (if available)</td><td>no</td></tr>
|
||||||
|
<tr><td>allowManaged</td><td>boolean</td><td>Whether ZeroTier-managed IP addresses are allowed.</td><td>yes</td></tr>
|
||||||
|
<tr><td>allowGlobal</td><td>boolean</td><td>Whether globally-reachable IP addresses are allowed to be assigned.</td><td>yes</td></tr>
|
||||||
|
<tr><td>allowDefault</td><td>boolean</td><td>Whether a default route is allowed to be assigned for the network (route all traffic via ZeroTier)</td><td>yes</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
`route` objects
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Writable</b></td></tr>
|
||||||
|
<tr><td>target</td><td>string</td><td>Target network / netmask bits, NULL, or 0.0.0.0/0 for default route</td><td>no</td></tr>
|
||||||
|
<tr><td>via</td><td>string</td><td>Gateway IP address</td><td>no</td></tr>
|
||||||
|
<tr><td>flags</td><td>integer</td><td>Route flags</td><td>no</td></tr>
|
||||||
|
<tr><td>metric</td><td>integer</td><td>Route metric (not currently used)</td><td>no</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
#### /peer
|
#### /peer
|
||||||
|
@ -99,8 +114,6 @@ Getting /peer returns an array of peer objects for all current peers. See below
|
||||||
<table>
|
<table>
|
||||||
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Writable</b></td></tr>
|
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Writable</b></td></tr>
|
||||||
<tr><td>address</td><td>string</td><td>10-digit hex ZeroTier address</td><td>no</td></tr>
|
<tr><td>address</td><td>string</td><td>10-digit hex ZeroTier address</td><td>no</td></tr>
|
||||||
<tr><td>lastUnicastFrame</td><td>integer</td><td>Time of last unicast frame in ms since epoch</td><td>no</td></tr>
|
|
||||||
<tr><td>lastMulticastFrame</td><td>integer</td><td>Time of last multicast frame in ms since epoch</td><td>no</td></tr>
|
|
||||||
<tr><td>versionMajor</td><td>integer</td><td>Major version of remote if known</td><td>no</td></tr>
|
<tr><td>versionMajor</td><td>integer</td><td>Major version of remote if known</td><td>no</td></tr>
|
||||||
<tr><td>versionMinor</td><td>integer</td><td>Minor version of remote if known</td><td>no</td></tr>
|
<tr><td>versionMinor</td><td>integer</td><td>Minor version of remote if known</td><td>no</td></tr>
|
||||||
<tr><td>versionRev</td><td>integer</td><td>Revision of remote if known</td><td>no</td></tr>
|
<tr><td>versionRev</td><td>integer</td><td>Revision of remote if known</td><td>no</td></tr>
|
||||||
|
|
233
windows/WinUI/MainWindow.xaml.cs
Normal file
233
windows/WinUI/MainWindow.xaml.cs
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Timers;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
|
namespace WinUI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for MainWindow.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
APIHandler handler;
|
||||||
|
Regex charRegex = new Regex("[0-9a-fxA-FX]");
|
||||||
|
Regex wholeStringRegex = new Regex("^[0-9a-fxA-FX]+$");
|
||||||
|
|
||||||
|
Timer timer = new Timer();
|
||||||
|
|
||||||
|
bool connected = false;
|
||||||
|
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
if (InitAPIHandler())
|
||||||
|
{
|
||||||
|
networksPage.SetAPIHandler(handler);
|
||||||
|
|
||||||
|
updateStatus();
|
||||||
|
if (!connected)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Unable to connect to ZeroTier Service.");
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNetworks();
|
||||||
|
//updatePeers();
|
||||||
|
|
||||||
|
DataObject.AddPastingHandler(joinNetworkID, OnPaste);
|
||||||
|
|
||||||
|
timer.Elapsed += new ElapsedEventHandler(OnUpdateTimer);
|
||||||
|
timer.Interval = 2000;
|
||||||
|
timer.Enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String readAuthToken(String path)
|
||||||
|
{
|
||||||
|
String authToken = "";
|
||||||
|
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] tmp = File.ReadAllBytes(path);
|
||||||
|
authToken = System.Text.Encoding.UTF8.GetString(tmp).Trim();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
MessageBox.Show("Unable to read ZeroTier One Auth Token from:\r\n" + path, "ZeroTier One");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Int32 readPort(String path)
|
||||||
|
{
|
||||||
|
Int32 port = 9993;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] tmp = File.ReadAllBytes(path);
|
||||||
|
port = Int32.Parse(System.Text.Encoding.ASCII.GetString(tmp).Trim());
|
||||||
|
if ((port <= 0) || (port > 65535))
|
||||||
|
port = 9993;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool InitAPIHandler()
|
||||||
|
{
|
||||||
|
String localZtDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\ZeroTier\\One";
|
||||||
|
String globalZtDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\ZeroTier\\One";
|
||||||
|
|
||||||
|
String authToken = "";
|
||||||
|
Int32 port = 9993;
|
||||||
|
|
||||||
|
if (!File.Exists(localZtDir + "\\authtoken.secret") || !File.Exists(localZtDir + "\\zerotier-one.port"))
|
||||||
|
{
|
||||||
|
// launch external process to copy file into place
|
||||||
|
String curPath = System.Reflection.Assembly.GetEntryAssembly().Location;
|
||||||
|
int index = curPath.LastIndexOf("\\");
|
||||||
|
curPath = curPath.Substring(0, index);
|
||||||
|
ProcessStartInfo startInfo = new ProcessStartInfo(curPath + "\\copyutil.exe", globalZtDir + " " + localZtDir);
|
||||||
|
startInfo.Verb = "runas";
|
||||||
|
|
||||||
|
|
||||||
|
var process = Process.Start(startInfo);
|
||||||
|
process.WaitForExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
authToken = readAuthToken(localZtDir + "\\authtoken.secret");
|
||||||
|
|
||||||
|
if ((authToken == null) || (authToken.Length <= 0))
|
||||||
|
{
|
||||||
|
MessageBox.Show("Unable to read ZeroTier One authtoken", "ZeroTier One");
|
||||||
|
this.Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
port = readPort(localZtDir + "\\zerotier-one.port");
|
||||||
|
handler = new APIHandler(port, authToken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateStatus()
|
||||||
|
{
|
||||||
|
var status = handler.GetStatus();
|
||||||
|
|
||||||
|
if (status != null)
|
||||||
|
{
|
||||||
|
connected = true;
|
||||||
|
|
||||||
|
networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
|
{
|
||||||
|
this.networkId.Text = status.Address;
|
||||||
|
}));
|
||||||
|
versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
|
{
|
||||||
|
this.versionString.Content = status.Version;
|
||||||
|
}));
|
||||||
|
onlineStatus.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
|
{
|
||||||
|
this.onlineStatus.Content = (status.Online ? "ONLINE" : "OFFLINE");
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connected = false;
|
||||||
|
|
||||||
|
networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
|
{
|
||||||
|
this.networkId.Text = "";
|
||||||
|
}));
|
||||||
|
versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
|
{
|
||||||
|
this.versionString.Content = "0";
|
||||||
|
}));
|
||||||
|
onlineStatus.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
|
{
|
||||||
|
this.onlineStatus.Content = "OFFLINE";
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateNetworks()
|
||||||
|
{
|
||||||
|
var networks = handler.GetNetworks();
|
||||||
|
|
||||||
|
networksPage.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
|
{
|
||||||
|
networksPage.setNetworks(networks);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePeers()
|
||||||
|
{
|
||||||
|
//var peers = handler.GetPeers();
|
||||||
|
|
||||||
|
//peersPage.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
|
//{
|
||||||
|
// peersPage.SetPeers(peers);
|
||||||
|
//}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUpdateTimer(object source, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
updateStatus();
|
||||||
|
updateNetworks();
|
||||||
|
//updatePeers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void joinButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (joinNetworkID.Text.Length < 16)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Invalid Network ID");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handler.JoinNetwork(joinNetworkID.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNetworkEntered(object sender, TextCompositionEventArgs e)
|
||||||
|
{
|
||||||
|
e.Handled = !charRegex.IsMatch(e.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPaste(object sender, DataObjectPastingEventArgs e)
|
||||||
|
{
|
||||||
|
var isText = e.SourceDataObject.GetDataPresent(DataFormats.UnicodeText, true);
|
||||||
|
if (!isText) return;
|
||||||
|
|
||||||
|
var text = e.SourceDataObject.GetData(DataFormats.UnicodeText) as string;
|
||||||
|
|
||||||
|
if (!wholeStringRegex.IsMatch(text))
|
||||||
|
{
|
||||||
|
e.CancelCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,7 +64,7 @@
|
||||||
<TextBlock x:Name="broadcastEnabled" FontFamily="Lucida Console" TextWrapping="Wrap" Text="ENABLED" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="6" Foreground="#FF000000"/>
|
<TextBlock x:Name="broadcastEnabled" FontFamily="Lucida Console" TextWrapping="Wrap" Text="ENABLED" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="6" Foreground="#FF000000"/>
|
||||||
<TextBlock x:Name="bridgingEnabled" FontFamily="Lucida Console" TextWrapping="Wrap" Text="DISABLED" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="7" Background="#FFEEEEEE" Foreground="#FF000000"/>
|
<TextBlock x:Name="bridgingEnabled" FontFamily="Lucida Console" TextWrapping="Wrap" Text="DISABLED" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="7" Background="#FFEEEEEE" Foreground="#FF000000"/>
|
||||||
<TextBlock x:Name="deviceName" FontFamily="Lucida Console" TextWrapping="Wrap" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="8" Foreground="#FF000000"><Span><Run Text="ethernet_32771"/></Span></TextBlock>
|
<TextBlock x:Name="deviceName" FontFamily="Lucida Console" TextWrapping="Wrap" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="8" Foreground="#FF000000"><Span><Run Text="ethernet_32771"/></Span></TextBlock>
|
||||||
<TextBlock x:Name="managedIps" TextWrapping="Wrap" FontFamily="Lucida Console" HorizontalAlignment="Right" TextAlignment="Right" Grid.Column="2" Grid.Row="9" Foreground="#FF000000"><Span><Run Text="28.2.169.248/7 "/></Span><LineBreak/><Span><Run Text="fd80:56c2:e21c:0000:0199:9383:4a02:a9f8/88"/></Span></TextBlock>
|
<TextBox x:Name="managedIps" TextWrapping="Wrap" FontFamily="Lucida Console" HorizontalAlignment="Right" TextAlignment="Right" Grid.Column="2" Grid.Row="9" Foreground="#FF000000" IsReadOnly="True" BorderThickness="0" Background="#FFEEEEEE" Text="28.2.169.248/7
fd80:56c2:e21c:0000:0199:9383:4a02:a9f8/88"/>
|
||||||
<CheckBox x:Name="allowGlobal" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="10" />
|
<CheckBox x:Name="allowGlobal" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="10" />
|
||||||
<CheckBox x:Name="allowManaged" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="11" />
|
<CheckBox x:Name="allowManaged" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="11" />
|
||||||
<CheckBox x:Name="allowDefault" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="12" />
|
<CheckBox x:Name="allowDefault" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="12" />
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace WinUI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class NetworkInfoView : UserControl
|
public partial class NetworkInfoView : UserControl
|
||||||
{
|
{
|
||||||
private ZeroTierNetwork network;
|
public ZeroTierNetwork network;
|
||||||
|
|
||||||
public NetworkInfoView(ZeroTierNetwork network)
|
public NetworkInfoView(ZeroTierNetwork network)
|
||||||
{
|
{
|
||||||
|
@ -29,19 +29,41 @@ namespace WinUI
|
||||||
this.network = network;
|
this.network = network;
|
||||||
|
|
||||||
UpdateNetworkData();
|
UpdateNetworkData();
|
||||||
|
|
||||||
|
allowDefault.Checked += AllowDefault_CheckStateChanged;
|
||||||
|
allowDefault.Unchecked += AllowDefault_CheckStateChanged;
|
||||||
|
allowGlobal.Checked += AllowGlobal_CheckStateChanged;
|
||||||
|
allowGlobal.Unchecked += AllowGlobal_CheckStateChanged;
|
||||||
|
allowManaged.Checked += AllowManaged_CheckStateChanged;
|
||||||
|
allowManaged.Unchecked += AllowManaged_CheckStateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateNetworkData()
|
private void UpdateNetworkData()
|
||||||
{
|
{
|
||||||
this.networkId.Text = network.NetworkId;
|
|
||||||
this.networkName.Text = network.NetworkName;
|
if (this.networkId.Text != network.NetworkId)
|
||||||
this.networkStatus.Text = network.NetworkStatus;
|
this.networkId.Text = network.NetworkId;
|
||||||
this.networkType.Text = network.NetworkType;
|
|
||||||
this.macAddress.Text = network.MacAddress;
|
if (this.networkName.Text != network.NetworkName)
|
||||||
this.mtu.Text = network.MTU.ToString();
|
this.networkName.Text = network.NetworkName;
|
||||||
|
|
||||||
|
if (this.networkStatus.Text != network.NetworkStatus)
|
||||||
|
this.networkStatus.Text = network.NetworkStatus;
|
||||||
|
|
||||||
|
if (this.networkType.Text != network.NetworkType)
|
||||||
|
this.networkType.Text = network.NetworkType;
|
||||||
|
|
||||||
|
if (this.macAddress.Text != network.MacAddress)
|
||||||
|
this.macAddress.Text = network.MacAddress;
|
||||||
|
|
||||||
|
if (this.mtu.Text != network.MTU.ToString())
|
||||||
|
this.mtu.Text = network.MTU.ToString();
|
||||||
|
|
||||||
this.broadcastEnabled.Text = (network.BroadcastEnabled ? "ENABLED" : "DISABLED");
|
this.broadcastEnabled.Text = (network.BroadcastEnabled ? "ENABLED" : "DISABLED");
|
||||||
this.bridgingEnabled.Text = (network.Bridge ? "ENABLED" : "DISABLED");
|
this.bridgingEnabled.Text = (network.Bridge ? "ENABLED" : "DISABLED");
|
||||||
this.deviceName.Text = network.DeviceName;
|
|
||||||
|
if (this.deviceName.Text != network.DeviceName)
|
||||||
|
this.deviceName.Text = network.DeviceName;
|
||||||
|
|
||||||
string iplist = "";
|
string iplist = "";
|
||||||
for (int i = 0; i < network.AssignedAddresses.Length; ++i)
|
for (int i = 0; i < network.AssignedAddresses.Length; ++i)
|
||||||
|
@ -51,19 +73,12 @@ namespace WinUI
|
||||||
iplist += "\n";
|
iplist += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
this.managedIps.Text = iplist;
|
if (this.managedIps.Text != iplist)
|
||||||
|
this.managedIps.Text = iplist;
|
||||||
|
|
||||||
this.allowDefault.IsChecked = network.AllowDefault;
|
this.allowDefault.IsChecked = network.AllowDefault;
|
||||||
this.allowGlobal.IsChecked = network.AllowGlobal;
|
this.allowGlobal.IsChecked = network.AllowGlobal;
|
||||||
this.allowManaged.IsChecked = network.AllowManaged;
|
this.allowManaged.IsChecked = network.AllowManaged;
|
||||||
|
|
||||||
allowDefault.Checked += AllowDefault_CheckStateChanged;
|
|
||||||
allowDefault.Unchecked += AllowDefault_CheckStateChanged;
|
|
||||||
allowGlobal.Checked += AllowGlobal_CheckStateChanged;
|
|
||||||
allowGlobal.Unchecked += AllowGlobal_CheckStateChanged;
|
|
||||||
allowManaged.Checked += AllowManaged_CheckStateChanged;
|
|
||||||
allowManaged.Unchecked += AllowManaged_CheckStateChanged;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasNetwork(ZeroTierNetwork network)
|
public bool HasNetwork(ZeroTierNetwork network)
|
||||||
|
@ -74,6 +89,13 @@ namespace WinUI
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetNetworkInfo(ZeroTierNetwork network)
|
||||||
|
{
|
||||||
|
this.network = network;
|
||||||
|
|
||||||
|
UpdateNetworkData();
|
||||||
|
}
|
||||||
|
|
||||||
private void leaveButton_Click(object sender, RoutedEventArgs e)
|
private void leaveButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
APIHandler.Instance.LeaveNetwork(network.NetworkId);
|
APIHandler.Instance.LeaveNetwork(network.NetworkId);
|
||||||
|
|
|
@ -93,7 +93,9 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
</ItemsPanelTemplate>
|
</ItemsPanelTemplate>
|
||||||
</StatusBar.ItemsPanel>
|
</StatusBar.ItemsPanel>
|
||||||
<StatusBarItem Grid.Column="0" x:Name="networkId" Content="deadbeef00" Foreground="White" FontFamily="Lucida Console"/>
|
<StatusBarItem Grid.Column="0" x:Name="networkId_placeholder">
|
||||||
|
<TextBox x:Name="networkId" Text="deadbeef00" HorizontalAlignment="Left" Grid.Column="0" Foreground="White" FontFamily="Lucida Console" BorderThickness="0" IsReadOnly="true" Background="Transparent"/>
|
||||||
|
</StatusBarItem>
|
||||||
<StatusBarItem Grid.Column="1" x:Name="onlineStatus" Content="ONLINE" Foreground="White" FontFamily="Lucida Console"/>
|
<StatusBarItem Grid.Column="1" x:Name="onlineStatus" Content="ONLINE" Foreground="White" FontFamily="Lucida Console"/>
|
||||||
<StatusBarItem Grid.Column="2" x:Name="versionString" Content="1.0.5" Foreground="White" FontFamily="Lucida Console"/>
|
<StatusBarItem Grid.Column="2" x:Name="versionString" Content="1.0.5" Foreground="White" FontFamily="Lucida Console"/>
|
||||||
<StatusBarItem Grid.Column="3" x:Name="blank" Content="" Height="43" Foreground="White"/>
|
<StatusBarItem Grid.Column="3" x:Name="blank" Content="" Height="43" Foreground="White"/>
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace WinUI
|
||||||
|
|
||||||
networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
{
|
{
|
||||||
this.networkId.Content = status.Address;
|
this.networkId.Text = status.Address;
|
||||||
}));
|
}));
|
||||||
versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
{
|
{
|
||||||
|
@ -80,7 +80,7 @@ namespace WinUI
|
||||||
|
|
||||||
networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
{
|
{
|
||||||
this.networkId.Content = "";
|
this.networkId.Text = "";
|
||||||
}));
|
}));
|
||||||
versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,18 +27,73 @@ namespace WinUI
|
||||||
|
|
||||||
public void setNetworks(List<ZeroTierNetwork> networks)
|
public void setNetworks(List<ZeroTierNetwork> networks)
|
||||||
{
|
{
|
||||||
this.wrapPanel.Children.Clear();
|
|
||||||
if (networks == null)
|
if (networks == null)
|
||||||
{
|
{
|
||||||
|
this.wrapPanel.Children.Clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < networks.Count; ++i)
|
foreach (ZeroTierNetwork network in networks)
|
||||||
{
|
{
|
||||||
this.wrapPanel.Children.Add(
|
NetworkInfoView view = ChildWithNetwork(network);
|
||||||
new NetworkInfoView(
|
if (view != null)
|
||||||
networks.ElementAt<ZeroTierNetwork>(i)));
|
{
|
||||||
|
view.SetNetworkInfo(network);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wrapPanel.Children.Add(
|
||||||
|
new NetworkInfoView(
|
||||||
|
network));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove networks we're no longer joined to.
|
||||||
|
List<ZeroTierNetwork> tmpList = GetNetworksFromChildren();
|
||||||
|
foreach (ZeroTierNetwork n in networks)
|
||||||
|
{
|
||||||
|
if (tmpList.Contains(n))
|
||||||
|
{
|
||||||
|
tmpList.Remove(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (ZeroTierNetwork n in tmpList)
|
||||||
|
{
|
||||||
|
NetworkInfoView view = ChildWithNetwork(n);
|
||||||
|
if (view != null)
|
||||||
|
{
|
||||||
|
wrapPanel.Children.Remove(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NetworkInfoView ChildWithNetwork(ZeroTierNetwork network)
|
||||||
|
{
|
||||||
|
List<NetworkInfoView> list = wrapPanel.Children.OfType<NetworkInfoView>().ToList();
|
||||||
|
|
||||||
|
foreach (NetworkInfoView view in list)
|
||||||
|
{
|
||||||
|
if (view.HasNetwork(network))
|
||||||
|
{
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ZeroTierNetwork> GetNetworksFromChildren()
|
||||||
|
{
|
||||||
|
List<ZeroTierNetwork> networks = new List<ZeroTierNetwork>(wrapPanel.Children.Count);
|
||||||
|
|
||||||
|
List<NetworkInfoView> list = wrapPanel.Children.OfType<NetworkInfoView>().ToList();
|
||||||
|
foreach (NetworkInfoView n in list)
|
||||||
|
{
|
||||||
|
networks.Add(n.network);
|
||||||
|
}
|
||||||
|
|
||||||
|
return networks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\controller\EmbeddedNetworkController.cpp" />
|
<ClCompile Include="..\..\controller\EmbeddedNetworkController.cpp" />
|
||||||
|
<ClCompile Include="..\..\controller\JSONDB.cpp" />
|
||||||
<ClCompile Include="..\..\ext\http-parser\http_parser.c" />
|
<ClCompile Include="..\..\ext\http-parser\http_parser.c" />
|
||||||
<ClCompile Include="..\..\ext\libnatpmp\getgateway.c" />
|
<ClCompile Include="..\..\ext\libnatpmp\getgateway.c" />
|
||||||
<ClCompile Include="..\..\ext\libnatpmp\natpmp.c" />
|
<ClCompile Include="..\..\ext\libnatpmp\natpmp.c" />
|
||||||
|
@ -269,7 +270,7 @@
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>
|
||||||
</AdditionalIncludeDirectories>
|
</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>NOMINMAX;STATICLIB;WIN32;ZT_TRACE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>NOMINMAX;STATICLIB;WIN32;ZT_TRACE;ZT_RULES_ENGINE_DEBUGGING;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<MultiProcessorCompilation>false</MultiProcessorCompilation>
|
<MultiProcessorCompilation>false</MultiProcessorCompilation>
|
||||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -261,6 +261,9 @@
|
||||||
<ClCompile Include="..\..\controller\EmbeddedNetworkController.cpp">
|
<ClCompile Include="..\..\controller\EmbeddedNetworkController.cpp">
|
||||||
<Filter>Source Files\controller</Filter>
|
<Filter>Source Files\controller</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\controller\JSONDB.cpp">
|
||||||
|
<Filter>Source Files\controller</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="resource.h">
|
<ClInclude Include="resource.h">
|
||||||
|
|
Loading…
Add table
Reference in a new issue