From a7c2496dfc3a65f481701730873b7a623a7e3c55 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Wed, 1 May 2019 14:23:14 -0700 Subject: [PATCH] Updated README.md and test/ --- README.md | 8 +- test/example.cpp | 280 +++++++++++++++++++++++++++++++++++++++++++++++ test/simple.cpp | 73 ++++++++++++ 3 files changed, 358 insertions(+), 3 deletions(-) create mode 100644 test/example.cpp create mode 100644 test/simple.cpp diff --git a/README.md b/README.md index eb198a4..99adf66 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,15 @@ Library edition of [ZeroTier](https://github.com/zerotier/ZeroTierOne) *** - + -The ZeroTier SDK is composed of two libraries: `libztcore` which is the platform-agnostic network hypervisor, and `libzt` which is the network hypervisor paired with a userspace network stack. `libzt` is a superset of `libztcore` and is distinguished by the fact that it exposes a standard [socket API](https://en.wikipedia.org/wiki/Berkeley_sockets) and simple network control API. With these libraries the stack and virtual link are exclusive to your app and traffic is fully encrypted via the [Salsa20](https://en.wikipedia.org/wiki/Salsa20) cipher. For a more in-depth discussion on the technical side of ZeroTier, check out our [Manual](https://www.zerotier.com/manual.shtml?pk_campaign=github_libzt) +The ZeroTier SDK is composed of two libraries: `libztcore` which is the platform-agnostic network hypervisor, and `libzt` which is the network hypervisor paired with a userspace network stack. `libzt` is a superset of `libztcore` and is distinguished by the fact that it exposes a standard socket API and simple network control API. With these libraries the stack and virtual link are exclusive to your app and traffic is fully encrypted via the [Salsa20](https://en.wikipedia.org/wiki/Salsa20) cipher. For a more in-depth discussion on the technical side of ZeroTier, check out our [Manual](https://www.zerotier.com/manual.shtml) ***
-For a complete example, see [test/simple.cpp](test/simple.cpp), and anything in the [examples](examples) directory. With no error checking, a paraphrased example is as follows: +For a complete example, see [test/simple.cpp](test/simple.cpp) or [test/example.cpp](test/example.cpp). With no error checking, a paraphrased example is as follows: ``` #include "ZeroTier.h" @@ -38,6 +38,8 @@ int main() ... ``` +The complete API specification can be found here: [API.md](API.md) + *** ## Build diff --git a/test/example.cpp b/test/example.cpp new file mode 100644 index 0000000..11ff33c --- /dev/null +++ b/test/example.cpp @@ -0,0 +1,280 @@ +#include +#include +#include +#include + +#include "ZeroTier.h" + +bool node_ready = false; +bool network_ready = false; + +// Example callbacks +void myZeroTierEventCallback(struct zts_callback_msg *msg) +{ + // + // Node events + // + if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { + printf("ZTS_EVENT_NODE_ONLINE, node=%llx\n", msg->node->address); + node_ready = true; + // ZeroTier service is running and online + } + if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) { + printf("ZTS_EVENT_NODE_OFFLINE\n"); + node_ready = false; + // ZeroTier service is running and online + } + if (msg->eventCode == ZTS_EVENT_NODE_NORMAL_TERMINATION) { + printf("ZTS_EVENT_NODE_NORMAL_TERMINATION\n"); + // ZeroTier service has stopped + } + + // + // Virtual network events + // + if (msg->eventCode == ZTS_EVENT_NETWORK_NOT_FOUND) { + printf("ZTS_EVENT_NETWORK_NOT_FOUND --- network=%llx\n", msg->network->nwid); + // Is your nwid incorrect? + } + if (msg->eventCode == ZTS_EVENT_NETWORK_REQUESTING_CONFIG) { + printf("ZTS_EVENT_NETWORK_REQUESTING_CONFIG --- network=%llx\n", msg->network->nwid); + // Node is requesting network config details from controller, please wait + } + if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { + printf("ZTS_EVENT_NETWORK_ACCESS_DENIED --- network=%llx\n", msg->network->nwid); + // This node is not authorized to join nwid + } + if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP4) { + printf("ZTS_EVENT_NETWORK_READY_IP4 --- network=%llx\n", msg->network->nwid); + network_ready = true; + // IPv4 traffic can now be processed for nwid + } + if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) { + printf("ZTS_EVENT_NETWORK_READY_IP6 --- network=%llx\n", msg->network->nwid); + network_ready = true; + } + if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) { + printf("ZTS_EVENT_NETWORK_DOWN --- network=%llx\n", msg->network->nwid); + // Can happen if another thread called zts_leave() + } + + // + // 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); + network_ready = true; + } + if (msg->eventCode == ZTS_EVENT_NETIF_DOWN) { + printf("ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n", + msg->netif->nwid, + msg->netif->mac); + + network_ready = true; + } + + // + // Address events + // + if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP4) { + char ipstr[INET_ADDRSTRLEN]; + struct sockaddr_in *in4 = (struct sockaddr_in*)&(msg->addr->addr); + inet_ntop(AF_INET, &(in4->sin_addr), ipstr, INET_ADDRSTRLEN); + printf("ZTS_EVENT_ADDR_NEW_IP4 --- addr=%s (on network=%llx)\n", + ipstr, msg->addr->nwid); + } + if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) { + char ipstr[INET6_ADDRSTRLEN]; + struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(msg->addr->addr); + inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); + printf("ZTS_EVENT_ADDR_NEW_IP6 --- addr=%s (on network=%llx)\n", + ipstr, msg->addr->nwid); + } + if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP4) { + char ipstr[INET_ADDRSTRLEN]; + struct sockaddr_in *in4 = (struct sockaddr_in*)&(msg->addr->addr); + inet_ntop(AF_INET, &(in4->sin_addr), ipstr, INET_ADDRSTRLEN); + printf("ZTS_EVENT_ADDR_REMOVED_IP4 --- addr=%s (on network=%llx)\n", + ipstr, msg->addr->nwid); + } + if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP6) { + char ipstr[INET6_ADDRSTRLEN]; + struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(msg->addr->addr); + inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); + printf("ZTS_EVENT_ADDR_REMOVED_IP6 --- addr=%s (on network=%llx)\n", + ipstr, msg->addr->nwid); + } + + // + // Peer events + // + if (msg->eventCode == ZTS_EVENT_PEER_P2P) { + printf("ZTS_EVENT_PEER_P2P --- 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 printPeerDetails(struct zts_peer_details *pd) +{ + printf("\npeer=%llx, latency=%d, version=%d.%d.%d, pathCount=%d\n", + pd->address, + pd->latency, + pd->versionMajor, + pd->versionMinor, + pd->versionRev, + pd->pathCount); + // Print all known paths for each peer + for (int j=0; jpathCount; j++) { + char ipstr[INET6_ADDRSTRLEN]; + int port; + struct sockaddr *sa = (struct sockaddr *)&(pd->paths[j].address); + if (sa->sa_family == AF_INET) { + struct sockaddr_in *in4 = (struct sockaddr_in*)sa; + inet_ntop(AF_INET, &(in4->sin_addr), ipstr, INET_ADDRSTRLEN); + port = ntohs(in4->sin_port); + } + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa; + inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); + } + printf("\tpath[%d]=%s, port=%d\n", j, ipstr, port); + } +} + +void getSinglePeerDetails(uint64_t peerId) +{ + struct zts_peer_details pd; + int err = zts_get_peer(&pd, peerId); + + if (err == ZTS_ERR_OK) { + printf("(%d) call succeeded\n", err); + } if (err == ZTS_ERR_INVALID_ARG) { + printf("(%d) invalid argument\n", err); + return; + } if (err == ZTS_ERR_SERVICE) { + printf("(%d) error: service is unavailable\n", err); + return; + } if (err == ZTS_ERR_INVALID_OP) { + printf("(%d) error: invalid API operation\n", err); + return; + } if (err == ZTS_ERR_NO_RESULT) { + printf("(%d) error: object or result not found\n", err); + return; + } + if (err == 0) { // ZTS_ERR_OK + printPeerDetails(&pd); + } +} + +// 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 */ + 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 (int i=0; i +#include +#include +#include + +#include "ZeroTier.h" + +bool node_ready = false; +bool network_ready = false; + +void myZeroTierEventCallback(struct zts_callback_msg *msg) +{ + switch (msg->eventCode) + { + case ZTS_EVENT_NODE_ONLINE: + printf("ZTS_EVENT_NODE_ONLINE, node=%llx\n", msg->node->address); + node_ready = true; + break; + case ZTS_EVENT_NODE_OFFLINE: + printf("ZTS_EVENT_NODE_OFFLINE\n"); + node_ready = false; + break; + case ZTS_EVENT_NETWORK_READY_IP4: + printf("ZTS_EVENT_NETWORK_READY_IP4 --- network=%llx\n", msg->network->nwid); + network_ready = true; + break; + case ZTS_EVENT_PEER_P2P: + printf("ZTS_EVENT_PEER_P2P --- node=%llx\n", msg->peer->address); + break; + case ZTS_EVENT_PEER_RELAY: + printf("ZTS_EVENT_PEER_RELAY --- node=%llx\n", msg->peer->address); + break; + // ... + default: + break; + } +} + +int main() +{ + char *str = "welcome to the machine"; + char *remoteIp = "11.7.7.223"; + int remotePort = 8082; + int fd, err = 0; + struct zts_sockaddr_in addr; + addr.sin_family = ZTS_AF_INET; + addr.sin_addr.s_addr = inet_addr(remoteIp); + addr.sin_port = htons(remotePort); + + // Set up ZeroTier service and wai for callbacks + int port = 9994; + int nwid = 0x0123456789abcdef; + zts_start("test/path", &myZeroTierEventCallback, port); + printf("Waiting for node to come online...\n"); + while (!node_ready) { sleep(1); } + zts_join(nwid); + printf("Joined virtual network. Requesting configuration...\n"); + while (!network_ready) { sleep(1); } + + // Socket API example + if ((fd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("error creating socket\n"); + } + if ((err = zts_connect(fd, (const struct sockaddr *)&addr, sizeof(addr))) < 0) { + printf("error connecting to remote host\n"); + } + if ((err = zts_write(fd, str, strlen(str))) < 0) { + printf("error writing to socket\n"); + } + zts_close(fd); + zts_stop(); + return 0; +} \ No newline at end of file