817 lines
25 KiB
C
817 lines
25 KiB
C
/**
|
|
* Selftest. To be run for every commit.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
#include <ZeroTierSockets.h>
|
|
|
|
#pragma GCC diagnostic ignored "-Wunused-value"
|
|
|
|
int random32() {
|
|
const int BITS_PER_RAND = (int)(log2(RAND_MAX/2 + 1) + 1.0);
|
|
int ret = 0;
|
|
for (int i = 0; i < sizeof(int) * CHAR_BIT; i += BITS_PER_RAND) {
|
|
ret <<= BITS_PER_RAND;
|
|
ret |= rand();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint64_t random64() {
|
|
return ((uint64_t)random32() << 32) | random32();
|
|
}
|
|
|
|
int is_online = 0;
|
|
int has_ip4 = 0;
|
|
int has_ip6 = 0;
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Event Handler //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
void on_zts_event(void *msgPtr)
|
|
{
|
|
struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr;
|
|
fprintf(stderr, "event=%d\n", msg->eventCode);
|
|
if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) {
|
|
fprintf(stderr, "ZTS_EVENT_NODE_ONLINE\n");
|
|
is_online = 1;
|
|
}
|
|
if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP4) {
|
|
fprintf(stderr, "ZTS_EVENT_NETWORK_READY_IP4\n");
|
|
has_ip4 = 1;
|
|
}
|
|
if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) {
|
|
fprintf(stderr, "ZTS_EVENT_NETWORK_READY_IP6\n");
|
|
has_ip6 = 1;
|
|
}
|
|
}
|
|
|
|
void api_value_arg_test(
|
|
int8_t i8, int16_t i16, int32_t i32, int64_t i64, void* nullable)
|
|
{
|
|
//fprintf(stderr, "%d, %d, %d, %lld, %p\n", i8, i16, i32, i64, nullable);
|
|
int res = ZTS_ERR_OK;
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Test uninitialized Network Stack API usage //
|
|
//----------------------------------------------------------------------------//
|
|
/*
|
|
res = zts_get_all_stats((struct zts_stats *)nullable);
|
|
assert(("pre-init call to zts_get_all_stats(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_get_protocol_stats(i32, nullable);
|
|
assert(("pre-init call to zts_get_protocol_stats(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
*/
|
|
res = zts_dns_set_server(i8, (const zts_ip_addr *)nullable);
|
|
assert(("pre-init call to zts_add_dns_nameserver(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
const zts_ip_addr *res_ptr = zts_dns_get_server(i8);
|
|
assert(("pre-init call to zts_del_dns_nameserver(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Test uninitialized Node API usage //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
res = zts_stop();
|
|
assert(("pre-init call to zts_stop(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_restart();
|
|
assert(("pre-init call to zts_restart(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_free();
|
|
assert(("pre-init call to zts_free(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_join(i64);
|
|
assert(("pre-init call to zts_join(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_leave(i64);
|
|
assert(("pre-init call to zts_leave(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_orbit(i64,i64);
|
|
assert(("pre-init call to zts_orbit(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_deorbit(i64);
|
|
assert(("pre-init call to zts_deorbit(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Test uninitialized Socket API usage //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
res = zts_socket(i32,i32,i32);
|
|
assert(("pre-init call to zts_socket(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_connect(i32, (const struct zts_sockaddr *)nullable, i32);
|
|
assert(("pre-init call to zts_connect(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_bind(i32, (const struct zts_sockaddr *)nullable, i32);
|
|
assert(("pre-init call to zts_bind(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_listen(i32, i32);
|
|
assert(("pre-init call to zts_listen(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_accept(i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
|
assert(("pre-init call to zts_accept(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_setsockopt(i32, i32, i32, nullable, i32);
|
|
assert(("pre-init call to zts_setsockopt(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_getsockopt(i32, i32, i32, nullable, (zts_socklen_t *)nullable);
|
|
assert(("pre-init call to zts_getsockopt(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_getsockname(i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
|
assert(("pre-init call to zts_getsockname(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_getpeername(i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
|
assert(("pre-init call to zts_getpeername(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_close(i32);
|
|
assert(("pre-init call to zts_close(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_select(i32, (zts_fd_set *)nullable, (zts_fd_set *)nullable, (zts_fd_set *)nullable, (struct zts_timeval *)nullable);
|
|
assert(("pre-init call to zts_select(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_fcntl(i32, i32, i32);
|
|
assert(("pre-init call to zts_fcntl(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_poll((struct zts_pollfd *)nullable, i32, i32);
|
|
assert(("pre-init call to zts_poll(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_ioctl(i32, i64, nullable);
|
|
assert(("pre-init call to zts_ioctl(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_send(i32, nullable, i32, i32);
|
|
assert(("pre-init call to zts_send(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_sendto(i32, nullable, i32, i32, (const struct zts_sockaddr *)nullable, i32);
|
|
assert(("pre-init call to zts_sendto(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_sendmsg(i32, (const struct zts_msghdr *)nullable, i32);
|
|
assert(("pre-init call to zts_sendmsg(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_recv(i32, nullable, i32, i32);
|
|
assert(("pre-init call to zts_recv(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_recvfrom(i32, nullable, i32, i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
|
assert(("pre-init call to zts_recvfrom(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_recvmsg(i32, (struct zts_msghdr *)nullable, i32);
|
|
assert(("pre-init call to zts_recvmsg(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_read(i32, nullable, i32);
|
|
assert(("pre-init call to zts_read(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_readv(i32, (const struct zts_iovec *)nullable, i32);
|
|
assert(("pre-init call to zts_readv(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_write(i32, nullable, i32);
|
|
assert(("pre-init call to zts_write(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_writev(i32, (const struct zts_iovec *)nullable, i32);
|
|
assert(("pre-init call to zts_writev(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
res = zts_shutdown(i32, i32);
|
|
assert(("pre-init call to zts_shutdown(): res != ZTS_ERR_SERVICE",
|
|
res == ZTS_ERR_SERVICE));
|
|
}
|
|
|
|
void test_pre_service()
|
|
{
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Test service-related API functions before initializing service //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
// Test null values
|
|
api_value_arg_test(0,0,0,0,NULL);
|
|
|
|
// Test wild values
|
|
for (int i=0; i<4096; i++) {
|
|
int8_t i8 = (uint8_t)random64();
|
|
int16_t i16 = (uint16_t)random64();
|
|
int32_t i32 = (uint32_t)random64();
|
|
int64_t i64 = (uint64_t)random64();
|
|
int x;
|
|
void* nullable = &x;
|
|
api_value_arg_test(i8,i16,i32,i64,nullable);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Test non-service helper functions //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
// (B) Test zts_inet_ntop
|
|
|
|
char ipstr[ZTS_INET6_ADDRSTRLEN];
|
|
int16_t port = 0;
|
|
struct zts_sockaddr_in in4;
|
|
|
|
in4.sin_port = htons(8080);
|
|
#if defined(_WIN32)
|
|
zts_inet_pton(ZTS_AF_INET, "192.168.22.1", &(in4.sin_addr.S_addr));
|
|
#else
|
|
zts_inet_pton(ZTS_AF_INET, "192.168.22.1", &(in4.sin_addr.s_addr));
|
|
#endif
|
|
|
|
in4.sin_family = ZTS_AF_INET;
|
|
|
|
struct zts_sockaddr *sa = (struct zts_sockaddr *)&in4;
|
|
if (sa->sa_family == ZTS_AF_INET) {
|
|
struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)sa;
|
|
zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr),
|
|
ipstr, ZTS_INET_ADDRSTRLEN);
|
|
port = ntohs(in4->sin_port);
|
|
}
|
|
if (sa->sa_family == ZTS_AF_INET6) {
|
|
struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)sa;
|
|
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr),
|
|
ipstr, ZTS_INET6_ADDRSTRLEN);
|
|
}
|
|
|
|
assert(("zts_inet_ntop(): port != 8080", port == 8080));
|
|
assert(("zts_inet_ntop(): strcmp(ipstr, \"192.168.22.1\") != 0",
|
|
!strcmp(ipstr, "192.168.22.1")));
|
|
|
|
// (C) Test zts_inet_pton
|
|
|
|
uint8_t buf[sizeof(struct zts_in6_addr)];
|
|
char str[ZTS_INET6_ADDRSTRLEN];
|
|
|
|
zts_inet_pton(ZTS_AF_INET, "192.168.22.2", buf);
|
|
zts_inet_ntop(ZTS_AF_INET, buf, str, ZTS_INET6_ADDRSTRLEN);
|
|
assert(("zts_inet_pton(): strcmp(ipstr, \"192.168.22.2\") != 0",
|
|
!strcmp(str, "192.168.22.2")));
|
|
}
|
|
|
|
void test_service()
|
|
{
|
|
int res = ZTS_ERR_OK;
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Test simplified API, proxy for setsockopt/getsockopt/ioctl etc //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
int s4 = zts_socket(ZTS_AF_INET6, ZTS_SOCK_STREAM, 0);
|
|
assert(s4 >= 0);
|
|
|
|
// TCP_NODELAY
|
|
|
|
// Check value before doing anything
|
|
res = zts_get_no_delay(s4);
|
|
assert(res == 0);
|
|
// Turn on
|
|
res = zts_set_no_delay(s4, 1);
|
|
assert(res == ZTS_ERR_OK);
|
|
res = zts_get_no_delay(s4);
|
|
// Should return value instead of error code
|
|
assert(res == 1);
|
|
// Turn off
|
|
res = zts_set_no_delay(s4, 0);
|
|
assert(res == ZTS_ERR_OK);
|
|
res = zts_get_no_delay(s4);
|
|
assert(res == ZTS_ERR_OK);
|
|
assert(res == 0);
|
|
|
|
// SO_LINGER
|
|
|
|
// Check value before doing anything
|
|
res = zts_get_linger_enabled(s4);
|
|
assert(res == 0);
|
|
res = zts_get_linger_value(s4);
|
|
assert(res == 0);
|
|
// Turn on, set to 7 seconds
|
|
res = zts_set_linger(s4, 1, 7);
|
|
res = zts_get_linger_enabled(s4);
|
|
assert(res == 1);
|
|
res = zts_get_linger_value(s4);
|
|
assert(res == 7);
|
|
res = zts_set_linger(s4, 0, 0);
|
|
// Turn off
|
|
res = zts_get_linger_enabled(s4);
|
|
assert(res == 0);
|
|
res = zts_get_linger_value(s4);
|
|
assert(res == 0);
|
|
|
|
// SO_REUSEADDR
|
|
|
|
// Check value before doing anything
|
|
res = zts_get_reuse_addr(s4);
|
|
assert(res == 0);
|
|
// Turn on
|
|
res = zts_set_reuse_addr(s4, 1);
|
|
assert(res == ZTS_ERR_OK);
|
|
res = zts_get_reuse_addr(s4);
|
|
// Should return value instead of error code
|
|
assert(res == 1);
|
|
// Turn off
|
|
res = zts_set_reuse_addr(s4, 0);
|
|
assert(res == ZTS_ERR_OK);
|
|
res = zts_get_reuse_addr(s4);
|
|
assert(res == ZTS_ERR_OK);
|
|
assert(res == 0);
|
|
|
|
// SO_RCVTIMEO
|
|
|
|
// Check value before doing anything
|
|
res = zts_get_recv_timeout(s4);
|
|
assert(res == 0);
|
|
// Set to value
|
|
res = zts_set_recv_timeout(s4, 3, 0);
|
|
res = zts_get_recv_timeout(s4);
|
|
assert(res == 3);
|
|
res = zts_set_recv_timeout(s4, 0, 0);
|
|
// Set to zero
|
|
res = zts_get_recv_timeout(s4);
|
|
assert(res == 0);
|
|
|
|
// SO_SNDTIMEO
|
|
|
|
// Check value before doing anything
|
|
res = zts_get_send_timeout(s4);
|
|
assert(res == 0);
|
|
// Set to value
|
|
res = zts_set_send_timeout(s4, 4, 0);
|
|
res = zts_get_send_timeout(s4);
|
|
assert(res == 4);
|
|
res = zts_set_send_timeout(s4, 0, 0);
|
|
// Set to zero
|
|
res = zts_get_send_timeout(s4);
|
|
assert(res == 0);
|
|
|
|
// SO_SNDBUF
|
|
|
|
// Check value before doing anything
|
|
res = zts_get_send_buf_size(s4);
|
|
assert(res == -1); // Unimplemented as of writing of test
|
|
// Set to 7 seconds
|
|
res = zts_set_send_buf_size(s4, 1024);
|
|
res = zts_get_send_buf_size(s4);
|
|
assert(res == -1); // Unimplemented as of writing of test
|
|
res = zts_set_send_buf_size(s4, 0);
|
|
// Set to zero
|
|
res = zts_get_send_buf_size(s4);
|
|
assert(res == -1); // Unimplemented as of writing of test
|
|
|
|
// SO_RCVBUF
|
|
|
|
// Check value before doing anything
|
|
res = zts_get_recv_buf_size(s4);
|
|
assert(res > 0);
|
|
// Set to value
|
|
res = zts_set_recv_buf_size(s4, 1024);
|
|
res = zts_get_recv_buf_size(s4);
|
|
assert(res == 1024);
|
|
res = zts_set_recv_buf_size(s4, 0);
|
|
// Set to zero
|
|
res = zts_get_recv_buf_size(s4);
|
|
assert(res == 0);
|
|
|
|
// IP_TTL
|
|
|
|
// Check value before doing anything
|
|
res = zts_get_ttl(s4);
|
|
assert(res == 255); // Defaults to max
|
|
// Set to value
|
|
res = zts_set_ttl(s4, 128);
|
|
res = zts_get_ttl(s4);
|
|
assert(res == 128);
|
|
res = zts_set_ttl(s4, 0);
|
|
// Set to zero
|
|
res = zts_get_ttl(s4);
|
|
assert(res == 0);
|
|
|
|
// O_NONBLOCK
|
|
|
|
// Check value before doing anything
|
|
res = zts_get_blocking(s4);
|
|
assert(res == 1);
|
|
// Turn off (non-blocking)
|
|
res = zts_set_blocking(s4, 0);
|
|
assert(res == ZTS_ERR_OK);
|
|
res = zts_get_blocking(s4);
|
|
// Should return value instead of error code
|
|
assert(res == 0);
|
|
// Turn off
|
|
res = zts_set_blocking(s4, 1);
|
|
assert(res == ZTS_ERR_OK);
|
|
res = zts_get_blocking(s4);
|
|
assert(res == 1);
|
|
|
|
// SO_KEEPALIVE
|
|
|
|
// Check value before doing anything
|
|
res = zts_get_keepalive(s4);
|
|
assert(res == 0);
|
|
// Turn on
|
|
res = zts_set_keepalive(s4, 1);
|
|
assert(res == ZTS_ERR_OK);
|
|
res = zts_get_keepalive(s4);
|
|
// Should return value instead of error code
|
|
assert(res == 1);
|
|
// Turn off
|
|
res = zts_set_keepalive(s4, 0);
|
|
assert(res == ZTS_ERR_OK);
|
|
res = zts_get_keepalive(s4);
|
|
assert(res == ZTS_ERR_OK);
|
|
assert(res == 0);
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Test *_easy API //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
//zts_connect_easy(0, ZTS_AF_INET, "192.168.7.9", 7878);
|
|
//zts_connect_easy(0, ZTS_AF_INET6, "FCC5:205E:4FF5:5311:DFF0::1", 7878);
|
|
//res = zts_bind_easy(0, ZTS_AF_INET6, "::", 8080);
|
|
//fprintf(stderr, "res=%d, zts_errno=%d\n", res, zts_errno);
|
|
//zts_delay_ms(60000);
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Test DNS client functionality //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
/*
|
|
// Set first nameserver
|
|
|
|
char *ns1_addr_str = "FCC5:205E:4FF5:5311:DFF0::1";
|
|
zts_ip_addr ns1;
|
|
zts_ipaddr_aton(ns1_addr_str, &ns1);
|
|
zts_dns_set_server(0, &ns1);
|
|
|
|
// Get first nameserver
|
|
|
|
const zts_ip_addr *ns1_result;
|
|
ns1_result = zts_dns_get_server(0);
|
|
printf("dns1 = %s\n", zts_ipaddr_ntoa(ns1_result));
|
|
|
|
// Set second nameserver
|
|
|
|
char *ns2_addr_str = "192.168.22.1";
|
|
zts_ip_addr ns2;
|
|
zts_ipaddr_aton(ns2_addr_str, &ns2);
|
|
zts_dns_set_server(1, &ns2);
|
|
|
|
// Get second nameserver
|
|
|
|
const zts_ip_addr *ns2_result;
|
|
ns2_result = zts_dns_get_server(1);
|
|
printf("dns1 = %s\n", zts_ipaddr_ntoa(ns2_result));
|
|
|
|
// Check that each nameserver address was properly set and get
|
|
|
|
assert(("zts_dns_get_server(): Address mismatch", !strcmp(ns1_addr_str, zts_ipaddr_ntoa(ns1_result))));
|
|
assert(("zts_dns_get_server(): Address mismatch", !strcmp(ns2_addr_str, zts_ipaddr_ntoa(ns2_result))));
|
|
*/
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Test shutting down the service //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
zts_stop();
|
|
s4 = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
|
assert(("s4 != ZTS_ERR_SERVICE, not shut down", s4 == ZTS_ERR_SERVICE));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Server //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
#define MAX_CONNECT_TIME 60
|
|
#define BUFLEN 128
|
|
char *msg = "welcome to the machine";
|
|
|
|
void start_server_app(uint16_t port4, uint16_t port6)
|
|
{
|
|
int err = ZTS_ERR_OK;
|
|
int bytes_read = 0;
|
|
int bytes_sent = 0;
|
|
|
|
int msglen = strlen(msg);
|
|
char dstbuf[BUFLEN];
|
|
int buflen = BUFLEN;
|
|
|
|
struct timespec start, now;
|
|
int time_diff = 0;
|
|
|
|
//
|
|
// IPv4 test
|
|
//
|
|
|
|
fprintf(stderr, "server4: will listen on: 0.0.0.0:%d\n", port4);
|
|
int s4 = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
|
assert(s4 == 0 && zts_errno == 0);
|
|
|
|
err = zts_bind_easy(s4, ZTS_AF_INET, "0.0.0.0", port4);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
err = zts_listen(s4, 1);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
struct zts_sockaddr_in in4;
|
|
zts_socklen_t addrlen4 = sizeof(in4);
|
|
|
|
int acc4 = -1;
|
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
|
do {
|
|
fprintf(stderr, "server4: accepting...\n");
|
|
acc4 = zts_accept(s4, &in4, &addrlen4);
|
|
zts_delay_ms(250);
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
time_diff = (now.tv_sec - start.tv_sec);
|
|
} while (err < 0 && time_diff < MAX_CONNECT_TIME);
|
|
|
|
assert(acc4 == 1 && zts_errno == 0);
|
|
|
|
// Read message
|
|
memset(dstbuf, 0, buflen);
|
|
bytes_read = zts_read(acc4, dstbuf, buflen);
|
|
fprintf(stderr, "server4: read (%d) bytes\n", bytes_read);
|
|
assert(bytes_read == msglen && zts_errno == 0);
|
|
|
|
// Send message
|
|
bytes_sent = zts_write(acc4, msg, msglen);
|
|
fprintf(stderr, "server4: wrote (%d) bytes\n", bytes_sent);
|
|
assert(bytes_sent == msglen && zts_errno == 0);
|
|
|
|
zts_close(s4);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
zts_close(acc4);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
//
|
|
// IPv6 test
|
|
//
|
|
|
|
fprintf(stderr, "server: will listen on: [::]:%d\n", port6);
|
|
int s6 = zts_socket(ZTS_AF_INET6, ZTS_SOCK_STREAM, 0);
|
|
assert(s6 == 0 && zts_errno == 0);
|
|
|
|
err = zts_bind_easy(s6, ZTS_AF_INET6, "::", port6);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
err = zts_listen(s6, 1);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
struct zts_sockaddr_in6 in6;
|
|
zts_socklen_t addrlen6 = sizeof(in6);
|
|
|
|
int acc6 = -1;
|
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
|
do {
|
|
fprintf(stderr, "server6: accepting...\n");
|
|
acc6 = zts_accept(s6, &in6, &addrlen6);
|
|
zts_delay_ms(250);
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
time_diff = (now.tv_sec - start.tv_sec);
|
|
} while (err < 0 && time_diff < MAX_CONNECT_TIME);
|
|
|
|
fprintf(stderr, "server6: accepted connection (fd=%d)\n", acc6);
|
|
assert(acc6 == 1 && zts_errno == 0);
|
|
|
|
// Read message
|
|
memset(dstbuf, 0, buflen);
|
|
bytes_read = zts_read(acc6, dstbuf, buflen);
|
|
fprintf(stderr, "server6: read (%d) bytes\n", bytes_read);
|
|
assert(bytes_read == msglen && zts_errno == 0);
|
|
|
|
// Send message
|
|
bytes_sent = zts_write(acc6, msg, msglen);
|
|
fprintf(stderr, "server6: wrote (%d) bytes\n", bytes_sent);
|
|
assert(bytes_sent == msglen && zts_errno == 0);
|
|
|
|
zts_close(s6);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
zts_close(acc6);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
zts_stop();
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
int s = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
|
assert(("s != ZTS_ERR_SERVICE, not shut down", s == ZTS_ERR_SERVICE));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Client //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
void start_client_app(char *ip4, uint16_t port4, char *ip6, uint16_t port6)
|
|
{
|
|
int err = ZTS_ERR_OK;
|
|
int bytes_read = 0;
|
|
int bytes_sent = 0;
|
|
|
|
int msglen = strlen(msg);
|
|
char dstbuf[BUFLEN];
|
|
int buflen = BUFLEN;
|
|
|
|
struct timespec start, now;
|
|
int time_diff = 0;
|
|
|
|
//
|
|
// IPv4 test
|
|
//
|
|
|
|
err = ZTS_ERR_OK;
|
|
int s4 = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
zts_set_blocking(s4, 1);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
|
do {
|
|
fprintf(stderr, "client4: connecting to: %s:%d\n", ip4, port4);
|
|
err = zts_connect_easy(s4, ZTS_AF_INET, ip4, port4);
|
|
zts_delay_ms(500);
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
time_diff = (now.tv_sec - start.tv_sec);
|
|
} while (err < 0 && time_diff < MAX_CONNECT_TIME);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
fprintf(stderr, "client4: connected\n");
|
|
// Send message
|
|
bytes_sent = zts_write(s4, msg, msglen);
|
|
fprintf(stderr, "client4: wrote (%d) bytes\n", bytes_sent);
|
|
assert(bytes_sent == msglen && zts_errno == 0);
|
|
|
|
// Read message
|
|
memset(dstbuf, 0, buflen);
|
|
bytes_read = zts_read(s4, dstbuf, buflen);
|
|
assert(bytes_read == msglen && zts_errno == 0);
|
|
|
|
fprintf(stderr, "client4: read (%d) bytes\n", bytes_read);
|
|
assert(bytes_sent == bytes_read && zts_errno == 0);
|
|
|
|
zts_close(s4);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
//
|
|
// IPv6 test
|
|
//
|
|
|
|
err = ZTS_ERR_OK;
|
|
int s6 = zts_socket(ZTS_AF_INET6, ZTS_SOCK_STREAM, 0);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
zts_set_blocking(s6, 1);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
|
do {
|
|
fprintf(stderr, "client6: connecting to: %s:%d\n", ip6, port6);
|
|
err = zts_connect_easy(s6, ZTS_AF_INET6, ip6, port6);
|
|
zts_delay_ms(500);
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
time_diff = (now.tv_sec - start.tv_sec);
|
|
} while (err < 0 && time_diff < MAX_CONNECT_TIME);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
fprintf(stderr, "client6: connected\n");
|
|
// Send message
|
|
bytes_sent = zts_write(s6, msg, msglen);
|
|
fprintf(stderr, "client6: wrote (%d) bytes\n", bytes_sent);
|
|
assert(bytes_sent == msglen && zts_errno == 0);
|
|
|
|
// Read message
|
|
memset(dstbuf, 0, buflen);
|
|
bytes_read = zts_read(s6, dstbuf, buflen);
|
|
assert(bytes_read == msglen && zts_errno == 0);
|
|
|
|
fprintf(stderr, "client6: read (%d) bytes\n", bytes_read);
|
|
assert(bytes_sent == bytes_read && zts_errno == 0);
|
|
|
|
zts_close(s6);
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
|
|
zts_stop();
|
|
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
|
int s = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
|
assert(("s != ZTS_ERR_SERVICE, not shut down", s == ZTS_ERR_SERVICE));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Start node //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
void start_node(char *path, uint64_t nwid)
|
|
{
|
|
struct timespec start, now;
|
|
int time_diff = 0;
|
|
|
|
fprintf(stderr, "starting node...\n");
|
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
|
int res = zts_start(path, &on_zts_event, 0);
|
|
assert(("error starting service: res != ZTS_ERR_OK", res == ZTS_ERR_OK));
|
|
do {
|
|
zts_delay_ms(25);
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
time_diff = (now.tv_sec - start.tv_sec);
|
|
} while (!is_online && (time_diff < MAX_CONNECT_TIME));
|
|
if (!is_online) {
|
|
fprintf(stderr, "node failed to come online\n");
|
|
exit(-1);
|
|
}
|
|
|
|
fprintf(stderr, "joining: %llx\n", nwid);
|
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
|
if (nwid) {
|
|
zts_join(nwid);
|
|
do {
|
|
zts_delay_ms(25);
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
time_diff = (now.tv_sec - start.tv_sec);
|
|
} while ((!has_ip4 || !has_ip6) && (time_diff < MAX_CONNECT_TIME));
|
|
if (!has_ip4 || !has_ip6) {
|
|
fprintf(stderr, "node failed to receive assigned addresses\n");
|
|
exit(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Main //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc != 1 && argc != 5 && argc != 7) {
|
|
fprintf(stderr, "Invalid number of arguments.\n");
|
|
exit(-1);
|
|
}
|
|
|
|
//
|
|
// API fuzz test
|
|
//
|
|
|
|
test_pre_service();
|
|
|
|
//
|
|
// Default test
|
|
//
|
|
|
|
// selftest
|
|
if (argc == 1) {
|
|
srand(time(NULL));
|
|
// Store identities in cwd, join 0x0
|
|
start_node(".",0x0);
|
|
test_service();
|
|
exit(0);
|
|
}
|
|
|
|
// Default test (single node)
|
|
// selftest <id-path>
|
|
/*
|
|
if (argc == 2) {
|
|
srand(time(NULL));
|
|
start_node(argv[1],0x0);
|
|
test_service();
|
|
exit(0);
|
|
}*/
|
|
|
|
//
|
|
// Client/Server communication test
|
|
//
|
|
|
|
// Server test
|
|
if (argc == 5) {
|
|
//fprintf(stderr, "server.path = %s\n", argv[1]);
|
|
//fprintf(stderr, "server.nwid = %s\n", argv[2]);
|
|
//fprintf(stderr, "server.port4 = %s\n", argv[3]);
|
|
//fprintf(stderr, "server.port6 = %s\n", argv[4]);
|
|
uint64_t nwid = strtoull(argv[2],NULL,16);
|
|
int port4 = atoi(argv[3]);
|
|
int port6 = atoi(argv[4]);
|
|
start_node(argv[1],nwid);
|
|
start_server_app(port4, port6);
|
|
exit(0);
|
|
}
|
|
// Client test
|
|
if (argc == 7) {
|
|
//fprintf(stderr, "client.path = %s\n", argv[1]);
|
|
//fprintf(stderr, "client.nwid = %s\n", argv[2]);
|
|
//fprintf(stderr, "client.port4 = %s\n", argv[3]);
|
|
//fprintf(stderr, "client.ip4 = %s\n", argv[4]);
|
|
//fprintf(stderr, "client.port6 = %s\n", argv[5]);
|
|
//fprintf(stderr, "client.ip6 = %s\n", argv[6]);
|
|
uint64_t nwid = strtoull(argv[2],NULL,16);
|
|
int port4 = atoi(argv[3]);
|
|
int port6 = atoi(argv[5]);
|
|
start_node(argv[1],nwid);
|
|
start_client_app(argv[4], port4, argv[6], port6);
|
|
exit(0);
|
|
}
|
|
return 0;
|
|
}
|