diff options
| author | Joseph Henry <[email protected]> | 2020-04-17 10:32:43 -0700 |
|---|---|---|
| committer | Joseph Henry <[email protected]> | 2020-04-17 10:32:43 -0700 |
| commit | d7be0b7052308ec64b1b50fe20b817545bfc2ad2 (patch) | |
| tree | 38342d1e822dd02901cb16847ef2a1ab6f3ae18f /test | |
| parent | 41c8f019a0182ac84f7f9be6ae2e7d9dda06cd88 (diff) | |
Remove outdated examples
Diffstat (limited to 'test')
| -rw-r--r-- | test/example.cpp | 280 | ||||
| -rw-r--r-- | test/selftest.cpp | 3411 | ||||
| -rw-r--r-- | test/simple.cpp | 92 |
3 files changed, 0 insertions, 3783 deletions
diff --git a/test/example.cpp b/test/example.cpp deleted file mode 100644 index 11ff33c..0000000 --- a/test/example.cpp +++ /dev/null @@ -1,280 +0,0 @@ -#include <arpa/inet.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#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; j<pd->pathCount; 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<num; i++) { - printPeerDetails(&pd[i]); - } - } -} - -struct zts_stats_proto protoSpecificStats; - -void display_stack_stats() -{ - int err = 0; - // Count received pings - if ((err = zts_get_protocol_stats(ZTS_STATS_PROTOCOL_ICMP, &protoSpecificStats)) != ZTS_ERR_OK) { - printf("zts_get_proto_stats()=%d", err); - return; - } - printf("icmp.recv=%d\n", protoSpecificStats.recv); - // Count dropped TCP packets - if ((err = zts_get_protocol_stats(ZTS_STATS_PROTOCOL_TCP, &protoSpecificStats)) != ZTS_ERR_OK) { - printf("zts_get_proto_stats()=%d", err); - return; - } - printf("tcp.drop=%d\n", protoSpecificStats.drop); -} - -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 - int defaultServicePort = 9994; - int nwid = 0x0123456789abcdef; - zts_start("test/path", &myZeroTierEventCallback, defaultServicePort); - printf("Waiting for node to come online...\n"); - - // Wait for the node to come online before joining a network - while (!node_ready) { sleep(1); } - zts_join(nwid); - printf("Joined virtual network. Requesting configuration...\n"); - - //sleep(1); - - // Get multiple peer's details - getAllPeerDetails(); - - // Get a single peer's details - getSinglePeerDetails(0x01b34f67c90); - 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(0x0123456789abcdef); - printf("zts_get_network_status()=%d\n", status); - - while (true) { - sleep(1); - status = zts_get_node_status(); - printf("zts_get_node_status()=%d\n", status); - display_stack_stats(); - } - - // Socket API example - printf("zts_errno=%d\n",zts_errno); - if ((fd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { - printf("error creating socket\n"); - } - printf("fd=%d, zts_errno=%d\n", fd, zts_errno); - 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; -} diff --git a/test/selftest.cpp b/test/selftest.cpp deleted file mode 100644 index 731814c..0000000 --- a/test/selftest.cpp +++ /dev/null @@ -1,3411 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <string> -#include <fcntl.h> -#include <errno.h> -#include <iostream> -#include <vector> -#include <algorithm> -#include <fstream> -#include <map> -#include <ctime> -#include <signal.h> -#include <cstring> -#include <chrono> -#include <thread> - -#include "libzt.h" - -#if defined(__SELFTEST__) -#include "Utils.hpp" -#endif - -#if defined(__linux__) || defined(__APPLE__) -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <netdb.h> -#include <poll.h> -#include <unistd.h> -#include <pthread.h> -#include <sys/time.h> -#endif - - -#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) - #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 -#else - #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL -#endif - -void micro_sleep(unsigned long us) -{ - std::this_thread::sleep_for(std::chrono::microseconds(us)); -} - -#if defined(_WIN32) -#include <WinSock2.h> -#include <WS2tcpip.h> -#include <Ws2def.h> -#include <stdint.h> -#include <windows.h> -#include <time.h> - -void sleep(unsigned long ms) -{ - Sleep(ms); -} - -struct timezone -{ - int tz_minuteswest; - int tz_dsttime; -}; - - -int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - FILETIME ft; - unsigned __int64 tmpres = 0; - static int tzflag; - - if (NULL != tv) - { - GetSystemTimeAsFileTime(&ft); - - tmpres |= ft.dwHighDateTime; - tmpres <<= 32; - tmpres |= ft.dwLowDateTime; - - /*converting file time to unix epoch*/ - tmpres -= DELTA_EPOCH_IN_MICROSECS; - tmpres /= 10; /*convert into microseconds*/ - tv->tv_sec = (long)(tmpres / 1000000UL); - tv->tv_usec = (long)(tmpres % 1000000UL); - } - - if (NULL != tz) - { - if (!tzflag) - { - _tzset(); - tzflag++; - } - tz->tz_minuteswest = _timezone / 60; - tz->tz_dsttime = _daylight; - } - - return 0; -} -#endif - - -#define EXIT_ON_FAIL false - -#define TEST_PASSED 1 -#define TEST_FAILED 0 - -#define ECHO_INTERVAL 1000000 // microseconds -#define SLAM_INTERVAL 500000 // microseconds - -#define ARTIFICIAL_SOCKET_LINGER 1 - -#define STR_SIZE 32 - -#define TEST_OP_N_BYTES 10 -#define TEST_OP_N_SECONDS 11 -#define TEST_OP_N_TIMES 12 - -#define TEST_MODE_CLIENT 20 -#define TEST_MODE_SERVER 21 - -#define TEST_TYPE_SIMPLE 30 -#define TEST_TYPE_SUSTAINED 31 -#define TEST_TYPE_PERF 32 -#define TEST_TYPE_PERF_TO_ECHO 33 - -#define MIN_PORT 5000 -#define MAX_PORT 50000 - -#define TCP_UNIT_TEST_SIG_4 struct sockaddr_in *addr, int op, int cnt, char *details, bool *passed -#define UDP_UNIT_TEST_SIG_4 struct sockaddr_in *local_addr, struct sockaddr_in *remote_addr, int op, int cnt, char *details, bool *passed - -#define TCP_UNIT_TEST_SIG_6 struct sockaddr_in6 *addr, int op, int cnt, char *details, bool *passed -#define UDP_UNIT_TEST_SIG_6 struct sockaddr_in6 *local_addr, struct sockaddr_in6 *remote_addr, int op, int cnt, char *details, bool *passed - -#define ECHOTEST_MODE_RX 333 -#define ECHOTEST_MODE_TX 666 - -#define MAX_RX_BUF_SZ 2048 -#define MAX_TX_BUF_SZ 2048 - -#define ONE_MEGABYTE 1024 * 1024 - -#define DETAILS_STR_LEN 128 - -// If running a self test, use libzt calls -#if defined(__SELFTEST__) -#define _SOCKET zts_socket -#define _BIND zts_bind -#define _LISTEN zts_listen -#define _ACCEPT zts_accept -#define _CONNECT zts_connect -#define _READ zts_read -#define _WRITE zts_write -#define _RECV zts_recv -#define _SEND zts_send -#define _RECVFROM zts_recvfrom -#define _SENDTO zts_sendto -#define _RECVMSG zts_recvmsg -#define _SENDMSG zts_sendmsg -#define _SETSOCKOPT zts_setsockopt -#define _GETSOCKOPT zts_getsockopt -#define _IOCTL zts_ioctl -#define _FCNTL zts_fcntl -#define _SELECT zts_select -#define _CLOSE zts_close -#define _GETPEERNAME zts_getpeername -#endif - -// If running a native instance to test against, use system calls -#if defined(__NATIVETEST__) -inline unsigned int gettid() -{ -#ifdef _WIN32 - return GetCurrentThreadId(); -#elif defined(__unix__) - return static_cast<unsigned int>(::syscall(__NR_gettid)); -#elif defined(__APPLE__) - uint64_t tid64; - pthread_threadid_np(NULL, &tid64); - return static_cast<unsigned int>(tid64); -#endif -} - -#define _SOCKET socket -#define _BIND bind -#define _LISTEN listen -#define _ACCEPT accept -#define _CONNECT connect -#define _RECV recvmsg -#define _SEND send -#define _RECVFROM recvfrom -#define _SENDTO sendto -#define _RECVMSG recvmsg -#define _SENDMSG sendmsg -#define _SETSOCKOPT setsockopt -#define _GETSOCKOPT getsockopt -#define _IOCTL ioctl -#define _FCNTL fcntl -#define _SELECT select - -#define _READ read -#define _WRITE write - -//#define _RECV recv -//#define _SEND send - -#if defined(_WIN32) -#define _CLOSE closesocket -#else -#define _CLOSE close -#endif - -#define _GETPEERNAME getpeername -#endif - -std::map<std::string, std::string> testConf; - -/* Tests in this file: - - Basic RX/TX connect()/accept() Functionality: - - [ ?] slam - perform thousands of the same call per second - [ ] random - act like a monkey, press all the buttons - [OK] simple client ipv4 - connect, send one message and wait for an echo - [OK] simple server ipv4 - accept, read one message and echo it back - [OK] simple client ipv6 - connect, send one message and wait for an echo - [OK] simple server ipv6 - accept, read one message and echo it back - [OK] sustained client ipv4 - connect and rx/tx many messages, VERIFIES data integrity - [OK] sustained server ipv4 - accept and echo messages, VERIFIES data integrity - [OK] sustained client ipv6 - connect and rx/tx many messages, VERIFIES data integrity - [OK] sustained server ipv6 - accept and echo messages, VERIFIES data integrity - [OK] comprehensive client ipv4 - test all ipv4/6 client simple/sustained modes - [OK] comprehensive server ipv6 - test all ipv4/6 server simple/sustained modes - [ ?] SOCK_RAW (VL2) ipv4 - See test/layer2.cpp - [ ?] SOCK_RAW (VL2) ipv6 - See test/layer2.cpp - - Performance: - (See libzt.h, compile libzt with appropriate ZT_TCP_TX_BUF_SZ, ZT_TCP_RX_BUF_SZ, ZT_UDP_TX_BUF_SZ, and ZT_UDO_RX_BUF_SZ for your test) - - [OK] Throughput - Test maximum RX/TX speeds - [ ] Memory Usage - Test memory consumption profile - [ ] CPU Usage - Test processor usage - [ ] - - Correctness: - - [ ] Block/Non-block - Test that blocking and non-blocking behaviour is consistent - [ ] Release of resources - Test that all destructor methods/blocks function properly - [OK] Multi-network handling - Test internal Tap multiplexing works for multiple networks - [ ] Address handling - Test that addresses are copied/parsed/returned properly - -*/ - - - - - -/****************************************************************************/ -/* Helper Functions */ -/****************************************************************************/ - -/** Returns true on success, or false if there was an error */ -bool SetSocketBlockingEnabled(int fd, bool blocking) -{ - if (fd < 0) return false; -#ifdef _WIN32 - unsigned long mode = blocking ? 0 : 1; - return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? true : false; -#else - int flags = _FCNTL(fd, F_GETFL, 0); - if (flags == -1) return false; - flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); - return (_FCNTL(fd, F_SETFL, flags) == 0) ? true : false; -#endif -} - -void displayResults(int *results, int size) -{ - int success = 0, failure = 0; - for (int i=0; i<size; i++) { - if (results[i] == 0) { - success++; - } - else { - failure++; - } - } - std::cout << "tials: " << size << std::endl; - std::cout << " - success = " << (float)success / (float)size << std::endl; - std::cout << " - failure = " << (float)failure / (float)size << std::endl; -} - -void loadTestConfigFile(std::string filepath) -{ - std::string key, value, prefix; - std::ifstream testFile; - testFile.open(filepath.c_str()); - while (testFile >> key >> value) { - if (key == "name") { - prefix = value; - } - if (key[0] != '#' && key[0] != ';') { - testConf[prefix + "." + key] = value; - fprintf(stderr, "%s.%s = %s\n", prefix.c_str(), key.c_str(), testConf[prefix + "." + key].c_str()); - } - - } - testFile.close(); -} - -long int get_now_ts() -{ - struct timeval tp; - gettimeofday(&tp, NULL); - return tp.tv_sec * 1000 + tp.tv_usec / 1000; -} - -// for syncronizing tests -void wait_until_tplus(long int original_time, int tplus_ms) -{ - while (original_time + tplus_ms > get_now_ts()) { - sleep(1); - } -} -void wait_until_tplus_s(long int original_time, int tplus_s) -{ - int current_time_offset = (get_now_ts() - original_time) / 1000; - fprintf(stderr, "\n\n--- WAITING FOR T+%d --- (current: T+%d)\n\n", tplus_s, current_time_offset); - if (current_time_offset > tplus_s) { - DEBUG_ERROR("--- ABORTING TEST: Tests are out of sync and might not yield valid results. ---"); - //exit(0); - } - if (current_time_offset == tplus_s) { - DEBUG_ERROR("--- WARNING: Tests might be out of sync and might not yield valid results. ---"); - } - wait_until_tplus(original_time, tplus_s * 1000); -} - -int rand_in_range(int min, int max) -{ -#if defined(__SELFTEST__) - unsigned int seed; - ZeroTier::Utils::getSecureRandom((void*)&seed,sizeof(seed)); - srand(seed); -#else - srand((unsigned int)time(NULL)); -#endif - return min + rand() % static_cast<int>(max - min + 1); -} - -void generate_random_data(void *buf, size_t n, int min, int max) -{ - char *b = (char*)buf; - for (size_t i=0; i<n; i++) { - b[i] = rand_in_range(min, max); - } -} - -void str2addr(std::string ipstr, int port, int ipv, struct sockaddr *saddr) -{ - if (ipv == 4) { - struct sockaddr_in *in4 = (struct sockaddr_in*)saddr; - in4->sin_addr.s_addr = inet_addr(ipstr.c_str()); - in4->sin_family = AF_INET; - in4->sin_port = htons(port); - } if (ipv == 6) { - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)saddr; - inet_pton(AF_INET6, ipstr.c_str(), &(in6->sin6_addr)); - in6->sin6_flowinfo = 0; - in6->sin6_family = AF_INET6; - in6->sin6_port = htons(port); - } -} - -void RECORD_RESULTS(bool passed, char *details, std::vector<std::string> *results) -{ - char *ok_str = (char*)"[ OK ]"; - char *fail_str = (char*)"[ FAIL ]"; - if (passed == TEST_PASSED) { - DEBUG_TEST("%s", ok_str); - results->push_back(std::string(ok_str) + " " + std::string(details)); - } else { - DEBUG_ERROR("%s", fail_str); - results->push_back(std::string(fail_str) + " " + std::string(details)); - } if (EXIT_ON_FAIL && !passed) { - fprintf(stderr, "%s\n", results->at(results->size()-1).c_str()); - exit(0); - } - memset(details, 0, DETAILS_STR_LEN); -} - -void wait_until_everyone_is_ready(struct sockaddr *local_addr, struct sockaddr *remote_addr, int start_port) -{ - /* try to connect to (and listen for) other selftest instances on the network. - When one is found, send some sort of synchronization message and allow test to - begin */ - int err; - bool connected = false; - int accepted_fd; - // listen socket setup - int listen_fd; - if ((listen_fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket"); - exit(0); - } if ((err = _BIND(listen_fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in)) < 0)) { - perror("bind"); - exit(0); - } if ((err = _LISTEN(listen_fd, 0)) < 0) { - perror("listen"); - exit(0); - } - SetSocketBlockingEnabled(listen_fd, true); - // connect socket setup - int conn_fd; - if ((conn_fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket"); - exit(0); - } - SetSocketBlockingEnabled(conn_fd, true); - while(connected == false) { - if ((err = _CONNECT(conn_fd, (const struct sockaddr *)remote_addr, sizeof(*remote_addr))) < 0) { - if (errno == EISCONN) { - DEBUG_TEST("connected"); - connected = true; - } - } - else { - connected = true; - } - if (connected == false) { - struct sockaddr_in client; - socklen_t client_addrlen = sizeof(sockaddr_in); - if ((accepted_fd = _ACCEPT(listen_fd, (struct sockaddr *)&client, &client_addrlen)) < 0) { - //DEBUG_TEST("errno = %d", errno); - } - else { - DEBUG_TEST("connected"); - connected = true; - } - } - sleep(1); - } - _CLOSE(listen_fd); - _CLOSE(conn_fd); - _CLOSE(accepted_fd); -} - - -/****************************************************************************/ -/* POLL/_SELECT */ -/****************************************************************************/ - -void tcp_select_server(TCP_UNIT_TEST_SIG_4) -{ - std::string testname = "tcp_select_server"; - std::string msg = "tcp_select"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "accept connection, create poll/select loop, read and write strings back and forth\n"); - int w=0, r=0, fd, client_fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - perror("socket"); - *passed = false; - return; - } - if ((err = _BIND(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - if ((err = _LISTEN(fd, 100)) < 0) { - printf("error placing socket in _LISTENING state (%d)", err); - perror("listen"); - *passed = false; - return; - } - struct sockaddr_in client; - socklen_t client_addrlen = sizeof(sockaddr_in); - if ((client_fd = _ACCEPT(fd, (struct sockaddr *)&client, &client_addrlen)) < 0) { - perror("accept"); - *passed = false; - return; - } - - DEBUG_TEST("accepted connection fd=%d", client_fd); - - fd_set read_set, write_set; - memset(&read_set, 0, sizeof(read_set)); - memset(&write_set, 0, sizeof(write_set)); - - uint32_t msecs = 5; - struct timeval tv; - tv.tv_sec = msecs / 1000; - tv.tv_usec = (msecs % 1000) * 1000; - int ret = 0; - - FD_SET(client_fd, &read_set); - FD_SET(client_fd, &write_set); - - int tot = 1000, rx_num = 0, tx_num = 0; - - while(rx_num < tot && tx_num < tot) { - - FD_ZERO(&read_set); - FD_ZERO(&write_set); - - FD_SET(client_fd, &read_set); - FD_SET(client_fd, &write_set); - - ret = _SELECT(client_fd + 1, &read_set, &write_set, NULL, &tv); - - if (ret > 0) { - for (int fd_i=0; fd_i<client_fd+1; fd_i++) { - - // process incoming messages - if (FD_ISSET(fd_i, &read_set)) { -#if defined(_WIN32) - r = _RECV(fd_i, rbuf, len, 0); -#else - r = _READ(fd_i, rbuf, len); -#endif - if (r == (int)msg.length()) { - rx_num++; - DEBUG_TEST("rx=%d", rx_num); - } - } - // write a message to the socket if allowed - if (FD_ISSET(fd_i, &write_set)) { -#if defined(_WIN32) - w = _SEND(fd_i, msg.c_str(), len, 0); -#else - w = _WRITE(fd_i, msg.c_str(), len); -#endif - if (w == (int)msg.length()) { - tx_num++; - DEBUG_TEST("tx=%d", tx_num); - } - } - } - } - } - DEBUG_TEST("complete"); - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); -} - -void tcp_select_client(TCP_UNIT_TEST_SIG_4) -{ - std::string testname = "tcp_select_client"; - std::string msg = "tcp_select"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "connect to remote host, create poll/select loop, read and write strings back and forth\n"); - int r, w, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _CONNECT(fd, (const struct sockaddr *)addr, sizeof(*addr))) < 0) { - DEBUG_ERROR("error connecting to remote host (%d)", err); - perror("connect"); - *passed = false; - return; - } - - DEBUG_TEST("connected fd=%d", fd); - - fd_set read_set, write_set; - memset(&read_set, 0, sizeof(read_set)); - memset(&write_set, 0, sizeof(write_set)); - - uint32_t msecs = 5; - struct timeval tv; - tv.tv_sec = msecs / 1000; - tv.tv_usec = (msecs % 1000) * 1000; - int ret = 0; - - FD_SET(fd, &read_set); - FD_SET(fd, &write_set); - - int tot = 1000, rx_num = 0, tx_num = 0; - - while(rx_num < tot && tx_num < tot) { - - FD_ZERO(&read_set); - FD_ZERO(&write_set); - - FD_SET(fd, &read_set); - FD_SET(fd, &write_set); - - ret = _SELECT(fd + 1, &read_set, &write_set, NULL, &tv); - - if (ret > 0) { - DEBUG_TEST("socket activity"); - for (int fd_i=0; fd_i<fd+1; fd_i++) { - // process incoming messages - if (FD_ISSET(fd_i, &read_set)) { -#if defined(_WIN32) - r = _RECV(fd_i, rbuf, len, 0); -#else - r = _READ(fd_i, rbuf, len); -#endif - if (r == (int)msg.length()) { - rx_num++; - DEBUG_TEST("rx=%d", rx_num); - } - } - // write a message to the socket if allowed - if (FD_ISSET(fd_i, &write_set)) { -#if defined(_WIN32) - w = _SEND(fd_i, msg.c_str(), len, 0); -#else - w = _WRITE(fd_i, msg.c_str(), len); -#endif - if (w == (int)msg.length()) { - tx_num++; - DEBUG_TEST("tx=%d", tx_num); - } - } - } - } - } - DEBUG_TEST("complete"); - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); -} - -/****************************************************************************/ -/* SIMPLE */ -/****************************************************************************/ - -// TCP - -void tcp_client_4(TCP_UNIT_TEST_SIG_4) -{ - std::string testname = "tcp_client_4"; - std::string msg = "tcp_cs_4"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "connect to remote host with IPv4 address, write string, read string, compare.\n"); - int r, w, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _CONNECT(fd, (const struct sockaddr *)addr, sizeof(*addr))) < 0) { - DEBUG_ERROR("error connecting to remote host (%d)", err); - perror("connect"); - *passed = false; - return; - } - // TODO: Put this test in the general API section - struct sockaddr_storage peer_addr; - struct sockaddr_in *in4 = (struct sockaddr_in*)&peer_addr; - socklen_t peer_addrlen = sizeof(peer_addr); - - if ((err = _GETPEERNAME(fd, (struct sockaddr*)&peer_addr, &peer_addrlen)) < 0) { - perror("getpeername"); - *passed = false; - return; - } - DEBUG_TEST("getpeername() => %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); - -#if defined(_WIN32) - w = _SEND(fd, msg.c_str(), len, 0); -#else - w = _WRITE(fd, msg.c_str(), len); -#endif -#if defined(_WIN32) - r = _RECV(fd, rbuf, len, 0); -#else - r = _READ(fd, rbuf, len); -#endif - DEBUG_TEST("Sent : %s", msg.c_str()); - DEBUG_TEST("Received : %s", rbuf); - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); -} - - - - - -void tcp_server_4(TCP_UNIT_TEST_SIG_4) -{ - std::string testname = "tcp_server_4"; - std::string msg = "tcp_cs_4"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "accept connection with IPv4 address, read string, write string, compare.\n"); - int w=0, r=0, fd, client_fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _BIND(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - if ((err = _LISTEN(fd, 100)) < 0) { - printf("error placing socket in _LISTENING state (%d)", err); - perror("listen"); - *passed = false; - return; - } - struct sockaddr_in client; - socklen_t client_addrlen = sizeof(sockaddr_in); - if ((client_fd = _ACCEPT(fd, (struct sockaddr *)&client, &client_addrlen)) < 0) { - perror("accept"); - *passed = false; - return; - } - DEBUG_TEST("accepted connection from %s, on port %d", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); - // TODO: Put this test in the general API section - struct sockaddr_storage peer_addr; - struct sockaddr_in *in4 = (struct sockaddr_in*)&peer_addr; - socklen_t peer_addrlen = sizeof(peer_addr); - - if ((err = _GETPEERNAME(client_fd, (struct sockaddr*)&peer_addr, &peer_addrlen)) < 0) { - perror("getpeername"); - *passed = false; - return; - } - DEBUG_TEST("getpeername() => %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); -#if defined(_WIN32) - r = _RECV(client_fd, rbuf, len, 0); -#else - r = _READ(client_fd, rbuf, len); -#endif - -#if defined(_WIN32) - w = _SEND(client_fd, rbuf, len, 0); -#else - w = _WRITE(client_fd, rbuf, len); -#endif - DEBUG_TEST("Received : %s, r=%d, w=%d", rbuf, r, w); - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - err = _CLOSE(client_fd); - sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); -} - - - - - -void tcp_client_6(TCP_UNIT_TEST_SIG_6) -{ - std::string testname = "tcp_client_6"; - std::string msg = "tcp_cs_6"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "connect to remote host with IPv6 address, write string, read string, compare.\n"); - int r, w, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET6, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _CONNECT(fd, (const struct sockaddr *)addr, sizeof(*addr))) < 0) { - DEBUG_ERROR("error connecting to remote host (%d)", err); - perror("connect"); - *passed = false; - return; - } - // TODO: Put this test in the general API section - struct sockaddr_storage peer_addr; - struct sockaddr_in6 *p6 = (struct sockaddr_in6*)&peer_addr; - socklen_t peer_addrlen = sizeof(peer_addr); - if ((err = _GETPEERNAME(fd, (struct sockaddr*)&peer_addr, &peer_addrlen)) < 0) { - perror("getpeername"); - *passed = false; - return; - } - char peer_addrstr[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(p6->sin6_addr), peer_addrstr, INET6_ADDRSTRLEN); - DEBUG_TEST("getpeername() => %s : %d", peer_addrstr, ntohs(p6->sin6_port)); - -#if defined(_WIN32) - w = _SEND(fd, msg.c_str(), len, 0); -#else - w = _WRITE(fd, msg.c_str(), len); -#endif -#if defined(_WIN32) - r = _RECV(fd, rbuf, len, 0); -#else - r = _READ(fd, rbuf, len); -#endif - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - DEBUG_TEST("Sent : %s", msg.c_str()); - DEBUG_TEST("Received : %s", rbuf); - *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); -} - - - - -void tcp_server_6(TCP_UNIT_TEST_SIG_6) -{ - std::string testname = "tcp_server_6"; - std::string msg = "tcp_cs_6"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "accept connection with IPv6 address, read string, write string, compare.\n"); - int w=0, r=0, fd, client_fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET6, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _BIND(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in6)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - if ((err = _LISTEN(fd, 100)) < 0) { - DEBUG_ERROR("error placing socket in _LISTENING state (%d)", err); - perror("listen"); - *passed = false; - return; - } - struct sockaddr_in6 client; - socklen_t client_addrlen = sizeof(sockaddr_in6); - if ((client_fd = _ACCEPT(fd, (struct sockaddr *)&client, &client_addrlen)) < 0) { - perror("accept"); - *passed = false; - return; - } - char ipstr[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &client.sin6_addr, ipstr, sizeof ipstr); - DEBUG_TEST("accepted connection from %s, on port %d", ipstr, ntohs(client.sin6_port)); - // TODO: Put this test in the general API section - struct sockaddr_storage peer_addr; - struct sockaddr_in6 *p6 = (struct sockaddr_in6*)&peer_addr; - socklen_t peer_addrlen = sizeof(peer_addr); - if ((err = _GETPEERNAME(client_fd, (struct sockaddr*)&peer_addr, &peer_addrlen)) < 0) { - perror("getpeername"); - *passed = false; - return; - } - char peer_addrstr[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(p6->sin6_addr), peer_addrstr, INET6_ADDRSTRLEN); - DEBUG_TEST("getpeername() => %s : %d", peer_addrstr, ntohs(p6->sin6_port)); -#if defined(_WIN32) - r = _RECV(client_fd, rbuf, sizeof rbuf, 0); -#else - r = _READ(client_fd, rbuf, sizeof rbuf); -#endif -#if defined(_WIN32) - w = _SEND(client_fd, rbuf, len, 0); -#else - w = _WRITE(client_fd, rbuf, len); -#endif - DEBUG_TEST("Received : %s", rbuf); - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - err = _CLOSE(client_fd); - sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); -} - - - - - -// UDP - -void udp_client_4(UDP_UNIT_TEST_SIG_4) -{ - std::string testname = "udp_client_4"; - std::string msg = "udp_cs_4"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "bind to interface with IPv4 address, send string until response is seen. compare.\n"); - int r, w, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET, SOCK_DGRAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - SetSocketBlockingEnabled(fd, true); - DEBUG_TEST("sending UDP packets until I get a single response..."); - if ((err = _BIND(fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - struct sockaddr_storage saddr; - while (true) { - sleep(1); - // tx - if ((w = _SENDTO(fd, msg.c_str(), strlen(msg.c_str()), 0, (struct sockaddr *)remote_addr, sizeof(*remote_addr))) < 0) { - DEBUG_ERROR("error sending packet, err=%d", errno); - } - memset(rbuf, 0, sizeof(rbuf)); - int serverlen = sizeof(struct sockaddr_storage); - // rx - r = _RECVFROM(fd, rbuf, STR_SIZE, 0, (struct sockaddr *)&saddr, (socklen_t *)&serverlen); - if (r == (int)strlen(msg.c_str())) { - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - DEBUG_TEST("%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - DEBUG_TEST("Sent : %s", msg.c_str()); - DEBUG_TEST("Received : %s", rbuf); - *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); - return; - } - } -} - - - - - -void udp_server_4(UDP_UNIT_TEST_SIG_4) -{ - std::string testname = "udp_server_4"; - std::string msg = "udp_cs_4"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "bind to interface with IPv4 address, read single string, send many responses. compare.\n"); - int r, w, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET, SOCK_DGRAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _BIND(fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - // rx - DEBUG_TEST("waiting for UDP packet..."); - struct sockaddr_storage saddr; - struct sockaddr_in *in4 = (struct sockaddr_in*)&saddr; - int serverlen = sizeof(saddr); - memset(&saddr, 0, sizeof(saddr)); - if ((r = _RECVFROM(fd, rbuf, STR_SIZE, 0, (struct sockaddr *)in4, (socklen_t *)&serverlen)) < 0) { - perror("recvfrom"); - *passed = false; - return; - } - char addrstr[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN); - // once we receive a UDP packet, spend 10 seconds sending responses in the hopes that the client will see - DEBUG_TEST("received DGRAM from %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); - DEBUG_TEST("sending DGRAM(s) to %s : %d", inet_ntoa(remote_addr->sin_addr), ntohs(remote_addr->sin_port)); - // tx - long int tx_ti = get_now_ts(); - while (true) { - sleep(1); - if ((w = _SENDTO(fd, msg.c_str(), len, 0, (struct sockaddr *)remote_addr, sizeof(*remote_addr))) < 0) { - DEBUG_ERROR("error sending packet, err=%d", errno); - } - if (get_now_ts() >= tx_ti + 10000) { - break; - } - } - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - DEBUG_TEST("%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - DEBUG_TEST("Sent : %s", msg.c_str()); - DEBUG_TEST("Received : %s", rbuf); - *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); -} - - - -int zts_bind_test(int fd, const struct sockaddr *addr, socklen_t addrlen) -{ - // int err = -1; - DEBUG_EXTRA("fd=%d", fd); - DEBUG_INFO("addrp=%p", addr); - DEBUG_INFO("addrlen=%d", addrlen); - DEBUG_INFO("sa_family======%d", addr->sa_family); - struct sockaddr_storage ss; - memcpy(&ss, addr, addrlen); - DEBUG_INFO("ss->sa_family=%d", ss.ss_family); - //fix_addr_socket_family((struct sockaddr*)&ss); - //ss.ss_family=AF_INET6; - //DEBUG_INFO("ss->sa_family=%d", ss.ss_family); - //err = lwip_bind(fd, (struct sockaddr*)&ss, addrlen); - exit(0); -} - -void udp_client_6(UDP_UNIT_TEST_SIG_6) -{ - std::string testname = "udp_client_6"; - std::string msg = "udp_cs_6"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "bind to interface with IPv6 address, send string until response is seen. compare.\n"); - int r, w, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - - if ((fd = _SOCKET(AF_INET6, SOCK_DGRAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - SetSocketBlockingEnabled(fd, true); - DEBUG_TEST("[1] binding and sending UDP packets until I get a single response..."); - if ((err = _BIND(fd, (struct sockaddr*)local_addr, sizeof(struct sockaddr_in6)) < 0)) { - DEBUG_ERROR("error binding to interface (err=%d, errno=%d)", err, errno); - perror("bind"); - *passed = false; - return; - } - // start sending UDP packets in the hopes that at least one will be picked up by the server - struct sockaddr_storage saddr; - while (true) { - // tx - if ((w = _SENDTO(fd, msg.c_str(), len, 0, (struct sockaddr *)remote_addr, sizeof(*remote_addr))) < 0) { - DEBUG_ERROR("error sending packet, err=%d", errno); - } - micro_sleep(100000); - memset(rbuf, 0, sizeof(rbuf)); - int serverlen = sizeof(struct sockaddr_storage); - // rx - r = _RECVFROM(fd, rbuf, len, 0, (struct sockaddr *)&saddr, (socklen_t *)&serverlen); - if (r == len) { - DEBUG_TEST("[2] complete"); - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - DEBUG_TEST("%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - DEBUG_TEST("Sent : %s", msg.c_str()); - DEBUG_TEST("Received : %s", rbuf); - *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); - return; - } - } -} - - - -void udp_server_6(UDP_UNIT_TEST_SIG_6) -{ - std::string testname = "udp_server_6"; - std::string msg = "udp_cs_6"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "bind to interface with IPv6 address, read single string, send many responses. compare.\n"); - int r, w, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - - if ((fd = _SOCKET(AF_INET6, SOCK_DGRAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _BIND(fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in6)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - // rx - DEBUG_TEST("[1/3] waiting for UDP packet to start test..."); - struct sockaddr_storage saddr; - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&saddr; - int serverlen = sizeof(saddr); - memset(&saddr, 0, sizeof(saddr)); - if ((r = _RECVFROM(fd, rbuf, len, 0, (struct sockaddr *)&saddr, (socklen_t *)&serverlen)) < 0) { - perror("recvfrom"); - *passed = false; - return; - } - char addrstr[INET6_ADDRSTRLEN], remote_addrstr[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(in6->sin6_addr), addrstr, INET6_ADDRSTRLEN); - inet_ntop(AF_INET6, &(remote_addr->sin6_addr), remote_addrstr, INET6_ADDRSTRLEN); - DEBUG_TEST("[2/3] received DGRAM from %s : %d", addrstr, ntohs(in6->sin6_port)); - DEBUG_TEST("[2/3] sending DGRAM(s) to %s : %d", remote_addrstr, ntohs(remote_addr->sin6_port)); - // once we receive a UDP packet, spend 10 seconds sending responses in the hopes that the client will see - // tx - long int tx_ti = get_now_ts(); - while (true) { - micro_sleep(100000); - //DEBUG_TEST("sending UDP packet"); - if ((w = _SENDTO(fd, msg.c_str(), len, 0, (struct sockaddr *)remote_addr, sizeof(*remote_addr))) < 0) { - DEBUG_ERROR("error sending packet, err=%d", errno); - } - if (get_now_ts() >= tx_ti + 10000) { - // DEBUG_TEST("[3/4] get_now_ts()-tx_ti=%d", get_now_ts()-tx_ti); - break; - } - } - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - DEBUG_TEST("[3/3] complete, %s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); - DEBUG_TEST("Sent : %s", msg.c_str()); - DEBUG_TEST("Received : %s", rbuf); - *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); -} - - - - - - -/****************************************************************************/ -/* SUSTAINED */ -/****************************************************************************/ - - - - - -void tcp_client_sustained_4(TCP_UNIT_TEST_SIG_4) -{ - std::string testname = "tcp_client_sustained_4"; - std::string msg = "tcp_sustained_4"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "connect to remote host with IPv4 address, exchange a sequence of packets, check order.\n"); - int n=0, w=0, r=0, fd, err; - char *rxbuf = (char*)malloc(cnt*sizeof(char)); - char *txbuf = (char*)malloc(cnt*sizeof(char)); - generate_random_data(txbuf, cnt, 0, 9); - - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _CONNECT(fd, (const struct sockaddr *)addr, sizeof(*addr))) < 0) { - DEBUG_ERROR("error connecting to remote host (%d)", err); - perror("connect"); - *passed = false; - return; - } - if (op == TEST_OP_N_BYTES) { - int wrem = cnt, rrem = cnt; - // TX - long int tx_ti = get_now_ts(); - while (wrem) { - int next_write = std::min(4096, wrem); -#if !defined(_WIN32) - signal(SIGPIPE, SIG_IGN); -#endif - DEBUG_TEST("writing..."); -#if defined(_WIN32) - n = _SEND(fd, &txbuf[w], next_write, 0); -#else - n = _WRITE(fd, &txbuf[w], next_write); -#endif - DEBUG_TEST("wrote=%d", n); - if (n > 0) { - w += n; - wrem -= n; - err = n; - DEBUG_TEST("wrote=%d, w=%d, wrem=%d", n, w, wrem); - } - } - long int tx_tf = get_now_ts(); - DEBUG_TEST("wrote=%d, reading next...", w); - // RX - long int rx_ti = 0; - while (rrem) { -#if defined(_WIN32) - n = _RECV(fd, &rxbuf[r], rrem, 0); -#else - n = _READ(fd, &rxbuf[r], rrem); -#endif - if (rx_ti == 0) { // wait for first message - rx_ti = get_now_ts(); - } - if (n > 0) { - r += n; - rrem -= n; - err = n; - } - } - long int rx_tf = get_now_ts(); - DEBUG_TEST("read=%d", r); - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - // Compare RX and TX buffer and detect mismatches - bool match = true; - for (int i=0; i<cnt; i++) { - if (rxbuf[i] != txbuf[i]) { - DEBUG_ERROR("buffer mismatch found at idx=%d", i); - match=false; - } - } - // Compute time deltas and transfer rates - float tx_dt = (tx_tf - tx_ti) / (float)1000; - float rx_dt = (rx_tf - rx_ti) / (float)1000; - float tx_rate = (float)cnt / (float)tx_dt; - float rx_rate = (float)cnt / (float)rx_dt; - sprintf(details, "%s, match=%d, n=%d, tx_dt=%.2f, rx_dt=%.2f, r=%d, w=%d, tx_rate=%.2f MB/s, rx_rate=%.2f MB/s", - testname.c_str(), match, cnt, tx_dt, rx_dt, r, w, (tx_rate / float(ONE_MEGABYTE) ), (rx_rate / float(ONE_MEGABYTE) )); - *passed = (r == cnt && w == cnt && match && err>=0); - } - free(rxbuf); - free(txbuf); -} - - - - - -void tcp_client_sustained_6(TCP_UNIT_TEST_SIG_6) -{ - std::string testname = "tcp_client_sustained_6"; - std::string msg = "tcp_sustained_6"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "connect to remote host with IPv6 address, exchange a sequence of packets, check order.\n"); - int n=0, w=0, r=0, fd, err; - char *rxbuf = (char*)malloc(cnt*sizeof(char)); - char *txbuf = (char*)malloc(cnt*sizeof(char)); - generate_random_data(txbuf, cnt, 0, 9); - if ((fd = _SOCKET(AF_INET6, SOCK_STREAM, 0)) < 0){ - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _CONNECT(fd, (const struct sockaddr *)addr, sizeof(*addr))) < 0) { - DEBUG_ERROR("error connecting to remote host (%d)", err); - perror("connect"); - *passed = false; - return; - } - - if (op == TEST_OP_N_BYTES) { - int wrem = cnt, rrem = cnt; - // TX - long int tx_ti = get_now_ts(); - while (wrem) { - int next_write = std::min(4096, wrem); -#if defined(_WIN32) - n = _SEND(fd, &txbuf[w], next_write, 0); -#else - n = _WRITE(fd, &txbuf[w], next_write); -#endif - if (n > 0) { - w += n; - wrem -= n; - err = n; - } - } - long int tx_tf = get_now_ts(); - DEBUG_TEST("wrote=%d", w); - // RX - long int rx_ti = 0; - while (rrem) { -#if defined(_WIN32) - n = _RECV(fd, &rxbuf[r], rrem, 0); -#else - n = _READ(fd, &rxbuf[r], rrem); -#endif - if (rx_ti == 0) { // wait for first message - rx_ti = get_now_ts(); - } - if (n > 0) { - r += n; - rrem -= n; - err = n; - } - } - long int rx_tf = get_now_ts(); - DEBUG_TEST("read=%d", r); - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - // Compare RX and TX buffer and detect mismatches - bool match = true; - for (int i=0; i<cnt; i++) { - if (rxbuf[i] != txbuf[i]) { - DEBUG_ERROR("buffer mismatch found at idx=%d", i); - match=false; - } - } - // Compute time deltas and transfer rates - float tx_dt = (tx_tf - tx_ti) / (float)1000; - float rx_dt = (rx_tf - rx_ti) / (float)1000; - float tx_rate = (float)cnt / (float)tx_dt; - float rx_rate = (float)cnt / (float)rx_dt; - sprintf(details, "%s, match=%d, n=%d, tx_dt=%.2f, rx_dt=%.2f, r=%d, w=%d, tx_rate=%.2f MB/s, rx_rate=%.2f MB/s", - testname.c_str(), match, cnt, tx_dt, rx_dt, r, w, (tx_rate / float(ONE_MEGABYTE) ), (rx_rate / float(ONE_MEGABYTE) )); - *passed = (r == cnt && w == cnt && match && err>=0); - } - free(rxbuf); - free(txbuf); -} - - - - - -void tcp_server_sustained_4(TCP_UNIT_TEST_SIG_4) -{ - std::string testname = "tcp_server_sustained_4"; - std::string msg = "tcp_sustained_4"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "accept connection from host with IPv4 address, exchange a sequence of packets, check order.\n"); - int n=0, w=0, r=0, fd, client_fd, err; - char *rxbuf = (char*)malloc(cnt*sizeof(char)); - memset(rxbuf, 0, cnt); - - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _BIND(fd, (struct sockaddr *)addr, (socklen_t)sizeof(*addr)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - if ((err = _LISTEN(fd, 1)) < 0) { - DEBUG_ERROR("error placing socket in _LISTENING state (%d)", err); - perror("listen"); - *passed = false; - return; - } - struct sockaddr_storage client; - struct sockaddr_in *in4 = (struct sockaddr_in*)&client; - socklen_t client_addrlen = sizeof(sockaddr_storage); - if ((client_fd = _ACCEPT(fd, (struct sockaddr *)in4, &client_addrlen)) < 0) { - fprintf(stderr,"error accepting connection (%d)\n", err); - perror("accept"); - } - DEBUG_TEST("accepted connection from %s, on port %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); - if (op == TEST_OP_N_BYTES) { - int wrem = cnt, rrem = cnt; - long int rx_ti = 0; - while (rrem) { -#if defined(_WIN32) - n = _RECV(client_fd, &rxbuf[r], rrem, 0); -#else - n = _READ(client_fd, &rxbuf[r], rrem); -#endif - if (n > 0) { - if (rx_ti == 0) { // wait for first message - rx_ti = get_now_ts(); - } - r += n; - rrem -= n; - err = n; - DEBUG_TEST("read=%d, r=%d, rrem=%d", n, r, rrem); - } - } - long int rx_tf = get_now_ts(); - DEBUG_TEST("read=%d, writing next...", r); - long int tx_ti = get_now_ts(); - while (wrem) { - int next_write = std::min(1024, wrem); -#if defined(_WIN32) - n = _SEND(client_fd, &rxbuf[w], next_write, 0); -#else - n = _WRITE(client_fd, &rxbuf[w], next_write); -#endif - if (n > 0) { - w += n; - wrem -= n; - err = n; - } - } - long int tx_tf = get_now_ts(); - DEBUG_TEST("wrote=%d", w); - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - err = _CLOSE(client_fd); - // Compute time deltas and transfer rates - float tx_dt = (tx_tf - tx_ti) / (float)1000; - float rx_dt = (rx_tf - rx_ti) / (float)1000; - float tx_rate = (float)cnt / (float)tx_dt; - float rx_rate = (float)cnt / (float)rx_dt; - sprintf(details, "%s, n=%d, tx_dt=%.2f, rx_dt=%.2f, r=%d, w=%d, tx_rate=%.2f MB/s, rx_rate=%.2f MB/s", - testname.c_str(), cnt, tx_dt, rx_dt, r, w, (tx_rate / float(ONE_MEGABYTE) ), (rx_rate / float(ONE_MEGABYTE) )); - *passed = (r == cnt && w == cnt && err>=0); - } - free(rxbuf); -} - - - - - -void tcp_server_sustained_6(TCP_UNIT_TEST_SIG_6) -{ - std::string testname = "tcp_server_sustained_6"; - std::string msg = "tcp_sustained_6"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "accept connection from host with IPv6 address, exchange a sequence of packets, check order.\n"); - int n=0, w=0, r=0, fd, client_fd, err; - char *rxbuf = (char*)malloc(cnt*sizeof(char)); - memset(rxbuf, 0, cnt); - - if ((fd = _SOCKET(AF_INET6, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - if ((err = _BIND(fd, (struct sockaddr *)addr, (socklen_t)sizeof(struct sockaddr_in6)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - if ((err = _LISTEN(fd, 1)) < 0) { - DEBUG_ERROR("error placing socket in _LISTENING state (%d)", err); - perror("listen"); - *passed = false; - return; - } - struct sockaddr_in6 client; - socklen_t client_addrlen = sizeof(sockaddr_in6); - if ((client_fd = _ACCEPT(fd, (struct sockaddr *)&client, &client_addrlen)) < 0) { - fprintf(stderr,"error accepting connection (%d)\n", err); - perror("accept"); - *passed = false; - return; - } - char ipstr[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &client.sin6_addr, ipstr, sizeof ipstr); - DEBUG_TEST("accepted connection from %s, on port %d", ipstr, ntohs(client.sin6_port)); - - if (op == TEST_OP_N_BYTES) { - int wrem = cnt, rrem = cnt; - long int rx_ti = 0; - while (rrem) { -#if defined(_WIN32) - n = _RECV(client_fd, &rxbuf[r], rrem, 0); -#else - n = _READ(client_fd, &rxbuf[r], rrem); -#endif - if (n > 0) { - if (rx_ti == 0) { // wait for first message - rx_ti = get_now_ts(); - } - r += n; - rrem -= n; - err = n; - } - } - long int rx_tf = get_now_ts(); - DEBUG_TEST("read=%d", r); - long int tx_ti = get_now_ts(); - while (wrem) { - int next_write = std::min(1024, wrem); -#if defined(_WIN32) - n = _SEND(client_fd, &rxbuf[w], next_write, 0); -#else - n = _WRITE(client_fd, &rxbuf[w], next_write); -#endif - if (n > 0) { - w += n; - wrem -= n; - err = n; - } - } - long int tx_tf = get_now_ts(); - DEBUG_TEST("wrote=%d", w); - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - err = _CLOSE(client_fd); - // Compute time deltas and transfer rates - float tx_dt = (tx_tf - tx_ti) / (float)1000; - float rx_dt = (rx_tf - rx_ti) / (float)1000; - float tx_rate = (float)cnt / (float)tx_dt; - float rx_rate = (float)cnt / (float)rx_dt; - sprintf(details, "%s, n=%d, tx_dt=%.2f, rx_dt=%.2f, r=%d, w=%d, tx_rate=%.2f MB/s, rx_rate=%.2f MB/s", - testname.c_str(), cnt, tx_dt, rx_dt, r, w, (tx_rate / float(ONE_MEGABYTE) ), (rx_rate / float(ONE_MEGABYTE) )); - - *passed = (r == cnt && w == cnt && err>=0); - } - free(rxbuf); -} - - - - - -void udp_client_sustained_4(UDP_UNIT_TEST_SIG_4) -{ - std::string testname = "udp_client_sustained_4"; - std::string msg = "udp_sustained_4"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "bind to interface with IPv4 address, TX n-datagrams\n"); - int w, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET, SOCK_DGRAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - SetSocketBlockingEnabled(fd, true); - DEBUG_TEST("sending UDP packets until I get a single response..."); - if ((err = _BIND(fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - int num_to_send = 10; - for (int i=0; i<num_to_send; i++) { - // tx - if ((w = _SENDTO(fd, msg.c_str(), strlen(msg.c_str()), 0, (struct sockaddr *)remote_addr, sizeof(*remote_addr))) < 0) { - DEBUG_ERROR("error sending packet, err=%d", errno); - } - } - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - DEBUG_TEST("%s, n=%d, err=%d, w=%d", testname.c_str(), cnt, err, w); - sprintf(details, "%s, n=%d, err=%d, w=%d", testname.c_str(), cnt, err, w); - DEBUG_TEST("Sent : %s", msg.c_str()); - *passed = (w == len && !err); - return; -} - - - - - -void udp_server_sustained_4(UDP_UNIT_TEST_SIG_4) -{ - std::string testname = "udp_server_sustained_4"; - std::string msg = "udp_sustained_4"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "bind to interface with IPv4 address, RX (n/x)-datagrams\n"); - int r, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET, SOCK_DGRAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - perror("socket"); - *passed = false; - return; - } - if ((err = _BIND(fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - int num_to_recv = 3; - DEBUG_TEST("waiting for UDP packet..."); - for (int i=0; i<num_to_recv; i++) { - // rx - struct sockaddr_storage saddr; - struct sockaddr_in *in4 = (struct sockaddr_in*)&saddr; - int serverlen = sizeof(saddr); - memset(&saddr, 0, sizeof(saddr)); - r = _RECVFROM(fd, rbuf, STR_SIZE, 0, (struct sockaddr *)in4, (socklen_t *)&serverlen); - char addrstr[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN); - // once we receive a UDP packet, spend 10 seconds sending responses in the hopes that the client will see - DEBUG_TEST("received DGRAM from %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); - DEBUG_TEST("sending DGRAM(s) to %s : %d", inet_ntoa(remote_addr->sin_addr), ntohs(remote_addr->sin_port)); - } - sleep(ARTIFICIAL_SOCKET_LINGER); - //err = _CLOSE(fd); - DEBUG_TEST("%s, n=%d, err=%d, r=%d", testname.c_str(), cnt, err, r); - sprintf(details, "%s, n=%d, err=%d, r=%d", testname.c_str(), cnt, err, r); - DEBUG_TEST("Received : %s", rbuf); - *passed = (r == len && !err) && !strcmp(rbuf, msg.c_str()); -} - - - - - -void udp_client_sustained_6(UDP_UNIT_TEST_SIG_6) -{ - std::string testname = "udp_client_sustained_6"; - std::string msg = "udp_sustained_6"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "bind to interface with IPv6 address, TX n-datagrams\n"); - int w, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET6, SOCK_DGRAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - exit(0); - perror("socket"); - *passed = false; - return; - } - SetSocketBlockingEnabled(fd, true); - DEBUG_TEST("sending UDP packets until I get a single response..."); - if ((err = _BIND(fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in6)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - int num_to_send = 10; - for (int i=0; i<num_to_send; i++) { - sleep(1); - // tx - if ((w = _SENDTO(fd, msg.c_str(), strlen(msg.c_str()), 0, (struct sockaddr *)remote_addr, sizeof(*remote_addr))) < 0) { - DEBUG_ERROR("error sending packet, err=%d", errno); - } - } - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - DEBUG_TEST("%s, n=%d, err=%d, w=%d", testname.c_str(), cnt, err, w); - sprintf(details, "%s, n=%d, err=%d, w=%d", testname.c_str(), cnt, err, w); - DEBUG_TEST("Sent : %s", msg.c_str()); - *passed = (w == len && !err); - return; -} - - - - - -void udp_server_sustained_6(UDP_UNIT_TEST_SIG_6) -{ - std::string testname = "udp_server_sustained_6"; - std::string msg = "udp_sustained_6"; - fprintf(stderr, "\n\n%s (ts=%lu)\n", testname.c_str(), get_now_ts()); - fprintf(stderr, "bind to interface with IPv6 address, RX (n/x)-datagrams\n"); - int r, fd, err, len = strlen(msg.c_str()); - char rbuf[STR_SIZE]; - memset(rbuf, 0, sizeof rbuf); - if ((fd = _SOCKET(AF_INET6, SOCK_DGRAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - perror("socket"); - *passed = false; - return; - } - if ((err = _BIND(fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in6)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - int num_to_recv = 3; - DEBUG_TEST("waiting for UDP packet..."); - for (int i=0; i<num_to_recv; i++) { - // rx - struct sockaddr_storage saddr; - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&saddr; - int serverlen = sizeof(saddr); - memset(&saddr, 0, sizeof(saddr)); - r = _RECVFROM(fd, rbuf, STR_SIZE, 0, (struct sockaddr *)in6, (socklen_t *)&serverlen); - char addrstr[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(in6->sin6_addr), addrstr, INET6_ADDRSTRLEN); - // once we receive a UDP packet, spend 10 seconds sending responses in the hopes that the client will see - //DEBUG_TEST("received DGRAM from %s : %d", inet_ntoa(in6->sin6_addr), ntohs(in6->sin6_port)); - //DEBUG_TEST("sending DGRAM(s) to %s : %d", inet_ntoa(remote_addr->sin6_addr), ntohs(remote_addr->sin6_port)); - } - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - DEBUG_TEST("%s, n=%d, err=%d, r=%d", testname.c_str(), cnt, err, r); - sprintf(details, "%s, n=%d, err=%d, r=%d", testname.c_str(), cnt, err, r); - DEBUG_TEST("Received : %s", rbuf); - *passed = (r == len && !err) && !strcmp(rbuf, msg.c_str()); -} - -/****************************************************************************/ -/* PERFORMANCE (between library instances) */ -/****************************************************************************/ - -// Maintain transfer for cnt OR cnt -void tcp_client_perf_4(TCP_UNIT_TEST_SIG_4) -{ - fprintf(stderr, "\n\n\ntcp_client_perf_4\n"); - /* - int w=0, fd, err; - int total_test_sz = cnt; - int arbitrary_chunk_sz_max = MAX_RX_BUF_SZ; - int arbitrary_chunk_sz_min = 512; - - char rbuf[arbitrary_chunk_sz_max]; - - for (int i=arbitrary_chunk_sz_min; (i*2) < arbitrary_chunk_sz_max; i*=2) { - - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) - DEBUG_ERROR("error creating ZeroTier socket"); - if ((err = _CONNECT(fd, (const struct sockaddr *)addr, sizeof(addr))) < 0) - DEBUG_ERROR("error connecting to remote host (%d)", err); - - DEBUG_TEST("[TX] Testing (%d) byte chunks: ", i); - - int chunk_sz = i; - long int start_time = get_now_ts(); - w = 0; - - // TX - while (w < total_test_sz) - w += _WRITE(fd, rbuf, chunk_sz); - - long int end_time = get_now_ts(); - float ts_delta = (end_time - start_time) / (float)1000; - float rate = (float)total_test_sz / (float)ts_delta; - sprintf(details, "tot=%d, dt=%.2f, rate=%.2f MB/s", w, ts_delta, (rate / float(ONE_MEGABYTE) )); - _CLOSE(fd); - } - *passed = (w == total_test_sz && !err) ? TEST_PASSED : TEST_FAILED; - */ -} - -// Maintain transfer for cnt OR cnt -void tcp_server_perf_4(TCP_UNIT_TEST_SIG_4) -{ - fprintf(stderr, "\n\n\ntcp_server_perf_4\n"); - /* - int r=0, fd, client_fd, err; - int total_test_sz = cnt; - int arbitrary_chunk_sz_max = MAX_RX_BUF_SZ; - int arbitrary_chunk_sz_min = 512; - - char rbuf[arbitrary_chunk_sz_max]; - - for (int i=arbitrary_chunk_sz_min; (i*2) < arbitrary_chunk_sz_max; i*=2) { - DEBUG_ERROR("TESTING chunk size = %d", i); - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) - DEBUG_ERROR("error creating ZeroTier socket"); - if ((err = _BIND(fd, (struct sockaddr *)addr, (socklen_t)sizeof(struct sockaddr_in)) < 0)) - DEBUG_ERROR("error binding to interface (%d)", err); - if ((err = _LISTEN(fd, 1)) < 0) - DEBUG_ERROR("error placing socket in _LISTENING state (%d)", err); - if ((client_fd = _ACCEPT(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0) - DEBUG_ERROR("error accepting connection (%d)", err); - - DEBUG_TEST("[RX] Testing (%d) byte chunks: ", i); - - int chunk_sz = i; - long int start_time = get_now_ts(); - r = 0; - - // RX - while (r < total_test_sz) - r += _READ(client_fd, rbuf, chunk_sz); - - long int end_time = get_now_ts(); - - float ts_delta = (end_time - start_time) / (float)1000; - float rate = (float)total_test_sz / (float)ts_delta; - - sprintf(details, "tot=%d, dt=%.2f, rate=%.2f MB/s", r, ts_delta, (rate / float(ONE_MEGABYTE) )); - - _CLOSE(fd); - _CLOSE(client_fd); - } - *passed = (r == total_test_sz && !err) ? TEST_PASSED : TEST_FAILED; - */ -} - - - - - -/****************************************************************************/ -/* PERFORMANCE (between library and native) */ -/****************************************************************************/ - -void tcp_perf_tx_echo_4(TCP_UNIT_TEST_SIG_4) -{ - std::string msg = "tcp_perf_tx_echo_4"; - fprintf(stderr, "\n\n%s\n\n", msg.c_str()); - - int err = 0; - int tot = 0; - int w = 0; - int fd, mode; - - char pbuf[64]; // test parameter buffer - char tbuf[MAX_TX_BUF_SZ]; - - mode = ECHOTEST_MODE_TX; - - // connect to remote echotest host - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - return; - } - if ((err = _CONNECT(fd, (const struct sockaddr *)addr, sizeof(*addr))) < 0) { - DEBUG_ERROR("error connecting to remote host (%d)", err); - return; - } - - DEBUG_TEST("copying test parameters to buffer"); - memset(pbuf, 0, sizeof pbuf); - memcpy(pbuf, &mode, sizeof mode); - memcpy(pbuf + sizeof mode, &cnt, sizeof cnt); - - DEBUG_TEST("sending test parameters to echotest"); -#if defined(_WIN32) - if ((w = _SEND(fd, pbuf, sizeof pbuf, 0)) < 0) { -#else - if ((w = _WRITE(fd, pbuf, sizeof pbuf)) < 0) { -#endif - DEBUG_ERROR("error while sending test parameters to echotest (err=%d)", w); - return; - } - - // begin - DEBUG_TEST("beginning test, sending test byte stream..."); - while (tot < cnt) { -#if defined(_WIN32) - if ((w = _SEND(fd, tbuf, sizeof tbuf, 0)) < 0) { -#else - if ((w = _WRITE(fd, tbuf, sizeof tbuf)) < 0) { -#endif - DEBUG_ERROR("error while sending test byte stream to echotest (err=%d)", w); - return; - } - tot += w; - DEBUG_TEST("tot=%d, sent=%d", tot, w); - } - // read results - memset(pbuf, 0, sizeof pbuf); - DEBUG_TEST("reading test results from echotest"); -#if defined(_WIN32) - if ((w = _RECV(fd, pbuf, sizeof tbuf, 0)) < 0) { -#else - if ((w = _READ(fd, pbuf, sizeof tbuf)) < 0) { -#endif - DEBUG_ERROR("error while reading results from echotest (err=%d)", w); - return; - } - - DEBUG_TEST("reading test results"); - long int start_time = 0, end_time = 0; - memcpy(&start_time, pbuf, sizeof start_time); - memcpy(&end_time, pbuf + sizeof start_time, sizeof end_time); - - float ts_delta = (end_time - start_time) / (float)1000; - float rate = (float)tot / (float)ts_delta; - sprintf(details, "%s, tot=%d, dt=%.2f, rate=%.2f MB/s", msg.c_str(), tot, ts_delta, (rate / float(ONE_MEGABYTE) )); - - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - *passed = (tot == cnt && !err) ? TEST_PASSED : TEST_FAILED; -} - - -void tcp_perf_rx_echo_4(TCP_UNIT_TEST_SIG_4) -{ - std::string msg = "tcp_perf_rx_echo_4"; - fprintf(stderr, "\n\n%s\n\n", msg.c_str()); - - int err = 0; - int mode = 0; - int tot = 0; - int r = 0; - - char pbuf[64]; // test parameter buffer - char tbuf[MAX_TX_BUF_SZ]; - int fd; - - mode = ECHOTEST_MODE_RX; - - // connect to remote echotest host - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating ZeroTier socket"); - return; - } - if ((err = _CONNECT(fd, (const struct sockaddr *)addr, sizeof(*addr))) < 0) { - DEBUG_ERROR("error connecting to remote host (%d)", err); - return; - } - - DEBUG_TEST("copying test parameters to buffer"); - memset(pbuf, 0, sizeof pbuf); - memcpy(pbuf, &mode, sizeof mode); - memcpy(pbuf + sizeof mode, &cnt, sizeof cnt); - - DEBUG_TEST("sending test parameters to echotest"); -#if defined(_WIN32) - if ((r = _SEND(fd, pbuf, sizeof pbuf, 0)) < 0) { -#else - if ((r = _WRITE(fd, pbuf, sizeof pbuf)) < 0) { -#endif - DEBUG_ERROR("error while sending test parameters to echotest (err=%d)", r); - return; - } - - // begin - DEBUG_TEST("beginning test, as soon as bytes are read we will start keeping time..."); -#if defined(_WIN32) - if ((r = _RECV(fd, tbuf, sizeof tbuf, 0)) < 0) { -#else - if ((r = _READ(fd, tbuf, sizeof tbuf)) < 0) { -#endif - DEBUG_ERROR("there was an error reading the test stream. aborting (err=%d, errno=%s)", r, strerror(errno)); - return; - } - - tot += r; - - long int start_time = get_now_ts(); - DEBUG_TEST("Received first set of bytes in test stream. now keeping time"); - - while (tot < cnt) { -#if defined(_WIN32) - if ((r = _RECV(fd, tbuf, sizeof tbuf, 0)) < 0) { -#else - if ((r = _READ(fd, tbuf, sizeof tbuf)) < 0) { -#endif - DEBUG_ERROR("there was an error reading the test stream. aborting (err=%d)", r); - return; - } - tot += r; - DEBUG_TEST("r=%d, tot=%d", r, tot); - } - long int end_time = get_now_ts(); - float ts_delta = (end_time - start_time) / (float)1000; - float rate = (float)tot / (float)ts_delta; - sprintf(details, "%s, tot=%d, dt=%.2f, rate=%.2f MB/s", msg.c_str(), tot, ts_delta, (rate / float(ONE_MEGABYTE) )); - - sleep(ARTIFICIAL_SOCKET_LINGER); - err = _CLOSE(fd); - *passed = (tot == cnt && !err) ? TEST_PASSED : TEST_FAILED; -} - -/****************************************************************************/ -/* OBSCURE API CALL TESTS */ -/****************************************************************************/ - -int obscure_api_test(bool *passed) -{ - int err = -1; - fprintf(stderr, "\n\nobscure API test\n\n"); - - /* - // --- - // getpeername() - int fd, client_fd; - - // after accept() - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) - DEBUG_ERROR("error creating ZeroTier socket"); - if ((err = _BIND(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0)) - DEBUG_ERROR("error binding to interface (%d)", err); - if ((err = _LISTEN(fd, 100)) < 0) - printf("error placing socket in _LISTENING state (%d)", err); - // accept - struct sockaddr_in client; - socklen_t client_addrlen = sizeof(sockaddr_in); - if ((client_fd = accept(fd, (struct sockaddr *)&client, &client_addrlen)) < 0) - fprintf(stderr,"error accepting connection (%d)\n", err); - fprintf(stderr, "accepted connection from %s, on port %d", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); - // getpeername - struct sockaddr_storage peer_addr; - struct sockaddr_in *in4 = (struct sockaddr_in*)&peer_addr; - socklen_t peer_addrlen = sizeof(peer_addr); - _GETPEERNAME(fd, (struct sockaddr*)&peer_addr, &peer_addrlen); - DEBUG_TEST("getpeername() => %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); - // compate getpeername() result to address returned by accept() - - // after connect - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) - DEBUG_ERROR("error creating ZeroTier socket"); - if ((err = _CONNECT(fd, (const struct sockaddr *)addr, sizeof(*addr))) < 0) - DEBUG_ERROR("error connecting to remote host (%d)", err); - // TODO: Put this test in the general API section - struct sockaddr_storage peer_addr; - struct sockaddr_in *in4 = (struct sockaddr_in*)&peer_addr; - socklen_t peer_addrlen = sizeof(peer_addr); - _GETPEERNAME(fd, (struct sockaddr*)&peer_addr, &peer_addrlen); - DEBUG_TEST("getpeername() => %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); - // compare result of getpeername to remote address - - // TODO: write an ipv6 version of the above ^^^ - */ -/* -int levels[] = { - IPPROTO_TCP, - IPPROTO_UDP, - IPPROTO_IP - }; - int num_levels = sizeof(levels) / sizeof(int); - - int optnames[] = { - TCP_NODELAY, - SO_LINGER - }; - int num_optnames = sizeof(optnames) / sizeof(int); - - - for (int i=0; i<num_levels; i++) { // test all levels - for (int j=0; j<num_optnames; j++) { // test all optnames - - // --- - // Disable Nagle's Algorithm on a socket (TCP_NODELAY) - int level = IPPROTO_TCP; - int optname = TCP_NODELAY; - int optval = 1; - socklen_t flag_len = sizeof(optval); - int fd = _SOCKET(AF_INET, SOCK_STREAM, 0); - DEBUG_TEST("setting level=%d, optname=%d, optval=%d...", level, optname, optval); - err = _SETSOCKOPT(fd, level, optname, (char *)&optval, sizeof(int)); - if (err < 0) { - DEBUG_ERROR("error while setting optval on socket"); - *passed = false; - err = -1; - } - optval = -99; // set junk value to test against - if ((err = _GETSOCKOPT(fd, level, optname, &optval, &flag_len)) < 0) { - DEBUG_ERROR("error while getting the optval"); - *passed = false; - err = -1; - } - DEBUG_TEST("flag_len=%d", flag_len); - if (optval <= 0) { - DEBUG_ERROR("incorrect optval=%d (from getsockopt)", optval); - *passed = false; - err = -1; - } else { - DEBUG_TEST("correctly read optval=%d, now reversing it", optval); - if (optval > 0) { // TODO: what should be expected for each platform? Should this mirror them? - optval = 0; - DEBUG_TEST("setting level=%d, optname=%d, optval=%d...", level, optname, optval); - if ((err = _SETSOCKOPT(fd, level, optname, (char *) &optval, (socklen_t)sizeof(int))) < 0) { - DEBUG_ERROR("error while setting on socket"); - *passed = false; - err = -1; - } - else { - DEBUG_TEST("success"); - *passed = true; - } - } else { - DEBUG_ERROR("the optval wasn't set correctly"); - *passed = false; - err = -1; - } - } - } - */ - return err; -} - -/****************************************************************************/ -/* SLAM API (multiple of each api call and/or plausible call sequence) */ -/****************************************************************************/ - -#if defined(__SELFTEST__) - -int ZT_control_semantics_test(bool *passed) -{ - // TODO: Each discrete operation should be tested in random order among every other discrete operation for a sustained period - - /* - std::vector<ZT_VirtualNetworkRoute> *zts_get_network_routes(char *nwid); - int zts_get_id_from_file(const char *filepath, char *devID); - void *zts_start_service(void *thread_id); - void disableTaps(); - void zts_get_address(const char *nwid, struct sockaddr_storage *addr, const size_t addrlen); - int zts_has_address(const char *nwid); - void zts_get_6plane_addr(struct sockaddr_storage *addr, const char *nwid, const char *devID); - void zts_get_rfc4193_addr(struct sockaddr_storage *addr, const char *nwid, const char *devID); - void zts_join(const uin64_t nwid); - void zts_leave(const uint64_t nwid); - int zts_running(); - int zts_start(const char *path); - int zts_start(const char *path, const char *nwid); - void zts_stop(); - void zts_get_homepath(char *homePath, size_t len); - int zts_get_id(char *devID); - unsigned long zts_get_peer_count(); - int zts_get_peer_address(char *peer, const char *devID); - */ - - //int n_times = 5; - char *nwid = (char*)"17d709436c2c5367"; - char *path = (char*)"fake_path"; -/* - // Perform operations on ZeroTier before calling zts_start(). Doing this makes absolutely no sense but could happen - zts_stop(); - zts_join(nwid); - zts_leave(nwid); - - DEBUG_TEST("---\n"); - sleep(1); - - // Perform operations on ZeroTier immediately upon startup, try to catch it with its pants down - // Ideally, the service wrapper should perform necessary checks to prevent any sort of issue - zts_start(path); - zts_join(nwid); - zts_leave(nwid); - zts_stop(); - - DEBUG_TEST("---\n"); - sleep(1); -*/ - zts_start(path, false); - zts_join(strtoull(nwid,NULL,16)); - zts_leave(strtoull(nwid,NULL,16)); - zts_stop(); - - DEBUG_TEST("---\n"); - sleep(1); -/* - // start the ZeroTier service many times - for (int i=0; i<n_times; i++) { zts_start(path); } - - // join the same network many times - for (int i=0; i<n_times; i++) { zts_join(nwid); } - - // leave the same network many times - for (int i=0; i<n_times; i++) { zts_leave(nwid); } - - // stop the ZeroTier service many times - for (int i=0; i<n_times; i++) { zts_stop(); } -*/ - DEBUG_TEST("---\n"); - *passed = true; - return 0; -} - -#define SLAM_NUMBER 16 -#define SLAM_REPEAT 1 - -/* -int slam_api_test() -{ - int err = 0; - int results[SLAM_NUMBER*SLAM_REPEAT]; - - struct hostent *server; - struct sockaddr_in6 addr6; - struct sockaddr_in addr; - - // int start_stack_timer_cnt = pico_ntimers(); // number of picoTCP timers allocated - - // TESTS: - // _SOCKET() - // close() - if (false) - { - // open and close SLAM_NUMBER*SLAM_REPEAT sockets - for (int j=0; j<SLAM_REPEAT; j++) { - std::cout << "slamming " << j << " time(s)" << std::endl; - micro_sleep(SLAM_INTERVAL); - // create sockets - int fds[SLAM_NUMBER]; - for (int i = 0; i<SLAM_NUMBER; i++) { - if ((err = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - std::cout << "error creating socket (errno = " << strerror(errno) << ")" << std::endl; - if (errno == EMFILE) - break; - else - return -1; - } - else - fds[i] = err; - std::cout << "\tcreating " << i << " _SOCKET(s) fd = " << err << std::endl; - - } - // close sockets - for (int i = 0; i<SLAM_NUMBER; i++) { - //std::cout << "\tclosing " << i << " _SOCKET(s)" << std::endl; - if ((err = _CLOSE(fds[i])) < 0) { - std::cout << "error closing socket (errno = " << strerror(errno) << ")" << std::endl; - //return -1; - } - else - fds[i] = -1; - } - } - //if (zts_num_active_virt_sockets() == 0) - // std::cout << "TEST_PASSED [slam open and close]" << std::endl; - //else - // std::cout << "TEST_FAILED [slam open and close] - sockets left unclosed" << std::endl; - } - - // --- - - // TESTS: - // _SOCKET() - // bind() - // listen() - // accept() - // close() - if (false) - { - int sock = 0; - std::vector<int> used_ports; - - for (int j=0; j<SLAM_REPEAT; j++) { - std::cout << "slamming " << j << " time(s)" << std::endl; - micro_sleep(SLAM_INTERVAL); - - for (int i = 0; i<SLAM_NUMBER; i++) { - if ((sock = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - std::cout << "error creating socket (errno = " << strerror(errno) << ")" << std::endl; - if (errno == EMFILE) - break; - else - return -1; - } - std::cout << "_SOCKET() = " << sock << std::endl; - micro_sleep(SLAM_INTERVAL); - - int port; - while ((std::find(used_ports.begin(),used_ports.end(),port) == used_ports.end()) == false) { - port = MIN_PORT + (rand() % (int)(MAX_PORT - MIN_PORT + 1)); - } - used_ports.push_back(port); - std::cout << "port = " << port << std::endl; - - if (false) { - server = gethostbyname2("::",AF_INET6); - memset((char *) &addr6, 0, sizeof(addr6)); - addr6.sin6_flowinfo = 0; - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(port); - addr6.sin6_addr = in6addr_any; - err = _BIND(sock, (struct sockaddr *)&addr6, (socklen_t)(sizeof addr6)); - } - - if (true) { - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr("10.9.9.50"); - //addr.sin_addr.s_addr = htons(INADDR_ANY); - addr.sin_family = AF_INET; - err = _BIND(sock, (struct sockaddr *)&addr, (socklen_t)(sizeof addr)); - } - if (err < 0) { - std::cout << "error binding socket (errno = " << strerror(errno) << ")" << std::endl; - return -1; - } - - if (sock > 0) { - if ((err = _CLOSE(sock)) < 0) { - std::cout << "error closing socket (errno = " << strerror(errno) << ")" << std::endl; - //return -1; - } - } - } - } - used_ports.clear(); - //if (zts_num_active_virt_sockets() == 0) - // std::cout << "TEST_PASSED [slam open, bind, listen, accept, close]" << std::endl; - //else - // std::cout << "TEST_FAILED [slam open, bind, listen, accept, close]" << std::endl; - } - - // TESTS: - // (1) _SOCKET() - // (2) connect() - // (3) close() - int num_times = 3;//zts_maxsockets(SOCK_STREAM); - std::cout << "socket/connect/close - " << num_times << " times" << std::endl; - for (int i=0;i<(SLAM_NUMBER*SLAM_REPEAT); i++) { results[i] = 0; } - if (true) - { - int port = 4545; - - // open, bind, listen, accept, close - for (int j=0; j<num_times; j++) { - int sock = 0; - errno = 0; - - micro_sleep(SLAM_INTERVAL); - - // _SOCKET() - printf("creating socket... (%d)\n", j); - if ((sock = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) - std::cout << "error creating socket (errno = " << strerror(errno) << ")" << std::endl; - results[j] = std::min(results[j], sock); - - SetSocketBlockingEnabled(sock, true); - results[j] = std::min(results[j], err); - - // connect() - if (false) { - server = gethostbyname2("::",AF_INET6); - memset((char *) &addr6, 0, sizeof(addr6)); - addr6.sin6_flowinfo = 0; - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(port); - addr6.sin6_addr = in6addr_any; - err = _CONNECT(sock, (struct sockaddr *)&addr6, (socklen_t)(sizeof addr6)); - } - if (true) { - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr("10.9.9.51"); - //addr.sin_addr.s_addr = htons(INADDR_ANY); - addr.sin_family = AF_INET; - err = _CONNECT(sock, (struct sockaddr *)&addr, (socklen_t)(sizeof addr)); - } - - if (errno != EINPROGRESS) { // acceptable error for non-block mode - if (err < 0) - std::cout << "error connecting socket (errno = " << strerror(errno) << ")" << std::endl; - results[j] = std::min(results[j], err); - } - - // close() - if ((err = _CLOSE(sock)) < 0) - std::cout << "error closing socket (errno = " << strerror(errno) << ")" << std::endl; - results[j] = std::min(results[j], err); - } - - displayResults(results, num_times); - //if (zts_num_active_virt_sockets() == 0) - // std::cout << "TEST_PASSED [slam open, connect, close]" << std::endl; - //else - // std::cout << "TEST_FAILED [slam open, connect, close]" << std::endl; - } - return 0; -} -*/ - -/* -void get_network_routes(char *nwid) -{ - // Retreive managed routes for a given ZeroTier network - std::vector<ZT_VirtualNetworkRoute> *routes = zts_get_network_routes(nwid); - - for (int i=0; i<routes->size(); i++) { - struct sockaddr_in *target = (struct sockaddr_in*)&(routes->at(i).target); - struct sockaddr_in *via = (struct sockaddr_in*)&(routes->at(i).via); - char target_str[INET6_ADDRSTRLEN]; - memset(target_str, 0, INET6_ADDRSTRLEN); - inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)target)->sin_addr.s_addr, target_str, INET_ADDRSTRLEN); - char via_str[INET6_ADDRSTRLEN]; - memset(via_str, 0, INET6_ADDRSTRLEN); - inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)via)->sin_addr.s_addr, via_str, INET_ADDRSTRLEN); - DEBUG_TEST("<target=%s, via=%s, flags=%d>", target_str, via_str, routes->at(i).flags); - } -} -*/ - -/****************************************************************************/ -/* RANDOMIZED API TEST */ -/****************************************************************************/ - -int random_api_test() -{ - // TEST_PASSED implies we didn't segfault or hang anywhere - - // variables which will be populated with random values - /* - int socket_family; - int socket_type; - int protocol; - int fd; - int len; - int addrlen; - int flags; - - struct sockaddr_storage; - struct sockaddr_in addr; - struct sockaddr_in6 addr6; - */ - - /* - int num_operations = 100; - char *opbuf = (char*)malloc(num_operations*sizeof(char)); - generate_random_data(opbuf, num_operations, 0, 9); - for (int i=0; i<num_operations; i++) { - sleep(1); - DEBUG_TEST("[i=%d, op=%d] calling X", i, opbuf[i]); - - // generate set of random arguments - - // addresses - - // buffers - - // buffer lengths - - // flags - - switch(opbuf[i]) - { - case 0: - _SOCKET(); - case 1: - _CONNECT(); - case 2: - _LISTEN(); - case 3: - _BIND(); - case 4: - _ACCEPT(); - case 5: - - } - } - - _SOCKET() - _CONNECT() - _LISTEN() - _ACCEPT() - _BIND() - _GETSOCKOPT() - _SETSOCKOPT() - FNCTL() - _CLOSE() - _SEND() - _RECV() - _SENDTO() - _RECVFROM() - _READ() - _WRITE() - - */ - - return TEST_PASSED; -} - - -/* - For each API call, test the following: - - All possible combinations of plausible system-defined arguments - - Common values in innappropriate locations {-1, 0, 1} - - Check for specific errno values for each function - -*/ - /* -void test_bad_args() -{ -// Protocol Family test set - int proto_families[] = { - AF_UNIX, -#if !defined(_WIN32) - AF_LOCAL, -#endif - AF_INET, - AF_INET6, - AF_IPX, - PF_LOCAL, - PF_UNIX, - PF_INET, - PF_ROUTE, - PF_KEY, - PF_INET6, -#if !defined(__linux__) - PF_SYSTEM, - PF_NDRV, -#endif -#if !defined(__APPLE__) - AF_NETLINK, - AF_X25, - AF_AX25, - AF_ATMPVC, - AF_ALG, - AF_PACKET, -#endif - AF_APPLETALK - }; - int num_proto_families = sizeof(proto_families) / sizeof(int); - -// Socket Type test set - int socket_types[] = { - SOCK_STREAM, - SOCK_DGRAM, - SOCK_RAW - }; - int num_socket_types = 3; - - -// Protocol test set - - // int min = -1; - int max = 2; - int err = 0; - - int min_protocol_family_value = 0; - int max_protocol_family_value = 0; - - int min_socket_type_value = 0; - int max_socket_type_value = 0; - - int min_protocol_value = 0; - int max_protocol_value = 0; - - // _SOCKET() - DEBUG_TEST("testing bad arguments for _SOCKET()"); - - // Try all plausible argument combinations - for (int i=0; i<num_proto_families; i++) { - for (int j=0; j<num_socket_types; j++) { - for (int k=0; k<max; k++) { - - int protocol_family = proto_families[i]; - int socket_type = socket_types[j]; - int protocol = -1; - - min_protocol_family_value = std::min(protocol_family, min_protocol_family_value); - max_protocol_family_value = std::max(protocol_family, max_protocol_family_value); - - min_socket_type_value = std::min(socket_type, min_socket_type_value); - max_socket_type_value = std::max(socket_type, max_socket_type_value); - - min_protocol_value = std::min(protocol, min_protocol_value); - max_protocol_value = std::max(protocol, max_protocol_value); - - err = _SOCKET(protocol_family, socket_type, protocol); - micro_sleep(100000); - if (err < 0) { - DEBUG_ERROR("_SOCKET(%d, %d, %d) = %d, errno=%d (%s)", protocol_family, socket_type, protocol, err, errno, strerror(errno)); - } - else { - DEBUG_TEST("_SOCKET(%d, %d, %d) = %d, errno=%d (%s)", protocol_family, socket_type, protocol, err, errno, strerror(errno)); - } - } - } - } - - DEBUG_TEST("min_protocol_family_value=%d",min_protocol_family_value); - DEBUG_TEST("max_protocol_family_value=%d",max_protocol_family_value); - - DEBUG_TEST("min_socket_type_value=%d",min_socket_type_value); - DEBUG_TEST("max_socket_type_value=%d",max_socket_type_value); - - DEBUG_TEST("min_protocol_value=%d",min_protocol_value); - DEBUG_TEST("max_protocol_value=%d",max_protocol_value); - - DEBUG_TEST("AF_INET = %d", AF_INET); - DEBUG_TEST("AF_INET6 = %d", AF_INET6); - DEBUG_TEST("SOCK_STREAM = %d", SOCK_STREAM); - DEBUG_TEST("SOCK_DGRAM = %d", SOCK_DGRAM); -} -*/ - -void dns_test(struct sockaddr *addr) -{ - fprintf(stderr, "\n\ndns_test\n\n"); - //zts_add_dns_nameserver(addr); - // resolve - //zts_del_dns_nameserver(addr); -} - -void close_while_writing_test() -{ - fprintf(stderr, "\n\nclose_while_writing_test\n\n"); - // TODO: Close a socket while another thread is writing to it or reading from it -} - -/****************************************************************************/ -/* test thread model, and locking */ -/****************************************************************************/ - -/* -#define CONCURRENCY_LEVEL 8 // how many threads we want to test with -#define TIME_GRANULARITY 10000 // multiple in microseconds -#define TIME_MULTIPLIER_MIN 1 // -#define TIME_MULTIPLIER_MAX 10 // -#define WORKER_ITERATIONS 100 // number of times a worker shall do its task -#define MASTER_ITERATIONS 10 // number of times we will create a set of workers - -// for passing info to worker threads -struct fd_addr_pair { - int fd; - struct sockaddr_in *remote_addr; -}; - -pthread_t tid[CONCURRENCY_LEVEL]; - -// over num_iterations, wait a random time, create a socket, wait a random time, and close the socket -void* worker_create__SOCKET(void *arg) -{ - pthread_t id = pthread_self(); - int fd, rs, rc; - // if (pthread_equal(id,tid[0])) { } - for (int i=0; i<WORKER_ITERATIONS; i++) { - rs = rand_in_range(TIME_MULTIPLIER_MIN, TIME_MULTIPLIER_MAX); - rc = rand_in_range(TIME_MULTIPLIER_MIN, TIME_MULTIPLIER_MAX); - //fprintf(stderr, "id=%d, rs = %d, rc = %d\n", id, rs, rc); - micro_sleep(rs * TIME_GRANULARITY); - fd = _SOCKET(AF_INET, SOCK_STREAM, 0); - micro_sleep(rc * TIME_GRANULARITY); - _CLOSE(fd); - } - return NULL; -} - -// test the core locking logic by creating large numbers of threads and performing random operations over an extended period of time - -void multithread_test(int num_iterations, bool *passed) -{ - int err = 0; - fprintf(stderr, "\n\nmultithread_socket_creation\n\n"); - for (int j=0; j<num_iterations; j++) { - fprintf(stderr, "iteration=%d\n", j); - // create threads - for (int i=0; i<CONCURRENCY_LEVEL; i++) { - fprintf(stderr,"creating thread [%d]\n", i); - if ((err = pthread_create(&(tid[i]), NULL, &worker_create_socket, NULL)) < 0) { - fprintf(stderr, "there was a problem while creating thread [%d]\n", i); - *passed = false; - return; - } - } - // join all threads - char *b; - for (int i=0; i<CONCURRENCY_LEVEL; i++) { - if ((err = pthread_join(tid[i],(void**)&b)) < 0) { - fprintf(stderr, "error while joining thread [%d]\n", i); - *passed = false; - return; - } - } - } - *passed = true; -} - -// write a simple string message to a SOCK_DGRAM socket -void* worker_write_to_udp__SOCKET(void *arg) { - fprintf(stderr, "\n\n\nwrite_to_udp_socket\n\n\n"); - struct fd_addr_pair *fdp = (struct fd_addr_pair*)arg; - int fd = fdp->fd; - struct sockaddr_in *remote_addr = fdp->remote_addr; - //fprintf(stderr, "fd=%d\n", fd); - int w = 0; - for (int i=0; i<WORKER_ITERATIONS; i++) { - int r = rand_in_range(TIME_MULTIPLIER_MIN, TIME_MULTIPLIER_MAX); - micro_sleep(r * TIME_GRANULARITY); - if ((w = _SENDTO(fd, "hello", 5, 0, (struct sockaddr *)remote_addr, sizeof(*remote_addr))) < 0) { - DEBUG_ERROR("error sending packet, err=%d", errno); - } - } - return NULL; -} - -// create a single socket and many threads to write to that single socket - -void multithread_udp_write(struct sockaddr_in *local_addr, struct sockaddr_in *remote_addr, bool *passed) -{ - fprintf(stderr, "\n\nmultithread_udp_broadcast\n\n"); - int fd, err; - if((fd = _SOCKET(AF_INET, SOCK_DGRAM, 0)) < 0) { - DEBUG_ERROR("error while creating socket"); - *passed = false; - return; - } - if ((err = _BIND(fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - perror("bind"); - *passed = false; - return; - } - // params to send to new threads - struct fd_addr_pair fdp; - fdp.fd = fd; - fdp.remote_addr = remote_addr; - - for (int i=0; i<CONCURRENCY_LEVEL; i++) { - fprintf(stderr,"creating thread [%d]\n", i); - if ((err = pthread_create(&(tid[i]), NULL, &worker_write_to_udp_socket, (void*)&fdp)) < 0) { - fprintf(stderr, "there was a problem while creating thread [%d]\n", i); - *passed = false; - return; - } - } - // join all threads - char *b; - for (int i=0; i<CONCURRENCY_LEVEL; i++) { - if ((err = pthread_join(tid[i],(void**)&b)) < 0) { - fprintf(stderr, "error while joining thread [%d]\n", i); - *passed = false; - return; - } - } - _CLOSE(fd); -} - -void multithread_rw_server() -{ - fprintf(stderr, "\n\nmultithread_rw_server\n\n"); - // TODO: Test read/writes from multiple threads -} - -void multithread_rw_client() -{ - fprintf(stderr, "\n\nmultithread_rw_client\n\n"); -} - -*/ - -/****************************************************************************/ -/* close() */ -/****************************************************************************/ - -// Tests rapid opening and closure of sockets -void close_test(struct sockaddr *bind_addr) -{ - fprintf(stderr, "\n\nclose_test\n\n"); - // BUG: While running an extended test of unassigned closures, the - // stack may crash at: `pico_check_timers at pico_stack.c:608, this appears - // to be a bad pointer to a timer within the stack. - bool extended = false; - int tries = !extended ? 8 : 1024; - int err = 0; - for (int i=0; i<tries; i++) - { - int fd; - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("error creating socket. sleeping until timers are released"); - sleep(30); - } - if ((err = _BIND(fd, (struct sockaddr *)bind_addr, sizeof(struct sockaddr_in)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); - } - micro_sleep(100000); - if ((err = _CLOSE(fd)) < 0) { - DEBUG_ERROR("error closing socket (%d)", err); - } - DEBUG_TEST("i=%d, close() = %d", i, err); - ((struct sockaddr_in *)bind_addr)->sin_port++; - } -} - -void bind_to_localhost_test(int port) -{ - fprintf(stderr, "\n\nbind_to_localhost_test\n\n"); - int fd, err = 0; - // ipv4, 0.0.0.0 - struct sockaddr_storage bind_addr; - DEBUG_TEST("binding to 0.0.0.0"); - str2addr("0.0.0.0", port, 4, (struct sockaddr *)&bind_addr); - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) > 0) { - if ((err = _BIND(fd, (struct sockaddr *)&bind_addr, sizeof(struct sockaddr_in))) == 0) { - micro_sleep(100000); - if ((err = _CLOSE(fd)) < 0) { - DEBUG_ERROR("error closing socket (%d)", err); - } - } - else{ - DEBUG_ERROR("error binding to interface (%d)", err); - } - } - else { - DEBUG_ERROR("error creating socket (%d)", err); - } - - port++; - - /* - // ipv4, 127.0.0.1 - DEBUG_TEST("binding to 127.0.0.1"); - str2addr("127.0.0.1", port, 4, (struct sockaddr *)&bind_addr); - if ((fd = _SOCKET(AF_INET, SOCK_STREAM, 0)) > 0) { - if ((err = _BIND(fd, (struct sockaddr *)&bind_addr, sizeof(struct sockaddr_in))) == 0) { - micro_sleep(100000); - if ((err = _CLOSE(fd)) < 0) { - DEBUG_ERROR("error closing socket (%d)", err); - } - } - else{ - DEBUG_ERROR("error binding to interface (%d)", err); - } - } - else { - DEBUG_ERROR("error creating socket", err); - } - - port++; - */ - - // ipv6, [::] - DEBUG_TEST("binding to [::]"); - str2addr("::", port, 6, (struct sockaddr *)&bind_addr); - if ((fd = _SOCKET(AF_INET6, SOCK_STREAM, 0)) > 0) { - if ((err = _BIND(fd, (struct sockaddr *)&bind_addr, sizeof(struct sockaddr_in))) == 0) { - micro_sleep(100000); - if ((err = _CLOSE(fd)) < 0) { - DEBUG_ERROR("error closing socket (%d)", err); - } - } - else{ - DEBUG_ERROR("error binding to interface (%d)", err); - } - } - else { - DEBUG_ERROR("error creating socket (%d)", err); - } -} - -#endif // __SELFTEST__ - -int trigger_address_sanitizer() -{ - // Deliberately create a bad read to trigger address sanitizer - /* - int stack_array[100]; - stack_array[1] = 0; - return stack_array[1 + 100]; // BOOM - */ - return 0; -} - -/****************************************************************************/ -/* main(), calls test_driver(...) */ -/****************************************************************************/ - -int main(int argc , char *argv[]) -{ -#if defined(__SELFTEST__) - if (argc == 4) { - DEBUG_TEST("generating id..."); - if (!strcmp(argv[1],"generate_id")) - { - DEBUG_TEST("generating ZeroTier identity for testing purposes..."); - if (strlen(argv[2]) <= 0) { - DEBUG_ERROR("invalid <nwid> was given"); - exit(-1); - } - if (strlen(argv[3]) <= 0) { - DEBUG_ERROR("invalid pathname was given"); - exit(-1); - } - uint64_t nwid = strtoull(argv[2],NULL,16); - uint64_t nodeId = zts_get_node_id(); - - zts_start(argv[3], true); - zts_join(nwid); - sleep(2); - DEBUG_TEST("generated id: %llx", (unsigned long long)nodeId); - exit(0); - } - } - -#endif // __SELFTEST__ - - if (argc < 6) { - fprintf(stderr, "usage: selftest <num_repeats> <selftest.conf> <alice|bob|ted|carol> to <bob|alice|ted|carol>\n"); - fprintf(stderr, "usage: selftest generate_id <nwid> <alice|bob...>\n"); - fprintf(stderr, "e.g. : selftest 3 test/test.conf alice to bob\n"); - return 1; - } - int num_repeats = atoi(argv[1]); - std::string path = argv[2]; - std::string from = argv[3]; - std::string to = argv[5]; - std::string me = from; - std::vector<std::string> results; - std::string remote_echo_ipv4, smode; - - std::string nwidstr, stype; - std::string ipstr, ipstr6, local_ipstr, local_ipstr6, remote_ipstr, remote_ipstr6; - - int err = 0; - int mode = 0; - int port = 0; - int op = 0; - int start_port = 0; - int cnt = 0; - int ipv; - // for timing - // how long we expect the specific test to take - int subtest_expected_duration; - // (T+X), when we plan to start this test - int subtest_start_time_offset = 0; - - char details[128]; - memset(&details, 0, sizeof details); - bool passed = 0; - struct sockaddr_storage local_addr; - struct sockaddr_storage remote_addr; - - // load config file - if (path.find(".conf") == std::string::npos) { - fprintf(stderr, "Possibly invalid conf file. Exiting...\n"); - exit(0); - } - loadTestConfigFile(path); - // get origin details - local_ipstr = testConf[me + ".ipv4"]; - local_ipstr6 = testConf[me + ".ipv6"]; - nwidstr = testConf[me + ".nwid"]; - path = testConf[me + ".path"]; - stype = testConf[me + ".test"]; - smode = testConf[me + ".mode"]; - start_port = atoi(testConf[me + ".port"].c_str()); - remote_echo_ipv4 = testConf[to + ".echo_ipv4"]; - remote_ipstr = testConf[to + ".ipv4"]; - remote_ipstr6 = testConf[to + ".ipv6"]; - - if (strcmp(smode.c_str(), "server") == 0) - mode = TEST_MODE_SERVER; - else - mode = TEST_MODE_CLIENT; - - fprintf(stderr, "\n\nORIGIN:\n\n"); - fprintf(stderr, "\tlocal_ipstr = %s\n", local_ipstr.c_str()); - fprintf(stderr, "\tlocal_ipstr6 = %s\n", local_ipstr6.c_str()); - fprintf(stderr, "\tstart_port = %d\n", start_port); - fprintf(stderr, "\tpath = %s\n", path.c_str()); - fprintf(stderr, "\tnwid = %s\n", nwidstr.c_str()); - fprintf(stderr, "\ttype = %s\n\n", stype.c_str()); - fprintf(stderr, "DESTINATION:\n\n"); - fprintf(stderr, "\tremote_ipstr = %s\n", remote_ipstr.c_str()); - fprintf(stderr, "\tremote_ipstr6 = %s\n", remote_ipstr6.c_str()); - fprintf(stderr, "\tremote_echo_ipv4 = %s\n", remote_echo_ipv4.c_str()); - -#if defined(__SELFTEST__) - if (me != "dummy") { // used for testing ZT service wrapper API (before, during, and after coming online) - // set start time here since we need to wait for both libzt instances to be online - DEBUG_TEST("app-thread, waiting for libzt to come online...\n"); - uint64_t nwid = strtoull(nwidstr.c_str(),NULL,16); - int portno = LIBZT_DEFAULT_PORT; - if (zts_set_service_port(portno) < 0) { - DEBUG_TEST("error, invalid zt service port number: %d", portno); - exit(0); - } - zts_startjoin(path.c_str(), nwid); - uint64_t nodeId = zts_get_node_id(); - DEBUG_TEST("I am %llx, %s", (unsigned long long)nodeId, me.c_str()); - if (mode == TEST_MODE_SERVER) { - DEBUG_TEST("Ready. You should start selftest program on second host now...\n\n"); - } - if (mode == TEST_MODE_CLIENT) { - DEBUG_TEST("Ready. Contacting selftest program on first host.\n\n"); - } - } - - // SYNCHRONIZE test start times between multiple instances of the selftest on the network - ipv = 4; - int negotiation_port = start_port + 1000; - port = negotiation_port; - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_everyone_is_ready((struct sockaddr *)&local_addr, (struct sockaddr *)&remote_addr, start_port); - DEBUG_TEST("both instances of selftest have started. beginning tests..."); - - long int selftest_start_time = get_now_ts(); - subtest_expected_duration = 5; -#endif // __SELFTEST__ - -for (int i=0; i<num_repeats; i++) -{ - DEBUG_TEST("\n\n\n --- COMPREHENSIVE TEST ITERATION: %d out of %d ---\n\n\n", i, num_repeats); - -#if defined(__SELFTEST__) - if (false) { - port = 1000; - // closure test - struct sockaddr_in in4; - DEBUG_TEST("testing closures by binding to: %s", local_ipstr.c_str()); - str2addr(local_ipstr, port, 4, (struct sockaddr *)&in4); - close_test((struct sockaddr*)&in4); - port++; - } - - // Test adding, resolving, and removing a DNS server - - // ipv = 4; - // str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - // dns_test((struct sockaddr *)&remote_addr); - - // close_while_writing_test(); - - // localhost bind test - - // bind_to_localhost_test(port); - - // Transmission Tests - - // RANDOM API TEST - //random_api_test(); - - // SLAM API TEST - //slam_api_test(); - - // BAD ARGS API TEST - //test_bad_args(); - - // OBSCURE API TEST - if (false) { - obscure_api_test(&passed); - } - // Test things like zts_start(), zts_stop(), zts_join(), etc - if (false) { - ZT_control_semantics_test(&passed); - exit(0); - } - // Spam a SOCK_DGRAM socket from many threads - /* - if (false) { - ipv = 4; - port = start_port; - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - multithread_udp_write((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, &passed); - } - // test thread safety - if (false) { - multithread_test(10, &passed); - } - */ - // make sure the address sanitizer is available - if (false) { - trigger_address_sanitizer(); - } - -#endif // __SELFTEST__ - - port = start_port+(100*i); // arbitrary - cnt = 64; - op = TEST_OP_N_BYTES; - - // set start time here since we aren't waiting for libzt to come online in NATIVETEST mode -#if defined(__NATIVETEST__) - long int selftest_start_time = get_now_ts(); - subtest_expected_duration = 20; // initial value, wait for other instance to come online -#endif - - // UDP 4 client/server - - ipv = 4; - subtest_start_time_offset += subtest_expected_duration; - subtest_expected_duration = 30; - - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - udp_server_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - udp_client_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles - port++; // move up one port - subtest_start_time_offset+=subtest_expected_duration; - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - udp_server_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - udp_client_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - port++; - - // UDP 4 sustained transfer - - ipv = 4; - subtest_start_time_offset+=subtest_expected_duration; - subtest_expected_duration = 30; - - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - udp_server_sustained_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - udp_client_sustained_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles - port++; // move up one port - subtest_start_time_offset+=subtest_expected_duration; - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - udp_server_sustained_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - udp_client_sustained_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - port++; - - // TCP 4 client/server (POLL/_SELECT TEST) - - ipv = 4; - subtest_start_time_offset+=subtest_expected_duration; - subtest_expected_duration = 30; - - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - tcp_select_server((struct sockaddr_in *)&local_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - tcp_select_client((struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles - port++; // move up one port - subtest_start_time_offset+=subtest_expected_duration; - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - tcp_select_server((struct sockaddr_in *)&local_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - tcp_select_client((struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - port++; - - // TCP 4 client/server - - ipv = 4; - subtest_start_time_offset+=subtest_expected_duration; - subtest_expected_duration = 30; - - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - tcp_server_4((struct sockaddr_in *)&local_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - tcp_client_4((struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles - port++; // move up one port - subtest_start_time_offset+=subtest_expected_duration; - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - tcp_server_4((struct sockaddr_in *)&local_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - tcp_client_4((struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - port++; - - // TCP 4 sustained transfer - - ipv = 4; - subtest_start_time_offset+=subtest_expected_duration; - subtest_expected_duration = 30; - - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - tcp_server_sustained_4((struct sockaddr_in *)&local_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - tcp_client_sustained_4((struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles - port++; - subtest_start_time_offset+=subtest_expected_duration; - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - tcp_server_sustained_4((struct sockaddr_in *)&local_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - tcp_client_sustained_4((struct sockaddr_in *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - port++; - -// IPV6 - - // UDP 6 client/server - - ipv = 6; - subtest_start_time_offset+=subtest_expected_duration; - subtest_expected_duration = 30; - - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr*)&local_addr); - str2addr(remote_ipstr6, port, ipv, (struct sockaddr*)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - udp_server_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - udp_client_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles - port++; // move up one port - subtest_start_time_offset+=subtest_expected_duration; - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - udp_server_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - udp_client_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - port++; - - // UDP 6 sustained transfer - - ipv = 6; - subtest_start_time_offset+=subtest_expected_duration; - subtest_expected_duration = 30; - - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - udp_server_sustained_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - udp_client_sustained_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles - port++; // move up one port - subtest_start_time_offset+=subtest_expected_duration; - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - udp_server_sustained_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - udp_client_sustained_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - port++; - - // TCP 6 client/server - - ipv = 6; - subtest_start_time_offset+=subtest_expected_duration; - subtest_expected_duration = 30; - - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - tcp_server_6((struct sockaddr_in6 *)&local_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - DEBUG_TEST("waiting (15s) for other selftest to complete before continuing..."); - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - tcp_client_6((struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles - port++; // move up one port - subtest_start_time_offset+=subtest_expected_duration; - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - tcp_server_6((struct sockaddr_in6 *)&local_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - tcp_client_6((struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - port++; - - // TCP 6 sustained transfer - - ipv = 6; - subtest_start_time_offset+=subtest_expected_duration; - subtest_expected_duration = 30; - - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - tcp_server_sustained_6((struct sockaddr_in6 *)&local_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - tcp_client_sustained_6((struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles - port++; - subtest_start_time_offset+=subtest_expected_duration; - if (mode == TEST_MODE_SERVER) { - str2addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset); - tcp_server_sustained_6((struct sockaddr_in6 *)&local_addr, op, cnt, details, &passed); - } - else if (mode == TEST_MODE_CLIENT) { - str2addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr); - wait_until_tplus_s(selftest_start_time, subtest_start_time_offset+5); - tcp_client_sustained_6((struct sockaddr_in6 *)&remote_addr, op, cnt, details, &passed); - } - RECORD_RESULTS(passed, details, &results); - port++; - - // Print results of all tests - printf("--------------------------------------------------------------------------------\n"); - for (size_t i=0;i<results.size(); i++) { - fprintf(stderr, "%s\n", results[i].c_str()); - } - } - return err; -} diff --git a/test/simple.cpp b/test/simple.cpp deleted file mode 100644 index 323c214..0000000 --- a/test/simple.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include <stdio.h> - -#ifdef _WIN32 -#include <WinSock2.h> -#include <stdint.h> -#include <WS2tcpip.h> -#include <Windows.h> -#else -#include <arpa/inet.h> -#include <string.h> -#include <unistd.h> -#endif - -#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; - } -} - -void delay(int n) -{ -#ifdef _WIN32 - Sleep(n * 1000); -#else - sleep(n); -#endif -} - -int main() -{ - char *str = "welcome to the machine"; - char *remoteIp = "11.7.7.223"; - int remotePort = 8082; - int fd, err = 0; - struct 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; - uint64_t nwid = 0x0123456789abcdef; - zts_start("path", &myZeroTierEventCallback, port); - printf("Waiting for node to come online...\n"); - while (!node_ready) { delay(1); } - printf("joining network...\n"); - zts_join(nwid); - printf("Joined virtual network. Requesting configuration...\n"); - while (!network_ready) { delay(1); } - - printf("I am %llx\n", zts_get_node_id()); - // 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 (%s)\n", remoteIp); - } - if ((err = zts_write(fd, str, strlen(str))) < 0) { - printf("error writing to socket\n"); - } - zts_close(fd); - zts_stop(); - return 0; -} |
