Improvements to selftest, closure bug addressed
This commit is contained in:
@@ -86,14 +86,14 @@
|
||||
#endif
|
||||
|
||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_TEST
|
||||
#define DEBUG_TEST(fmt, args...) fprintf(stderr, ZT_CYN "TEST [%d] : %16s:%5d:%25s: " fmt \
|
||||
#define DEBUG_TEST(fmt, args...) fprintf(stderr, ZT_CYN "TEST [%d] : %17s:%5d:%25s: " fmt \
|
||||
"\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#else
|
||||
#define DEBUG_ERROR(fmt, args...)
|
||||
#endif
|
||||
|
||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_ERROR
|
||||
#define DEBUG_ERROR(fmt, args...) fprintf(stderr, ZT_RED "ERROR[%d] : %16s:%5d:%25s: " fmt \
|
||||
#define DEBUG_ERROR(fmt, args...) fprintf(stderr, ZT_RED "ERROR[%d] : %17s:%5d:%25s: " fmt \
|
||||
"\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#else
|
||||
#define DEBUG_ERROR(fmt, args...)
|
||||
@@ -102,22 +102,22 @@
|
||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_INFO
|
||||
#if defined(__ANDROID__)
|
||||
#define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||
"INFO : %16s:%5d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
"INFO : %17s:%5d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
#define DEBUG_BLANK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||
"INFO : %16s:%5d:" fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
"INFO : %17s:%5d:" fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
#define DEBUG_ATTN(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||
"INFO : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
"INFO : %17s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
#define DEBUG_STACK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||
"STACK: %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
"STACK: %17s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
#else
|
||||
#define DEBUG_INFO(fmt, args...) fprintf(stderr, \
|
||||
"INFO [%d] : %16s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
"INFO [%d] : %17s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#define DEBUG_ATTN(fmt, args...) fprintf(stderr, ZT_CYN \
|
||||
"ATTN [%d] : %16s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
"ATTN [%d] : %17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#define DEBUG_STACK(fmt, args...) fprintf(stderr, ZT_YEL \
|
||||
"STACK[%d] : %16s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
"STACK[%d] : %17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#define DEBUG_BLANK(fmt, args...) fprintf(stderr, \
|
||||
"INFO [%d] : %16s:%5d:" fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, ##args)
|
||||
"INFO [%d] : %17s:%5d:" fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, ##args)
|
||||
#endif
|
||||
#else
|
||||
#define DEBUG_INFO(fmt, args...)
|
||||
@@ -129,9 +129,9 @@
|
||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER
|
||||
#if defined(__ANDROID__)
|
||||
#define DEBUG_TRANS(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||
"TRANS : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
"TRANS : %17s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
#else
|
||||
#define DEBUG_TRANS(fmt, args...) fprintf(stderr, ZT_GRN "TRANS[%ld] : %16s:%5d:%25s: " fmt \
|
||||
#define DEBUG_TRANS(fmt, args...) fprintf(stderr, ZT_GRN "TRANS[%ld] : %17s:%5d:%25s: " fmt \
|
||||
"\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#endif
|
||||
#else
|
||||
@@ -141,10 +141,10 @@
|
||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_EXTRA
|
||||
#if defined(__ANDROID__)
|
||||
#define DEBUG_EXTRA(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||
"EXTRA : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
"EXTRA : %17s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
#else
|
||||
#define DEBUG_EXTRA(fmt, args...) fprintf(stderr, \
|
||||
"EXTRA[%d] : %16s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
"EXTRA[%d] : %17s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#endif
|
||||
#else
|
||||
#define DEBUG_EXTRA(fmt, args...)
|
||||
@@ -153,9 +153,9 @@
|
||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_FLOW
|
||||
#if defined(__ANDROID__)
|
||||
#define DEBUG_FLOW(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||
"FLOW : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
"FLOW : %17s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
#else
|
||||
#define DEBUG_FLOW(fmt, args...) fprintf(stderr, "FLOW [%ld] : %16s:%5d:%25s: " fmt "\n", \
|
||||
#define DEBUG_FLOW(fmt, args...) fprintf(stderr, "FLOW [%ld] : %17s:%5d:%25s: " fmt "\n", \
|
||||
ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#endif
|
||||
#else
|
||||
|
||||
@@ -193,6 +193,8 @@ struct zts_ifreq {
|
||||
#define ZT_SELECT_SIG int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout
|
||||
#define ZT_GETSOCKNAME_SIG int fd, struct sockaddr *addr, socklen_t *addrlen
|
||||
#define ZT_GETPEERNAME_SIG int fd, struct sockaddr *addr, socklen_t *addrlen
|
||||
#define ZT_GETHOSTNAME_SIG char *name, size_t len
|
||||
#define ZT_SETHOSTNAME_SIG const char *name, size_t len
|
||||
#define ZT_FCNTL_SIG int fd, int cmd, int flags
|
||||
#define ZT_IOCTL_SIG int fd, unsigned long request, void *argp
|
||||
#define ZT_SYSCALL_SIG long number, ...
|
||||
@@ -400,6 +402,16 @@ int zts_getsockname(ZT_GETSOCKNAME_SIG);
|
||||
*/
|
||||
int zts_getpeername(ZT_GETPEERNAME_SIG);
|
||||
|
||||
/**
|
||||
* Gets current hostname
|
||||
*/
|
||||
int zts_gethostname(ZT_GETHOSTNAME_SIG);
|
||||
|
||||
/**
|
||||
* Sets current hostname
|
||||
*/
|
||||
int zts_sethostname(ZT_SETHOSTNAME_SIG);
|
||||
|
||||
/**
|
||||
* Close a socket
|
||||
* TODO: Check that closing a socket immediately after writing doesn't behave in
|
||||
@@ -427,6 +439,11 @@ int zts_fcntl(ZT_FCNTL_SIG);
|
||||
*/
|
||||
int zts_ioctl(ZT_IOCTL_SIG);
|
||||
|
||||
/**
|
||||
* Send data to a remote host
|
||||
*/
|
||||
ssize_t zts_send(ZT_SEND_SIG);
|
||||
|
||||
/**
|
||||
* Send data to a remote host
|
||||
*/
|
||||
@@ -437,6 +454,11 @@ ssize_t zts_sendto(ZT_SENDTO_SIG);
|
||||
*/
|
||||
ssize_t zts_sendmsg(ZT_SENDMSG_SIG);
|
||||
|
||||
/**
|
||||
* Receive data from a remote host
|
||||
*/
|
||||
ssize_t zts_recv(ZT_RECV_SIG);
|
||||
|
||||
/**
|
||||
* Receive data from a remote host
|
||||
*/
|
||||
@@ -486,6 +508,7 @@ namespace ZeroTier
|
||||
extern ZeroTier::lwIP *lwipstack;
|
||||
|
||||
class VirtualTap;
|
||||
struct VirtualSocket;
|
||||
struct InetAddress;
|
||||
}
|
||||
|
||||
@@ -526,11 +549,21 @@ ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress &addr);
|
||||
ZeroTier::VirtualTap *getTapByName(char *ifname);
|
||||
ZeroTier::VirtualTap *getTapByIndex(int index);
|
||||
|
||||
/*
|
||||
* Returns a pointer to a VirtualSocket for a given fd
|
||||
*/
|
||||
ZeroTier::VirtualSocket *get_virtual_socket(int fd);
|
||||
|
||||
/*
|
||||
* Destroys all virtual tap devices
|
||||
*/
|
||||
void dismantleTaps();
|
||||
|
||||
/*
|
||||
* Get device ID (from file)
|
||||
*/
|
||||
int zts_get_device_id_from_file(const char *filepath, char *devID);
|
||||
|
||||
/**
|
||||
* Don't call this directly, use 'zts_start()'
|
||||
*/
|
||||
|
||||
@@ -58,33 +58,31 @@ namespace ZeroTier {
|
||||
RingBuffer<unsigned char> *TXbuf;
|
||||
RingBuffer<unsigned char> *RXbuf;
|
||||
Mutex _tx_m, _rx_m;
|
||||
|
||||
PhySocket *sock;
|
||||
PhySocket *sock = NULL;
|
||||
|
||||
#if defined(STACK_PICO)
|
||||
struct pico_socket *picosock;
|
||||
struct pico_socket *picosock = NULL;
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
void *pcb;
|
||||
void *pcb = NULL;
|
||||
#endif
|
||||
|
||||
// TODO: For getsockname, etc
|
||||
struct sockaddr_storage *local_addr; // Address we've bound to locally
|
||||
struct sockaddr_storage *peer_addr; // Address of connection call to remote host
|
||||
struct sockaddr_storage local_addr; // address we've bound to locally
|
||||
struct sockaddr_storage peer_addr; // address of connection call to remote host
|
||||
|
||||
int socket_family, socket_type, protocol;
|
||||
|
||||
int app_fd; // used by app for I/O
|
||||
int sdk_fd; // used by lib for I/O
|
||||
int socket_family = 0;
|
||||
int socket_type = 0;
|
||||
int protocol = 0;
|
||||
int state = 0; // See libzt.h for (ZT_SOCK_STATE_*)
|
||||
int app_fd = 0; // used by app for I/O
|
||||
int sdk_fd = 0; // used by lib for I/O
|
||||
|
||||
std::queue<VirtualSocket*> _AcceptedConnections;
|
||||
VirtualTap *tap;
|
||||
int state; // See libzt.h for (ZT_SOCK_STATE_*)
|
||||
|
||||
// timestamp for closure event
|
||||
std::time_t closure_ts;
|
||||
VirtualTap *tap = NULL;
|
||||
std::time_t closure_ts = 0;
|
||||
|
||||
VirtualSocket() {
|
||||
DEBUG_EXTRA("this=0x%x, socket_family=%d, socket_type=%d", this, socket_family, socket_type);
|
||||
TXbuf = new RingBuffer<unsigned char>(ZT_TCP_TX_BUF_SZ);
|
||||
RXbuf = new RingBuffer<unsigned char>(ZT_TCP_RX_BUF_SZ);
|
||||
|
||||
@@ -99,7 +97,9 @@ namespace ZeroTier {
|
||||
sdk_fd = fdpair[0];
|
||||
app_fd = fdpair[1];
|
||||
}
|
||||
~VirtualSocket() { }
|
||||
~VirtualSocket() {
|
||||
DEBUG_EXTRA("this=0x%x", this);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -111,7 +111,10 @@ namespace ZeroTier {
|
||||
_phy.whack();
|
||||
Thread::join(_thread);
|
||||
_phy.close(_unixListenSocket,false);
|
||||
for(int i=0; i<_VirtualSockets.size(); i++) delete _VirtualSockets[i];
|
||||
for(int i=0; i<_VirtualSockets.size(); i++) {
|
||||
delete _VirtualSockets[i];
|
||||
_VirtualSockets[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualTap::setEnabled(bool en)
|
||||
@@ -262,7 +265,7 @@ namespace ZeroTier {
|
||||
|
||||
void VirtualTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len)
|
||||
{
|
||||
DEBUG_ATTN("sock->fd=%d", _phy.getDescriptor(sock));
|
||||
//DEBUG_ATTN("sock->fd=%d", _phy.getDescriptor(sock));
|
||||
VirtualSocket *vs = (VirtualSocket*)*uptr;
|
||||
if(!vs)
|
||||
return;
|
||||
@@ -459,15 +462,7 @@ namespace ZeroTier {
|
||||
if(vs->sock)
|
||||
_phy.close(vs->sock, false);
|
||||
}
|
||||
close(_phy.getDescriptor(vs->sock));
|
||||
for(size_t i=0;i<_VirtualSockets.size();++i) {
|
||||
if(_VirtualSockets[i] == vs){
|
||||
// FIXME: double free issue exists here (potentially)
|
||||
// _VirtualSockets.erase(_VirtualSockets.begin() + i);
|
||||
//delete conn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//close(_phy.getDescriptor(vs->sock));
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
|
||||
@@ -109,27 +109,27 @@ namespace ZeroTier {
|
||||
unsigned int len);
|
||||
|
||||
/*
|
||||
*
|
||||
* Get device name
|
||||
*/
|
||||
std::string deviceName() const;
|
||||
|
||||
/*
|
||||
*
|
||||
* Set friendly name
|
||||
*/
|
||||
void setFriendlyName(const char *friendlyName);
|
||||
|
||||
/*
|
||||
*
|
||||
* Scan multicast groups
|
||||
*/
|
||||
void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
|
||||
/*
|
||||
*
|
||||
* Set MTU
|
||||
*/
|
||||
void setMtu(unsigned int mtu);
|
||||
|
||||
/*
|
||||
*
|
||||
* Calls main network stack loops
|
||||
*/
|
||||
void threadMain()
|
||||
throw();
|
||||
@@ -176,28 +176,28 @@ namespace ZeroTier {
|
||||
*/
|
||||
bool picodev_initialized = false;
|
||||
|
||||
struct pico_device *picodev;
|
||||
struct pico_device *picodev6;
|
||||
struct pico_device *picodev = NULL;
|
||||
struct pico_device *picodev6 = NULL;
|
||||
|
||||
/****************************************************************************/
|
||||
/* Guarded RX Frame Buffer for picoTCP */
|
||||
/****************************************************************************/
|
||||
|
||||
unsigned char pico_frame_rxbuf[MAX_PICO_FRAME_RX_BUF_SZ];
|
||||
int pico_frame_rxbuf_tot;
|
||||
int pico_frame_rxbuf_tot = 0;
|
||||
Mutex _pico_frame_rxbuf_m;
|
||||
#endif
|
||||
|
||||
#if defined(STACK_LWIP)
|
||||
netif lwipdev;
|
||||
netif lwipdev6;
|
||||
netif lwipdev = NULL;
|
||||
netif lwipdev6 = NULL;
|
||||
#endif
|
||||
|
||||
std::vector<std::pair<ZeroTier::InetAddress, ZeroTier::InetAddress>> routes;
|
||||
void *zt1ServiceRef;
|
||||
void *zt1ServiceRef = NULL;
|
||||
|
||||
static int devno;
|
||||
int ifindex;
|
||||
int ifindex = 0;
|
||||
|
||||
std::vector<InetAddress> ips() const;
|
||||
std::vector<InetAddress> _ips;
|
||||
|
||||
284
src/libzt.cpp
284
src/libzt.cpp
@@ -408,7 +408,7 @@ int zts_socket(ZT_SOCKET_SIG) {
|
||||
#if defined(STACK_PICO)
|
||||
struct pico_socket *p;
|
||||
err = ZeroTier::picostack->pico_Socket(&p, socket_family, socket_type, protocol);
|
||||
if(p) {
|
||||
if(!err && p) {
|
||||
ZeroTier::VirtualSocket *vs = new ZeroTier::VirtualSocket();
|
||||
vs->socket_family = socket_family;
|
||||
vs->socket_type = socket_type;
|
||||
@@ -625,6 +625,10 @@ int zts_connect(ZT_CONNECT_SIG) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!err) {
|
||||
// for calls like getpeername()
|
||||
memcpy(&(vs->peer_addr), addr, sizeof(vs->peer_addr));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -837,6 +841,11 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
||||
err = accepted_vs->app_fd;
|
||||
}
|
||||
}
|
||||
if(!err) {
|
||||
// copy address into provided address buffer and len buffer
|
||||
memcpy(addr, &(vs->peer_addr), sizeof(struct sockaddr));
|
||||
*addrlen = sizeof(vs->peer_addr);
|
||||
}
|
||||
}
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
return err;
|
||||
@@ -963,9 +972,12 @@ int zts_getsockname(ZT_GETSOCKNAME_SIG)
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Linux:
|
||||
|
||||
[--] [EBADF] The argument s is not a valid descriptor.
|
||||
[ ] [ENOTSOCK] The argument s is a file, not a socket.
|
||||
[ ] [ENOTCONN] The socket is not connected.
|
||||
[--] [ENOTCONN] The socket is not connected.
|
||||
[ ] [ENOBUFS] Insufficient resources were available in the system to
|
||||
perform the operation.
|
||||
[ ] [EFAULT] The name parameter points to memory not in a valid
|
||||
@@ -973,18 +985,60 @@ int zts_getsockname(ZT_GETSOCKNAME_SIG)
|
||||
*/
|
||||
int zts_getpeername(ZT_GETPEERNAME_SIG)
|
||||
{
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
// TODO
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
if(!vs) {
|
||||
errno = ENOTCONN;
|
||||
return -1;
|
||||
}
|
||||
memcpy(addr, &(vs->peer_addr), sizeof(struct sockaddr_storage));
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Linux:
|
||||
|
||||
[ ] [EFAULT] name is an invalid address.
|
||||
[ ] [EINVAL] len is negative or, for sethostname(), len is larger than the
|
||||
maximum allowed size.
|
||||
[ ] [ENAMETOOLONG] (glibc gethostname()) len is smaller than the actual size.
|
||||
(Before version 2.1, glibc uses EINVAL for this case.)
|
||||
[ ] [EPERM] For sethostname(), the caller did not have the CAP_SYS_ADMIN
|
||||
capability in the user namespace associated with its UTS
|
||||
namespace (see namespaces(7)).
|
||||
*/
|
||||
|
||||
int zts_gethostname(ZT_GETHOSTNAME_SIG)
|
||||
{
|
||||
return gethostname(name, len);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Linux:
|
||||
|
||||
[ ] [EFAULT] name is an invalid address.
|
||||
[ ] [EINVAL] len is negative or, for sethostname(), len is larger than the
|
||||
maximum allowed size.
|
||||
[ ] [ENAMETOOLONG] (glibc gethostname()) len is smaller than the actual size.
|
||||
(Before version 2.1, glibc uses EINVAL for this case.)
|
||||
[ ] [EPERM] For sethostname(), the caller did not have the CAP_SYS_ADMIN
|
||||
capability in the user namespace associated with its UTS
|
||||
namespace (see namespaces(7)).
|
||||
*/
|
||||
|
||||
int zts_sethostname(ZT_SETHOSTNAME_SIG)
|
||||
{
|
||||
return sethostname(name, len);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Linux:
|
||||
|
||||
See: http://yarchive.net/comp/linux/close_return_value.html
|
||||
@@ -1031,6 +1085,7 @@ int zts_close(ZT_CLOSE_SIG)
|
||||
if((err = close(vs->sdk_fd)) < 0)
|
||||
DEBUG_ERROR("error closing sdk_fd");
|
||||
delete vs;
|
||||
vs = NULL;
|
||||
ZeroTier::unmap.erase(fd);
|
||||
}
|
||||
else // assigned
|
||||
@@ -1089,6 +1144,8 @@ int zts_close(ZT_CLOSE_SIG)
|
||||
|
||||
//DEBUG_INFO("s->state = %s", ZeroTier::picoTCP::beautify_pico_state(vs->picosock->state));
|
||||
tap->Close(vs);
|
||||
delete vs;
|
||||
vs = NULL;
|
||||
ZeroTier::fdmap.erase(fd);
|
||||
err = 0;
|
||||
}
|
||||
@@ -1204,33 +1261,49 @@ int zts_ioctl(ZT_IOCTL_SIG)
|
||||
|
||||
Linux:
|
||||
|
||||
[ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and the requested operation would block. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.
|
||||
[ ] [EBADF] An invalid descriptor was specified.
|
||||
[ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and the requested operation would block.
|
||||
POSIX.1-2001 allows either error to be returned for this case, and does not
|
||||
require these constants to have the same value, so a portable application
|
||||
should check for both possibilities.
|
||||
[--] [EBADF] An invalid descriptor was specified.
|
||||
[ ] [ECONNRESET] VirtualSocket reset by peer.
|
||||
[ ] [EDESTADDRREQ] The socket is not VirtualSocket-mode, and no peer address is set.
|
||||
[ ] [EFAULT] An invalid user space address was specified for an argument.
|
||||
[ ] [EINTR] A signal occurred before any data was transmitted; see signal(7).
|
||||
[ ] [EINVAL] Invalid argument passed.
|
||||
[ ] [EISCONN] The VirtualSocket-mode socket was connected already but a recipient was specified. (Now either this error is returned, or the recipient specification is ignored.)
|
||||
[ ] [EMSGSIZE] The socket type requires that message be sent atomically, and the size of the message to be sent made this impossible.
|
||||
[ ] [ENOBUFS] The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.)
|
||||
[ ] [EISCONN] The VirtualSocket-mode socket was connected already but a recipient was
|
||||
specified. (Now either this error is returned, or the recipient
|
||||
specification is ignored.)
|
||||
[ ] [EMSGSIZE] The socket type requires that message be sent atomically, and the size
|
||||
of the message to be sent made this impossible.
|
||||
[ ] [ENOBUFS] The output queue for a network interface was full. This generally indicates
|
||||
that the interface has stopped sending, but may be caused by transient congestion.
|
||||
(Normally, this does not occur in Linux. Packets are just silently
|
||||
dropped when a device queue overflows.)
|
||||
[ ] [ENOMEM] No memory available.
|
||||
[ ] [ENOTCONN] The socket is not connected, and no target has been given.
|
||||
[ ] [ENOTSOCK] The argument sockfd is not a socket.
|
||||
[ ] [EOPNOTSUPP] Some bit in the flags argument is inappropriate for the socket type.
|
||||
[ ] [EPIPE] The local end has been shut down on a VirtualSocket oriented socket. In this case the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set.
|
||||
[ ] [EPIPE] The local end has been shut down on a VirtualSocket oriented socket.
|
||||
In this case the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set.
|
||||
|
||||
*/
|
||||
ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||
{
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
//DEBUG_INFO("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("invalid vs");
|
||||
handle_general_failure();
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ZeroTier::InetAddress iaddr;
|
||||
ZeroTier::VirtualTap *tap;
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
@@ -1238,6 +1311,7 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||
|
||||
if(vs->socket_type == SOCK_DGRAM) {
|
||||
// form addresses
|
||||
if(vs->socket_family == AF_INET) {
|
||||
inet_ntop(AF_INET,
|
||||
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||
@@ -1249,22 +1323,24 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
||||
// TODO: This is a hack, determine a proper way to do this
|
||||
char addrstr[64];
|
||||
sprintf(addrstr, "%s%s", ipstr, std::string("/88").c_str());
|
||||
sprintf(addrstr, "%s%s", ipstr, std::string("/40").c_str());
|
||||
iaddr.fromString(addrstr);
|
||||
port = ((struct sockaddr_in6*)addr)->sin6_port;
|
||||
}
|
||||
// get tap
|
||||
tap = getTapByAddr(iaddr);
|
||||
if(tap) {
|
||||
tap->SendTo(vs, buf, len, flags, addr, addrlen);
|
||||
}
|
||||
else {
|
||||
if(!tap) {
|
||||
DEBUG_INFO("SOCK_DGRAM, tap not found");
|
||||
errno = EDESTADDRREQ; // TODO: double check this is the best errno to report
|
||||
return -1;
|
||||
}
|
||||
// write
|
||||
if((err = tap->SendTo(vs, buf, len, flags, addr, addrlen)) < 0) {
|
||||
DEBUG_ERROR("error while attempting to sendto");
|
||||
errno = EINVAL; // TODO: Not correct, but what else could we use?
|
||||
}
|
||||
if(vs->socket_type == SOCK_RAW)
|
||||
{
|
||||
}
|
||||
if(vs->socket_type == SOCK_RAW) {
|
||||
struct sockaddr_ll *socket_address = (struct sockaddr_ll *)addr;
|
||||
ZeroTier::VirtualTap *tap = getTapByIndex(socket_address->sll_ifindex);
|
||||
if(tap)
|
||||
@@ -1288,10 +1364,61 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||
}
|
||||
//err = sendto(fd, buf, len, flags, addr, addrlen);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
Linux:
|
||||
|
||||
[ ] EACCES (For UNIX domain sockets, which are identified by pathname)
|
||||
Write permission is denied on the destination socket file, or
|
||||
search permission is denied for one of the directories the
|
||||
path prefix. (See path_resolution(7).)
|
||||
|
||||
(For UDP sockets) An attempt was made to send to a
|
||||
network/broadcast address as though it was a unicast address.
|
||||
[ ] EAGAIN or EWOULDBLOCK The socket is marked nonblocking and the requested operation
|
||||
would block. POSIX.1-2001 allows either error to be returned
|
||||
for this case, and does not require these constants to have
|
||||
the same value, so a portable application should check for
|
||||
both possibilities.
|
||||
[ ] EAGAIN (Internet domain datagram sockets) The socket referred to by
|
||||
sockfd had not previously been bound to an address and, upon
|
||||
attempting to bind it to an ephemeral port, it was determined
|
||||
that all port numbers in the ephemeral port range are
|
||||
currently in use. See the discussion of
|
||||
/proc/sys/net/ipv4/ip_local_port_range in ip(7).
|
||||
[ ] EBADF sockfd is not a valid open file descriptor.
|
||||
[ ] ECONNRESET Connection reset by peer.
|
||||
[ ] EDESTADDRREQ The socket is not connection-mode, and no peer address is set.
|
||||
[ ] EFAULT An invalid user space address was specified for an argument.
|
||||
[ ] EINTR A signal occurred before any data was transmitted
|
||||
[ ] EINVAL Invalid argument passed.
|
||||
[ ] EISCONN The connection-mode socket was connected already but a
|
||||
recipient was specified. (Now either this error is returned,
|
||||
or the recipient specification is ignored.)
|
||||
[ ] EMSGSIZE The socket type requires that message be sent atomically, and
|
||||
the size of the message to be sent made this impossible.
|
||||
[ ] ENOBUFS The output queue for a network interface was full. This
|
||||
generally indicates that the interface has stopped sending,
|
||||
but may be caused by transient congestion. (Normally, this
|
||||
does not occur in Linux. Packets are just silently dropped
|
||||
when a device queue overflows.)
|
||||
[ ] ENOMEM No memory available.
|
||||
[ ] ENOTCONN The socket is not connected, and no target has been given.
|
||||
[ ] ENOTSOCK The file descriptor sockfd does not refer to a socket.
|
||||
[ ] EOPNOTSUPP Some bit in the flags argument is inappropriate for the socket
|
||||
type.
|
||||
[ ] EPIPE The local end has been shut down on a connection oriented
|
||||
socket. In this case, the process will also receive a SIGPIPE
|
||||
unless MSG_NOSIGNAL is set.
|
||||
|
||||
*/
|
||||
ssize_t zts_send(ZT_SEND_SIG)
|
||||
{
|
||||
return send(fd, buf, len, flags);
|
||||
}
|
||||
|
||||
// TODO
|
||||
ssize_t zts_sendmsg(ZT_SENDMSG_SIG)
|
||||
{
|
||||
@@ -1307,19 +1434,77 @@ ssize_t zts_sendmsg(ZT_SENDMSG_SIG)
|
||||
return err;
|
||||
}
|
||||
|
||||
// TODO
|
||||
/*
|
||||
|
||||
Linux:
|
||||
|
||||
These are some standard errors generated by the socket layer.
|
||||
Additional errors may be generated and returned from the underlying
|
||||
protocol modules; see their manual pages.
|
||||
|
||||
[ ] EAGAIN or EWOULDBLOCK The socket is marked nonblocking and the receive operation
|
||||
would block, or a receive timeout had been set and the timeout
|
||||
expired before data was received.
|
||||
[ ] EBADF The argument sockfd is an invalid file descriptor.
|
||||
[ ] ECONNREFUSED
|
||||
A remote host refused to allow the network connection
|
||||
(typically because it is not running the requested service).
|
||||
[ ] EFAULT The receive buffer pointer(s) point outside the process's
|
||||
address space.
|
||||
[ ] EINTR The receive was interrupted by delivery of a signal before any
|
||||
data were available; see signal(7).
|
||||
[ ] EINVAL Invalid argument passed.
|
||||
[ ] ENOMEM Could not allocate memory for recvmsg().
|
||||
[ ] ENOTCONN The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).
|
||||
[ ] ENOTSOCK The file descriptor sockfd does not refer to a socket.
|
||||
*/
|
||||
ssize_t zts_recv(ZT_RECV_SIG)
|
||||
{
|
||||
return recv(fd, buf, len, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
Linux:
|
||||
|
||||
[ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and the receive operation
|
||||
would block, or a receive timeout had been set and the
|
||||
timeout expired before data was received. POSIX.1-2001
|
||||
allows either error to be returned for this case, and does
|
||||
not require these constants to have the same value, so a
|
||||
portable application should check for both possibilities.
|
||||
[ ] [EBADF] The argument sockfd is an invalid descriptor.
|
||||
[ ] [ECONNREFUSED] A remote host refused to allow the network connection
|
||||
(typically because it is not running the requested service).
|
||||
[ ] [EFAULT] The receive buffer pointer(s) point outside the process's
|
||||
address space.
|
||||
[ ] [EINTR] The receive was interrupted by delivery of a signal before any
|
||||
data were available; see signal(7).
|
||||
[ ] [EINVAL] Invalid argument passed.
|
||||
[ ] [ENOMEM] Could not allocate memory for recvmsg().
|
||||
[ ] [ENOTCONN] The socket is associated with a connection-oriented protocol
|
||||
and has not been connected (see connect(2) and accept(2)).
|
||||
[ ] [ENOTSOCK] The argument sockfd does not refer to a socket.
|
||||
*/
|
||||
ssize_t zts_recvfrom(ZT_RECVFROM_SIG)
|
||||
{
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
int err = 0;
|
||||
//DEBUG_INFO("fd = %d", fd);
|
||||
int r = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
err = recvfrom(fd, buf, len, flags, addr, addrlen);
|
||||
char udp_msg_buf[ZT_MAX_MTU];
|
||||
r = read(fd, udp_msg_buf, sizeof(udp_msg_buf));
|
||||
if(r > 0) {
|
||||
int udp_msg_len = 0;
|
||||
memcpy(&udp_msg_len, udp_msg_buf, sizeof(udp_msg_len));
|
||||
memcpy(addr, udp_msg_buf + sizeof(int), sizeof(struct sockaddr_in));
|
||||
*addrlen = sizeof(struct sockaddr_in);
|
||||
int payload_sz = udp_msg_len - sizeof(struct sockaddr_in);
|
||||
memcpy(buf, udp_msg_buf + sizeof(int) + sizeof(struct sockaddr_in), payload_sz);
|
||||
r = payload_sz;
|
||||
}
|
||||
return err;
|
||||
return r;
|
||||
}
|
||||
|
||||
// TODO
|
||||
@@ -1338,12 +1523,12 @@ ssize_t zts_recvmsg(ZT_RECVMSG_SIG)
|
||||
}
|
||||
|
||||
int zts_read(ZT_READ_SIG) {
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
//DEBUG_INFO("fd = %d", fd);
|
||||
return read(fd, buf, len);
|
||||
}
|
||||
|
||||
int zts_write(ZT_WRITE_SIG) {
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
//DEBUG_INFO("fd = %d", fd);
|
||||
return write(fd, buf, len);
|
||||
}
|
||||
|
||||
@@ -1386,6 +1571,7 @@ int zts_shutdown(ZT_SHUTDOWN_SIG)
|
||||
if((err = pico_socket_shutdown(vs->picosock, mode)) < 0)
|
||||
DEBUG_ERROR("error calling pico_socket_shutdown()");
|
||||
delete vs;
|
||||
vs = NULL;
|
||||
ZeroTier::unmap.erase(fd);
|
||||
// FIXME: Is deleting this correct behaviour?
|
||||
}
|
||||
@@ -1795,6 +1981,7 @@ ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress &addr)
|
||||
s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||
// check address schemes
|
||||
for(int j=0; j<s->_ips.size(); j++) {
|
||||
DEBUG_INFO("looking at tap <addr=%s> for <%s>", s->_ips[j].toString(ipbuf), addr.toString(ipbuf2));
|
||||
if(s->_ips[j].isEqualPrefix(addr)
|
||||
|| s->_ips[j].ipsEqual(addr)
|
||||
|| s->_ips[j].containsAddress(addr))
|
||||
@@ -1813,7 +2000,7 @@ ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress &addr)
|
||||
nm = target.netmask();
|
||||
via = managed_routes->at(i).via;
|
||||
if(target.containsAddress(addr)) {
|
||||
DEBUG_INFO("chose tap with route <target=%s, nm=%s, via=%s>", target.toString(ipbuf), nm.toString(ipbuf2), via.toString(ipbuf3));
|
||||
// DEBUG_INFO("chose tap with route <target=%s, nm=%s, via=%s>", target.toString(ipbuf), nm.toString(ipbuf2), via.toString(ipbuf3));
|
||||
tap = s;
|
||||
break;
|
||||
}
|
||||
@@ -1852,14 +2039,45 @@ ZeroTier::VirtualTap *getTapByIndex(int index)
|
||||
return tap;
|
||||
}
|
||||
|
||||
ZeroTier::VirtualSocket *get_virtual_socket(int fd)
|
||||
{
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
// try to locate in unmapped set
|
||||
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||
if(!vs) {
|
||||
// if not, try to find in mapped set (bind to vtap has been performed)
|
||||
std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *p = ZeroTier::fdmap[fd];
|
||||
if(p) {
|
||||
vs = p->first;
|
||||
}
|
||||
}
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
return vs;
|
||||
}
|
||||
|
||||
void dismantleTaps()
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
for(int i=0; i<ZeroTier::vtaps.size(); i++) { delete (ZeroTier::VirtualTap*)ZeroTier::vtaps[i]; }
|
||||
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||
delete (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||
ZeroTier::vtaps[i] = NULL;
|
||||
}
|
||||
ZeroTier::vtaps.clear();
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
}
|
||||
|
||||
int zts_get_device_id_from_file(const char *filepath, char *devID) {
|
||||
std::string fname("identity.public");
|
||||
std::string fpath(filepath);
|
||||
|
||||
if(ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) {
|
||||
std::string oldid;
|
||||
ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid);
|
||||
memcpy(devID, oldid.c_str(), 10); // first 10 bytes of file
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Starts a ZeroTier service in the background
|
||||
void *zts_start_service(void *thread_id) {
|
||||
|
||||
293
src/picoTCP.cpp
293
src/picoTCP.cpp
@@ -86,14 +86,15 @@ namespace ZeroTier {
|
||||
bool picoTCP::pico_init_interface(VirtualTap *tap, const InetAddress &ip)
|
||||
{
|
||||
char ipbuf[64];
|
||||
uint8_t hwaddr[6];
|
||||
if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) {
|
||||
tap->_ips.push_back(ip);
|
||||
std::sort(tap->_ips.begin(),tap->_ips.end());
|
||||
|
||||
if(!tap->picodev_initialized)
|
||||
{
|
||||
picodev.send = pico_eth_send; // tx
|
||||
picodev.poll = pico_eth_poll; // rx
|
||||
picodev.send = pico_eth_tx; // tx
|
||||
picodev.poll = pico_eth_poll; // calls pico_eth_rx
|
||||
picodev.mtu = tap->_mtu;
|
||||
picodev.tap = tap;
|
||||
uint8_t mac[PICO_SIZE_ETH];
|
||||
@@ -112,7 +113,10 @@ namespace ZeroTier {
|
||||
netmask.addr = *((uint32_t *)ip.netmask().rawIpData());
|
||||
pico_ipv4_link_add(&picodev, ipaddr, netmask);
|
||||
DEBUG_INFO("addr=%s", ip.toString(ipbuf));
|
||||
//DEBUG_INFO("mac = %s", tap->_mac.toString(ipbuf));
|
||||
tap->_mac.copyTo(hwaddr, 6);
|
||||
char macbuf[18];
|
||||
mac2str(macbuf, sizeof(macbuf), hwaddr);
|
||||
DEBUG_INFO("mac=%s", macbuf);
|
||||
return true;
|
||||
}
|
||||
if(ip.isV6())
|
||||
@@ -124,8 +128,11 @@ namespace ZeroTier {
|
||||
pico_string_to_ipv6(ipv6_str, ipaddr.addr);
|
||||
pico_string_to_ipv6(nm_str, netmask.addr);
|
||||
pico_ipv6_link_add(&picodev, ipaddr, netmask);
|
||||
DEBUG_INFO("addr6 = %s", ipv6_str);
|
||||
//DEBUG_INFO("mac = %s", tap->_mac.toString(ipbuf));
|
||||
DEBUG_INFO("addr=%s", ipv6_str);
|
||||
tap->_mac.copyTo(hwaddr, 6);
|
||||
char macbuf[18];
|
||||
mac2str(macbuf, sizeof(macbuf), hwaddr);
|
||||
DEBUG_INFO("mac=%s", macbuf);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -181,8 +188,13 @@ namespace ZeroTier {
|
||||
VirtualSocket *vs = (VirtualSocket*)((VirtualBindingPair*)(s->priv))->vs;
|
||||
Mutex::Lock _l(vs->_rx_m);
|
||||
|
||||
if(!vs || !tap) {
|
||||
DEBUG_ERROR("invalid tap or vs");
|
||||
if(!tap) {
|
||||
DEBUG_ERROR("invalid tap");
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("invalid vs");
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
@@ -232,60 +244,64 @@ namespace ZeroTier {
|
||||
// from stack socket to app socket
|
||||
void picoTCP::pico_cb_udp_read(VirtualTap *tap, struct pico_socket *s)
|
||||
{
|
||||
/*
|
||||
DEBUG_INFO();
|
||||
// DEBUG_INFO();
|
||||
VirtualSocket *vs = (VirtualSocket*)((VirtualBindingPair*)(s->priv))->vs;
|
||||
Mutex::Lock _l(vs->_rx_m);
|
||||
if(vs) {
|
||||
|
||||
if(!tap) {
|
||||
DEBUG_ERROR("invalid tap");
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("invalid vs");
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t port = 0;
|
||||
union {
|
||||
struct pico_ip4 ip4;
|
||||
struct pico_ip6 ip6;
|
||||
} peer;
|
||||
int r = 0;
|
||||
|
||||
char tmpbuf[ZT_SDK_MTU];
|
||||
unsigned char *addr_pos, *sz_pos, *payload_pos;
|
||||
struct sockaddr_in addr_in;
|
||||
addr_in.sin_addr.s_addr = peer.ip4.addr;
|
||||
addr_in.sin_port = port;
|
||||
|
||||
// RX
|
||||
int r = pico_socket_recvfrom(s, tmpbuf, ZT_SDK_MTU, (void *)&peer.ip4.addr, &port);
|
||||
//DEBUG_FLOW(" [ RXBUF <- STACK] Receiving (%d) from stack, copying to receving buffer", r);
|
||||
|
||||
if(vs->rxsz == ZT_UDP_RX_BUF_SZ) { // if UDP buffer full
|
||||
//DEBUG_FLOW(" [ RXBUF <- STACK] UDP RX buffer full. Discarding oldest payload segment");
|
||||
memmove(vs->rxbuf, vs->rxbuf + ZT_SDK_MTU, ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU);
|
||||
addr_pos = vs->rxbuf + (ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU); // TODO:
|
||||
sz_pos = addr_pos + sizeof(struct sockaddr_storage);
|
||||
vs->rxsz -= ZT_SDK_MTU;
|
||||
if(vs->socket_family == AF_INET) {
|
||||
struct sockaddr_in in4;
|
||||
char udp_payload_buf[ZT_MAX_MTU];
|
||||
if((r = pico_socket_recvfrom(s, udp_payload_buf, ZT_SDK_MTU, (void *)&peer.ip4.addr, &port)) < 0) {
|
||||
DEBUG_ERROR("err=%d, %s", r, beautify_pico_error(pico_err));
|
||||
}
|
||||
else {
|
||||
addr_pos = vs->rxbuf + vs->rxsz; // where we'll prepend the size of the address
|
||||
sz_pos = addr_pos + sizeof(struct sockaddr_storage);
|
||||
in4.sin_addr.s_addr = peer.ip4.addr;
|
||||
in4.sin_port = port;
|
||||
// immediately attempt to write addr and payload to app socket. The idea is that the zts_recvfrom() has
|
||||
// been called and will pick this up and correctly handle it
|
||||
char udp_msg_buf[ZT_MAX_MTU]; // [sz : addr : payload]
|
||||
int len = sizeof(struct sockaddr_in) + r;
|
||||
int tot_len = sizeof(len) + len;
|
||||
memcpy(udp_msg_buf, &len, sizeof(len)); // len: sockaddr+payload
|
||||
memcpy(udp_msg_buf + sizeof(len), &in4, sizeof(in4)); // sockaddr
|
||||
memcpy(udp_msg_buf + sizeof(len) + sizeof(in4), &udp_payload_buf, r); // payload
|
||||
int w = write(vs->sdk_fd, udp_msg_buf, tot_len);
|
||||
}
|
||||
payload_pos = addr_pos + sizeof(struct sockaddr_storage) + sizeof(r);
|
||||
memcpy(addr_pos, &addr_in, sizeof(struct sockaddr_storage));
|
||||
memcpy(payload_pos, tmpbuf, r); // write payload to app's socket
|
||||
|
||||
// Adjust buffer size
|
||||
if(r) {
|
||||
vs->rxsz += ZT_SDK_MTU;
|
||||
memcpy(sz_pos, &r, sizeof(r));
|
||||
if(vs->socket_family == AF_INET6) {
|
||||
struct sockaddr_in6 in6;
|
||||
char udp_payload_buf[ZT_MAX_MTU];
|
||||
if((r = pico_socket_recvfrom(s, udp_payload_buf, ZT_SDK_MTU, (void *)&peer.ip6.addr, &port)) < 0) {
|
||||
DEBUG_ERROR("err=%d, %s", r, beautify_pico_error(pico_err));
|
||||
}
|
||||
if (r < 0) {
|
||||
DEBUG_ERROR("unable to read from picosock=%p", s);
|
||||
handle_general_failure();
|
||||
memcpy(&(in6.sin6_addr.s6_addr), &(peer.ip6.addr), sizeof(peer.ip6.addr));
|
||||
in6.sin6_port = port;
|
||||
// immediately attempt to write addr and payload to app socket. The idea is that the zts_recvfrom() has
|
||||
// been called and will pick this up and correctly handle it
|
||||
char udp_msg_buf[ZT_MAX_MTU]; // [sz : addr : payload]
|
||||
int len = sizeof(struct sockaddr_in6) + r;
|
||||
int tot_len = sizeof(len) + len;
|
||||
memcpy(udp_msg_buf, &len, sizeof(len)); // len: sockaddr+payload
|
||||
memcpy(udp_msg_buf + sizeof(len), &in6, sizeof(in6)); // sockaddr
|
||||
memcpy(udp_msg_buf + sizeof(len) + sizeof(in6), &udp_payload_buf, r); // payload
|
||||
int w = write(vs->sdk_fd, udp_msg_buf, tot_len);
|
||||
}
|
||||
tap->_rx_buf_m.unlock();
|
||||
|
||||
if(r)
|
||||
tap->phyOnUnixWritable(vs->sock, NULL, true);
|
||||
//DEBUG_EXTRA(" Copied onto rxbuf (%d) from stack socket", r);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void picoTCP::pico_cb_tcp_write(VirtualTap *tap, struct pico_socket *s)
|
||||
@@ -349,19 +365,27 @@ namespace ZeroTier {
|
||||
if(vs->state == ZT_SOCK_STATE_LISTENING)
|
||||
{
|
||||
Mutex::Lock _l(tap->_tcpconns_m);
|
||||
uint32_t peer;
|
||||
|
||||
uint16_t port;
|
||||
struct pico_socket *client_psock = pico_socket_accept(s, &peer, &port);
|
||||
struct pico_socket *client_psock = nullptr;
|
||||
struct pico_ip4 orig4;
|
||||
struct pico_ip6 orig6;
|
||||
|
||||
if(vs->socket_family == AF_INET) { // NOTE: p->net->proto_number == PICO_PROTO_IPV4
|
||||
client_psock = pico_socket_accept(s, &orig4, &port);
|
||||
}
|
||||
if(vs->socket_family == AF_INET6) { // NOTE: p->net->proto_number == PICO_PROTO_IPV4
|
||||
client_psock = pico_socket_accept(s, &orig6, &port);
|
||||
}
|
||||
|
||||
if(!client_psock) {
|
||||
DEBUG_ERROR("pico_err=%s, picosock=%p", beautify_pico_error(pico_err), s);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new VirtualSocket and add it to the queue,
|
||||
// some time in the future a call to zts_multiplex_accept() will pick up
|
||||
// this new VirtualSocket, add it to the VirtualSocket list and return its
|
||||
// VirtualSocket->sock to the application
|
||||
|
||||
VirtualSocket *new_vs = new VirtualSocket();
|
||||
new_vs->socket_type = SOCK_STREAM;
|
||||
new_vs->picosock = client_psock;
|
||||
@@ -369,10 +393,30 @@ namespace ZeroTier {
|
||||
new_vs->picosock->priv = new VirtualBindingPair(tap,new_vs);
|
||||
tap->_VirtualSockets.push_back(new_vs);
|
||||
vs->_AcceptedConnections.push(new_vs);
|
||||
// TODO: Condense this
|
||||
if(vs->socket_family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in in4;
|
||||
in4.sin_addr.s_addr = orig4.addr;
|
||||
in4.sin_port = Utils::hton(port);
|
||||
memcpy(&(new_vs->peer_addr), &in4, sizeof(new_vs->peer_addr));
|
||||
char addrstr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &(in4.sin_addr), addrstr, INET_ADDRSTRLEN);
|
||||
DEBUG_EXTRA("accepted connection from: %s : %d", addrstr, port);
|
||||
}
|
||||
if(vs->socket_family == AF_INET6)
|
||||
{
|
||||
struct sockaddr_in6 in6;
|
||||
memcpy(&(in6.sin6_addr.s6_addr), &orig6, sizeof(in6.sin6_addr.s6_addr));
|
||||
in6.sin6_port = Utils::hton(port);
|
||||
memcpy(&(new_vs->peer_addr), &in6, sizeof(new_vs->peer_addr));
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &(in6.sin6_addr), addrstr, INET6_ADDRSTRLEN);
|
||||
DEBUG_EXTRA("accepted connection from: %s : %d", addrstr, port);
|
||||
}
|
||||
|
||||
|
||||
int value = 1;
|
||||
pico_socket_setoption(new_vs->picosock, PICO_TCP_NODELAY, &value);
|
||||
// int value = 1;
|
||||
// pico_socket_setoption(new_vs->picosock, PICO_TCP_NODELAY, &value);
|
||||
|
||||
if(ZT_SOCK_BEHAVIOR_LINGER) {
|
||||
int linger_time_ms = ZT_SOCK_BEHAVIOR_LINGER_TIME;
|
||||
@@ -380,16 +424,7 @@ namespace ZeroTier {
|
||||
if((t_err = pico_socket_setoption(new_vs->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0)
|
||||
DEBUG_ERROR("unable to set LINGER size, err=%d, pico_err=%d, app_fd=%d, sdk_fd=%d", t_err, pico_err, vs->app_fd, vs->sdk_fd);
|
||||
}
|
||||
/*
|
||||
linger_time_ms = 0;
|
||||
if((t_err = pico_socket_getoption(new_vs->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0)
|
||||
DEBUG_ERROR("unable to set LINGER size, err = %d, pico_err = %d", t_err, pico_err);
|
||||
DEBUG_TEST("getting linger = %d", linger_time_ms);
|
||||
*/
|
||||
// For I/O loop participation and referencing the PhySocket's parent VirtualSocket in callbacks
|
||||
new_vs->sock = tap->_phy.wrapSocket(new_vs->sdk_fd, new_vs);
|
||||
//DEBUG_ERROR("sock->fd = %d", tap->_phy.getDescriptor(new_vs->sock));
|
||||
|
||||
}
|
||||
if(vs->state != ZT_SOCK_STATE_LISTENING) {
|
||||
// set state so socket multiplexer logic will pick this up
|
||||
@@ -410,7 +445,8 @@ namespace ZeroTier {
|
||||
DEBUG_ERROR("PICO_ERR_ECONNRESET");
|
||||
vs->state = PICO_ERR_ECONNRESET;
|
||||
}
|
||||
DEBUG_ERROR("PICO_SOCK_EV_ERR, err=%s, picosock=%p, app_fd=%d, sdk_fd=%d", beautify_pico_error(pico_err), s, vs->app_fd, vs->sdk_fd);
|
||||
DEBUG_ERROR("PICO_SOCK_EV_ERR, err=%s, picosock=%p, app_fd=%d, sdk_fd=%d",
|
||||
beautify_pico_error(pico_err), s, vs->app_fd, vs->sdk_fd);
|
||||
}
|
||||
// PICO_SOCK_EV_CLOSE - triggered when a FIN segment is received (TCP only). This event
|
||||
// indicates that the oher endpont has closed the VirtualSocket, so the local TCP layer is only
|
||||
@@ -438,7 +474,7 @@ namespace ZeroTier {
|
||||
}
|
||||
}
|
||||
|
||||
int pico_eth_send(struct pico_device *dev, void *buf, int len)
|
||||
int pico_eth_tx(struct pico_device *dev, void *buf, int len)
|
||||
{
|
||||
//DEBUG_INFO("len = %d", len);
|
||||
VirtualTap *tap = (VirtualTap*)(dev->tap);
|
||||
@@ -453,16 +489,26 @@ namespace ZeroTier {
|
||||
MAC dest_mac;
|
||||
src_mac.setTo(ethhdr->saddr, 6);
|
||||
dest_mac.setTo(ethhdr->daddr, 6);
|
||||
|
||||
if(ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER) {
|
||||
char macBuf[18], nodeBuf[11];
|
||||
mac2str(macBuf, sizeof(macBuf), ethhdr->daddr);
|
||||
ZeroTier::MAC mac;
|
||||
mac.setTo(ethhdr->daddr, 6);
|
||||
mac.toAddress(tap->_nwid).toString(nodeBuf);
|
||||
DEBUG_TRANS("len=%5d, dest=%s, node=%s, proto=0x%04x (%s)", len, macBuf, nodeBuf, Utils::ntoh(ethhdr->proto), beautify_eth_proto_nums(Utils::ntoh(ethhdr->proto)));
|
||||
}
|
||||
|
||||
tap->_handler(tap->_arg,NULL,tap->_nwid,src_mac,dest_mac,
|
||||
Utils::ntoh((uint16_t)ethhdr->proto),0, ((char*)buf) + sizeof(struct pico_eth_hdr),len - sizeof(struct pico_eth_hdr));
|
||||
Utils::ntoh((uint16_t)ethhdr->proto),0, ((char*)buf)
|
||||
+ sizeof(struct pico_eth_hdr),len - sizeof(struct pico_eth_hdr));
|
||||
return len;
|
||||
}
|
||||
|
||||
// receive frames from zerotier virtual wire and copy them to a guarded buffer awaiting placement into network stack
|
||||
void picoTCP::pico_rx(VirtualTap *tap, const MAC &from,const MAC &to,unsigned int etherType,
|
||||
void picoTCP::pico_eth_rx(VirtualTap *tap, const MAC &from,const MAC &to,unsigned int etherType,
|
||||
const void *data,unsigned int len)
|
||||
{
|
||||
DEBUG_INFO("len = %d", len);
|
||||
if(!tap) {
|
||||
DEBUG_ERROR("invalid tap");
|
||||
handle_general_failure();
|
||||
@@ -471,7 +517,6 @@ namespace ZeroTier {
|
||||
// Since picoTCP only allows the reception of frames from within the polling function, we
|
||||
// must enqueue each frame into a memory structure shared by both threads. This structure will
|
||||
Mutex::Lock _l(tap->_pico_frame_rxbuf_m);
|
||||
|
||||
// assemble new eth header
|
||||
struct pico_eth_hdr ethhdr;
|
||||
from.copyTo(ethhdr.saddr, 6);
|
||||
@@ -479,19 +524,19 @@ namespace ZeroTier {
|
||||
ethhdr.proto = Utils::hton((uint16_t)etherType);
|
||||
int newlen = len + sizeof(int) + sizeof(struct pico_eth_hdr);
|
||||
|
||||
int mylen;
|
||||
// FIXME
|
||||
while(newlen > (MAX_PICO_FRAME_RX_BUF_SZ-tap->pico_frame_rxbuf_tot) && ethhdr.proto == 56710)
|
||||
{
|
||||
mylen = 0;
|
||||
memset(tap->pico_frame_rxbuf,0,MAX_PICO_FRAME_RX_BUF_SZ);
|
||||
tap->pico_frame_rxbuf_tot=0;
|
||||
if(ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER) {
|
||||
char macBuf[18], nodeBuf[11];
|
||||
mac2str(macBuf, sizeof(macBuf), ethhdr.saddr);
|
||||
ZeroTier::MAC mac;
|
||||
mac.setTo(ethhdr.saddr, 6);
|
||||
mac.toAddress(tap->_nwid).toString(nodeBuf);
|
||||
DEBUG_TRANS("len=%5d, src=%s, node=%s, proto=0x%04x (%s)", len, macBuf, nodeBuf, etherType, beautify_eth_proto_nums(etherType));
|
||||
}
|
||||
// write virtual ethernet frame to guarded buffer (emptied by pico_eth_poll())
|
||||
memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot, &newlen, sizeof(newlen)); // size of frame + meta
|
||||
memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot + sizeof(newlen), ðhdr, sizeof(ethhdr)); // new eth header
|
||||
memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot + sizeof(newlen) + sizeof(ethhdr), data, len); // frame data
|
||||
tap->pico_frame_rxbuf_tot += newlen;
|
||||
//DEBUG_FLOW("[ ZWIRE -> FBUF ] Move FRAME(sz=%d) into FBUF(sz=%d), data_len=%d", newlen, tap->pico_frame_rxbuf_tot, len);
|
||||
}
|
||||
|
||||
// feed frames on the guarded RX buffer (from zerotier virtual wire) into the network stack
|
||||
@@ -519,7 +564,7 @@ namespace ZeroTier {
|
||||
memcpy(frame, tap->pico_frame_rxbuf + sizeof(len), len-(sizeof(len)) ); // get frame data
|
||||
memmove(tap->pico_frame_rxbuf, tap->pico_frame_rxbuf + len, MAX_PICO_FRAME_RX_BUF_SZ-len); // shift buffer
|
||||
err = pico_stack_recv(dev, (uint8_t*)frame, (len-sizeof(len)));
|
||||
//DEBUG_INFO("recv = %d", err);
|
||||
// DEBUG_INFO("pico_stack_recv() = %d", err);
|
||||
tap->pico_frame_rxbuf_tot-=len;
|
||||
}
|
||||
else {
|
||||
@@ -563,8 +608,9 @@ namespace ZeroTier {
|
||||
int tx_buf_sz = ZT_STACK_TCP_SOCKET_TX_SZ;
|
||||
int rx_buf_sz = ZT_STACK_TCP_SOCKET_RX_SZ;
|
||||
int t_err = 0;
|
||||
int value = 1;
|
||||
pico_socket_setoption(psock, PICO_TCP_NODELAY, &value);
|
||||
|
||||
//int value = 1;
|
||||
// pico_socket_setoption(psock, PICO_TCP_NODELAY, &value);
|
||||
|
||||
if((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_SNDBUF, &tx_buf_sz)) < 0)
|
||||
DEBUG_ERROR("unable to set SNDBUF size, err = %d, pico_err = %d", t_err, pico_err);
|
||||
@@ -722,84 +768,8 @@ namespace ZeroTier {
|
||||
|
||||
int picoTCP::pico_Read(VirtualTap *tap, PhySocket *sock, VirtualSocket* vs, bool stack_invoked)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
//exit(0);
|
||||
/*
|
||||
if(!vs || !tap || !vs) {
|
||||
DEBUG_ERROR("invalid tap, sock, or vs");
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
// DEBUG_INFO();
|
||||
if(!stack_invoked) {
|
||||
// The stack thread writes to RXBUF as well
|
||||
tap->_tcpconns_m.lock();
|
||||
tap->_rx_buf_m.lock();
|
||||
}
|
||||
int tot = 0, n = -1, write_attempts = 0;
|
||||
|
||||
if(vs && vs->rxsz) {
|
||||
//DEBUG_INFO("vs = %p", vs);
|
||||
//
|
||||
if(vs->socket_type==SOCK_DGRAM) {
|
||||
// Try to write ZT_SDK_MTU-sized chunk to app socket
|
||||
while(tot < ZT_SDK_MTU) {
|
||||
write_attempts++;
|
||||
n = tap->_phy.streamSend(vs->sock, (vs->rxbuf)+tot, ZT_SDK_MTU);
|
||||
tot += n;
|
||||
//DEBUG_FLOW("[ ZTSOCK <- RXBUF] wrote = %d, errno=%d", n, errno);
|
||||
// If socket is unavailable, attempt to write N times before giving up
|
||||
if(errno==35) {
|
||||
if(write_attempts == 1024) {
|
||||
n = ZT_SDK_MTU; // say we wrote it, even though we didn't (drop packet)
|
||||
tot = ZT_SDK_MTU;
|
||||
}
|
||||
}
|
||||
}
|
||||
int payload_sz, addr_sz_offset = sizeof(struct sockaddr_storage);
|
||||
memcpy(&payload_sz, vs->rxbuf + addr_sz_offset, sizeof(int));
|
||||
struct sockaddr_storage addr;
|
||||
memcpy(&addr, vs->rxbuf, addr_sz_offset);
|
||||
// adjust buffer
|
||||
if(vs->rxsz-n > 0) { // If more remains on buffer
|
||||
memcpy(vs->rxbuf, vs->rxbuf+ZT_SDK_MTU, vs->rxsz - ZT_SDK_MTU);
|
||||
}
|
||||
vs->rxsz -= ZT_SDK_MTU;
|
||||
}
|
||||
//
|
||||
if(vs->socket_type==SOCK_STREAM) {
|
||||
//DEBUG_INFO("writing to vs->sock = %p, vs->sdk_fd=%d, vs->app_fd=%d", vs->sock, vs->sdk_fd, vs->app_fd);
|
||||
n = tap->_phy.streamSend(vs->sock, vs->rxbuf, vs->rxsz);
|
||||
// FIXME: Revisit the idea of writing directly to the app socketpair instead of using Phy I/O
|
||||
// n = write(vs->sdk_fd, vs->rxbuf, vs->rxsz);
|
||||
if(vs->rxsz-n > 0) // If more remains on buffer
|
||||
memcpy(vs->rxbuf, vs->rxbuf+n, vs->rxsz - n);
|
||||
vs->rxsz -= n;
|
||||
}
|
||||
// Notify ZT I/O loop that it has new buffer contents
|
||||
if(n) {
|
||||
if(vs->socket_type==SOCK_STREAM) {
|
||||
//#if DEBUG_LEVEL >= MSG_TRANSFER
|
||||
// DEBUG_TRANS("[ TCP RX <- STACK] :: vs = %p, len = %d", vs, n);
|
||||
//#endif
|
||||
}
|
||||
if(vs->rxsz == 0) {
|
||||
tap->_phy.setNotifyWritable(sock, false);
|
||||
}
|
||||
else {
|
||||
tap->_phy.setNotifyWritable(sock, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tap->_phy.setNotifyWritable(sock, false);
|
||||
}
|
||||
}
|
||||
if(!stack_invoked) {
|
||||
tap->_tcpconns_m.unlock();
|
||||
tap->_rx_buf_m.unlock();
|
||||
}
|
||||
// DEBUG_FLOW("[ ZTSOCK <- RXBUF] Emitted (%d) from RXBUF(%d) to socket", tot, vs->rxsz);
|
||||
*/
|
||||
// Vestigial
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -807,7 +777,7 @@ namespace ZeroTier {
|
||||
{
|
||||
int err = 0;
|
||||
// TODO: Add RingBuffer overflow checks
|
||||
DEBUG_INFO("vs=%p, len=%d", vs, len);
|
||||
// DEBUG_INFO("vs=%p, len=%d", vs, len);
|
||||
Mutex::Lock _l(vs->_tx_m);
|
||||
if(len <= 0) {
|
||||
DEBUG_ERROR("invalid write length (len=%d)", len);
|
||||
@@ -828,13 +798,14 @@ namespace ZeroTier {
|
||||
{
|
||||
int r;
|
||||
if((r = pico_socket_write(vs->picosock, data, len)) < 0) {
|
||||
DEBUG_ERROR("unable to write to picosock=%p, r=%d", vs->picosock, r);
|
||||
DEBUG_ERROR("unable to write to picosock=%p, err=%d (%s)",
|
||||
vs->picosock, r, pico_err, beautify_pico_error(pico_err));
|
||||
err = -1;
|
||||
}
|
||||
else {
|
||||
err = r; // successful write
|
||||
}
|
||||
DEBUG_TRANS("[ UDP TX -> STACK] :: vs=%p, len=%d, err=%s", vs, r, beautify_pico_error(pico_err));
|
||||
// DEBUG_TRANS("[ UDP TX -> STACK] :: vs=%p, len=%d", vs, r);
|
||||
}
|
||||
if(vs->socket_type == SOCK_STREAM)
|
||||
{
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace ZeroTier
|
||||
/*
|
||||
* Send raw frames from the stack to the ZeroTier virtual wire
|
||||
*/
|
||||
int pico_eth_send(struct pico_device *dev, void *buf, int len);
|
||||
int pico_eth_tx(struct pico_device *dev, void *buf, int len);
|
||||
|
||||
/*
|
||||
* Read raw frames from RX frame buffer into the stack
|
||||
@@ -134,7 +134,7 @@ namespace ZeroTier
|
||||
/*
|
||||
* Packets from the ZeroTier virtual wire enter the stack here
|
||||
*/
|
||||
void pico_rx(VirtualTap *tap, const ZeroTier::MAC &from,const ZeroTier::MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
void pico_eth_rx(VirtualTap *tap, const ZeroTier::MAC &from,const ZeroTier::MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
|
||||
/*
|
||||
* Creates a stack-specific "socket" or "VirtualSocket object"
|
||||
|
||||
@@ -79,8 +79,12 @@
|
||||
#define MIN_PORT 5000
|
||||
#define MAX_PORT 50000
|
||||
|
||||
#define UNIT_TEST_SIG_4 struct sockaddr_in *addr, int operation, int count, int delay, char *details, bool *passed
|
||||
#define UNIT_TEST_SIG_6 struct sockaddr_in6 *addr, int operation, int count, int delay, char *details, bool *passed
|
||||
#define TCP_UNIT_TEST_SIG_4 struct sockaddr_in *addr, int operation, int count, int delay, char *details, bool *passed
|
||||
#define UDP_UNIT_TEST_SIG_4 struct sockaddr_in *local_addr, struct sockaddr_in *remote_addr, int operation, int count, int delay, char *details, bool *passed
|
||||
|
||||
#define TCP_UNIT_TEST_SIG_6 struct sockaddr_in6 *addr, int operation, int count, int delay, char *details, bool *passed
|
||||
#define UDP_UNIT_TEST_SIG_6 struct sockaddr_in6 *local_addr, struct sockaddr_in6 *remote_addr, int operation, int count, int delay, char *details, bool *passed
|
||||
|
||||
|
||||
#define ECHOTEST_MODE_RX 333
|
||||
#define ECHOTEST_MODE_TX 666
|
||||
@@ -142,8 +146,7 @@ std::map<std::string, std::string> testConf;
|
||||
/* Helper Functions */
|
||||
/****************************************************************************/
|
||||
|
||||
void displayResults(int *results, int size)
|
||||
{
|
||||
void displayResults(int *results, int size) {
|
||||
int success = 0, failure = 0;
|
||||
for(int i=0; i<size; i++) {
|
||||
if(results[i] == 0)
|
||||
@@ -156,8 +159,7 @@ void displayResults(int *results, int size)
|
||||
std::cout << " - failure = " << (float)failure / (float)size << std::endl;
|
||||
}
|
||||
|
||||
void loadTestConfigFile(std::string filepath)
|
||||
{
|
||||
void loadTestConfigFile(std::string filepath) {
|
||||
std::string key, value, prefix;
|
||||
std::ifstream testFile;
|
||||
testFile.open(filepath.c_str());
|
||||
@@ -174,15 +176,13 @@ void loadTestConfigFile(std::string filepath)
|
||||
testFile.close();
|
||||
}
|
||||
|
||||
long int get_now_ts()
|
||||
{
|
||||
long int get_now_ts() {
|
||||
struct timeval tp;
|
||||
gettimeofday(&tp, NULL);
|
||||
return tp.tv_sec * 1000 + tp.tv_usec / 1000;
|
||||
}
|
||||
|
||||
void generate_random_data(void *buf, size_t n)
|
||||
{
|
||||
void generate_random_data(void *buf, size_t n) {
|
||||
char *b = (char*)buf;
|
||||
int min = 0, max = 9;
|
||||
srand((unsigned)time(0));
|
||||
@@ -191,9 +191,7 @@ void generate_random_data(void *buf, size_t n)
|
||||
}
|
||||
}
|
||||
|
||||
void create_addr(std::string ipstr, int port, int ipv, struct sockaddr *saddr)
|
||||
{
|
||||
struct hostent *server;
|
||||
void create_addr(std::string ipstr, int port, int ipv, struct sockaddr *saddr) {
|
||||
if(ipv == 4) {
|
||||
struct sockaddr_in *in4 = (struct sockaddr_in*)saddr;
|
||||
in4->sin_port = htons(port);
|
||||
@@ -202,11 +200,9 @@ void create_addr(std::string ipstr, int port, int ipv, struct sockaddr *saddr)
|
||||
}
|
||||
if(ipv == 6) {
|
||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)saddr;
|
||||
server = gethostbyname2(ipstr.c_str(),AF_INET6);
|
||||
memset((char *) in6, 0, sizeof(struct sockaddr_in6));
|
||||
inet_pton(AF_INET6, ipstr.c_str(), &(in6->sin6_addr));
|
||||
in6->sin6_flowinfo = 0;
|
||||
in6->sin6_family = AF_INET6;
|
||||
memmove((char *) in6->sin6_addr.s6_addr, (char *) server->h_addr, server->h_length);
|
||||
in6->sin6_port = htons(port);
|
||||
}
|
||||
}
|
||||
@@ -244,7 +240,7 @@ void RECORD_RESULTS(int *test_number, bool passed, char *details, std::vector<st
|
||||
// TCP
|
||||
|
||||
//
|
||||
void tcp_client_4(UNIT_TEST_SIG_4)
|
||||
void tcp_client_4(TCP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_client_4\n");
|
||||
int r, w, sockfd, err, len = strlen(str);
|
||||
@@ -254,6 +250,13 @@ void tcp_client_4(UNIT_TEST_SIG_4)
|
||||
DEBUG_ERROR("error creating ZeroTier socket");
|
||||
if((err = zts_connect(sockfd, (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_in peer_addr;
|
||||
socklen_t peer_addrlen;
|
||||
zts_getpeername(sockfd, (struct sockaddr*)&peer_addr, &peer_addrlen);
|
||||
DEBUG_INFO("getpeername() => %s : %d", inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port));
|
||||
|
||||
w = zts_write(sockfd, str, len);
|
||||
r = zts_read(sockfd, rbuf, len);
|
||||
DEBUG_TEST("Sent : %s", str);
|
||||
@@ -265,7 +268,7 @@ void tcp_client_4(UNIT_TEST_SIG_4)
|
||||
}
|
||||
|
||||
//
|
||||
void tcp_server_4(UNIT_TEST_SIG_4)
|
||||
void tcp_server_4(TCP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_server_4\n");
|
||||
int w=0, r=0, sockfd, accfd, err, len = strlen(str);
|
||||
@@ -279,6 +282,13 @@ void tcp_server_4(UNIT_TEST_SIG_4)
|
||||
printf("error placing socket in LISTENING state (%d)", err);
|
||||
if((accfd = zts_accept(sockfd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0)
|
||||
DEBUG_ERROR("error accepting connection (%d)", err);
|
||||
|
||||
// TODO: Put this test in the general API section
|
||||
struct sockaddr_in peer_addr;
|
||||
socklen_t peer_addrlen;
|
||||
zts_getpeername(accfd, (struct sockaddr*)&peer_addr, &peer_addrlen);
|
||||
DEBUG_INFO("getpeername() => %s : %d", inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port));
|
||||
|
||||
r = zts_read(accfd, rbuf, sizeof rbuf);
|
||||
w = zts_write(accfd, rbuf, len);
|
||||
DEBUG_TEST("Received : %s", rbuf);
|
||||
@@ -290,7 +300,7 @@ void tcp_server_4(UNIT_TEST_SIG_4)
|
||||
}
|
||||
|
||||
//
|
||||
void tcp_client_6(UNIT_TEST_SIG_6)
|
||||
void tcp_client_6(TCP_UNIT_TEST_SIG_6)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_client_6\n");
|
||||
int r, w, sockfd, err, len = strlen(str);
|
||||
@@ -300,6 +310,16 @@ void tcp_client_6(UNIT_TEST_SIG_6)
|
||||
DEBUG_ERROR("error creating ZeroTier socket");
|
||||
if((err = zts_connect(sockfd, (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_in6 *p6 = (struct sockaddr_in6*)&peer_addr;
|
||||
socklen_t peer_addrlen;
|
||||
zts_getpeername(sockfd, (struct sockaddr*)&peer_addr, &peer_addrlen);
|
||||
char peer_addrstr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &(p6->sin6_addr), peer_addrstr, INET6_ADDRSTRLEN);
|
||||
DEBUG_INFO("getpeername() => %s : %d", peer_addrstr, ntohs(p6->sin6_port));
|
||||
|
||||
w = zts_write(sockfd, str, len);
|
||||
r = zts_read(sockfd, rbuf, len);
|
||||
sleep(WAIT_FOR_TRANSMISSION_TO_COMPLETE);
|
||||
@@ -311,7 +331,7 @@ void tcp_client_6(UNIT_TEST_SIG_6)
|
||||
}
|
||||
|
||||
//
|
||||
void tcp_server_6(UNIT_TEST_SIG_6)
|
||||
void tcp_server_6(TCP_UNIT_TEST_SIG_6)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_server_6\n");
|
||||
int w=0, r=0, sockfd, accfd, err, len = strlen(str);
|
||||
@@ -325,6 +345,16 @@ void tcp_server_6(UNIT_TEST_SIG_6)
|
||||
DEBUG_ERROR("error placing socket in LISTENING state (%d)", err);
|
||||
if((accfd = zts_accept(sockfd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0)
|
||||
DEBUG_ERROR("error accepting connection (%d)", err);
|
||||
|
||||
// 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;
|
||||
zts_getpeername(accfd, (struct sockaddr*)&peer_addr, &peer_addrlen);
|
||||
char peer_addrstr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &(p6->sin6_addr), peer_addrstr, INET6_ADDRSTRLEN);
|
||||
DEBUG_INFO("getpeername() => %s : %d", peer_addrstr, ntohs(p6->sin6_port));
|
||||
|
||||
r = zts_read(accfd, rbuf, sizeof rbuf);
|
||||
w = zts_write(accfd, rbuf, len);
|
||||
DEBUG_TEST("Received : %s", rbuf);
|
||||
@@ -338,88 +368,170 @@ void tcp_server_6(UNIT_TEST_SIG_6)
|
||||
// UDP
|
||||
|
||||
//
|
||||
void udp_client_4(UNIT_TEST_SIG_4)
|
||||
void udp_client_4(UDP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\nudp_client_4\n");
|
||||
int r, w, sockfd, err, len = strlen(str);
|
||||
char rbuf[STR_SIZE];
|
||||
memset(rbuf, 0, sizeof rbuf);
|
||||
|
||||
if((sockfd = zts_socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
DEBUG_ERROR("error creating ZeroTier socket");
|
||||
if((err = zts_fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0))
|
||||
std::cout << "error setting O_NONBLOCK (errno=" << strerror(errno) << ")" << std::endl;
|
||||
fprintf(stderr, "sending UDP packets until I get a single response...\n");
|
||||
if((err = zts_bind(sockfd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in)) < 0))
|
||||
DEBUG_ERROR("error binding to interface (%d)", err);
|
||||
|
||||
w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)addr, sizeof(addr));
|
||||
struct sockaddr_in saddr;
|
||||
while(1) {
|
||||
// tx
|
||||
if((w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)remote_addr, sizeof(remote_addr))) < 0) {
|
||||
DEBUG_ERROR("error sending packet, err=%d", errno);
|
||||
}
|
||||
sleep(1);
|
||||
memset(rbuf, 0, sizeof(rbuf));
|
||||
int serverlen = sizeof(addr);
|
||||
r = zts_recvfrom(sockfd, rbuf, STR_SIZE, 0, (struct sockaddr *)&addr, (socklen_t *)&serverlen);
|
||||
|
||||
int serverlen = sizeof(remote_addr);
|
||||
// rx
|
||||
r = zts_recvfrom(sockfd, rbuf, STR_SIZE, 0, (struct sockaddr *)&saddr, (socklen_t *)&serverlen);
|
||||
if(r == strlen(str)) {
|
||||
sleep(WAIT_FOR_TRANSMISSION_TO_COMPLETE);
|
||||
err = zts_close(sockfd);
|
||||
DEBUG_INFO("udp_client_4, n=%d, err=%d, r=%d, w=%d\n", count, err, r, w);
|
||||
sprintf(details, "udp_client_4, n=%d, err=%d, r=%d, w=%d", count, err, r, w);
|
||||
DEBUG_TEST("Sent : %s", str);
|
||||
DEBUG_TEST("Received : %s", rbuf);
|
||||
*passed = (w == len && r == len && !err) && !strcmp(rbuf, str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void udp_server_4(UNIT_TEST_SIG_4)
|
||||
void udp_server_4(UDP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\nudp_server_4\n");
|
||||
int r, w, sockfd, err, len = strlen(str);
|
||||
char rbuf[STR_SIZE];
|
||||
memset(rbuf, 0, sizeof rbuf);
|
||||
|
||||
if((sockfd = zts_socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
DEBUG_ERROR("error creating ZeroTier socket");
|
||||
|
||||
if((err = zts_bind(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0))
|
||||
if((err = zts_bind(sockfd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in)) < 0))
|
||||
DEBUG_ERROR("error binding to interface (%d)", err);
|
||||
|
||||
int serverlen = sizeof(addr);
|
||||
r = zts_recvfrom(sockfd, rbuf, STR_SIZE, 0, (struct sockaddr *)&addr, (socklen_t *)&serverlen);
|
||||
memset(rbuf, 0, sizeof(rbuf));
|
||||
w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)addr, sizeof(addr));
|
||||
|
||||
// rx
|
||||
fprintf(stderr, "waiting for UDP packet...\n");
|
||||
struct sockaddr_in saddr;
|
||||
int serverlen = sizeof(saddr);
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
r = zts_recvfrom(sockfd, rbuf, STR_SIZE, 0, (struct sockaddr *)&saddr, (socklen_t *)&serverlen);
|
||||
char addrstr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &(saddr.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_INFO("received DGRAM from %s : %d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
|
||||
DEBUG_INFO("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(1) {
|
||||
sleep(1);
|
||||
DEBUG_INFO("sending UDP packet");
|
||||
if((w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)remote_addr, sizeof(remote_addr))) < 0) {
|
||||
DEBUG_ERROR("error sending packet, err=%d", errno);
|
||||
}
|
||||
if(get_now_ts() >= tx_ti + 20000) {
|
||||
//fprintf(stderr, "tx_ti=%d\n", tx_ti);
|
||||
break;
|
||||
}
|
||||
}
|
||||
sleep(WAIT_FOR_TRANSMISSION_TO_COMPLETE);
|
||||
err = zts_close(sockfd);
|
||||
//err = zts_close(sockfd);
|
||||
DEBUG_INFO("udp_server_4, n=%d, err=%d, r=%d, w=%d\n", count, err, r, w);
|
||||
sprintf(details, "udp_server_4, n=%d, err=%d, r=%d, w=%d", count, err, r, w);
|
||||
DEBUG_TEST("Sent : %s", str);
|
||||
DEBUG_TEST("Received : %s", rbuf);
|
||||
*passed = (w == len && r == len && !err) && !strcmp(rbuf, str);
|
||||
}
|
||||
|
||||
void udp_client_6(UNIT_TEST_SIG_6)
|
||||
//
|
||||
void udp_client_6(UDP_UNIT_TEST_SIG_6)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_client_6\n");
|
||||
fprintf(stderr, "\n\n\nudp_client_6\n");
|
||||
int r, w, sockfd, err, len = strlen(str);
|
||||
char rbuf[STR_SIZE];
|
||||
memset(rbuf, 0, sizeof rbuf);
|
||||
if((sockfd = zts_socket(AF_INET6, SOCK_STREAM, 0)) < 0)
|
||||
|
||||
if((sockfd = zts_socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
|
||||
DEBUG_ERROR("error creating ZeroTier socket");
|
||||
if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0)
|
||||
DEBUG_ERROR("error connecting to remote host (%d)", err);
|
||||
w = zts_write(sockfd, str, len);
|
||||
r = zts_read(sockfd, rbuf, len);
|
||||
if((err = zts_fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0))
|
||||
std::cout << "error setting O_NONBLOCK (errno=" << strerror(errno) << ")" << std::endl;
|
||||
fprintf(stderr, "sending UDP packets until I get a single response...\n");
|
||||
if((err = zts_bind(sockfd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in6)) < 0))
|
||||
DEBUG_ERROR("error binding to interface (%d)", err);
|
||||
|
||||
struct sockaddr_in saddr;
|
||||
while(1) {
|
||||
// tx
|
||||
if((w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)remote_addr, sizeof(remote_addr))) < 0) {
|
||||
DEBUG_ERROR("error sending packet, err=%d", errno);
|
||||
}
|
||||
sleep(1);
|
||||
memset(rbuf, 0, sizeof(rbuf));
|
||||
int serverlen = sizeof(remote_addr);
|
||||
// rx
|
||||
r = zts_recvfrom(sockfd, rbuf, STR_SIZE, 0, (struct sockaddr *)&saddr, (socklen_t *)&serverlen);
|
||||
if(r == strlen(str)) {
|
||||
sleep(WAIT_FOR_TRANSMISSION_TO_COMPLETE);
|
||||
err = zts_close(sockfd);
|
||||
sprintf(details, "tcp_client_6, n=%d, err=%d, r=%d, w=%d", count, err, r, w);
|
||||
DEBUG_INFO("udp_client_6, n=%d, err=%d, r=%d, w=%d\n", count, err, r, w);
|
||||
sprintf(details, "udp_client_6, n=%d, err=%d, r=%d, w=%d", count, err, r, w);
|
||||
DEBUG_TEST("Sent : %s", str);
|
||||
DEBUG_TEST("Received : %s", rbuf);
|
||||
*passed = (w == len && r == len && !err) && !strcmp(rbuf, str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void udp_server_6(UNIT_TEST_SIG_6)
|
||||
void udp_server_6(UDP_UNIT_TEST_SIG_6)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_client_6\n");
|
||||
fprintf(stderr, "\n\n\nudp_server_6\n");
|
||||
int r, w, sockfd, err, len = strlen(str);
|
||||
char rbuf[STR_SIZE];
|
||||
memset(rbuf, 0, sizeof rbuf);
|
||||
if((sockfd = zts_socket(AF_INET6, SOCK_STREAM, 0)) < 0)
|
||||
|
||||
if((sockfd = zts_socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
|
||||
DEBUG_ERROR("error creating ZeroTier socket");
|
||||
if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0)
|
||||
DEBUG_ERROR("error connecting to remote host (%d)", err);
|
||||
w = zts_write(sockfd, str, len);
|
||||
r = zts_read(sockfd, rbuf, len);
|
||||
if((err = zts_bind(sockfd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in6)) < 0))
|
||||
DEBUG_ERROR("error binding to interface (%d)", err);
|
||||
// rx
|
||||
fprintf(stderr, "waiting for UDP packet...\n");
|
||||
struct sockaddr_in6 saddr;
|
||||
int serverlen = sizeof(saddr);
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
r = zts_recvfrom(sockfd, rbuf, STR_SIZE, 0, (struct sockaddr *)&saddr, (socklen_t *)&serverlen);
|
||||
|
||||
char addrstr[INET6_ADDRSTRLEN], remote_addrstr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &(saddr.sin6_addr), addrstr, INET6_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET6, &(remote_addr->sin6_addr), remote_addrstr, INET6_ADDRSTRLEN);
|
||||
DEBUG_INFO("received DGRAM from %s : %d", addrstr, ntohs(saddr.sin6_port));
|
||||
DEBUG_INFO("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(1) {
|
||||
sleep(1);
|
||||
DEBUG_INFO("sending UDP packet");
|
||||
if((w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)remote_addr, sizeof(remote_addr))) < 0) {
|
||||
DEBUG_ERROR("error sending packet, err=%d", errno);
|
||||
}
|
||||
if(get_now_ts() >= tx_ti + 20000) {
|
||||
//fprintf(stderr, "tx_ti=%d\n", tx_ti);
|
||||
break;
|
||||
}
|
||||
}
|
||||
sleep(WAIT_FOR_TRANSMISSION_TO_COMPLETE);
|
||||
err = zts_close(sockfd);
|
||||
sprintf(details, "tcp_client_6, n=%d, err=%d, r=%d, w=%d", count, err, r, w);
|
||||
//err = zts_close(sockfd);
|
||||
DEBUG_INFO("udp_server_6, n=%d, err=%d, r=%d, w=%d\n", count, err, r, w);
|
||||
sprintf(details, "udp_server_6, n=%d, err=%d, r=%d, w=%d", count, err, r, w);
|
||||
DEBUG_TEST("Sent : %s", str);
|
||||
DEBUG_TEST("Received : %s", rbuf);
|
||||
*passed = (w == len && r == len && !err) && !strcmp(rbuf, str);
|
||||
@@ -432,7 +544,7 @@ void udp_server_6(UNIT_TEST_SIG_6)
|
||||
/****************************************************************************/
|
||||
|
||||
// Maintain transfer for count OR count
|
||||
void tcp_client_sustained_4(UNIT_TEST_SIG_4)
|
||||
void tcp_client_sustained_4(TCP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_client_sustained_4\n");
|
||||
int n=0, w=0, r=0, sockfd, err;
|
||||
@@ -508,7 +620,7 @@ void tcp_client_sustained_4(UNIT_TEST_SIG_4)
|
||||
|
||||
|
||||
// Maintain transfer for count OR count
|
||||
void tcp_client_sustained_6(UNIT_TEST_SIG_6)
|
||||
void tcp_client_sustained_6(TCP_UNIT_TEST_SIG_6)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_client_sustained_6\n");
|
||||
int n=0, w=0, r=0, sockfd, err;
|
||||
@@ -584,7 +696,7 @@ void tcp_client_sustained_6(UNIT_TEST_SIG_6)
|
||||
|
||||
|
||||
// Maintain transfer for count OR count
|
||||
void tcp_server_sustained_4(UNIT_TEST_SIG_4)
|
||||
void tcp_server_sustained_4(TCP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_server_sustained_4\n");
|
||||
int n=0, w=0, r=0, sockfd, accfd, err;
|
||||
@@ -650,7 +762,7 @@ void tcp_server_sustained_4(UNIT_TEST_SIG_4)
|
||||
|
||||
|
||||
// Maintain transfer for count OR count
|
||||
void tcp_server_sustained_6(UNIT_TEST_SIG_6)
|
||||
void tcp_server_sustained_6(TCP_UNIT_TEST_SIG_6)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_server_sustained_6\n");
|
||||
int n=0, w=0, r=0, sockfd, accfd, err;
|
||||
@@ -712,13 +824,65 @@ void tcp_server_sustained_6(UNIT_TEST_SIG_6)
|
||||
free(rxbuf);
|
||||
}
|
||||
|
||||
void udp_client_sustained_4(TCP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\nudp_client_sustained_4\n");
|
||||
int r, w, sockfd, err, len = strlen(str);
|
||||
char rbuf[STR_SIZE];
|
||||
memset(rbuf, 0, sizeof rbuf);
|
||||
if((sockfd = zts_socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
DEBUG_ERROR("error creating ZeroTier socket");
|
||||
|
||||
for(int i=0; i<1000; i++) {
|
||||
w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)addr, sizeof(addr));
|
||||
}
|
||||
memset(rbuf, 0, sizeof(rbuf));
|
||||
int serverlen = sizeof(addr);
|
||||
r = zts_recvfrom(sockfd, rbuf, STR_SIZE, 0, (struct sockaddr *)&addr, (socklen_t *)&serverlen);
|
||||
|
||||
sleep(WAIT_FOR_TRANSMISSION_TO_COMPLETE);
|
||||
err = zts_close(sockfd);
|
||||
sprintf(details, "udp_client_4, n=%d, err=%d, r=%d, w=%d", count, err, r, w);
|
||||
DEBUG_TEST("Sent : %s", str);
|
||||
DEBUG_TEST("Received : %s", rbuf);
|
||||
*passed = (w == len && r == len && !err) && !strcmp(rbuf, str);
|
||||
}
|
||||
|
||||
void udp_server_sustained_4(TCP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\nudp_server_sustained_4\n");
|
||||
int r, w, sockfd, err, len = strlen(str);
|
||||
char rbuf[STR_SIZE];
|
||||
memset(rbuf, 0, sizeof rbuf);
|
||||
if((sockfd = zts_socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
DEBUG_ERROR("error creating ZeroTier socket");
|
||||
|
||||
if((err = zts_bind(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0))
|
||||
DEBUG_ERROR("error binding to interface (%d)", err);
|
||||
|
||||
int serverlen = sizeof(addr);
|
||||
for(int i=0; i<100; i++) {
|
||||
memset(rbuf, 0, sizeof(rbuf));
|
||||
r = zts_recvfrom(sockfd, rbuf, STR_SIZE, 0, (struct sockaddr *)&addr, (socklen_t *)&serverlen);
|
||||
DEBUG_TEST("Received : %s", rbuf);
|
||||
}
|
||||
//memset(rbuf, 0, sizeof(rbuf));
|
||||
//w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)addr, sizeof(addr));
|
||||
w = r;
|
||||
//sleep(WAIT_FOR_TRANSMISSION_TO_COMPLETE);
|
||||
//err = zts_close(sockfd);
|
||||
sprintf(details, "udp_server_4, n=%d, err=%d, r=%d, w=%d", count, err, r, w);
|
||||
DEBUG_TEST("Sent : %s", str);
|
||||
DEBUG_TEST("Received : %s", rbuf);
|
||||
*passed = (w == len && r == len && !err) && !strcmp(rbuf, str);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* PERFORMANCE (between library instances) */
|
||||
/****************************************************************************/
|
||||
|
||||
// Maintain transfer for count OR count
|
||||
void tcp_client_perf_4(UNIT_TEST_SIG_4)
|
||||
void tcp_client_perf_4(TCP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_client_perf_4\n");
|
||||
/*
|
||||
@@ -757,7 +921,7 @@ void tcp_client_perf_4(UNIT_TEST_SIG_4)
|
||||
}
|
||||
|
||||
// Maintain transfer for count OR count
|
||||
void tcp_server_perf_4(UNIT_TEST_SIG_4)
|
||||
void tcp_server_perf_4(TCP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_server_perf_4\n");
|
||||
/*
|
||||
@@ -811,7 +975,7 @@ void tcp_server_perf_4(UNIT_TEST_SIG_4)
|
||||
/* PERFORMANCE (between library and native) */
|
||||
/****************************************************************************/
|
||||
|
||||
void tcp_perf_tx_echo_4(UNIT_TEST_SIG_4)
|
||||
void tcp_perf_tx_echo_4(TCP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_perf_tx_echo_4\n");
|
||||
|
||||
@@ -879,7 +1043,7 @@ void tcp_perf_tx_echo_4(UNIT_TEST_SIG_4)
|
||||
}
|
||||
|
||||
|
||||
void tcp_perf_rx_echo_4(UNIT_TEST_SIG_4)
|
||||
void tcp_perf_rx_echo_4(TCP_UNIT_TEST_SIG_4)
|
||||
{
|
||||
fprintf(stderr, "\n\n\ntcp_perf_rx_echo_4\n");
|
||||
|
||||
@@ -1335,14 +1499,29 @@ void test_bad_args()
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
// Tests rapid opening and closure of sockets
|
||||
void close_test(struct sockaddr *bind_addr)
|
||||
{
|
||||
int err = 0;
|
||||
for(int i=0; i<64; i++)
|
||||
{
|
||||
int fd = zts_socket(AF_INET, SOCK_STREAM, 0);
|
||||
if((err = zts_bind(fd, (struct sockaddr *)&bind_addr, sizeof(struct sockaddr_in)) < 0))
|
||||
DEBUG_ERROR("error binding to interface (%d)", err);
|
||||
if((err = zts_close(fd)) < 0) {
|
||||
DEBUG_ERROR("error closing socket (%d)", err);
|
||||
}
|
||||
DEBUG_INFO("i=%d, close() = %d", i, err);
|
||||
usleep(100000);
|
||||
((struct sockaddr_in *)bind_addr)->sin_port++;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* main(), calls test_driver(...) */
|
||||
@@ -1443,147 +1622,214 @@ int main(int argc , char *argv[])
|
||||
/****************************************************************************/
|
||||
|
||||
int test_number = 0, ipv;
|
||||
struct sockaddr addr;
|
||||
char details[128];
|
||||
memset(&details, 0, sizeof details);
|
||||
bool passed = 0;
|
||||
|
||||
struct sockaddr local_addr;
|
||||
struct sockaddr remote_addr;
|
||||
|
||||
// closure test
|
||||
|
||||
port = 1000;
|
||||
struct sockaddr_in in4;
|
||||
create_addr(local_ipstr, port, 4, (struct sockaddr *)&in4);
|
||||
close_test((struct sockaddr*)&in4);
|
||||
|
||||
// Transmission Tests
|
||||
|
||||
port = start_port;
|
||||
delay = 0;
|
||||
count = 1024*128;
|
||||
operation = TEST_OP_N_BYTES;
|
||||
|
||||
// ipv4 client/server (UDP)
|
||||
ipv = 4;
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
udp_server_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
udp_client_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles
|
||||
port++; // move up one port
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
udp_server_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
udp_client_4((struct sockaddr_in *)&local_addr, (struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
port++;
|
||||
|
||||
// ipv6 client/server (UDP)
|
||||
ipv = 6;
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr);
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
udp_server_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr);
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
udp_client_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles
|
||||
port++; // move up one port
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr);
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
udp_server_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr);
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
udp_client_6((struct sockaddr_in6 *)&local_addr, (struct sockaddr_in6 *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
port++;
|
||||
|
||||
// ipv4 sustained transfer (UDP)
|
||||
ipv = 4;
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr);
|
||||
tcp_server_sustained_4((struct sockaddr_in *)&local_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_client_sustained_4((struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles
|
||||
port++;
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr);
|
||||
tcp_server_sustained_4((struct sockaddr_in *)&local_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_client_sustained_4((struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
port++;
|
||||
|
||||
// ipv4 client/server
|
||||
|
||||
ipv = 4;
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_server_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_server_4
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr);
|
||||
tcp_server_4((struct sockaddr_in *)&local_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_client_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_client_4
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_client_4((struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles
|
||||
port++; // move up one port
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_server_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_server_4
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr);
|
||||
tcp_server_4((struct sockaddr_in *)&local_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_client_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_client_4
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_client_4((struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
port++;
|
||||
|
||||
// UDP
|
||||
/*
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
udp_server_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_server_4
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
udp_client_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_client_4
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles
|
||||
port++; // move up one port
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
udp_server_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_server_4
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
udp_client_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_client_4
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
port++;
|
||||
*/
|
||||
// ipv4 sustained transfer
|
||||
// ipv4 sustained transfer (TCP)
|
||||
ipv = 4;
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_server_sustained_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_server_sustained_4
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr);
|
||||
tcp_server_sustained_4((struct sockaddr_in *)&local_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_client_sustained_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_client_sustained_4
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_client_sustained_4((struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results); // swtich roles
|
||||
mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles
|
||||
port++;
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_server_sustained_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_server_sustained_4
|
||||
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr);
|
||||
tcp_server_sustained_4((struct sockaddr_in *)&local_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_client_sustained_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_client_sustained_4
|
||||
create_addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_client_sustained_4((struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
port++;
|
||||
|
||||
|
||||
// ipv6 client/server
|
||||
// ipv6 client/server (TCP)
|
||||
ipv = 6;
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_server_6((struct sockaddr_in6 *)&addr, operation, count, delay, details, &passed); // tcp_server_6
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr);
|
||||
tcp_server_6((struct sockaddr_in6 *)&local_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
DEBUG_TEST("waiting (15s) for other selftest to complete before continuing...");
|
||||
sleep(WAIT_FOR_TEST_TO_CONCLUDE);
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_client_6((struct sockaddr_in6 *)&addr, operation, count, delay, details, &passed); // tcp_client_6
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_client_6((struct sockaddr_in6 *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles
|
||||
port++; // move up one port
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_server_6((struct sockaddr_in6 *)&addr, operation, count, delay, details, &passed); // tcp_server_6
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr);
|
||||
tcp_server_6((struct sockaddr_in6 *)&local_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_client_6((struct sockaddr_in6 *)&addr, operation, count, delay, details, &passed); // tcp_client_6
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_client_6((struct sockaddr_in6 *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
port++;
|
||||
|
||||
|
||||
// ipv6 sustained transfer
|
||||
// ipv6 sustained transfer (TCP)
|
||||
ipv = 6;
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_server_sustained_6((struct sockaddr_in6 *)&addr, operation, count, delay, details, &passed); // tcp_server_sustained_4
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr);
|
||||
tcp_server_sustained_6((struct sockaddr_in6 *)&local_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_client_sustained_6((struct sockaddr_in6 *)&addr, operation, count, delay, details, &passed); // tcp_client_sustained_4
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_client_sustained_6((struct sockaddr_in6 *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results); // swtich roles
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
mode = mode == TEST_MODE_SERVER ? TEST_MODE_CLIENT : TEST_MODE_SERVER; // switch roles
|
||||
port++;
|
||||
if(mode == TEST_MODE_SERVER) {
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_server_sustained_6((struct sockaddr_in6 *)&addr, operation, count, delay, details, &passed); // tcp_server_sustained_4
|
||||
create_addr(local_ipstr6, port, ipv, (struct sockaddr *)&local_addr);
|
||||
tcp_server_sustained_6((struct sockaddr_in6 *)&local_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
else if(mode == TEST_MODE_CLIENT) {
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_client_sustained_6((struct sockaddr_in6 *)&addr, operation, count, delay, details, &passed); // tcp_client_sustained_4
|
||||
create_addr(remote_ipstr6, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_client_sustained_6((struct sockaddr_in6 *)&remote_addr, operation, count, delay, details, &passed);
|
||||
}
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
port++;
|
||||
@@ -1591,28 +1837,30 @@ int main(int argc , char *argv[])
|
||||
// PERFORMANCE (between this library instance and a native non library instance (echo) )
|
||||
// Client/Server mode isn't being tested here, so it isn't important, we'll just set it to client
|
||||
|
||||
// ipv4 echo test
|
||||
// ipv4 echo test (TCP)
|
||||
/*
|
||||
ipv = 4;
|
||||
if(me == "alice" || me == "ted") {
|
||||
port=start_port+100; // e.g. 7100
|
||||
create_addr(remote_echo_ipv4, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_perf_tx_echo_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_perf_tx_echo_4
|
||||
create_addr(remote_echo_ipv4, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_perf_tx_echo_4((struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
tcp_perf_rx_echo_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_perf_rx_echo_4
|
||||
tcp_perf_rx_echo_4((struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
}
|
||||
if(me == "bob" || me == "carol") {
|
||||
DEBUG_TEST("waiting (15s) for other selftest to complete before continuing...");
|
||||
sleep(WAIT_FOR_TEST_TO_CONCLUDE);
|
||||
port=start_port+101; // e.g. 7101
|
||||
create_addr(remote_echo_ipv4, port, ipv, (struct sockaddr *)&addr);
|
||||
tcp_perf_rx_echo_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_perf_tx_echo_4
|
||||
create_addr(remote_echo_ipv4, port, ipv, (struct sockaddr *)&remote_addr);
|
||||
tcp_perf_rx_echo_4((struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
sleep(WAIT_FOR_SERVER_TO_COME_ONLINE);
|
||||
tcp_perf_tx_echo_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_perf_rx_echo_4
|
||||
tcp_perf_tx_echo_4((struct sockaddr_in *)&remote_addr, operation, count, delay, details, &passed);
|
||||
RECORD_RESULTS(&test_number, passed, details, &results);
|
||||
}
|
||||
*/
|
||||
|
||||
// RANDOM API TEST
|
||||
//random_api_test();
|
||||
|
||||
Reference in New Issue
Block a user