diff --git a/examples/cpp/adhoc.cpp b/examples/cpp/adhoc.cpp index ec6ee0e..cdad3f6 100644 --- a/examples/cpp/adhoc.cpp +++ b/examples/cpp/adhoc.cpp @@ -12,7 +12,7 @@ * the location given in the first argument to zts_start(path, ...). If you accidentally * duplicate the identity files and use them simultaneously in a different node instance * you will experience undefined behavior and it is likely nothing will work. - * + * * - You must authorize the node ID provided by the ZTS_EVENT_NODE_ONLINE callback to join * your network, otherwise nothing will happen. This can be done manually or via * our web API: https://my.zerotier.com/help/api @@ -51,12 +51,12 @@ * Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors * returned by these functions can be any of the following: * - * ZTS_ERR_OK 0 // No error - * ZTS_ERR_SOCKET -1 // Socket error, see zts_errno - * ZTS_ERR_SERVICE -2 // You probably did something at the wrong time - * ZTS_ERR_ARG -3 // Invalid argument - * ZTS_ERR_NO_RESULT -4 // No result (not necessarily an error) - * ZTS_ERR_GENERAL -5 // Consider filing a bug report + * ZTS_ERR_OK // No error + * ZTS_ERR_SOCKET // Socket error, see zts_errno + * ZTS_ERR_SERVICE // You probably did something at the wrong time + * ZTS_ERR_ARG // Invalid argument + * ZTS_ERR_NO_RESULT // No result (not necessarily an error) + * ZTS_ERR_GENERAL // Consider filing a bug report * * Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc). * Errors returned by these functions can be the same as the above. With @@ -74,7 +74,7 @@ * are a few guidelines: * * If you are calling a zts_* function, use the appropriate ZTS_* constants: - * + * * zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT) * zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT) * @@ -91,10 +91,19 @@ #include "ZeroTierSockets.h" -bool nodeReady = false; -bool networkReady = false; +struct Node +{ + Node() : online(false), joinedAtLeastOneNetwork(false), id(0) {} + bool online; + bool joinedAtLeastOneNetwork; + uint64_t id; + // etc +} myNode; -// Example callbacks +/* Callback handler, you should return control from this function as quickly as you can +to ensure timely receipt of future events. You should not call libzt API functions from +this function unless it's something trivial like zts_inet_ntop() or similar that has +no state-change implications. */ void myZeroTierEventCallback(void *msgPtr) { struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr; @@ -102,11 +111,12 @@ void myZeroTierEventCallback(void *msgPtr) // Node events if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->address); - nodeReady = true; + myNode.id = msg->node->address; + myNode.online = true; } if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) { printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, firewall, etc. What ports are you blocking?\n"); - nodeReady = false; + myNode.online = false; } // Virtual network events @@ -116,7 +126,7 @@ void myZeroTierEventCallback(void *msgPtr) } if (msg->eventCode == ZTS_EVENT_NETWORK_REQ_CONFIG) { printf("ZTS_EVENT_NETWORK_REQ_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", msg->network->nwid); - } + } if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { printf("ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n", msg->network->nwid); @@ -124,7 +134,7 @@ void myZeroTierEventCallback(void *msgPtr) if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) { printf("ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent over network %llx\n", msg->network->nwid); - networkReady = true; + myNode.joinedAtLeastOneNetwork = true; } if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) { printf("ZTS_EVENT_NETWORK_DOWN --- %llx\n", msg->network->nwid); @@ -132,17 +142,15 @@ void myZeroTierEventCallback(void *msgPtr) // Network stack events if (msg->eventCode == ZTS_EVENT_NETIF_UP) { - printf("ZTS_EVENT_NETIF_UP --- network=%llx, mac=%llx, mtu=%d\n", + printf("ZTS_EVENT_NETIF_UP --- network=%llx, mac=%llx, mtu=%d\n", msg->netif->nwid, msg->netif->mac, msg->netif->mtu); - networkReady = true; } if (msg->eventCode == ZTS_EVENT_NETIF_DOWN) { - printf("ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n", + printf("ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n", msg->netif->nwid, msg->netif->mac); - networkReady = true; } // Address events @@ -150,19 +158,32 @@ void myZeroTierEventCallback(void *msgPtr) char ipstr[ZTS_INET6_ADDRSTRLEN]; struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n", + printf("ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n", msg->addr->nwid, ipstr); } // Peer events - // Don't worry if you don't recognize a peer ID, it's most likely our infrastructure - if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { - printf("ZTS_EVENT_PEER_DIRECT --- There is now a direct path to peer %llx\n", - msg->peer->address); - } - if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { - printf("ZTS_EVENT_PEER_RELAY --- No direct path to peer %llx\n", - msg->peer->address); + if (msg->peer) { + if (msg->peer->role == ZTS_PEER_ROLE_PLANET) { + /* Safe to ignore, these are our roots. They orchestrate the P2P connection. + You might also see other unknown peers, these are our network controllers. */ + return; + } + if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { + printf("ZTS_EVENT_PEER_DIRECT --- A direct path is known for node=%llx\n", + msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { + printf("ZTS_EVENT_PEER_RELAY --- No direct path to node=%llx\n", msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_PATH_DISCOVERED) { + printf("ZTS_EVENT_PEER_PATH_DISCOVERED --- A new direct path was discovered for node=%llx\n", + msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_PATH_DEAD) { + printf("ZTS_EVENT_PEER_PATH_DEAD --- A direct path has died for node=%llx\n", + msg->peer->address); + } } } @@ -191,7 +212,7 @@ be taken to avoid exposing vulnerable services or sharing unwanted files or othe */ -int main(int argc, char **argv) +int main(int argc, char **argv) { if (argc != 5) { printf("\nlibzt example\n"); @@ -212,7 +233,7 @@ int main(int argc, char **argv) exit(1); } printf("Waiting for node to come online...\n"); - while (!nodeReady) { zts_delay_ms(50); } + while (!myNode.online) { zts_delay_ms(50); } printf("This node's identity is stored in %s\n", argv[1]); if((err = zts_join(adhoc_nwid)) != ZTS_ERR_OK) { @@ -220,7 +241,7 @@ int main(int argc, char **argv) exit(1); } printf("Joining network %llx\n", adhoc_nwid); - while (!networkReady) { zts_delay_ms(50); } + while (!myNode.joinedAtLeastOneNetwork) { zts_delay_ms(50); } // Idle and just show callback events, stack statistics, etc diff --git a/examples/cpp/client.cpp b/examples/cpp/client.cpp index 75b35d3..e247094 100644 --- a/examples/cpp/client.cpp +++ b/examples/cpp/client.cpp @@ -9,10 +9,19 @@ #include "ZeroTierSockets.h" -bool nodeReady = false; -bool networkReady = false; +struct Node +{ + Node() : online(false), joinedAtLeastOneNetwork(false), id(0) {} + bool online; + bool joinedAtLeastOneNetwork; + uint64_t id; + // etc +} myNode; -// Example callbacks +/* Callback handler, you should return control from this function as quickly as you can +to ensure timely receipt of future events. You should not call libzt API functions from +this function unless it's something trivial like zts_inet_ntop() or similar that has +no state-change implications. */ void myZeroTierEventCallback(void *msgPtr) { struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr; @@ -20,11 +29,12 @@ void myZeroTierEventCallback(void *msgPtr) // Node events if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->address); - nodeReady = true; + myNode.id = msg->node->address; + myNode.online = true; } if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) { printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, firewall, etc. What ports are you blocking?\n"); - nodeReady = false; + myNode.online = false; } if (msg->eventCode == ZTS_EVENT_NODE_NORMAL_TERMINATION) { printf("ZTS_EVENT_NODE_NORMAL_TERMINATION\n"); @@ -37,7 +47,7 @@ void myZeroTierEventCallback(void *msgPtr) } if (msg->eventCode == ZTS_EVENT_NETWORK_REQ_CONFIG) { printf("ZTS_EVENT_NETWORK_REQ_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", msg->network->nwid); - } + } if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { printf("ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n", msg->network->nwid); @@ -45,12 +55,12 @@ void myZeroTierEventCallback(void *msgPtr) if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP4) { printf("ZTS_EVENT_NETWORK_READY_IP4 --- Network config received. IPv4 traffic can now be sent over network %llx\n", msg->network->nwid); - networkReady = true; + myNode.joinedAtLeastOneNetwork = true; } if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) { printf("ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent over network %llx\n", msg->network->nwid); - networkReady = true; + myNode.joinedAtLeastOneNetwork = true; } if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) { printf("ZTS_EVENT_NETWORK_DOWN --- %llx\n", msg->network->nwid); @@ -61,38 +71,52 @@ void myZeroTierEventCallback(void *msgPtr) char ipstr[ZTS_INET_ADDRSTRLEN]; struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_NEW_IP4 --- This node's virtual address on network %llx is %s\n", + printf("ZTS_EVENT_ADDR_NEW_IP4 --- This node's virtual address on network %llx is %s\n", msg->addr->nwid, ipstr); } if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) { char ipstr[ZTS_INET6_ADDRSTRLEN]; struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_NEW_IP6 --- This node's virtual address on network %llx is %s\n", + printf("ZTS_EVENT_ADDR_NEW_IP6 --- This node's virtual address on network %llx is %s\n", msg->addr->nwid, ipstr); } if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP4) { char ipstr[ZTS_INET_ADDRSTRLEN]; struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_REMOVED_IP4 --- The virtual address %s for this node on network %llx has been removed.\n", + printf("ZTS_EVENT_ADDR_REMOVED_IP4 --- The virtual address %s for this node on network %llx has been removed.\n", ipstr, msg->addr->nwid); } if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP6) { char ipstr[ZTS_INET6_ADDRSTRLEN]; struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_REMOVED_IP6 --- The virtual address %s for this node on network %llx has been removed.\n", + printf("ZTS_EVENT_ADDR_REMOVED_IP6 --- The virtual address %s for this node on network %llx has been removed.\n", ipstr, msg->addr->nwid); } // Peer events - if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { - printf("ZTS_EVENT_PEER_DIRECT --- node=%llx\n", msg->peer->address); - // A direct path is known for nodeId - } - if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { - printf("ZTS_EVENT_PEER_RELAY --- node=%llx\n", msg->peer->address); - // No direct path is known for nodeId + if (msg->peer) { + if (msg->peer->role == ZTS_PEER_ROLE_PLANET) { + /* Safe to ignore, these are our roots. They orchestrate the P2P connection. + You might also see other unknown peers, these are our network controllers. */ + return; + } + if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { + printf("ZTS_EVENT_PEER_DIRECT --- A direct path is known for node=%llx\n", + msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { + printf("ZTS_EVENT_PEER_RELAY --- No direct path to node=%llx\n", msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_PATH_DISCOVERED) { + printf("ZTS_EVENT_PEER_PATH_DISCOVERED --- A new direct path was discovered for node=%llx\n", + msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_PATH_DEAD) { + printf("ZTS_EVENT_PEER_PATH_DEAD --- A direct path has died for node=%llx\n", + msg->peer->address); + } } } @@ -104,7 +128,7 @@ void myZeroTierEventCallback(void *msgPtr) * the location given in the first argument to zts_start(path, ...). If you accidentally * duplicate the identity files and use them simultaneously in a different node instance * you will experience undefined behavior and it is likely nothing will work. - * + * * - You must authorize the node ID provided by the ZTS_EVENT_NODE_ONLINE callback to join * your network, otherwise nothing will happen. This can be done manually or via * our web API: https://my.zerotier.com/help/api @@ -143,12 +167,12 @@ void myZeroTierEventCallback(void *msgPtr) * Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors * returned by these functions can be any of the following: * - * ZTS_ERR_OK 0 // No error - * ZTS_ERR_SOCKET -1 // Socket error, see zts_errno - * ZTS_ERR_SERVICE -2 // You probably did something at the wrong time - * ZTS_ERR_ARG -3 // Invalid argument - * ZTS_ERR_NO_RESULT -4 // No result (not necessarily an error) - * ZTS_ERR_GENERAL -5 // Consider filing a bug report + * ZTS_ERR_OK // No error + * ZTS_ERR_SOCKET // Socket error, see zts_errno + * ZTS_ERR_SERVICE // You probably did something at the wrong time + * ZTS_ERR_ARG // Invalid argument + * ZTS_ERR_NO_RESULT // No result (not necessarily an error) + * ZTS_ERR_GENERAL // Consider filing a bug report * * Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc). * Errors returned by these functions can be the same as the above. With @@ -166,7 +190,7 @@ void myZeroTierEventCallback(void *msgPtr) * are a few guidelines: * * If you are calling a zts_* function, use the appropriate ZTS_* constants: - * + * * zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT) * zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT) * @@ -178,7 +202,7 @@ void myZeroTierEventCallback(void *msgPtr) * */ -int main(int argc, char **argv) +int main(int argc, char **argv) { if (argc != 6) { printf("\nlibzt example client\n"); @@ -208,7 +232,7 @@ int main(int argc, char **argv) exit(1); } printf("Waiting for node to come online...\n"); - while (!nodeReady) { zts_delay_ms(50); } + while (!myNode.online) { zts_delay_ms(50); } printf("This node's identity is stored in %s\n", argv[1]); if((err = zts_join(nwid)) != ZTS_ERR_OK) { @@ -217,7 +241,7 @@ int main(int argc, char **argv) } printf("Joining network %llx\n", nwid); printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); - while (!networkReady) { zts_delay_ms(50); } + while (!myNode.joinedAtLeastOneNetwork) { zts_delay_ms(50); } // Socket-like API example @@ -243,7 +267,7 @@ int main(int argc, char **argv) exit(1); } zts_delay_ms(250); - } + } else { printf("Connected.\n"); break; diff --git a/examples/cpp/comprehensive.cpp b/examples/cpp/comprehensive.cpp index eeaf08a..46f25c2 100644 --- a/examples/cpp/comprehensive.cpp +++ b/examples/cpp/comprehensive.cpp @@ -12,7 +12,7 @@ * the location given in the first argument to zts_start(path, ...). If you accidentally * duplicate the identity files and use them simultaneously in a different node instance * you will experience undefined behavior and it is likely nothing will work. - * + * * - You must authorize the node ID provided by the ZTS_EVENT_NODE_ONLINE callback to join * your network, otherwise nothing will happen. This can be done manually or via * our web API: https://my.zerotier.com/help/api @@ -51,12 +51,12 @@ * Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors * returned by these functions can be any of the following: * - * ZTS_ERR_OK 0 // No error - * ZTS_ERR_SOCKET -1 // Socket error, see zts_errno - * ZTS_ERR_SERVICE -2 // You probably did something at the wrong time - * ZTS_ERR_ARG -3 // Invalid argument - * ZTS_ERR_NO_RESULT -4 // No result (not necessarily an error) - * ZTS_ERR_GENERAL -5 // Consider filing a bug report + * ZTS_ERR_OK // No error + * ZTS_ERR_SOCKET // Socket error, see zts_errno + * ZTS_ERR_SERVICE // You probably did something at the wrong time + * ZTS_ERR_ARG // Invalid argument + * ZTS_ERR_NO_RESULT // No result (not necessarily an error) + * ZTS_ERR_GENERAL // Consider filing a bug report * * Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc). * Errors returned by these functions can be the same as the above. With @@ -74,7 +74,7 @@ * are a few guidelines: * * If you are calling a zts_* function, use the appropriate ZTS_* constants: - * + * * zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT) * zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT) * @@ -88,126 +88,45 @@ #include #include +#include #include "ZeroTierSockets.h" -bool nodeReady = false; -bool networkReady = false; +#include "winsock.h" -// Example callbacks -void myZeroTierEventCallback(void *msgPtr) +struct Node { - struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr; + Node() : online(false), joinedAtLeastOneNetwork(false), id(0) {} + bool online; + bool joinedAtLeastOneNetwork; + uint64_t id; + // etc +} myNode; - // Node events - if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { - printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->address); - nodeReady = true; - } - if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) { - printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, firewall, etc. What ports are you blocking?\n"); - nodeReady = false; - } - if (msg->eventCode == ZTS_EVENT_NODE_NORMAL_TERMINATION) { - printf("ZTS_EVENT_NODE_NORMAL_TERMINATION\n"); - } - - // Virtual network events - if (msg->eventCode == ZTS_EVENT_NETWORK_NOT_FOUND) { - printf("ZTS_EVENT_NETWORK_NOT_FOUND --- Are you sure %llx is a valid network?\n", - msg->network->nwid); - } - if (msg->eventCode == ZTS_EVENT_NETWORK_REQ_CONFIG) { - printf("ZTS_EVENT_NETWORK_REQ_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", msg->network->nwid); - } - if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { - printf("ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n", - msg->network->nwid); - } - if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP4) { - printf("ZTS_EVENT_NETWORK_READY_IP4 --- Network config received. IPv4 traffic can now be sent over network %llx\n", - msg->network->nwid); - networkReady = true; - } - if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) { - printf("ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent over network %llx\n", - msg->network->nwid); - networkReady = true; - } - if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) { - printf("ZTS_EVENT_NETWORK_DOWN --- %llx\n", msg->network->nwid); - } - - // Network stack events - if (msg->eventCode == ZTS_EVENT_NETIF_UP) { - printf("ZTS_EVENT_NETIF_UP --- network=%llx, mac=%llx, mtu=%d\n", - msg->netif->nwid, - msg->netif->mac, - msg->netif->mtu); - networkReady = true; - } - if (msg->eventCode == ZTS_EVENT_NETIF_DOWN) { - printf("ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n", - msg->netif->nwid, - msg->netif->mac); - networkReady = true; - } - - // Address events - if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP4) { - char ipstr[ZTS_INET_ADDRSTRLEN]; - struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr); - zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_NEW_IP4 --- This node's virtual address on network %llx is %s\n", - msg->addr->nwid, ipstr); - } - if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) { - char ipstr[ZTS_INET6_ADDRSTRLEN]; - struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); - zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_NEW_IP6 --- This node's virtual address on network %llx is %s\n", - msg->addr->nwid, ipstr); - } - if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP4) { - char ipstr[ZTS_INET_ADDRSTRLEN]; - struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr); - zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_REMOVED_IP4 --- The virtual address %s for this node on network %llx has been removed.\n", - ipstr, msg->addr->nwid); - } - if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP6) { - char ipstr[ZTS_INET6_ADDRSTRLEN]; - struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); - zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_REMOVED_IP6 --- The virtual address %s for this node on network %llx has been removed.\n", - ipstr, msg->addr->nwid); - } - - // Peer events - if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { - printf("ZTS_EVENT_PEER_DIRECT --- node=%llx\n", msg->peer->address); - // A direct path is known for nodeId - } - if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { - printf("ZTS_EVENT_PEER_RELAY --- node=%llx\n", msg->peer->address); - // No direct path is known for nodeId - } +void printNodeDetails(const char *msgStr, struct zts_node_details *d) +{ + printf("\n%s\n", msgStr); + printf("\t- id : %llx\n", d->address); + printf("\t- version : %d.%d.%d\n", d->versionMajor, d->versionMinor, d->versionRev); + printf("\t- primaryPort : %d\n", d->primaryPort); + printf("\t- secondaryPort : %d\n", d->secondaryPort); } -void printPeerDetails(struct zts_peer_details *pd) +void printPeerDetails(const char *msgStr, struct zts_peer_details *d) { - printf("\npeer=%llx, latency=%d, version=%d.%d.%d, pathCount=%d\n", - pd->address, - pd->latency, - pd->versionMajor, - pd->versionMinor, - pd->versionRev, - pd->pathCount); + printf("\n%s\n", msgStr); + printf("\t- peer : %llx\n", d->address); + printf("\t- role : %llx\n", d->role); + printf("\t- latency : %llx\n", d->latency); + printf("\t- pathCount : %llx\n", d->pathCount); + printf("\t- version : %d.%d.%d\n", d->versionMajor, d->versionMinor, d->versionRev); + printf("\t- paths:\n"); + // Print all known paths for each peer - for (unsigned int j=0; jpathCount; j++) { + for (unsigned int j=0; jpathCount; j++) { char ipstr[ZTS_INET6_ADDRSTRLEN]; int port = 0; - struct zts_sockaddr *sa = (struct zts_sockaddr *)&(pd->paths[j].address); + struct zts_sockaddr *sa = (struct zts_sockaddr *)&(d->paths[j].address); if (sa->sa_family == ZTS_AF_INET) { // TODO: Probably broken struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)sa; zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); @@ -217,51 +136,219 @@ void printPeerDetails(struct zts_peer_details *pd) struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)sa; zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); } - printf("\tpath[%d]=%s, port=%d\n", j, ipstr, port); + printf("\t - %15s : %6d\n", ipstr, port); } + printf("\n"); } -void getSinglePeerDetails(uint64_t peerId) +void printNetworkDetails(const char *msgStr, struct zts_network_details *d) { - struct zts_peer_details pd; - int err = zts_get_peer(&pd, peerId); + printf("\n%s\n", msgStr); + printf("\t- nwid : %llx\n", d->nwid); + printf("\t- mac : %lx\n", d->mac); + printf("\t- name : %s\n", d->name); + printf("\t- type : %d\n", d->type); + /* MTU for the virtual network can be set via our web API */ + printf("\t- mtu : %d\n", d->mtu); + printf("\t- dhcp : %d\n", d->dhcp); + printf("\t- bridge : %d\n", d->bridge); + printf("\t- broadcastEnabled : %d\n", d->broadcastEnabled); + printf("\t- portError : %d\n", d->portError); + printf("\t- netconfRevision : %d\n", d->netconfRevision); + printf("\t- routeCount : %d\n", d->routeCount); + printf("\t- multicastSubscriptionCount : %d\n", d->multicastSubscriptionCount); - if (err == ZTS_ERR_OK) { - printf("(%d) call succeeded\n", err); - printPeerDetails(&pd); - } if (err == ZTS_ERR_ARG) { - printf("(%d) invalid argument\n", err); - return; - } if (err == ZTS_ERR_SERVICE) { - printf("(%d) error: invalid API operation or service error\n", err); - return; - } if (err == ZTS_ERR_NO_RESULT) { - printf("(%d) error: object or result not found\n", err); - return; + for (int i=0; imulticastSubscriptionCount; i++) { + printf("\t - mac=%llx, adi=%x\n", d->multicastSubscriptions[i].mac, d->multicastSubscriptions[i].adi); } -} -// Similar to "zerotier-cli listpeers" -void getAllPeerDetails() -{ - struct zts_peer_details pd[128]; - /* This number should be large enough to handle the - expected number of peers. This call can also get - expensive for large numbers of peers. Consider using - get_peer(struct zts_peer_details *pds, uint64_t peerId) - instead */ - unsigned int num = 128; - int err; - if ((err = zts_get_peers(pd, &num)) < 0) { - printf("error (%d)\n", err); - return; - } - if (num) { - printf("num=%d\n", num); - for (unsigned int i=0; iassignedAddressCount; i++) { + if (d->assignedAddresses[i].ss_family == ZTS_AF_INET) { + char ipstr[ZTS_INET_ADDRSTRLEN]; + struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(d->assignedAddresses[i]); + zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); + printf("\t - %s\n",ipstr); + } + if (d->assignedAddresses[i].ss_family == ZTS_AF_INET6) { + char ipstr[ZTS_INET6_ADDRSTRLEN]; + struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(d->assignedAddresses[i]); + zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); + printf("\t - %s\n",ipstr); } } + + printf("\t- routes:\n"); + + for (int i=0; irouteCount; i++) { + if (d->routes[i].target.ss_family == ZTS_AF_INET) { + char ipstr[ZTS_INET_ADDRSTRLEN]; + struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(d->routes[i].target); + zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); + printf("\t - target : %s\n",ipstr); + in4 = (struct zts_sockaddr_in*)&(d->routes[i].via); + zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); + printf("\t - via : %s\n",ipstr); + } + if (d->routes[i].target.ss_family == ZTS_AF_INET6) { + char ipstr[ZTS_INET6_ADDRSTRLEN]; + struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(d->routes[i].target); + zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); + printf("\t - target : %s\n",ipstr); + in6 = (struct zts_sockaddr_in6*)&(d->routes[i].via); + zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); + printf("\t - via : %s\n",ipstr); + } + printf("\t - flags : %d\n", d->routes[i].flags); + printf("\t - metric : %d\n", d->routes[i].metric); + } +} + +void printNetifDetails(const char *msgStr, struct zts_netif_details *d) +{ + printf("\n%s\n", msgStr); + printf("\t- nwid : %llx\n", d->nwid); + printf("\t- mac : %llx\n", d->mac); + printf("\t- mtu : %d\n", d->mtu); +} + +/* Callback handler, you should return control from this function as quickly as you can +to ensure timely receipt of future events. You should not call libzt API functions from +this function unless it's something trivial like zts_inet_ntop() or similar that has +no state-change implications. */ +void myZeroTierEventCallback(void *msgPtr) +{ + struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr; + printf("code=%d\n", msg->eventCode); + + // Node events + if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { + printNodeDetails("nZTS_EVENT_NODE_ONLINE", msg->node); + myNode.id = msg->node->address; + myNode.online = true; + } + if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) { + printf("\nZTS_EVENT_NODE_OFFLINE --- Check your Internet connection, router, firewall, etc. What ports are you blocking?\n"); + myNode.online = false; + } + if (msg->eventCode == ZTS_EVENT_NODE_NORMAL_TERMINATION) { + printf("\nZTS_EVENT_NODE_NORMAL_TERMINATION -- A call to zts_start() will restart ZeroTier.\n"); + myNode.online = false; + } + + // Virtual network events + if (msg->eventCode == ZTS_EVENT_NETWORK_NOT_FOUND) { + printf("\nZTS_EVENT_NETWORK_NOT_FOUND --- Are you sure %llx is a valid network?\n", + msg->network->nwid); + } + if (msg->eventCode == ZTS_EVENT_NETWORK_REQ_CONFIG) { + printf("\nZTS_EVENT_NETWORK_REQ_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", + msg->network->nwid); + } + if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { + printf("\nZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n", + msg->network->nwid); + } + if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP4) { + printNetworkDetails("ZTS_EVENT_NETWORK_READY_IP4 --- Network config received.", msg->network); + myNode.joinedAtLeastOneNetwork = true; + } + if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) { + printNetworkDetails("ZTS_EVENT_NETWORK_READY_IP6 --- Network config received.", msg->network); + myNode.joinedAtLeastOneNetwork = true; + } + if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) { + printf("\nZTS_EVENT_NETWORK_DOWN --- %llx\n", msg->network->nwid); + } + if (msg->eventCode == ZTS_EVENT_NETWORK_UPDATE) { + printNetworkDetails("ZTS_EVENT_NETWORK_UPDATE --- Network config received.", msg->network); + } + + // Address events + if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP4) { + char ipstr[ZTS_INET_ADDRSTRLEN]; + struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr); + zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); + printf("\nZTS_EVENT_ADDR_ADDED_IP4 --- This node's virtual address on network %llx is %s\n", + msg->addr->nwid, ipstr); + } + if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) { + char ipstr[ZTS_INET6_ADDRSTRLEN]; + struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); + zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); + printf("\nZTS_EVENT_ADDR_ADDED_IP6 --- This node's virtual address on network %llx is %s\n", + msg->addr->nwid, ipstr); + } + if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP4) { + char ipstr[ZTS_INET_ADDRSTRLEN]; + struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr); + zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); + printf("\nZTS_EVENT_ADDR_REMOVED_IP4 --- The virtual address %s for this node on network %llx has been removed.\n", + ipstr, msg->addr->nwid); + } + if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP6) { + char ipstr[ZTS_INET6_ADDRSTRLEN]; + struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); + zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); + printf("\nZTS_EVENT_ADDR_REMOVED_IP6 --- The virtual address %s for this node on network %llx has been removed.\n", + ipstr, msg->addr->nwid); + } + + // Peer events + if (msg->peer) { + if (msg->peer->role == ZTS_PEER_ROLE_PLANET) { + /* Safe to ignore, these are our roots. They orchestrate the P2P connection. + You might also see other unknown peers, these are our network controllers. */ + return; + } + if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { + printPeerDetails("ZTS_EVENT_PEER_DIRECT --- A direct path is known.", msg->peer); + } + if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { + printPeerDetails("ZTS_EVENT_PEER_RELAY --- No direct path known.", msg->peer); + } + if (msg->eventCode == ZTS_EVENT_PEER_PATH_DISCOVERED) { + printPeerDetails("ZTS_EVENT_PEER_PATH_DISCOVERED --- A new direct path was discovered.", msg->peer); + } + if (msg->eventCode == ZTS_EVENT_PEER_PATH_DEAD) { + printPeerDetails("ZTS_EVENT_PEER_PATH_DEAD --- A direct path has died.", msg->peer); + } + } + + // Network stack (netif) events (used for debugging, can be ignored) + if (msg->eventCode == ZTS_EVENT_NETIF_UP) { + printNetifDetails("ZTS_EVENT_NETIF_UP --- No action required.", msg->netif); + } + if (msg->eventCode == ZTS_EVENT_NETIF_DOWN) { + printNetifDetails("ZTS_EVENT_NETIF_DOWN --- No action required.", msg->netif); + } + if (msg->eventCode == ZTS_EVENT_NETIF_REMOVED) { + printNetifDetails("ZTS_EVENT_NETIF_REMOVED --- No action required.", msg->netif); + } + if (msg->eventCode == ZTS_EVENT_NETIF_LINK_UP) { + printNetifDetails("ZTS_EVENT_NETIF_LINK_UP --- No action required.", msg->netif); + } + if (msg->eventCode == ZTS_EVENT_NETIF_LINK_DOWN) { + printNetifDetails("ZTS_EVENT_NETIF_LINK_DOWN --- No action required.", msg->netif); + } + // Network stack events (used for debugging, can be ignored) + if (msg->eventCode == ZTS_EVENT_STACK_UP) { + printf("\nZTS_EVENT_STACK_UP --- No action required.\n"); + } + if (msg->eventCode == ZTS_EVENT_STACK_DOWN) { + printf("\nZTS_EVENT_STACK_DOWN --- No action required. An app restart is needed to use ZeroTier again.\n"); + } +} + +void get6PLANEAddressOfPeer(uint64_t peerId, uint64_t nwId) +{ + char peerAddrStr[ZTS_INET6_ADDRSTRLEN] = {0}; + struct zts_sockaddr_storage sixplane_addr; + zts_get_6plane_addr(&sixplane_addr, nwId, peerId); + struct zts_sockaddr_in6 *p6 = (struct zts_sockaddr_in6*)&sixplane_addr; + zts_inet_ntop(ZTS_AF_INET6, &(p6->sin6_addr), peerAddrStr, ZTS_INET6_ADDRSTRLEN); + printf("6PLANE address of peer is: %s\n", peerAddrStr); } struct zts_stats_proto protoSpecificStats; @@ -283,35 +370,36 @@ void display_stack_stats() printf("tcp.drop=%d\n", protoSpecificStats.drop); } -int main(int argc, char **argv) +int main(int argc, char **argv) { + fprintf(stderr, "AF_INET=%d, SOCK_STREAM=%d, IPPROTO_TCP=%d", AF_INET, SOCK_STREAM, IPPROTO_TCP); if (argc != 4) { printf("\nlibzt example server\n"); printf("comprehensive \n"); exit(0); } + std::string configPath = std::string(argv[1]); uint64_t nwid = strtoull(argv[2],NULL,16); // Network ID to join int ztServicePort = atoi(argv[3]); // Port ZT uses to send encrypted UDP packets to peers (try something like 9994) - + // Bring up ZeroTier service and join network + // Enable/Disable caching of network details in networks.d + // (read function documentation before disabling!) + // zts_allow_network_caching(0) + + // Enable/Disable caching of peer details in peers.d + // (read function documentation before disabling!) + // zts_allow_network_caching(1) + int err = ZTS_ERR_OK; - // Disable caching of network details in networks.d - // (read function documentation before disabling!) - // zts_set_network_caching(false) - - // Disable caching of peer details in peers.d - // (read function documentation before disabling!) - // zts_set_network_caching(false) - - if((err = zts_start(argv[1], &myZeroTierEventCallback, ztServicePort)) != ZTS_ERR_OK) { + if((err = zts_start(configPath.c_str(), &myZeroTierEventCallback, ztServicePort)) != ZTS_ERR_OK) { printf("Unable to start service, error = %d. Exiting.\n", err); exit(1); } printf("Waiting for node to come online...\n"); - while (!nodeReady) { zts_delay_ms(50); } - printf("This node ID is %llx\n", zts_get_node_id()); + while (!myNode.online) { zts_delay_ms(50); } printf("This node's identity is stored in %s\n", argv[1]); if((err = zts_join(nwid)) != ZTS_ERR_OK) { @@ -320,35 +408,29 @@ int main(int argc, char **argv) } printf("Joining network %llx\n", nwid); printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); - while (!networkReady) { zts_delay_ms(50); } - - // Get multiple peer's details - getAllPeerDetails(); - - // Get a single peer's details - uint64_t peerId = 0xabcdef1234; - getSinglePeerDetails(peerId); - int status = -1; - - // Get status of the node/service - status = zts_get_node_status(); - printf("zts_get_node_status()=%d\n", status); - - // Get status of a network - status = zts_get_network_status(nwid); - printf("zts_get_network_status()=%d\n", status); + while (!myNode.joinedAtLeastOneNetwork) { zts_delay_ms(50); } // Idle and just show callback events, stack statistics, etc + // Alternatively, this is where you could start making calls to the socket API - while (true) { - zts_delay_ms(1000); - status = zts_get_node_status(); - printf("zts_get_node_status()=%d\n", status); + /* + while(true) { display_stack_stats(); + zts_delay_ms(1000); } + */ - // Shut down service and stack threads - + int delay = 500000; + printf("This program will delay for %d seconds and then shut down.\n", (delay / 1000)); + zts_delay_ms(delay); + //printf("Leaving network %llx\n", nwid); + //zts_leave(nwid); + //zts_delay_ms(3000); /* added for demo purposes so that events show up */ + printf("Stopping ZeroTier\n"); zts_stop(); + zts_delay_ms(delay); /* added for demo purposes so that events show up */ + printf("Stopping network stack\n"); + zts_free(); + zts_delay_ms(delay); /* added for demo purposes so that events show up */ return 0; } diff --git a/examples/cpp/earthtest.cpp b/examples/cpp/earthtest.cpp index a6dff6a..89ee426 100644 --- a/examples/cpp/earthtest.cpp +++ b/examples/cpp/earthtest.cpp @@ -12,7 +12,7 @@ * the location given in the first argument to zts_start(path, ...). If you accidentally * duplicate the identity files and use them simultaneously in a different node instance * you will experience undefined behavior and it is likely nothing will work. - * + * * - You must authorize the node ID provided by the ZTS_EVENT_NODE_ONLINE callback to join * your network, otherwise nothing will happen. This can be done manually or via * our web API: https://my.zerotier.com/help/api @@ -51,12 +51,12 @@ * Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors * returned by these functions can be any of the following: * - * ZTS_ERR_OK 0 // No error - * ZTS_ERR_SOCKET -1 // Socket error, see zts_errno - * ZTS_ERR_SERVICE -2 // You probably did something at the wrong time - * ZTS_ERR_ARG -3 // Invalid argument - * ZTS_ERR_NO_RESULT -4 // No result (not necessarily an error) - * ZTS_ERR_GENERAL -5 // Consider filing a bug report + * ZTS_ERR_OK // No error + * ZTS_ERR_SOCKET // Socket error, see zts_errno + * ZTS_ERR_SERVICE // You probably did something at the wrong time + * ZTS_ERR_ARG // Invalid argument + * ZTS_ERR_NO_RESULT // No result (not necessarily an error) + * ZTS_ERR_GENERAL // Consider filing a bug report * * Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc). * Errors returned by these functions can be the same as the above. With @@ -74,7 +74,7 @@ * are a few guidelines: * * If you are calling a zts_* function, use the appropriate ZTS_* constants: - * + * * zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT) * zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT) * @@ -91,25 +91,35 @@ #include "ZeroTierSockets.h" -bool nodeReady = false; -bool networkReady = false; +struct Node +{ + Node() : online(false), joinedAtLeastOneNetwork(false), id(0) {} + bool online; + bool joinedAtLeastOneNetwork; + uint64_t id; + // etc +} myNode; -// Example callbacks +/* Callback handler, you should return control from this function as quickly as you can +to ensure timely receipt of future events. You should not call libzt API functions from +this function unless it's something trivial like zts_inet_ntop() or similar that has +no state-change implications. */ void myZeroTierEventCallback(void *msgPtr) { struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr; if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->address); - nodeReady = true; + myNode.id = msg->node->address; + myNode.online = true; } if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) { printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, firewall, etc. What ports are you blocking?\n"); - nodeReady = false; + myNode.online = false; } if (msg->eventCode == ZTS_EVENT_NETWORK_REQ_CONFIG) { printf("ZTS_EVENT_NETWORK_REQ_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", msg->network->nwid); - } + } if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { printf("ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n", msg->network->nwid); @@ -117,7 +127,7 @@ void myZeroTierEventCallback(void *msgPtr) if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) { printf("ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent over network %llx\n", msg->network->nwid); - networkReady = true; + myNode.joinedAtLeastOneNetwork = true; } if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) { printf("ZTS_EVENT_NETWORK_DOWN --- %llx\n", msg->network->nwid); @@ -126,28 +136,42 @@ void myZeroTierEventCallback(void *msgPtr) char ipstr[ZTS_INET_ADDRSTRLEN]; struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_NEW_IP4 --- Join %llx and ping me at %s\n", + printf("ZTS_EVENT_ADDR_NEW_IP4 --- Join %llx and ping me at %s\n", msg->addr->nwid, ipstr); } if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) { char ipstr[ZTS_INET6_ADDRSTRLEN]; struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n", + printf("ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n", msg->addr->nwid, ipstr); } - // Don't worry if you don't recognize a peer ID, it's most likely our infrastructure - if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { - printf("ZTS_EVENT_PEER_DIRECT --- There is now a direct path to peer %llx\n", - msg->peer->address); - } - if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { - printf("ZTS_EVENT_PEER_RELAY --- No direct path to peer %llx\n", - msg->peer->address); + // Peer events + if (msg->peer) { + if (msg->peer->role == ZTS_PEER_ROLE_PLANET) { + /* Safe to ignore, these are our roots. They orchestrate the P2P connection. + You might also see other unknown peers, these are our network controllers. */ + return; + } + if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { + printf("ZTS_EVENT_PEER_DIRECT --- A direct path is known for node=%llx\n", + msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { + printf("ZTS_EVENT_PEER_RELAY --- No direct path to node=%llx\n", msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_PATH_DISCOVERED) { + printf("ZTS_EVENT_PEER_PATH_DISCOVERED --- A new direct path was discovered for node=%llx\n", + msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_PATH_DEAD) { + printf("ZTS_EVENT_PEER_PATH_DEAD --- A direct path has died for node=%llx\n", + msg->peer->address); + } } } -int main(int argc, char **argv) +int main(int argc, char **argv) { if (argc != 3) { printf("\nlibzt example\n"); @@ -155,7 +179,7 @@ int main(int argc, char **argv) exit(0); } int ztServicePort = atoi(argv[2]); // Port ZT uses to send encrypted UDP packets to peers (try something like 9994) - + int err = ZTS_ERR_OK; zts_allow_network_caching(false); @@ -164,7 +188,7 @@ int main(int argc, char **argv) exit(1); } printf("Waiting for node to come online...\n"); - while (!nodeReady) { zts_delay_ms(50); } + while (!myNode.online) { zts_delay_ms(50); } printf("This node's identity is stored in %s\n", argv[1]); uint64_t nwid = 0x8056c2e21c000001; @@ -174,7 +198,7 @@ int main(int argc, char **argv) exit(1); } printf("Joining network %llx\n", nwid); - while (!networkReady) { zts_delay_ms(50); } + while (!myNode.joinedAtLeastOneNetwork) { zts_delay_ms(50); } // Idle and just show callback events, stack statistics, etc diff --git a/examples/cpp/server.cpp b/examples/cpp/server.cpp index 51e61bb..3588937 100644 --- a/examples/cpp/server.cpp +++ b/examples/cpp/server.cpp @@ -9,10 +9,19 @@ #include "ZeroTierSockets.h" -bool nodeReady = false; -bool networkReady = false; +struct Node +{ + Node() : online(false), joinedAtLeastOneNetwork(false), id(0) {} + bool online; + bool joinedAtLeastOneNetwork; + uint64_t id; + // etc +} myNode; -// Example callbacks +/* Callback handler, you should return control from this function as quickly as you can +to ensure timely receipt of future events. You should not call libzt API functions from +this function unless it's something trivial like zts_inet_ntop() or similar that has +no state-change implications. */ void myZeroTierEventCallback(void *msgPtr) { struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr; @@ -20,11 +29,12 @@ void myZeroTierEventCallback(void *msgPtr) // Node events if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->address); - nodeReady = true; + myNode.id = msg->node->address; + myNode.online = true; } if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) { printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, firewall, etc. What ports are you blocking?\n"); - nodeReady = false; + myNode.online = false; } if (msg->eventCode == ZTS_EVENT_NODE_NORMAL_TERMINATION) { printf("ZTS_EVENT_NODE_NORMAL_TERMINATION\n"); @@ -37,7 +47,7 @@ void myZeroTierEventCallback(void *msgPtr) } if (msg->eventCode == ZTS_EVENT_NETWORK_REQ_CONFIG) { printf("ZTS_EVENT_NETWORK_REQ_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", msg->network->nwid); - } + } if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { printf("ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n", msg->network->nwid); @@ -45,12 +55,12 @@ void myZeroTierEventCallback(void *msgPtr) if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP4) { printf("ZTS_EVENT_NETWORK_READY_IP4 --- Network config received. IPv4 traffic can now be sent over network %llx\n", msg->network->nwid); - networkReady = true; + myNode.joinedAtLeastOneNetwork = true; } if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) { printf("ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent over network %llx\n", msg->network->nwid); - networkReady = true; + myNode.joinedAtLeastOneNetwork = true; } if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) { printf("ZTS_EVENT_NETWORK_DOWN --- %llx\n", msg->network->nwid); @@ -61,38 +71,52 @@ void myZeroTierEventCallback(void *msgPtr) char ipstr[ZTS_INET_ADDRSTRLEN]; struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_NEW_IP4 --- This node's virtual address on network %llx is %s\n", + printf("ZTS_EVENT_ADDR_NEW_IP4 --- This node's virtual address on network %llx is %s\n", msg->addr->nwid, ipstr); } if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) { char ipstr[ZTS_INET6_ADDRSTRLEN]; struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_NEW_IP6 --- This node's virtual address on network %llx is %s\n", + printf("ZTS_EVENT_ADDR_NEW_IP6 --- This node's virtual address on network %llx is %s\n", msg->addr->nwid, ipstr); } if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP4) { char ipstr[ZTS_INET_ADDRSTRLEN]; struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_REMOVED_IP4 --- The virtual address %s for this node on network %llx has been removed.\n", + printf("ZTS_EVENT_ADDR_REMOVED_IP4 --- The virtual address %s for this node on network %llx has been removed.\n", ipstr, msg->addr->nwid); } if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP6) { char ipstr[ZTS_INET6_ADDRSTRLEN]; struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); - printf("ZTS_EVENT_ADDR_REMOVED_IP6 --- The virtual address %s for this node on network %llx has been removed.\n", + printf("ZTS_EVENT_ADDR_REMOVED_IP6 --- The virtual address %s for this node on network %llx has been removed.\n", ipstr, msg->addr->nwid); } // Peer events - if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { - printf("ZTS_EVENT_PEER_DIRECT --- node=%llx\n", msg->peer->address); - // A direct path is known for nodeId - } - if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { - printf("ZTS_EVENT_PEER_RELAY --- node=%llx\n", msg->peer->address); - // No direct path is known for nodeId + if (msg->peer) { + if (msg->peer->role == ZTS_PEER_ROLE_PLANET) { + /* Safe to ignore, these are our roots. They orchestrate the P2P connection. + You might also see other unknown peers, these are our network controllers. */ + return; + } + if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { + printf("ZTS_EVENT_PEER_DIRECT --- A direct path is known for node=%llx\n", + msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { + printf("ZTS_EVENT_PEER_RELAY --- No direct path to node=%llx\n", msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_PATH_DISCOVERED) { + printf("ZTS_EVENT_PEER_PATH_DISCOVERED --- A new direct path was discovered for node=%llx\n", + msg->peer->address); + } + if (msg->eventCode == ZTS_EVENT_PEER_PATH_DEAD) { + printf("ZTS_EVENT_PEER_PATH_DEAD --- A direct path has died for node=%llx\n", + msg->peer->address); + } } } @@ -104,7 +128,7 @@ void myZeroTierEventCallback(void *msgPtr) * the location given in the first argument to zts_start(path, ...). If you accidentally * duplicate the identity files and use them simultaneously in a different node instance * you will experience undefined behavior and it is likely nothing will work. - * + * * - You must authorize the node ID provided by the ZTS_EVENT_NODE_ONLINE callback to join * your network, otherwise nothing will happen. This can be done manually or via * our web API: https://my.zerotier.com/help/api @@ -143,12 +167,12 @@ void myZeroTierEventCallback(void *msgPtr) * Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors * returned by these functions can be any of the following: * - * ZTS_ERR_OK 0 // No error - * ZTS_ERR_SOCKET -1 // Socket error, see zts_errno - * ZTS_ERR_SERVICE -2 // You probably did something at the wrong time - * ZTS_ERR_ARG -3 // Invalid argument - * ZTS_ERR_NO_RESULT -4 // No result (not necessarily an error) - * ZTS_ERR_GENERAL -5 // Consider filing a bug report + * ZTS_ERR_OK // No error + * ZTS_ERR_SOCKET // Socket error, see zts_errno + * ZTS_ERR_SERVICE // You probably did something at the wrong time + * ZTS_ERR_ARG // Invalid argument + * ZTS_ERR_NO_RESULT // No result (not necessarily an error) + * ZTS_ERR_GENERAL // Consider filing a bug report * * Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc). * Errors returned by these functions can be the same as the above. With @@ -166,7 +190,7 @@ void myZeroTierEventCallback(void *msgPtr) * are a few guidelines: * * If you are calling a zts_* function, use the appropriate ZTS_* constants: - * + * * zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT) * zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT) * @@ -178,7 +202,7 @@ void myZeroTierEventCallback(void *msgPtr) * */ -int main(int argc, char **argv) +int main(int argc, char **argv) { if (argc != 5) { printf("\nlibzt example server\n"); @@ -188,7 +212,7 @@ int main(int argc, char **argv) uint64_t nwid = strtoull(argv[2],NULL,16); // Network ID to join int serverBindPort = atoi(argv[3]); // Port the application should bind to int ztServicePort = atoi(argv[4]); // Port ZT uses to send encrypted UDP packets to peers (try something like 9994) - + struct zts_sockaddr_in in4, acc_in4; in4.sin_port = zts_htons(serverBindPort); #if defined(_WIN32) @@ -208,7 +232,7 @@ int main(int argc, char **argv) exit(1); } printf("Waiting for node to come online...\n"); - while (!nodeReady) { zts_delay_ms(50); } + while (!myNode.online) { zts_delay_ms(50); } printf("This node's identity is stored in %s\n", argv[1]); if((err = zts_join(nwid)) != ZTS_ERR_OK) { @@ -217,7 +241,7 @@ int main(int argc, char **argv) } printf("Joining network %llx\n", nwid); printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); - while (!networkReady) { zts_delay_ms(50); } + while (!myNode.joinedAtLeastOneNetwork) { zts_delay_ms(50); } // Socket-like API example @@ -237,7 +261,7 @@ int main(int argc, char **argv) printf("Error placing socket in LISTENING state (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno); exit(1); } - + int bytes=0; char recvBuf[128]; memset(recvBuf, 0, sizeof(recvBuf)); diff --git a/examples/objective-c/adhoc.m b/examples/objective-c/adhoc.m index 46b2c67..46ab811 100644 --- a/examples/objective-c/adhoc.m +++ b/examples/objective-c/adhoc.m @@ -60,12 +60,12 @@ * Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors * returned by these functions can be any of the following: * - * ZTS_ERR_OK 0 // No error - * ZTS_ERR_SOCKET -1 // Socket error, see zts_errno - * ZTS_ERR_SERVICE -2 // You probably did something at the wrong time - * ZTS_ERR_ARG -3 // Invalid argument - * ZTS_ERR_NO_RESULT -4 // No result (not necessarily an error) - * ZTS_ERR_GENERAL -5 // Consider filing a bug report + * ZTS_ERR_OK // No error + * ZTS_ERR_SOCKET // Socket error, see zts_errno + * ZTS_ERR_SERVICE // You probably did something at the wrong time + * ZTS_ERR_ARG // Invalid argument + * ZTS_ERR_NO_RESULT // No result (not necessarily an error) + * ZTS_ERR_GENERAL // Consider filing a bug report * * Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc). * Errors returned by these functions can be the same as the above. With @@ -83,7 +83,7 @@ * are a few guidelines: * * If you are calling a zts_* function, use the appropriate ZTS_* constants: - * + * * zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT) * zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT) * @@ -119,7 +119,7 @@ void myZeroTierEventCallback(struct zts_callback_msg *msg) } if (msg->eventCode == ZTS_EVENT_NETWORK_REQ_CONFIG) { NSLog(@"ZTS_EVENT_NETWORK_REQ_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", msg->network->nwid); - } + } if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { NSLog(@"ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n", msg->network->nwid); @@ -134,17 +134,17 @@ void myZeroTierEventCallback(struct zts_callback_msg *msg) } // Network stack events if (msg->eventCode == ZTS_EVENT_NETIF_UP) { - NSLog(@"ZTS_EVENT_NETIF_UP --- network=%llx, mac=%llx, mtu=%d\n", + NSLog(@"ZTS_EVENT_NETIF_UP --- network=%llx, mac=%llx, mtu=%d\n", msg->netif->nwid, msg->netif->mac, msg->netif->mtu); networkReady = true; } if (msg->eventCode == ZTS_EVENT_NETIF_DOWN) { - NSLog(@"ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n", + NSLog(@"ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n", msg->netif->nwid, msg->netif->mac); - + networkReady = true; } // Address events @@ -152,7 +152,7 @@ void myZeroTierEventCallback(struct zts_callback_msg *msg) char ipstr[INET6_ADDRSTRLEN]; struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); - NSLog(@"ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n", + NSLog(@"ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n", msg->addr->nwid, ipstr); } // Peer events @@ -192,7 +192,7 @@ be taken to avoid exposing vulnerable services or sharing unwanted files or othe */ -int main(int argc, char **argv) +int main(int argc, char **argv) { if (argc != 5) { NSLog(@"\nlibzt example\n"); diff --git a/examples/swift/Makefile b/examples/swift/Makefile new file mode 100644 index 0000000..91247b1 --- /dev/null +++ b/examples/swift/Makefile @@ -0,0 +1,2 @@ +all: + swiftc -g -lc++ -import-objc-header ../../include/ZeroTierSockets.h ../../lib/debug/macos-x86_64/zt.framework/zt main.swift -o main diff --git a/examples/swift/main.swift b/examples/swift/main.swift index bb82621..5056f3c 100644 --- a/examples/swift/main.swift +++ b/examples/swift/main.swift @@ -1,10 +1,5 @@ /** - * libzt Swift example - * - * swiftc -lc++ -import-objc-header ../../include/ZeroTierSockets.h -L. -lzt main.swift -o main; - * ./main - * - * TODO: This example is incomplete + * I'll order you a pizza if you can rewrite this in modern idomatic Swift */ import Swift @@ -56,12 +51,12 @@ import Foundation * Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors * returned by these functions can be any of the following: * - * ZTS_ERR_OK 0 // No error - * ZTS_ERR_SOCKET -1 // Socket error, see zts_errno - * ZTS_ERR_SERVICE -2 // You probably did something at the wrong time - * ZTS_ERR_ARG -3 // Invalid argument - * ZTS_ERR_NO_RESULT -4 // No result (not necessarily an error) - * ZTS_ERR_GENERAL -5 // Consider filing a bug report + * ZTS_ERR_OK // No error + * ZTS_ERR_SOCKET // Socket error, see zts_errno + * ZTS_ERR_SERVICE // You probably did something at the wrong time + * ZTS_ERR_ARG // Invalid argument + * ZTS_ERR_NO_RESULT // No result (not necessarily an error) + * ZTS_ERR_GENERAL // Consider filing a bug report * * Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc). * Errors returned by these functions can be the same as the above. With @@ -91,6 +86,119 @@ import Foundation * */ +let printNodeDetails : @convention(c) (UnsafeMutableRawPointer?) -> Void = +{ + (msgPtr) -> Void in + let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1) + let d = msg?.pointee.node; + print(String(format: "\t- id : %llx", d!.pointee.address)); + print(String(format: "\t- version : %d.%d.%d", d!.pointee.versionMajor, d!.pointee.versionMinor, d!.pointee.versionRev)); + print(String(format: "\t- primaryPort : %d", d!.pointee.primaryPort)); + print(String(format: "\t- secondaryPort : %d", d!.pointee.secondaryPort)); +} + +/* +func convertTupleToArray(from tuple: Tuple) -> [Value] { + let tupleMirror = Mirror(reflecting: tuple) + func convert(child: Mirror.Child) -> Value? { + let valueMirror = Mirror(reflecting: child.value) + return child.value as? Value + } + return tupleMirror.children.flatMap(convert) +} +*/ + +let printNetworkDetails : @convention(c) (UnsafeMutableRawPointer?) -> Void = +{ + (msgPtr) -> Void in + let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1) + let d = msg?.pointee.network; + let name = ""; // String(d!.pointee.name); + + print(String(format: "\t- nwid : %llx", d!.pointee.nwid)); + print(String(format: "\t- mac : %lx", d!.pointee.mac)); + print(String(format: "\t- name : %s", name)); + print(String(format: "\t- type : %d", Int(d!.pointee.type.rawValue))); + /* MTU for the virtual network can be set via our web API */ + print(String(format: "\t- mtu : %d", d!.pointee.mtu)); + print(String(format: "\t- dhcp : %d", d!.pointee.dhcp)); + print(String(format: "\t- bridge : %d", d!.pointee.bridge)); + print(String(format: "\t- broadcastEnabled : %d", d!.pointee.broadcastEnabled)); + print(String(format: "\t- portError : %d", d!.pointee.portError)); + print(String(format: "\t- netconfRevision : %d", d!.pointee.netconfRevision)); + print(String(format: "\t- routeCount : %d", d!.pointee.routeCount)); + print(String(format: "\t- multicastSubscriptionCount : %d", d!.pointee.multicastSubscriptionCount)); +/* + var addresses: [zts_sockaddr_storage] = convertTupleToArray(from: d!.pointee.assignedAddresses) + + print("\t- addresses:\n"); + for i in 0...d!.pointee.assignedAddressCount { + if (addresses[Int(i)].ss_family == ZTS_AF_INET) { + // Allocate a byte array that can hold the largest possible IPv4 human-readable string + var ipCharByteArray = Array(repeating: 0, count: Int(ZTS_INET_ADDRSTRLEN)) + // Cast unsafe pointer from zts_sockaddr_storage to zts_sockaddr_in + var addr:zts_sockaddr_in = withUnsafePointer(to: &(addresses[Int(i)])) { + $0.withMemoryRebound(to: zts_sockaddr_in.self, capacity: 1) { + $0.pointee + } + } + // Pass unsafe pointer (addr) to a ntop to convert into human-readable byte array + zts_inet_ntop(ZTS_AF_INET, &(addr.sin_addr), &ipCharByteArray, UInt32(ZTS_INET_ADDRSTRLEN)) + //print(ipCharByteArray) // [49, 55, 50, 46, 50, 55, 46, 49, 49, 54, 46, 49, 54, 55, 0, 0] + // Somehow convery Int8 byte array to Swift String ??? + //let ipString = String(bytes: ipStr, encoding: .utf8) + //print(ipString) + + // Pass unsafe pointer (addr) to a ntop to convert into human-readable byte array + // convert to UInt8 byte array + let uintArray = ipCharByteArray.map { UInt8(bitPattern: $0) } + if let string = String(bytes: uintArray, encoding: .utf8) { + print("\t\t-", string) + } + } + if (addresses[Int(i)].ss_family == ZTS_AF_INET6) { + // ... + } + } +*/ +/* + print("\t- routes:\n"); + + for i in 0...d!.pointee.routeCount { + // ... + } +*/ +} + +let printPeerDetails : @convention(c) (UnsafeMutableRawPointer?) -> Void = +{ + (msgPtr) -> Void in + let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1) + let d = msg?.pointee.peer; + print(String(format: "\t- peer : %llx", d!.pointee.address)); + print(String(format: "\t- role : %d", Int(d!.pointee.role.rawValue))); + print(String(format: "\t- latency : %llx", d!.pointee.latency)); + print(String(format: "\t- pathCount : %llx", d!.pointee.pathCount)); + print(String(format: "\t- version : %d.%d.%d", d!.pointee.versionMajor, d!.pointee.versionMinor, d!.pointee.versionRev)); + print(String(format: "\t- paths:\n")); + +/* + for i in 0...d!.pointee.pathCount { + // ... + } +*/ +} + +let printNetifDetails : @convention(c) (UnsafeMutableRawPointer?) -> Void = +{ + (msgPtr) -> Void in + let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1) + let d = msg?.pointee.netif; + print(String(format: "\t- nwid : %llx", d!.pointee.nwid)); + print(String(format: "\t- mac : %llx", d!.pointee.mac)); + print(String(format: "\t- mtu : %d", d!.pointee.mtu)); +} + var nodeReady:Bool = false var networkReady:Bool = false @@ -99,16 +207,18 @@ let myZeroTierEventCallback : @convention(c) (UnsafeMutableRawPointer?) -> Void (msgPtr) -> Void in let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1) - var eventCode = msg!.pointee.eventCode - - let node = msg?.pointee.node; + let eventCode = msg!.pointee.eventCode let network = msg?.pointee.network; + let peer = msg?.pointee.peer; + + switch Int32(eventCode) + { + case ZTS_EVENT_NODE_UP: + print("ZTS_EVENT_NODE_UP (you can ignore this)\n") - switch Int32(eventCode) - { case ZTS_EVENT_NODE_ONLINE: - let nodeId:UInt64 = node!.pointee.address - print(String(format: "ZTS_EVENT_NODE_ONLINE (%llx)", nodeId)) + print("ZTS_EVENT_NODE_ONLINE\n") + printNodeDetails(msg) nodeReady = true; case ZTS_EVENT_NODE_OFFLINE: @@ -144,71 +254,68 @@ let myZeroTierEventCallback : @convention(c) (UnsafeMutableRawPointer?) -> Void let networkId:UInt64 = network!.pointee.nwid print(String(format: "ZTS_EVENT_NETWORK_DOWN (%llx)", networkId)) -/* - // Network stack events - case ZTS_EVENT_NETIF_UP: - print("ZTS_EVENT_NETIF_UP --- network=%llx, mac=%llx, mtu=%d\n", - msg.netif->nwid, - msg.netif->mac, - msg.netif->mtu) - //networkReady = true; + case ZTS_EVENT_NETWORK_UPDATE: + print("ZTS_EVENT_NETWORK_UPDATE\n") + printNetworkDetails(msg) - case ZTS_EVENT_NETIF_DOWN: - print("ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n", - msg.netif->nwid, - msg.netif->mac) - //networkReady = true; - // Address events case ZTS_EVENT_ADDR_ADDED_IP4: - print("ZTS_EVENT_ADDR_ADDED_IP4") - /* - char ipstr[INET_ADDRSTRLEN]; - struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg.addr->addr); - inet_ntop(AF_INET, &(in4->sin_addr), ipstr, INET_ADDRSTRLEN); - print("ZTS_EVENT_ADDR_NEW_IP4 --- This node's virtual address on network %llx is %s\n", - msg.addr->nwid, ipstr) - */ + print("ZTS_EVENT_ADDR_ADDED_IP4\n") case ZTS_EVENT_ADDR_ADDED_IP6: - print("ZTS_EVENT_ADDR_ADDED_IP6") - /* - char ipstr[INET6_ADDRSTRLEN]; - struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg.addr->addr); - inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); - print("ZTS_EVENT_ADDR_NEW_IP6 --- This node's virtual address on network %llx is %s\n", - msg.addr->nwid, ipstr) - */ + print("ZTS_EVENT_ADDR_ADDED_IP6\n") case ZTS_EVENT_ADDR_REMOVED_IP4: - print("ZTS_EVENT_ADDR_REMOVED_IP4") - /* - char ipstr[INET_ADDRSTRLEN]; - struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg.addr->addr); - inet_ntop(AF_INET, &(in4->sin_addr), ipstr, INET_ADDRSTRLEN); - print("ZTS_EVENT_ADDR_REMOVED_IP4 --- The virtual address %s for this node on network %llx has been removed.\n", - ipstr, msg.addr->nwid) - */ + print("ZTS_EVENT_ADDR_REMOVED_IP4\n") case ZTS_EVENT_ADDR_REMOVED_IP6: - print("ZTS_EVENT_ADDR_REMOVED_IP6") - /* - char ipstr[INET6_ADDRSTRLEN]; - struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg.addr->addr); - inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); - print("ZTS_EVENT_ADDR_REMOVED_IP6 --- The virtual address %s for this node on network %llx has been removed.\n", - ipstr, msg.addr->nwid) - */ - // Peer events + print("ZTS_EVENT_ADDR_REMOVED_IP6\n") + + case ZTS_EVENT_PEER_DIRECT: - print("ZTS_EVENT_PEER_DIRECT --- node=%llx\n", msg.peer->address) + let peerId:UInt64 = peer!.pointee.address + print(String(format: "ZTS_EVENT_PEER_DIRECT (%llx)", peerId)) + printPeerDetails(msg) + case ZTS_EVENT_PEER_RELAY: - print("ZTS_EVENT_PEER_RELAY --- node=%llx\n", msg.peer->address) + let peerId:UInt64 = peer!.pointee.address + print(String(format: "ZTS_EVENT_PEER_RELAY (%llx)", peerId)) + printPeerDetails(msg) + + case ZTS_EVENT_PEER_PATH_DISCOVERED: + let peerId:UInt64 = peer!.pointee.address + print(String(format: "ZTS_EVENT_PEER_PATH_DISCOVERED (%llx)", peerId)) + printPeerDetails(msg) + + case ZTS_EVENT_PEER_PATH_DEAD: + let peerId:UInt64 = peer!.pointee.address + print(String(format: "ZTS_EVENT_PEER_PATH_DEAD (%llx)", peerId)) + printPeerDetails(msg) -*/ + case ZTS_EVENT_NETIF_UP: + print("ZTS_EVENT_NETIF_UP\n") + + case ZTS_EVENT_NETIF_DOWN: + print("ZTS_EVENT_NETIF_DOWN\n") + + case ZTS_EVENT_NETIF_REMOVED: + print("ZTS_EVENT_NETIF_REMOVED\n") + + case ZTS_EVENT_NETIF_LINK_UP: + print("ZTS_EVENT_NETIF_LINK_UP\n") + + case ZTS_EVENT_NETIF_LINK_DOWN: + print("ZTS_EVENT_NETIF_LINK_DOWN\n") + + case ZTS_EVENT_STACK_UP: + print("ZTS_EVENT_STACK_UP\n") + + case ZTS_EVENT_STACK_DOWN: + print("ZTS_EVENT_STACK_DOWN\n") + default: - print("UNKNOWN_EVENT") + print("UNKNOWN_EVENT: ", eventCode) } } @@ -221,6 +328,26 @@ func main() } print("Joining network") + let nwId : UInt64 = 0x0123456789abcdef; // Specify your network ID here + zts_join(nwId); + + // create address structure + let addr_str = "0.0.0.0" + let port = 8080 + var in4 = zts_sockaddr_in(sin_len: UInt8(MemoryLayout.size), + sin_family: UInt8(ZTS_AF_INET), + sin_port: UInt16(port).bigEndian, + sin_addr: zts_in_addr(s_addr: 0), + sin_zero: (0,0,0,0,0,0,0,0)) + zts_inet_pton(ZTS_AF_INET, addr_str, &(in4.sin_addr)); + + print("fd=", zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0)); + + // ... + + while(true) { + sleep(1); + } } main()