diff --git a/examples/c/looping-client.c b/examples/c/looping-client.c new file mode 100644 index 00000000..3cf07f12 --- /dev/null +++ b/examples/c/looping-client.c @@ -0,0 +1,199 @@ +/** + * libzt C API example + * + * Simple socket-based client application + */ + +#define _GNU_SOURCE + +#include "ZeroTierSockets.h" + +#include "lwip/dns.h" +#include "lwip/netdb.h" +#include "lwip/sockets.h" + +#include +#include +#include +#include // for uint64_t +#include // for PRIx64 +#include // for getpid +#include + +int main(int argc, char** argv) { + + fprintf(stderr, "CLIENT PROCESS ID: %d\n", getpid()); + +#if defined(__APPLE__) + pthread_setname_np("main"); +#elif defined(__linux__) + pthread_setname_np(pthread_self(), "main"); +#endif + + int nodelay = 0; + int single = 0; + + for (int i = 2; i < argc; i++) { + if (strcmp(argv[i], "nodelay") == 0) { + nodelay = 1; + } else if (strcmp(argv[i], "single") == 0) { + single = 1; + } + } + + char* storagePath = "client_storage"; + + unsigned short port = 8080; + + int ztsFamily; + char *remoteAddr; + struct zts_sockaddr_in serv_addr; + struct zts_sockaddr_in6 serv_addr6; + struct zts_sockaddr *serv_addr_p; + int serv_addr_len; + if (strcmp(argv[1], "4") == 0) { + +#if defined(__APPLE__) + remoteAddr = "172.30.75.127"; +#elif defined(__linux__) + remoteAddr = "172.30.71.15"; +#endif + + ztsFamily = ZTS_AF_INET; + + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(port); + + if (zts_inet_pton(AF_INET, remoteAddr, &serv_addr.sin_addr) <= 0) { + fprintf(stderr, "Invalid address/ Address not supported \n"); + exit(1); + } + + serv_addr_p = (struct zts_sockaddr *)&serv_addr; + serv_addr_len = sizeof(serv_addr); + + } else if (strcmp(argv[1], "6") == 0) { + + // + // rfc4193 + // + +#if defined(__APPLE__) + remoteAddr = "fd9e:1948:db63:f87e:3e99:933b:a302:6272"; +#elif defined(__linux__) + remoteAddr = "fd9e:1948:db63:f87e:3e99:938c:9ecd:6aa1"; +#endif + + ztsFamily = ZTS_AF_INET6; + + serv_addr6.sin6_family = AF_INET6; + serv_addr6.sin6_port = htons(port); + + if (zts_inet_pton(AF_INET6, remoteAddr, &serv_addr6.sin6_addr) <= 0) { + fprintf(stderr, "Invalid address/ Address not supported \n"); + exit(1); + } + + serv_addr_p = (struct zts_sockaddr *)&serv_addr6; + serv_addr_len = sizeof(serv_addr6); + + } else { + fprintf(stderr, "Unable to start client. Exiting.\n"); + exit(1); + } + + if (!nodelay) { + sleep(15); + } + + uint64_t networdId = strtoull("9e1948db63f87e3e", NULL, 16); + + // + // ZeroTier setup + // + + // Initialize node + + int err; + + if ((err = zts_init_from_storage(storagePath)) != ZTS_ERR_OK) { + fprintf(stderr, "Unable to start service, error = %d. Exiting.\n", err); + exit(1); + } + + fprintf(stderr, "start\n"); + if ((err = zts_node_start()) != ZTS_ERR_OK) { + fprintf(stderr, "Unable to start service, error = %d. Exiting.\n", err); + exit(1); + } + + fprintf(stderr, "Waiting for node to come online\n"); + while (! zts_node_is_online()) { + zts_util_delay(50); + } + + fprintf(stderr, "Node ID: %" PRIx64 "\n", zts_node_get_id()); + + fprintf(stderr, "Joining network...\n"); + if (zts_net_join(networdId) != ZTS_ERR_OK) { + fprintf(stderr, "Unable to join network. Exiting.\n"); + exit(1); + } + fprintf(stderr, "Joined\n"); + + fprintf(stderr, "delaying until transport ready...\n"); + while (! zts_net_transport_is_ready(networdId)) { + zts_util_delay(50); + } + fprintf(stderr, "done delaying until transport ready\n"); + + // Socket logic + + fprintf(stderr, "Starting client...\n"); + + for (;;) { + + int fd; + + if ((fd = zts_bsd_socket(ztsFamily, ZTS_SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "zts_bsd_socket error. Exiting.\n"); + exit(1); + } + + fprintf(stderr, "fd: %d\n", fd); + + if ((err = zts_bsd_connect(fd, serv_addr_p, serv_addr_len)) != ZTS_ERR_OK) { + fprintf(stderr, "zts_bsd_connect error: err: %d zts_errno: %d\n", err, zts_errno); + exit(1); + } + + ssize_t bytes; + + if ((bytes = zts_write(fd, "Hello from C Client!", 20)) < 0) { + fprintf(stderr, "zts_write error. Exiting.\n"); + exit(1); + } + + + char recvBuf[128] = { 0 }; + + if ((bytes = zts_read(fd, recvBuf, sizeof(recvBuf))) < 0) { + fprintf(stderr, "zts_read error. Exiting.\n"); + exit(1); + } + + fprintf(stderr, "recv: %s\n", recvBuf); + + + if ((err = zts_close(fd)) != ZTS_ERR_OK) { + fprintf(stderr, "zts_close error. Exiting.\n"); + exit(1); + } + + if (single) { + break; + } + + zts_util_delay(500); + } +} diff --git a/examples/c/looping-server.c b/examples/c/looping-server.c new file mode 100644 index 00000000..04ae9ddb --- /dev/null +++ b/examples/c/looping-server.c @@ -0,0 +1,206 @@ +/** + * libzt C API example + * + * Simple socket-based server application + */ + +#define _GNU_SOURCE + +#include "ZeroTierSockets.h" + +#include "lwip/dns.h" +#include "lwip/netdb.h" +#include "lwip/sockets.h" + +#include +#include +#include +#include // for uint64_t +#include // for PRIx64 +#include // for getpid +#include + +int main(int argc, char** argv) { + + fprintf(stderr, "SERVER PROCESS ID: %d\n", getpid()); + +#if defined(__APPLE__) + pthread_setname_np("main"); +#elif defined(__linux__) + pthread_setname_np(pthread_self(), "main"); +#endif + + int nodelay = 0; + int single = 0; + + for (int i = 2; i < argc; i++) { + if (strcmp(argv[i], "nodelay") == 0) { + nodelay = 1; + } else if (strcmp(argv[i], "single") == 0) { + single = 1; + } + } + + unsigned short port = 8080; + + int ztsFamily; + struct zts_sockaddr_in addr; + struct zts_sockaddr_in6 addr6; + struct zts_sockaddr *addr_p; + int addr_len; + if (strcmp(argv[1], "4") == 0) { + + ztsFamily = ZTS_AF_INET; + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port); + + addr_p = (struct zts_sockaddr *)&addr; + addr_len = sizeof(addr); + + } else if (strcmp(argv[1], "6") == 0) { + + // + // rfc4193 + // + + ztsFamily = ZTS_AF_INET6; + + addr6.sin6_family = AF_INET6; + + addr6.sin6_addr = zts_in6addr_any; + + addr6.sin6_port = htons(port); + + addr_p = (struct zts_sockaddr *)&addr6; + addr_len = sizeof(addr6); + + } else { + fprintf(stderr, "Unable to start server. Exiting.\n"); + exit(1); + } + + if (!nodelay) { + sleep(15); + } + + char* storagePath = "server_storage"; + + uint64_t networdId = strtoull("9e1948db63f87e3e", NULL, 16); + + // + // ZeroTier setup + // + + fprintf(stderr, "init from storage...\n"); + if ((zts_init_from_storage(storagePath)) != ZTS_ERR_OK) { + printf("Unable to start service. Exiting.\n"); + exit(1); + } + + fprintf(stderr, "start\n"); + if ((zts_node_start()) != ZTS_ERR_OK) { + printf("Unable to start service. Exiting.\n"); + exit(1); + } + + fprintf(stderr, "Waiting for node to come online\n"); + while (! zts_node_is_online()) { + zts_util_delay(50); + } + + fprintf(stderr, "Node ID: %" PRIx64 "\n", zts_node_get_id()); + + fprintf(stderr, "Joining network...\n"); + if (zts_net_join(networdId) != ZTS_ERR_OK) { + printf("Unable to join network. Exiting.\n"); + exit(1); + } + + fprintf(stderr, "Waiting for network...\n"); + while (! zts_net_transport_is_ready(networdId)) { + zts_util_delay(50); + } + + fprintf(stderr, "Joined\n"); + + // IPv4 + + char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 }; + zts_addr_get_str(networdId, ZTS_AF_INET, ipstr, ZTS_IP_MAX_STR_LEN); + fprintf(stderr, "IPv4 address on network %" PRIx64 " is %s\n", networdId, ipstr); + + // IPv6 + + zts_addr_get_str(networdId, ZTS_AF_INET6, ipstr, ZTS_IP_MAX_STR_LEN); + fprintf(stderr, "IPv6 address on network %" PRIx64 " is %s\n", networdId, ipstr); + + // Socket logic + + fprintf(stderr, "Starting server...\n"); + + int err; + int fd; + + if ((fd = zts_bsd_socket(ztsFamily, ZTS_SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "zts_bsd_socket error. Exiting.\n"); + exit(1); + } + + if ((err = zts_bsd_bind(fd, addr_p, addr_len)) < 0) { + printf("zts_bsd_bind error (fd=%d, err=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno); + exit(1); + } + + int backlog = 100; + if (zts_bsd_listen(fd, backlog) < 0) { + fprintf(stderr, "zts_bsd_listen error. Exiting.\n"); + exit(1); + } + + for (;;) { + + int accfd; + struct zts_sockaddr client_addr; + zts_socklen_t client_addrlen; + if ((accfd = zts_bsd_accept(fd, &client_addr, &client_addrlen)) < 0) { + printf("zts_bsd_accept error (fd=%d, accfd=%d, zts_errno=%d). Exiting.\n", fd, accfd, zts_errno); + exit(1); + } + + fprintf(stderr, "accfd: %d\n", accfd); + + char recvBuf[128] = { 0 }; + + ssize_t bytes; + + if ((bytes = zts_read(accfd, recvBuf, sizeof(recvBuf))) < 0) { + printf("zts_read error. Exiting.\n"); + exit(1); + } + + fprintf(stderr, "recv: %s\n", recvBuf); + + + if ((bytes = zts_write(accfd, "Hello from C Server!", 20)) < 0) { + printf("zts_write error. Exiting.\n"); + exit(1); + } + + + if (zts_close(accfd) != ZTS_ERR_OK) { + printf("zts_close error. Exiting.\n"); + exit(1); + } + + if (single) { + break; + } + } + + if (zts_close(fd) != ZTS_ERR_OK) { + printf("zts_close error. Exiting.\n"); + exit(1); + } +} diff --git a/include/ZeroTierSockets.h b/include/ZeroTierSockets.h index 8c74b9f6..ba9732ae 100644 --- a/include/ZeroTierSockets.h +++ b/include/ZeroTierSockets.h @@ -437,6 +437,12 @@ typedef void (*CppCallback)(void* msg); /** 255.255.255.255 */ #define ZTS_INADDR_BROADCAST ZTS_IPADDR_BROADCAST + +#define ZTS_IN6ADDR_ANY_INIT {{{0,0,0,0}}} + + + + // Socket protocol types #define ZTS_SOCK_STREAM 0x0001 #define ZTS_SOCK_DGRAM 0x0002 @@ -503,6 +509,8 @@ struct zts_in6_addr { //#define s6_addr un.u8_addr }; +const struct zts_in6_addr zts_in6addr_any = ZTS_IN6ADDR_ANY_INIT; + /** * Address structure to specify an IPv4 endpoint */ diff --git a/src/Controls.cpp b/src/Controls.cpp index 8aa0a722..f768bf0f 100644 --- a/src/Controls.cpp +++ b/src/Controls.cpp @@ -318,9 +318,13 @@ void* cbRun(void* arg) #endif { ZTS_UNUSED_ARG(arg); + #if defined(__APPLE__) - // pthread_setname_np(ZTS_EVENT_CALLBACK_THREAD_NAME); + pthread_setname_np(ZTS_EVENT_CALLBACK_THREAD_NAME); +#elif defined(__linux__) + pthread_setname_np(pthread_self(), ZTS_EVENT_CALLBACK_THREAD_NAME); #endif + zts_events->run(); //#if ZTS_ENABLE_JAVA // _java_detach_from_thread(); @@ -533,22 +537,33 @@ void* _runNodeService(void* arg) #endif { ZTS_UNUSED_ARG(arg); + #if defined(__APPLE__) - // pthread_setname_np(ZTS_SERVICE_THREAD_NAME); + pthread_setname_np(ZTS_SERVICE_THREAD_NAME); +#elif defined(__linux__) + pthread_setname_np(pthread_self(), ZTS_SERVICE_THREAD_NAME); #endif + try { zts_service->run(); + // Begin shutdown + service_m.lock(); + zts_events->clrState(ZTS_STATE_NODE_RUNNING); delete zts_service; zts_service = (NodeService*)0; + service_m.unlock(); + events_m.lock(); + zts_util_delay(ZTS_CALLBACK_PROCESSING_INTERVAL * 2); if (zts_events) { zts_events->disable(); } + events_m.unlock(); } catch (...) { @@ -573,9 +588,6 @@ int zts_node_start() #else pthread_t cbThread; if ((res = pthread_create(&cbThread, NULL, cbRun, NULL)) != 0) {} -#endif -#if defined(__linux__) - // pthread_setname_np(cbThread, ZTS_EVENT_CALLBACK_THREAD_NAME); #endif if (res != ZTS_ERR_OK) { zts_events->clrState(ZTS_STATE_CALLBACKS_RUNNING); @@ -590,9 +602,6 @@ int zts_node_start() #else pthread_t service_thread; if ((res = pthread_create(&service_thread, NULL, _runNodeService, (void*)NULL)) != 0) {} -#endif -#if defined(__linux__) - // pthread_setname_np(service_thread, ZTS_SERVICE_THREAD_NAME); #endif if (res != ZTS_ERR_OK) { zts_events->clrState(ZTS_STATE_NODE_RUNNING); diff --git a/src/VirtualTap.cpp b/src/VirtualTap.cpp index a13dcbd7..8feca771 100644 --- a/src/VirtualTap.cpp +++ b/src/VirtualTap.cpp @@ -240,17 +240,21 @@ void VirtualTap::threadMain() throw() { fd_set readfds, nullfds; struct timeval tv; + +#if defined(__APPLE__) + pthread_setname_np("ZT_VirtualTap_threadMain"); + // pthread_setname_np(vtap_full_name); +#elif defined(__linux__) + pthread_setname_np(pthread_self(), "ZT_VirtualTap_threadMain"); + // pthread_setname_np(pthread_self(), vtap_full_name); +#endif + tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&readfds); FD_ZERO(&nullfds); int nfds = (int)std::max(_shutdownSignalPipe[0], 0) + 1; -#if defined(__linux__) - // pthread_setname_np(pthread_self(), vtap_full_name); -#endif -#if defined(__APPLE__) - // pthread_setname_np(vtap_full_name); -#endif + while (true) { FD_SET(_shutdownSignalPipe[0], &readfds); select(nfds, &readfds, &nullfds, &nullfds, &tv); @@ -294,12 +298,12 @@ static void zts_tcpip_init_done(void* arg) static void zts_main_lwip_driver_loop(void* arg) { -#if defined(__linux__) - // pthread_setname_np(pthread_self(), ZTS_LWIP_THREAD_NAME); -#endif #if defined(__APPLE__) - // pthread_setname_np(ZTS_LWIP_THREAD_NAME); + pthread_setname_np(ZTS_LWIP_THREAD_NAME); +#elif defined(__linux__) + pthread_setname_np(pthread_self(), ZTS_LWIP_THREAD_NAME); #endif + sys_sem_t sem; LWIP_UNUSED_ARG(arg); if (sys_sem_new(&sem, 0) != ERR_OK) { @@ -363,10 +367,15 @@ void zts_lwip_remove_netif(void* netif) return; } struct netif* n = (struct netif*)netif; + + // already present LOCK_TCPIP_CORE(); + netif_remove(n); netif_set_down(n); netif_set_link_down(n); + + // already present UNLOCK_TCPIP_CORE(); } @@ -454,6 +463,11 @@ void zts_lwip_eth_rx( if (Utils::ntoh(ethhdr.type) == 0x800 || Utils::ntoh(ethhdr.type) == 0x806) { if (tap->netif4) { + + // + // netif->input is tcpip_input + // + if ((err = ((struct netif*)tap->netif4)->input(p, (struct netif*)tap->netif4)) != ERR_OK) { // DEBUG_ERROR("packet input error (%d)", err); pbuf_free(p); @@ -462,6 +476,11 @@ void zts_lwip_eth_rx( } if (Utils::ntoh(ethhdr.type) == 0x86DD) { if (tap->netif6) { + + // + // netif->input is ethernet_input + // + if ((err = ((struct netif*)tap->netif6)->input(p, (struct netif*)tap->netif6)) != ERR_OK) { // DEBUG_ERROR("packet input error (%d)", err); pbuf_free(p); @@ -475,9 +494,15 @@ bool zts_lwip_is_netif_up(void* n) if (! n) { return false; } + + // already present LOCK_TCPIP_CORE(); + bool result = netif_is_up((struct netif*)n); + + // already present UNLOCK_TCPIP_CORE(); + return result; } @@ -543,10 +568,17 @@ void zts_lwip_init_interface(void* tapref, const InetAddress& ip) IP4_ADDR(&gw, 127, 0, 0, 1); ip4.addr = *((u32_t*)ip.rawIpData()); netmask.addr = *((u32_t*)ip.netmask().rawIpData()); - LOCK_TCPIP_CORE(); + + // already present + LOCK_TCPIP_CORE(); + netif_add(n, &ip4, &netmask, &gw, (void*)vtap, zts_netif_init4, tcpip_input); + vtap->netif4 = (void*)n; - UNLOCK_TCPIP_CORE(); + + // already present + UNLOCK_TCPIP_CORE(); + snprintf( macbuf, ZTS_MAC_ADDRSTRLEN, @@ -568,11 +600,25 @@ void zts_lwip_init_interface(void* tapref, const InetAddress& ip) netifCount++; } static ip6_addr_t ip6; + memcpy(&(ip6.addr), ip.rawIpData(), sizeof(ip6.addr)); - LOCK_TCPIP_CORE(); + + // already present + LOCK_TCPIP_CORE(); + if (isNewNetif) { vtap->netif6 = (void*)n; + + netif_add(n, NULL, NULL, NULL, (void*)vtap, zts_netif_init6, ethernet_input); + + // + // > With NO_SYS=0, this must be set to tcpip_input for all netif types (whether ethernet, PPP, slipif, etc.) + // https://lwip.fandom.com/wiki/Writing_a_device_driver + // + // netif_add(n, NULL, NULL, NULL, (void*)vtap, zts_netif_init6, tcpip_input); + + n->ip6_autoconfig_enabled = 1; vtap->_mac.copyTo(n->hwaddr, n->hwaddr_len); netif_create_ip6_linklocal_address(n, 1); @@ -581,8 +627,11 @@ void zts_lwip_init_interface(void* tapref, const InetAddress& ip) netif_set_default(n); } netif_add_ip6_address(n, &ip6, NULL); - n->output_ip6 = ethip6_output; - UNLOCK_TCPIP_CORE(); + n->output_ip6 = ethip6_output; // needed!? + + // already present + UNLOCK_TCPIP_CORE(); + snprintf( macbuf, ZTS_MAC_ADDRSTRLEN,