Skip to content

Commit

Permalink
Expand C API and simplify NodeService
Browse files Browse the repository at this point in the history
  • Loading branch information
joseph-henry committed Apr 22, 2021
1 parent 565b56d commit 4335069
Show file tree
Hide file tree
Showing 30 changed files with 7,495 additions and 5,265 deletions.
192 changes: 96 additions & 96 deletions CMakeLists.txt

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div align="center">

<h1>ZeroTier SDK</h1>
<img alt="zts_socket()" src="https://i.imgur.com/BwSHwE3.png"> </img>
<img alt="zts_socket()" src="https://i.imgur.com/BwSHwE3.png" class="doxyhidden"> </img>

Peer-to-peer and cross-platform encrypted connections built right into your app or service. No drivers, no root, and no host configuration.

Expand Down
97 changes: 97 additions & 0 deletions examples/c/adhoc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* libzt C API example
*
* Pingable node joined to controller-less adhoc network with a 6PLANE addressing scheme
*/

#include "ZeroTierSockets.h"

#include <stdio.h>
#include <stdlib.h>

/*
Ad-hoc Network:
ffSSSSEEEE000000
| | | |
| | | Reserved for future use, must be 0
| | End of port range (hex)
| Start of port range (hex)
Reserved ZeroTier address prefix indicating a controller-less network.
Ad-hoc networks are public (no access control) networks that have no network controller. Instead
their configuration and other credentials are generated locally. Ad-hoc networks permit only IPv6
UDP and TCP unicast traffic (no multicast or broadcast) using 6plane format NDP-emulated IPv6
addresses. In addition an ad-hoc network ID encodes an IP port range. UDP packets and TCP SYN
(connection open) packets are only allowed to destination ports within the encoded range.
For example ff00160016000000 is an ad-hoc network allowing only SSH, while ff0000ffff000000 is an
ad-hoc network allowing any UDP or TCP port.
Keep in mind that these networks are public and anyone in the entire world can join them. Care must
be taken to avoid exposing vulnerable services or sharing unwanted files or other resources.
*/
int main(int argc, char** argv)
{
if (argc != 3) {
printf("\nUsage:\n");
printf("adhoc <adhocStartPort> <adhocEndPort>\n");
exit(0);
}
int err = ZTS_ERR_OK;

uint16_t adhocStartPort = atoi(argv[1]); // Start of port range your application will use
uint16_t adhocEndPort = atoi(argv[2]); // End of port range your application will use
uint64_t net_id = zts_net_compute_adhoc_id(adhocStartPort, adhocEndPort);

// Start node and get identity

printf("Starting node...\n");
zts_node_start();
printf("Waiting for node to come online\n");
while (! zts_node_is_online()) {
zts_util_delay(50);
}
uint64_t node_id = zts_node_get_id();
printf("My public identity (node ID) is %llx\n", node_id);
char keypair[ZTS_ID_STR_BUF_LEN] = { 0 };
uint16_t len = ZTS_ID_STR_BUF_LEN;
if (zts_node_get_id_pair(keypair, &len) != ZTS_ERR_OK) {
printf("Error getting identity keypair. Exiting.\n");
}
printf("Identity [public/secret pair] = %s\n", keypair);

// Join the adhoc network

printf("Joining network %llx\n", net_id);
if (zts_net_join(net_id) != ZTS_ERR_OK) {
printf("Unable to join network. Exiting.\n");
exit(1);
}
printf("Waiting for join to complete\n");
while (zts_net_count() < 1) {
zts_util_delay(50);
}

// Get address

char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 };
if ((err = zts_addr_compute_rfc4193_str(net_id, node_id, ipstr, ZTS_IP_MAX_STR_LEN))
!= ZTS_ERR_OK) {
printf("Unable to compute address (error = %d). Exiting.\n", err);
exit(1);
}
printf("Join %llx from another machine and ping6 me at %s\n", net_id, ipstr);

// Do network stuff!
// zts_socket, zts_connect, etc

while (1) {
zts_util_delay(500); // Idle indefinitely
}

printf("Stopping node\n");
return zts_node_stop();
}
113 changes: 113 additions & 0 deletions examples/c/callbackapi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
* libzt C API example
*
* Pingable node that demonstrates basic usage of the callback API. To see
* more exhaustive examples look at test/selftest.c
*/

#include "ZeroTierSockets.h"

#include <stdio.h>
#include <stdlib.h>

void on_zts_event(void* msgPtr)
{
zts_event_msg_t* msg = (zts_event_msg_t*)msgPtr;
// Node events
if (msg->event_code == ZTS_EVENT_NODE_ONLINE) {
printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->node_id);
}
if (msg->event_code == ZTS_EVENT_NODE_OFFLINE) {
printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, "
"firewall, etc. What ports are you blocking?\n");
}
// Virtual network events
if (msg->event_code == ZTS_EVENT_NETWORK_NOT_FOUND) {
printf(
"ZTS_EVENT_NETWORK_NOT_FOUND --- Are you sure %llx is a valid network?\n",
msg->network->net_id);
}
if (msg->event_code == 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->net_id);
}
if (msg->event_code == 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->net_id);
}
// Address events
if (msg->event_code == ZTS_EVENT_ADDR_ADDED_IP6) {
char ipstr[ZTS_INET6_ADDRSTRLEN] = { 0 };
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",
msg->addr->net_id,
ipstr);
}

// To see more exhaustive examples look at test/selftest.c
}

int main(int argc, char** argv)
{
if (argc != 2) {
printf("\nUsage:\n");
printf("pingable-node <net_id>\n");
exit(0);
}
uint64_t net_id = strtoull(argv[1], NULL, 16);

zts_init_set_event_handler(&on_zts_event);

printf("Starting node...\n");
zts_node_start();

printf("Waiting for node to come online\n");
while (! zts_node_is_online()) {
zts_util_delay(50);
}

printf("My public identity (node ID) is %llx\n", zts_node_get_id());
char keypair[ZTS_ID_STR_BUF_LEN] = { 0 };
uint16_t len = ZTS_ID_STR_BUF_LEN;
if (zts_node_get_id_pair(keypair, &len) != ZTS_ERR_OK) {
printf("Error getting identity keypair. Exiting.\n");
}
printf("Identity [public/secret pair] = %s\n", keypair);

printf("Joining network %llx\n", net_id);
if (zts_net_join(net_id) != ZTS_ERR_OK) {
printf("Unable to join network. Exiting.\n");
exit(1);
}

printf("Waiting for join to complete\n");
while (zts_net_count() < 1) {
zts_util_delay(50);
}

printf("Waiting for address assignment from network\n");
int err = 0;
while (! (err = zts_addr_is_assigned(net_id, ZTS_AF_INET))) {
zts_util_delay(500);
}

char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 };
zts_addr_get_str(net_id, ZTS_AF_INET, ipstr, ZTS_IP_MAX_STR_LEN);
printf("Join %llx from another machine and ping me at %s\n", net_id, ipstr);

// Do network stuff!
// zts_socket, zts_connect, etc

while (1) {
zts_util_delay(500); // Idle indefinitely
}

printf("Stopping node\n");
return zts_node_stop();
}
109 changes: 109 additions & 0 deletions examples/c/centralapi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include "ZeroTierSockets.h"

#include <iomanip>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>

// For optional JSON parsing
#include "../ext/ZeroTierOne/ext/json/json.hpp"

void process_response(char* response, int http_resp_code)
{
if (http_resp_code == 0) {
// Request failed at library level, do nothing. There would be no HTTP code at this point.
return;
}
printf("Raw response string (%d) = %s\n", http_resp_code, response);
// Parse into navigable JSON object
if (http_resp_code < 200 || http_resp_code >= 300) {
return;
}
nlohmann::json res = nlohmann::json::parse(response);
if (! res.is_object()) {
fprintf(stderr, "Unable to parse (root element is not a JSON object)");
}
// Pretty print JSON blob
std::cout << std::setw(4) << res << std::endl;
}

int main(int argc, char** argv)
{
if (argc != 3) {
printf("\nlibzt example central API client\n");
printf("centralapi <central_url> <api_token>\n");
exit(0);
}
char* central_url = argv[1]; // API endpoint
char* api_token = argv[2]; // User token (generate at my.zerotier.com)

/**
* This example demonstrates how to use the ZeroTier Central API to:
*
* - Get the status of our hosted service (or your own)
* - Create a network
* - Get the full configuration of a network
* - Authorize/Deauthorize nodes on a network
*
* This example does not start a node (though you can if you wish.) This portion of the
* libzt API is merely a wrapper around our web API endpoint (https://my.zerotier.com/help/api).
* The HTTP requests are done via libcurl. This API is thread-safe but not multi-threaded.
*
* Error Codes:
* -2 : [ZTS_ERR_SERVICE] The API may not have been initialized properly
* -3 : [ZTS_ERR_ARG] Invalid argument
* [100-500] : Standard HTTP error codes
*
* Usage example: centralapi https://my.zerotier.com e7no7nVRFItge7no7cVR5Ibge7no8nV1
*
*/

int err = ZTS_ERR_OK;
// Buffer to store server response as JSON string blobs
char rbuf[ZTS_CENTRAL_RESP_BUF_DEFAULT_SZ] = { 0 };

// Provide URL to Central API server and user API token generated at https://my.zerotier.com
printf("Initializing Central API client...\n");
if ((err = zts_central_init(central_url, api_token, rbuf, ZTS_CENTRAL_RESP_BUF_DEFAULT_SZ))
!= ZTS_ERR_OK) {
fprintf(stderr, "Error while initializing client's Central API parameters\n");
return 0;
}

zts_central_set_verbose(false); // (optional) Turn on reporting from libcurl
zts_central_set_access_mode(ZTS_CENTRAL_READ /*| ZTS_CENTRAL_WRITE*/);

int http_res_code = 0;

// Get hosted service status
printf("Requesting Central API server status (/api/status):\n");
if ((err = zts_central_status_get(&http_res_code)) != ZTS_ERR_OK) {
fprintf(stderr, "Error (%d) making the request.\n", err);
}
else {
process_response(rbuf, http_res_code);
}
// Get network config
int64_t nwid = 0x1234567890abcdef;
printf("Requesting network config: /api/network/%llx\n", nwid);
if ((err = zts_central_net_get(&http_res_code, nwid)) != ZTS_ERR_OK) {
fprintf(stderr, "Error (%d) making the request.\n", err);
}
else {
process_response(rbuf, http_res_code);
}
// Authorize a node on a network
int64_t nodeid = 0x9934343434;
printf("Authorizing: /api/network/%llx/member/%llx\n", nwid, nodeid);
if ((err = zts_central_node_auth(&http_res_code, nwid, nodeid, ZTS_CENTRAL_NODE_AUTH_TRUE))
!= ZTS_ERR_OK) {
fprintf(stderr, "Error (%d) making the request.\n", err);
}
else {
process_response(rbuf, http_res_code);
}

return 0;
}
Loading

0 comments on commit 4335069

Please sign in to comment.