significant upgrade to selftest, added echotest, better checks for data in queue before socket closure
This commit is contained in:
@@ -21,13 +21,14 @@ Pre-Built Binaries Here: [zerotier.com/download.shtml](https://zerotier.com/down
|
||||
|
||||
char *str = "welcome to the machine"; // test msg
|
||||
char *nwid = "c7cd7c9e1b0f52a2"; // network to join
|
||||
char *pasth = "zt1"; // path where this node's keys and configs will be stored
|
||||
char *ip = "10.8.8.42"; // resource on ZeroTier network
|
||||
char *path = "zt1"; // path where this node's keys and configs will be stored
|
||||
char *ip = "10.8.8.42"; // host on ZeroTier network
|
||||
int port = 8080; // resource's port
|
||||
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = inet_addr(ip);
|
||||
addr.sin_port = hton(8080);
|
||||
addr.sin_port = hton(port);
|
||||
|
||||
zts_simple_start(path, nwid);
|
||||
int fd = zts_socket(AF_INET, SOCK_STREAM, 0);
|
||||
@@ -42,7 +43,7 @@ Bindings for various [languages](examples)
|
||||
|
||||
### Building (linux, macos, bsd, win, ios)
|
||||
|
||||
All build targets will output to `build/`. Complete instructions [here](BUILDING.md).
|
||||
All targets will output to `build/`. Complete instructions [here](BUILDING.md)
|
||||
|
||||
- Static Library (linux, mac, win, bsd): `make static_lib`
|
||||
- iOS App Framework: `make ios_app_framework`
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
### 2017-06-30 -- Version 1.1.5
|
||||
|
||||
- Improvements in API consistency and coverage
|
||||
- Additional safety checks
|
||||
- Various bug fixes for socket abstraction layer
|
||||
- Rework of Connection lock scheme
|
||||
- IPv4 and IPv6 enabled by default
|
||||
- Performance (RX and TX) upgrades
|
||||
|
||||
***
|
||||
|
||||
|
||||
73
TESTING.md
73
TESTING.md
@@ -21,66 +21,59 @@ build
|
||||
|--darwin
|
||||
| |-libzt.a
|
||||
| |-selftest
|
||||
| |-echotest
|
||||
|
|
||||
|--linux
|
||||
| |-libzt.a
|
||||
| |-selftest
|
||||
| |-echotest
|
||||
|
|
||||
|--freebsd
|
||||
| |-libzt.a
|
||||
| |-selftest
|
||||
| |-echotest
|
||||
|
|
||||
|--win
|
||||
|-libzt.a
|
||||
|-selftest
|
||||
|-echotest
|
||||
```
|
||||
|
||||
### Simple Tests
|
||||
The self test will be performed over the network in the following configuration (addresses and ports are subject to change depending on what you define in your `test/*.conf` files):
|
||||

|
||||
|
||||
Simple tests merely test one aspect of the library. For instance, its role as an IPv4 server, or IPv6 client.
|
||||
### Test sets:
|
||||
|
||||
To run a single-test IPv4 client/server test:
|
||||
- Test set A: Tests for correctness, error handling, blocking behaviour, on-system performance, etc
|
||||
- Test set B: Tests RX performance (from non-libzt app)
|
||||
- Test set C: Tests TX performance (to non-libzt app)
|
||||
|
||||
- host-1: `./build/linux/selftest zt1 c7cd7c9e1b0f52a2 simple 4 server 10.9.9.40 8787`
|
||||
- host-2: `./build/linux/selftest zt2 c7cd7c9e1b0f52a2 simple 4 client 10.9.9.40 8787`
|
||||
### Types of tests (defined in `selftest.cpp`)
|
||||
|
||||
To run a multi-message IPv4 client/server test:
|
||||
#### Simple Tests:
|
||||
|
||||
- host-1: `./build/linux/selftest zt1 c7cd7c9e1b0f52a2 simple 4 server 10.9.9.40 8787 n_bytes 100 50`
|
||||
- host-2: `./build/linux/selftest zt2 c7cd7c9e1b0f52a2 simple 4 client 10.9.9.40 8787 n_bytes 100 50`
|
||||
- Simple tests merely test one aspect of the library. For instance, its role as an IPv4 server, or IPv6 client.
|
||||
|
||||
### Sustained Tests
|
||||
#### Sustained Tests
|
||||
|
||||
Sustained tests will test the library's ability to support long-duration connections and data transfers.
|
||||
- Sustained tests will test the library's ability to support long-duration connections and data transfers.
|
||||
|
||||
- host-1: `./build/linux/selftest sustained test/bob.conf`
|
||||
- host-2: `./build/linux/selftest sustained test/alice.conf`
|
||||
#### Slam Tests
|
||||
|
||||
### Slam Tests
|
||||
- Slam tests will test the library's ability to handle many repeated API calls or repeated common sequences of API calls that a typical application may make. For instance, it will try to create as many sockets as possible, or try to create a socket, bind to an address, listen, and accept over and over. This is useful for detecting memory leaks and architectural limitations in the stack drivers.
|
||||
|
||||
Slam tests will test the library's ability to handle many repeated API calls or repeated common sequences of API calls that a typical application may make. For instance, it will try to create as many sockets as possible, or try to create a socket, bind to an address, listen, and accept over and over. This is useful for detecting memory leaks and architectural limitations in the stack drivers.
|
||||
#### Comprehensive Tests
|
||||
|
||||
- host-1: `./build/linux/selftest slam test/bob.conf`
|
||||
- host-2: `./build/linux/selftest slam test/alice.conf`
|
||||
- A comprehensive test will test each aspect of the library one time.
|
||||
|
||||
### Comprehensive Tests
|
||||
#### Random Tests
|
||||
|
||||
A comprehensive test will test each aspect of the library one time.
|
||||
- Makes random API calls with random (or plausible arguments/data) to test for proper error handling
|
||||
|
||||
- host-1: `./build/linux/selftest comprehensive test/bob.conf`
|
||||
- host-2: `./build/linux/selftest comprehensive test/alice.conf`
|
||||
|
||||
### Random Tests
|
||||
|
||||
Makes random API calls with random (or plausible arguments/data) to test for proper error handling
|
||||
|
||||
- host-1: `./build/linux/selftest random test/bob.conf`
|
||||
|
||||
### Performance Tests
|
||||
|
||||
Test's the library's performance characteristics
|
||||
|
||||
- host-1: `./build/linux/selftest performance test/bob.conf`
|
||||
- host-2: `./build/linux/selftest performance test/alice.conf`
|
||||
|
||||
### Correctness Tests
|
||||
|
||||
Tests's the library's error handling, address treatment, and blocking/non-blocking behaviour.
|
||||
|
||||
- host-1: `./build/linux/selftest correctness test/bob.conf`
|
||||
- host-2: `./build/linux/selftest correctness test/alice.conf`
|
||||
#### Performance Tests
|
||||
|
||||
- Test's the library's performance characteristics
|
||||
|
||||
#### Correctness Tests
|
||||
|
||||
- Tests's the library's error handling, address treatment, and blocking/non-blocking behaviour.
|
||||
|
||||
BIN
docs/test_diagram.png
Normal file
BIN
docs/test_diagram.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
@@ -9,7 +9,7 @@
|
||||
#include "pico_frame.h"
|
||||
#include "pico_constants.h"
|
||||
|
||||
#define PICO_MAX_TIMERS 20
|
||||
#define PICO_MAX_TIMERS 64
|
||||
|
||||
#define PICO_ETH_MRU (1514u)
|
||||
#define PICO_IP_MRU (1500u)
|
||||
|
||||
@@ -1996,7 +1996,7 @@ int pico_transport_process_in(struct pico_protocol *self, struct pico_frame *f)
|
||||
return ret;
|
||||
|
||||
if (!IS_BCAST(f)) {
|
||||
dbg("Socket not found... \n");
|
||||
DEBUG_EXTRA("Socket not found...");
|
||||
pico_notify_socket_unreachable(f);
|
||||
ret = -1;
|
||||
pico_err = PICO_ERR_ENOENT;
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "pico_socket.h"
|
||||
#include "heap.h"
|
||||
|
||||
#include "../../../include/Debug.hpp"
|
||||
|
||||
/* Mockables */
|
||||
#if defined UNIT_TEST
|
||||
# define MOCKABLE __attribute__((weak))
|
||||
@@ -831,13 +833,13 @@ pico_timer_ref_add(pico_time expire, struct pico_timer *t, uint32_t id, uint32_t
|
||||
tref.hash = hash;
|
||||
|
||||
if (heap_insert(Timers, &tref) < 0) {
|
||||
dbg("Error: failed to insert timer(ID %u) into heap\n", id);
|
||||
DEBUG_ERROR("Error: failed to insert timer(ID %u) into heap", id);
|
||||
PICO_FREE(t);
|
||||
pico_err = PICO_ERR_ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
if (Timers->n > PICO_MAX_TIMERS) {
|
||||
dbg("Warning: I have %d timers\n", (int)Timers->n);
|
||||
DEBUG_ERROR("Warning: I have %d timers", (int)Timers->n);
|
||||
}
|
||||
|
||||
return tref.id;
|
||||
|
||||
@@ -24,21 +24,19 @@
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
/****************************************************************************/
|
||||
/* Debug */
|
||||
/****************************************************************************/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define ZT_DEBUG_LEVEL 5 // Set this to adjust what you'd like to see in the debug traces
|
||||
#define ZT_DEBUG_LEVEL 6 // Set this to adjust what you'd like to see in the debug traces
|
||||
|
||||
#define ZT_MSG_ERROR 1 // Errors
|
||||
#define ZT_MSG_TRANSFER 2 // RX/TX specific statements
|
||||
#define ZT_MSG_TEST 1 // For use in selftest
|
||||
#define ZT_MSG_ERROR 2 // Errors
|
||||
#define ZT_MSG_INFO 3 // Information which is generally useful to any developer
|
||||
#define ZT_MSG_EXTRA 4 // If nothing in your world makes sense
|
||||
#define ZT_MSG_FLOW 5 // High-level flow messages
|
||||
#define ZT_MSG_TRANSFER 5 // RX/TX specific statements
|
||||
#define ZT_MSG_FLOW 6 // High-level flow messages
|
||||
|
||||
#define ZT_COLOR true
|
||||
|
||||
// Debug output colors
|
||||
@@ -87,8 +85,15 @@
|
||||
#define ZT_LOG_TAG "ZTSDK"
|
||||
#endif
|
||||
|
||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_TEST
|
||||
#define DEBUG_TEST(fmt, args...) fprintf(stderr, ZT_CYN "ZT_TEST [%d] : %16s:%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 "ZT_ERROR[%ld] : %16s:%5d:%25s: " fmt \
|
||||
#define DEBUG_ERROR(fmt, args...) fprintf(stderr, ZT_RED "ZT_ERROR[%d] : %16s:%5d:%25s: " fmt \
|
||||
"\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#else
|
||||
#define DEBUG_ERROR(fmt, args...)
|
||||
@@ -106,13 +111,13 @@
|
||||
"ZT_STACK: %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
#else
|
||||
#define DEBUG_INFO(fmt, args...) fprintf(stderr, \
|
||||
"ZT_INFO [%ld] : %16s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
"ZT_INFO [%d] : %16s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#define DEBUG_ATTN(fmt, args...) fprintf(stderr, ZT_CYN \
|
||||
"ZT_ATTN [%ld] : %16s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
"ZT_ATTN [%d] : %16s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#define DEBUG_STACK(fmt, args...) fprintf(stderr, ZT_YEL \
|
||||
"ZT_STACK[%ld] : %16s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
"ZT_STACK[%d] : %16s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#define DEBUG_BLANK(fmt, args...) fprintf(stderr, \
|
||||
"ZT_INFO [%ld] : %16s:%5d:" fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, ##args)
|
||||
"ZT_INFO [%d] : %16s:%5d:" fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, ##args)
|
||||
#endif
|
||||
#else
|
||||
#define DEBUG_INFO(fmt, args...)
|
||||
@@ -139,7 +144,7 @@
|
||||
"ZT_EXTRA : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
#else
|
||||
#define DEBUG_EXTRA(fmt, args...) fprintf(stderr, \
|
||||
"ZT_EXTRA[%ld] : %16s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
"ZT_EXTRA[%d] : %16s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#endif
|
||||
#else
|
||||
#define DEBUG_EXTRA(fmt, args...)
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
|
||||
#define MAX_PICO_FRAME_RX_BUF_SZ ZT_MAX_MTU * 128
|
||||
|
||||
#define ZT_TCP_TX_BUF_SZ 1024 * 1024
|
||||
#define ZT_TCP_RX_BUF_SZ 1024 * 1024
|
||||
#define ZT_TCP_TX_BUF_SZ 1024 * 1024 * 5
|
||||
#define ZT_TCP_RX_BUF_SZ 1024 * 1024 * 5
|
||||
#define ZT_UDP_TX_BUF_SZ ZT_MAX_MTU
|
||||
#define ZT_UDP_RX_BUF_SZ ZT_MAX_MTU * 10
|
||||
|
||||
@@ -50,11 +50,11 @@
|
||||
|
||||
#define ZT_CORE_VERSION_MAJOR 1
|
||||
#define ZT_CORE_VERSION_MINOR 2
|
||||
#define ZT_CORE_VERSION_REVISION 4
|
||||
#define ZT_CORE_VERSION_REVISION 5
|
||||
|
||||
#define ZT_SDK_VERSION_MAJOR 1
|
||||
#define ZT_SDK_VERSION_MINOR 0
|
||||
#define ZT_SDK_VERSION_REVISION 0
|
||||
#define ZT_LIB_VERSION_MAJOR 1
|
||||
#define ZT_LIB_VERSION_MINOR 1
|
||||
#define ZT_LIB_VERSION_REVISION 4
|
||||
|
||||
#define ZT_MAX_IPADDR_LEN 64
|
||||
#define ZT_ID_LEN 10
|
||||
@@ -77,6 +77,9 @@
|
||||
#define ZT_SOCK_BEHAVIOR_LINGER true
|
||||
#define ZT_SOCK_BEHAVIOR_LINGER_TIME 3 // s
|
||||
|
||||
// Wait time for socket closure if data is still present in the write queue
|
||||
#define ZT_SDK_CLTIME 60
|
||||
|
||||
// After closing a pico_socket, other threads might still try to use the
|
||||
// Connection object for remaining data I/O, as a safety measure we will wait to
|
||||
// delete this Connection object until the socket has been closed for some arbitrary
|
||||
@@ -115,7 +118,7 @@
|
||||
|
||||
/****************************************************************************/
|
||||
/* SDK Socket API (ZeroTier Service Controls) */
|
||||
/* Implemented in SDKService.cpp */
|
||||
/* Implemented in libzt.cpp */
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -169,9 +172,9 @@ void zts_get_homepath(char *homePath, const int len);
|
||||
void zts_core_version(char *ver);
|
||||
|
||||
/**
|
||||
* Provides core SDK service version
|
||||
* Provides core libzt service version
|
||||
*/
|
||||
void zts_sdk_version(char *ver);
|
||||
void zts_lib_version(char *ver);
|
||||
|
||||
/**
|
||||
* Get device ID
|
||||
|
||||
@@ -80,6 +80,7 @@ INCLUDES+= -Iext \
|
||||
-I$(ZTO)/node \
|
||||
-I$(ZTO)/service \
|
||||
-I$(ZTO)/include \
|
||||
-I$(ZTO)/controller \
|
||||
-I../$(ZTO)/osdep \
|
||||
-I../$(ZTO)/node \
|
||||
-I../$(ZTO)/service \
|
||||
@@ -192,7 +193,7 @@ UNIT_TEST_LIBS := -L$(BUILD) -lzt $(COMMON_LIBS)
|
||||
|
||||
$(TEST_BUILD_DIR)/%: $(UNIT_TEST_SRC_DIR)/%.cpp
|
||||
@mkdir -p $(TEST_BUILD_DIR)
|
||||
@-$(CXX) $(UNIT_TEST_INCLUDES) -o $@ $< $(UNIT_TEST_LIBS)
|
||||
@-$(CXX) $(CXXFLAGS) $(UNIT_TEST_INCLUDES) $(INCLUDES) -o $@ $< $(UNIT_TEST_LIBS)
|
||||
@-./check.sh $@
|
||||
|
||||
unit_tests: $(UNIT_TEST_OBJ_FILES)
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
// SDK
|
||||
#include "libzt.h"
|
||||
#include "SocketTap.hpp"
|
||||
//#include "RingBuffer.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
@@ -48,8 +47,7 @@ namespace ZeroTier {
|
||||
*/
|
||||
struct Connection
|
||||
{
|
||||
//circular_buffer<char> crbuf = circular_buffer<char>(ZT_TCP_RX_BUF_SZ);
|
||||
//circular_buffer<char> ctbuf = circular_buffer<char>(ZT_TCP_TX_BUF_SZ);
|
||||
Mutex _tx_m, _rx_m;
|
||||
|
||||
int pid;
|
||||
PhySocket *sock;
|
||||
@@ -79,7 +77,6 @@ namespace ZeroTier {
|
||||
|
||||
Connection() {
|
||||
closure_ts = -1;
|
||||
// DEBUG_INFO("Connection() this = %p", this);
|
||||
ZT_PHY_SOCKFD_TYPE fdpair[2];
|
||||
if(socketpair(PF_LOCAL, SOCK_STREAM, 0, fdpair) < 0) {
|
||||
if(errno < 0) {
|
||||
|
||||
@@ -27,13 +27,10 @@
|
||||
// picoTCP
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/poll.h>
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
// SDK
|
||||
#include "SocketTap.hpp"
|
||||
|
||||
194
src/libzt.cpp
194
src/libzt.cpp
@@ -24,8 +24,14 @@
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
/* This file implements the libzt library API, it talks to the network
|
||||
stack driver and core ZeroTier service to create a socket-like interface
|
||||
for applications to use. See also: include/libzt.h */
|
||||
|
||||
#include <sys/socket.h>
|
||||
//#include <sys/ioctl.h>
|
||||
//#include <stropts.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -165,8 +171,8 @@ void zts_core_version(char *ver) {
|
||||
sprintf(ver, "%d.%d.%d", major, minor, revision);
|
||||
}
|
||||
|
||||
void zts_sdk_version(char *ver) {
|
||||
sprintf(ver, "%d.%d.%d", ZT_SDK_VERSION_MAJOR, ZT_SDK_VERSION_MINOR, ZT_SDK_VERSION_REVISION);
|
||||
void zts_lib_version(char *ver) {
|
||||
sprintf(ver, "%d.%d.%d", ZT_LIB_VERSION_MAJOR, ZT_LIB_VERSION_MINOR, ZT_LIB_VERSION_REVISION);
|
||||
}
|
||||
|
||||
int zts_get_device_id(char *devID) {
|
||||
@@ -314,11 +320,11 @@ void zts_disable_http_control_plane()
|
||||
|
||||
/*
|
||||
|
||||
socket fd = 0 (nwid=X)---\ /--- SocketTap=A // e.x. 172.27.0.0/?
|
||||
socket fd = 0 (nwid=X)---\ /--- SocketTap=A // e.x. 172.27.0.0 / 16
|
||||
\ /
|
||||
socket fd = 1 (nwid=Y)--------Multiplexed z* calls-------- SocketTap=B // e.x. 192.168.0.1/16
|
||||
socket fd = 1 (nwid=Y)--------Multiplexed z* calls-------- SocketTap=B // e.x. 192.168.0.1 / 16
|
||||
/ \
|
||||
socket fd = 2 (nwid=Z)---/ \--- SocketTap=C // e.x. 10.9.9.0/24
|
||||
socket fd = 2 (nwid=Z)---/ \--- SocketTap=C // e.x. 10.9.9.0 / 24
|
||||
|
||||
*/
|
||||
|
||||
@@ -332,22 +338,26 @@ Darwin:
|
||||
[NA] [ENFILE] The system file table is full.
|
||||
[ ] [ENOBUFS] Insufficient buffer space is available. The socket cannot be created until sufficient resources are freed.
|
||||
[ ] [ENOMEM] Insufficient memory was available to fulfill the request.
|
||||
[ ] [EPROTONOSUPPORT] The protocol type or the specified protocol is not supported within this domain.
|
||||
[--] [EPROTONOSUPPORT] The protocol type or the specified protocol is not supported within this domain.
|
||||
[ ] [EPROTOTYPE] The socket type is not supported by the protocol.
|
||||
*/
|
||||
|
||||
// int socket_family, int socket_type, int protocol
|
||||
int zts_socket(ZT_SOCKET_SIG) {
|
||||
DEBUG_INFO();
|
||||
int err = 0;
|
||||
if(!zt1Service) {
|
||||
DEBUG_ERROR("cannot create socket, no service running. call zts_start() first.");
|
||||
errno = EMFILE; // could also be ENFILE
|
||||
err = -1;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if(socket_type == SOCK_SEQPACKET) {
|
||||
DEBUG_ERROR("SOCK_SEQPACKET not yet supported.");
|
||||
errno = EPROTONOSUPPORT; // seemingly closest match
|
||||
return -1;
|
||||
}
|
||||
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
//DEBUG_INFO("unmap=%d, fdmap=%d", ZeroTier::unmap.size(), ZeroTier::fdmap.size());
|
||||
//DEBUG_INFO("timers = %d, max = %d", pico_ntimers(), PICO_MAX_TIMERS);
|
||||
if(pico_ntimers() >= PICO_MAX_TIMERS) {
|
||||
DEBUG_ERROR("cannot provision additional socket due to limitation of PICO_MAX_TIMERS. current = %d", pico_ntimers());
|
||||
errno = EMFILE;
|
||||
@@ -359,19 +369,10 @@ int zts_socket(ZT_SOCKET_SIG) {
|
||||
int protocol_version = 0;
|
||||
struct pico_socket *psock;
|
||||
|
||||
// TODO: check ifdef logic here
|
||||
//#if defined(SDK_IPV4)
|
||||
if(socket_family == AF_INET){
|
||||
// DEBUG_ERROR("AF_INET");
|
||||
if(socket_family == AF_INET)
|
||||
protocol_version = PICO_PROTO_IPV4;
|
||||
}
|
||||
//#endif
|
||||
//#if defined(SDK_IPV6)
|
||||
if(socket_family == AF_INET6) {
|
||||
// DEBUG_ERROR("AF_INET6");
|
||||
if(socket_family == AF_INET6)
|
||||
protocol_version = PICO_PROTO_IPV6;
|
||||
}
|
||||
//#endif
|
||||
|
||||
if(socket_type == SOCK_DGRAM) {
|
||||
psock = pico_socket_open(
|
||||
@@ -395,9 +396,7 @@ int zts_socket(ZT_SOCKET_SIG) {
|
||||
err = -1;
|
||||
}
|
||||
}
|
||||
//DEBUG_INFO(" unmap=%d, fdmap=%d", ZeroTier::unmap.size(), ZeroTier::fdmap.size());
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -415,7 +414,8 @@ Darwin:
|
||||
[ ] [ECONNREFUSED] The attempt to connect was ignored (because the target is not listening for connections) or explicitly rejected.
|
||||
[ ] [EFAULT] The address parameter specifies an area outside the process address space.
|
||||
[ ] [EHOSTUNREACH] The target host cannot be reached (e.g., down, disconnected).
|
||||
[--] [EINPROGRESS] The socket is non-blocking and the connection cannot be completed immediately. It is possible to select(2) for completion by selecting the socket for writing.
|
||||
[--] [EINPROGRESS] The socket is non-blocking and the connection cannot be completed immediately.
|
||||
It is possible to select(2) for completion by selecting the socket for writing.
|
||||
[NA] [EINTR] Its execution was interrupted by a signal.
|
||||
[ ] [EINVAL] An invalid argument was detected (e.g., address_len is not valid for the address family, the specified address family is invalid).
|
||||
[ ] [EISCONN] The socket is already connected.
|
||||
@@ -427,9 +427,35 @@ Darwin:
|
||||
[ ] [EPROTOTYPE] address has a different type than the socket that is bound to the specified peer address.
|
||||
[ ] [ETIMEDOUT] Connection establishment timed out without establishing a connection.
|
||||
[ ] [ECONNRESET] Remote host reset the connection request.
|
||||
|
||||
Linux:
|
||||
|
||||
[ ] [EACCES] For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket file,
|
||||
or search permission is denied for one of the directories in the path prefix. (See also path_resolution(7).)
|
||||
[ ] [EACCES, EPERM] The user tried to connect to a broadcast address without having the socket broadcast flag enabled or the
|
||||
connection request failed because of a local firewall rule.
|
||||
[ ] [EADDRINUSE] Local address is already in use.
|
||||
[ ] [EAFNOSUPPORT] The passed address didn't have the correct address family in its sa_family field.
|
||||
[ ] [EAGAIN] No more free local ports or insufficient entries in the routing cache. For AF_INET see the description
|
||||
of /proc/sys/net/ipv4/ip_local_port_range ip(7) for information on how to increase the number of local ports.
|
||||
[ ] [EALREADY] The socket is nonblocking and a previous connection attempt has not yet been completed.
|
||||
[ ] [EBADF] The file descriptor is not a valid index in the descriptor table.
|
||||
[ ] [ECONNREFUSED] No-one listening on the remote address.
|
||||
[ ] [EFAULT] The socket structure address is outside the user's address space.
|
||||
[ ] [EINPROGRESS] The socket is nonblocking and the connection cannot be completed immediately. It is possible to select(2) or
|
||||
poll(2) for completion by selecting the socket for writing. After select(2) indicates writability, use getsockopt(2)
|
||||
to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero)
|
||||
or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure).
|
||||
[ ] [EINTR] The system call was interrupted by a signal that was caught; see signal(7).
|
||||
[ ] [EISCONN] The socket is already connected.
|
||||
[ ] [ENETUNREACH] Network is unreachable.
|
||||
[ ] [ENOTSOCK] The file descriptor is not associated with a socket.
|
||||
[ ] [ETIMEDOUT] Timeout while attempting connection. The server may be too busy to accept new connections. Note that for
|
||||
IP sockets the timeout may be very long when syncookies are enabled on the server.
|
||||
|
||||
*/
|
||||
int zts_connect(ZT_CONNECT_SIG) {
|
||||
// DEBUG_INFO("fd = %d", fd);
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
@@ -566,16 +592,16 @@ Darwin:
|
||||
address space.
|
||||
*/
|
||||
int zts_bind(ZT_BIND_SIG) {
|
||||
//DEBUG_EXTRA("fd = %d", fd);
|
||||
DEBUG_EXTRA("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
return -1;
|
||||
}
|
||||
if(!zt1Service) {
|
||||
DEBUG_ERROR("Service not started. Call zts_start(path) first");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
@@ -618,7 +644,6 @@ int zts_bind(ZT_BIND_SIG) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
return err;
|
||||
}
|
||||
@@ -629,17 +654,24 @@ Darwin:
|
||||
|
||||
[--] [EACCES] The current process has insufficient privileges.
|
||||
[--] [EBADF] The argument socket is not a valid file descriptor.
|
||||
[ ] [EDESTADDRREQ] The socket is not bound to a local address and the protocol does not support listening on an unbound socket.
|
||||
[--] [EDESTADDRREQ] The socket is not bound to a local address and the protocol does not support listening on an unbound socket.
|
||||
[ ] [EINVAL] socket is already connected.
|
||||
[ ] [ENOTSOCK] The argument socket does not reference a socket.
|
||||
[ ] [EOPNOTSUPP] The socket is not of a type that supports the operation listen().
|
||||
|
||||
Linux:
|
||||
|
||||
[ ] [EADDRINUSE] Another socket is already listening on the same port.
|
||||
[--] [EBADF] The argument sockfd is not a valid descriptor.
|
||||
[ ] [ENOTSOCK] The argument sockfd is not a socket.
|
||||
[ ] [EOPNOTSUPP] The socket is not of a type that supports the listen() operation.
|
||||
*/
|
||||
int zts_listen(ZT_LISTEN_SIG) {
|
||||
DEBUG_EXTRA("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
return -1;
|
||||
}
|
||||
if(!zt1Service) {
|
||||
DEBUG_ERROR("service not started. call zts_start(path) first");
|
||||
@@ -650,18 +682,21 @@ int zts_listen(ZT_LISTEN_SIG) {
|
||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
||||
if(!p) {
|
||||
DEBUG_ERROR("unable to locate connection pair. did you bind?");
|
||||
errno = EDESTADDRREQ;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::Connection *conn = p->first;
|
||||
ZeroTier::SocketTap *tap = p->second;
|
||||
|
||||
if(!tap || !conn) {
|
||||
DEBUG_ERROR("unable to locate tap interface for file descriptor");
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
if(!err) {
|
||||
backlog = backlog > 128 ? 128 : backlog; // See: /proc/sys/net/core/somaxconn
|
||||
err = tap->Listen(conn, fd, backlog);
|
||||
//DEBUG_INFO("put conn=%p into LISTENING state (err=%d)", conn, err);
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -684,7 +719,7 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -704,7 +739,6 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
||||
else {
|
||||
ZeroTier::Connection *conn = p->first;
|
||||
ZeroTier::SocketTap *tap = p->second;
|
||||
ZeroTier::Connection *accepted_conn;
|
||||
|
||||
// BLOCKING: loop and keep checking until we find a newly accepted connection
|
||||
int f_err, blocking = 1;
|
||||
@@ -715,15 +749,16 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
||||
else {
|
||||
blocking = !(f_err & O_NONBLOCK);
|
||||
}
|
||||
if(!err && !blocking) { // non-blocking
|
||||
if(!err) {
|
||||
ZeroTier::Connection *accepted_conn;
|
||||
if(!blocking) { // non-blocking
|
||||
DEBUG_EXTRA("EWOULDBLOCK, not a real error, assuming non-blocking mode");
|
||||
errno = EWOULDBLOCK;
|
||||
err = -1;
|
||||
accepted_conn = tap->Accept(conn);
|
||||
}
|
||||
else if (!err && blocking) { // blocking
|
||||
else { // blocking
|
||||
while(true) {
|
||||
DEBUG_EXTRA("checking...");
|
||||
usleep(ZT_ACCEPT_RECHECK_DELAY * 1000);
|
||||
accepted_conn = tap->Accept(conn);
|
||||
if(accepted_conn)
|
||||
@@ -735,6 +770,7 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
||||
err = accepted_conn->app_fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
}
|
||||
return err;
|
||||
@@ -745,19 +781,19 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
||||
Linux accept() (and accept4()) passes already-pending network errors on the new socket as an error code from accept(). This behavior differs from other BSD socket implementations. For reliable operation the application should detect the network errors defined for the protocol after accept() and treat them like EAGAIN by retrying. In the case of TCP/IP, these are ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH.
|
||||
Errors
|
||||
|
||||
[ ] EAGAIN or EWOULDBLOCK The socket is marked nonblocking and no connections are present to be accepted. 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 descriptor is invalid.
|
||||
[ ] ECONNABORTED A connection has been aborted.
|
||||
[ ] EFAULT The addr argument is not in a writable part of the user address space.
|
||||
[NA] EINTR The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).
|
||||
[ ] EINVAL Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
|
||||
[ ] EINVAL (accept4()) invalid value in flags.
|
||||
[ ] EMFILE The per-process limit of open file descriptors has been reached.
|
||||
[ ] ENFILE The system limit on the total number of open files has been reached.
|
||||
[ ] ENOBUFS, ENOMEM Not enough free memory. This often means that the memory allocation is limited by the socket buffer limits, not by the system memory.
|
||||
[ ] ENOTSOCK The descriptor references a file, not a socket.
|
||||
[ ] EOPNOTSUPP The referenced socket is not of type SOCK_STREAM.
|
||||
[ ] EPROTO Protocol error.
|
||||
[ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and no connections are present to be accepted. 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 descriptor is invalid.
|
||||
[ ] [ECONNABORTED] A connection has been aborted.
|
||||
[ ] [EFAULT] The addr argument is not in a writable part of the user address space.
|
||||
[NA] [EINTR] The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).
|
||||
[ ] [EINVAL] Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
|
||||
[ ] [EINVAL] (accept4()) invalid value in flags.
|
||||
[ ] [EMFILE] The per-process limit of open file descriptors has been reached.
|
||||
[ ] [ENFILE] The system limit on the total number of open files has been reached.
|
||||
[ ] [ENOBUFS, ENOMEM] Not enough free memory. This often means that the memory allocation is limited by the socket buffer limits, not by the system memory.
|
||||
[ ] [ENOTSOCK] The descriptor references a file, not a socket.
|
||||
[ ] [EOPNOTSUPP] The referenced socket is not of type SOCK_STREAM.
|
||||
[ ] [EPROTO] Protocol error.
|
||||
|
||||
In addition, Linux accept() may fail if:
|
||||
|
||||
@@ -870,7 +906,7 @@ Linux:
|
||||
|
||||
See: http://yarchive.net/comp/linux/close_return_value.html
|
||||
|
||||
Darwin:
|
||||
Linux / Darwin:
|
||||
|
||||
[--] [EBADF] fildes is not a valid, active file descriptor.
|
||||
[NA] [EINTR] Its execution was interrupted by a signal.
|
||||
@@ -881,7 +917,7 @@ Darwin:
|
||||
|
||||
int zts_close(ZT_CLOSE_SIG)
|
||||
{
|
||||
//DEBUG_EXTRA("fd = %d", fd);
|
||||
DEBUG_EXTRA("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
@@ -898,7 +934,6 @@ int zts_close(ZT_CLOSE_SIG)
|
||||
{
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
//DEBUG_INFO("unmap=%d, fdmap=%d", ZeroTier::unmap.size(), ZeroTier::fdmap.size());
|
||||
|
||||
// First, look for for unassigned connections
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
|
||||
@@ -925,31 +960,44 @@ int zts_close(ZT_CLOSE_SIG)
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
else
|
||||
else // found everything, begin closure
|
||||
{
|
||||
|
||||
conn = p->first;
|
||||
ZeroTier::SocketTap *tap = p->second;
|
||||
|
||||
//DEBUG_ERROR("close...., conn = %p, fd = %d", conn, fd);
|
||||
// check if socket is blocking
|
||||
int f_err, blocking = 1;
|
||||
if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) {
|
||||
DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno);
|
||||
err = -1;
|
||||
}
|
||||
else {
|
||||
blocking = !(f_err & O_NONBLOCK);
|
||||
}
|
||||
|
||||
if(blocking) {
|
||||
DEBUG_INFO("socket is blocking, waiting for write operations before closure");
|
||||
for(int i=0; i<ZT_SDK_CLTIME; i++) {
|
||||
if(conn->txsz == 0)
|
||||
break;
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
// For cases where data might still need to pass through the library
|
||||
// before socket closure
|
||||
if(ZT_SOCK_BEHAVIOR_LINGER) {
|
||||
socklen_t optlen;
|
||||
struct linger so_linger;
|
||||
so_linger.l_linger = 0;
|
||||
zts_getsockopt(fd, SOL_SOCKET, SO_LINGER, &so_linger, &optlen);
|
||||
if (so_linger.l_linger != 0) {
|
||||
DEBUG_EXTRA("lingering before closure for (%d) seconds...", so_linger.l_linger);
|
||||
sleep(so_linger.l_linger); // do the linger!
|
||||
}
|
||||
|
||||
}
|
||||
// Tell the tap to stop monitoring this PhySocket
|
||||
//if((err = pico_socket_close(conn->picosock)) < 0)
|
||||
// DEBUG_ERROR("error calling pico_socket_close()");
|
||||
tap->Close(conn);
|
||||
// delete objects
|
||||
// FIXME: double check this
|
||||
//delete p;
|
||||
ZeroTier::fdmap.erase(fd);
|
||||
err = 0;
|
||||
}
|
||||
@@ -964,7 +1012,7 @@ int zts_close(ZT_CLOSE_SIG)
|
||||
int zts_fcntl(ZT_FCNTL_SIG)
|
||||
{
|
||||
//DEBUG_INFO("fd = %d", fd);
|
||||
int err;
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
@@ -979,7 +1027,7 @@ int zts_fcntl(ZT_FCNTL_SIG)
|
||||
ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||
{
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
int err;
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
@@ -994,7 +1042,7 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||
ssize_t zts_sendmsg(ZT_SENDMSG_SIG)
|
||||
{
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
int err;
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
@@ -1009,7 +1057,7 @@ ssize_t zts_sendmsg(ZT_SENDMSG_SIG)
|
||||
ssize_t zts_recvfrom(ZT_RECVFROM_SIG)
|
||||
{
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
int err;
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
@@ -1024,7 +1072,7 @@ ssize_t zts_recvfrom(ZT_RECVFROM_SIG)
|
||||
ssize_t zts_recvmsg(ZT_RECVMSG_SIG)
|
||||
{
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
int err;
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
@@ -1353,10 +1401,10 @@ void *zts_start_service(void *thread_id) {
|
||||
return NULL;
|
||||
}
|
||||
// rpc dir
|
||||
if(!ZeroTier::OSUtils::mkdir(ZeroTier::homeDir + "/" + ZT_SDK_RPC_DIR_PREFIX)) {
|
||||
DEBUG_ERROR("unable to create dir: " ZT_SDK_RPC_DIR_PREFIX);
|
||||
return NULL;
|
||||
}
|
||||
// if(!ZeroTier::OSUtils::mkdir(ZeroTier::homeDir + "/" + ZT_SDK_RPC_DIR_PREFIX)) {
|
||||
// DEBUG_ERROR("unable to create dir: " ZT_SDK_RPC_DIR_PREFIX);
|
||||
// return NULL;
|
||||
//}
|
||||
|
||||
// Generate random port for new service instance
|
||||
unsigned int randp = 0;
|
||||
|
||||
@@ -175,6 +175,7 @@ namespace ZeroTier {
|
||||
{
|
||||
DEBUG_INFO();
|
||||
Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn;
|
||||
Mutex::Lock _l(conn->_rx_m);
|
||||
if(conn) {
|
||||
|
||||
uint16_t port = 0;
|
||||
@@ -229,6 +230,7 @@ namespace ZeroTier {
|
||||
{
|
||||
//DEBUG_INFO();
|
||||
Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn;
|
||||
Mutex::Lock _l(conn->_tx_m);
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("invalid connection");
|
||||
return;
|
||||
@@ -248,18 +250,17 @@ namespace ZeroTier {
|
||||
if(sz)
|
||||
memmove(&conn->txbuf, (conn->txbuf+r), sz);
|
||||
conn->txsz -= r;
|
||||
//DEBUG_INFO("conn->txsz = %d, r = %d, sz = %d", conn->txsz, r, sz);
|
||||
|
||||
#if DEBUG_LEVEL >= MSG_TRANSFER
|
||||
int max = conn->socket_type == SOCK_STREAM ? ZT_TCP_TX_BUF_SZ : ZT_UDP_TX_BUF_SZ;
|
||||
DEBUG_TRANS("[ TCP TX -> STACK] :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
||||
(float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r);
|
||||
DEBUG_TRANS("[ TCP TX -> STACK] :: conn = %p, len = %d", conn, r);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void picoTCP::pico_cb_socket_activity(uint16_t ev, struct pico_socket *s)
|
||||
{
|
||||
//DEBUG_INFO();
|
||||
if(!(SocketTap*)((ConnectionPair*)(s->priv)))
|
||||
return;
|
||||
SocketTap *tap = (SocketTap*)((ConnectionPair*)(s->priv))->tap;
|
||||
@@ -268,18 +269,19 @@ namespace ZeroTier {
|
||||
DEBUG_ERROR("invalid tap or conn");
|
||||
return;
|
||||
}
|
||||
|
||||
int err;
|
||||
Mutex::Lock _l(tap->_tcpconns_m);
|
||||
int err = 0;
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("invalid connection");
|
||||
return;
|
||||
}
|
||||
//DEBUG_INFO("conn = %p", conn);
|
||||
//DEBUG_ERROR(" STATE = %d", conn->picosock->state);
|
||||
// accept()
|
||||
// PICO_SOCK_EV_CONN - triggered when connection is established (TCP only). This event is
|
||||
// received either after a successful call to pico socket connect to indicate that the connection
|
||||
// has been established, or on a listening socket, indicating that a call to pico socket accept
|
||||
// may now be issued in order to accept the incoming connection from a remote host.
|
||||
if (ev & PICO_SOCK_EV_CONN) {
|
||||
if(conn->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);
|
||||
@@ -311,34 +313,47 @@ namespace ZeroTier {
|
||||
conn->state = ZT_SOCK_STATE_UNHANDLED_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
// PICO_SOCK_EV_FIN - triggered when the socket is closed. No further communication is
|
||||
// possible from this point on the socket.
|
||||
if (ev & PICO_SOCK_EV_FIN) {
|
||||
// DEBUG_EXTRA("PICO_SOCK_EV_FIN (socket closed), picosock=%p, conn=%p", s, conn);
|
||||
conn->closure_ts = std::time(nullptr);
|
||||
}
|
||||
|
||||
// PICO_SOCK_EV_ERR - triggered when an error occurs.
|
||||
if (ev & PICO_SOCK_EV_ERR) {
|
||||
if(pico_err == PICO_ERR_ECONNRESET) {
|
||||
DEBUG_ERROR("PICO_ERR_ECONNRESET");
|
||||
conn->state = PICO_ERR_ECONNRESET;
|
||||
}
|
||||
//DEBUG_INFO("PICO_SOCK_EV_ERR (socket error received) err=%d, picosock=%p", pico_err, s);
|
||||
// DEBUG_INFO("PICO_SOCK_EV_ERR (socket error received) err=%d, picosock=%p", pico_err, s);
|
||||
}
|
||||
// PICO_SOCK_EV_CLOSE - triggered when a FIN segment is received (TCP only). This event
|
||||
// indicates that the oher endpont has closed the connection, so the local TCP layer is only
|
||||
// allowed to send new data until a local shutdown or close is initiated. PicoTCP is able to
|
||||
// keep the connection half-open (only for sending) after the FIN packet has been received,
|
||||
// allowing new data to be sent in the TCP CLOSE WAIT state.
|
||||
if (ev & PICO_SOCK_EV_CLOSE) {
|
||||
err = pico_socket_close(s);
|
||||
//DEBUG_INFO("PICO_SOCK_EV_CLOSE (socket closure) err = %d, picosock=%p, conn=%p", err, s, conn);
|
||||
// DEBUG_INFO("PICO_SOCK_EV_CLOSE (socket closure) err = %d, picosock=%p, conn=%p", err, s, conn);
|
||||
conn->closure_ts = std::time(nullptr);
|
||||
return;
|
||||
}
|
||||
// Read from picoTCP socket
|
||||
// PICO_SOCK_EV_RD - triggered when new data arrives on the socket. A new receive action
|
||||
// can be taken by the socket owner because this event indicates there is new data to receive.
|
||||
if (ev & PICO_SOCK_EV_RD) {
|
||||
if(conn->socket_type==SOCK_STREAM)
|
||||
pico_cb_tcp_read(tap, s);
|
||||
if(conn->socket_type==SOCK_DGRAM)
|
||||
pico_cb_udp_read(tap, s);
|
||||
}
|
||||
// Write to picoTCP socket
|
||||
if (ev & PICO_SOCK_EV_WR)
|
||||
// PICO_SOCK_EV_WR - triggered when ready to write to the socket. Issuing a write/send call
|
||||
// will now succeed if the buffer has enough space to allocate new outstanding data
|
||||
if (ev & PICO_SOCK_EV_WR) {
|
||||
pico_cb_tcp_write(tap, s);
|
||||
}
|
||||
}
|
||||
|
||||
int pico_eth_send(struct pico_device *dev, void *buf, int len)
|
||||
{
|
||||
@@ -362,7 +377,7 @@ namespace ZeroTier {
|
||||
void picoTCP::pico_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,
|
||||
const void *data,unsigned int len)
|
||||
{
|
||||
DEBUG_INFO("len = %d", len);
|
||||
//DEBUG_INFO("len = %d", len);
|
||||
if(!tap) {
|
||||
DEBUG_ERROR("invalid tap");
|
||||
return;
|
||||
@@ -405,7 +420,7 @@ namespace ZeroTier {
|
||||
Mutex::Lock _l(tap->_pico_frame_rxbuf_m);
|
||||
unsigned char frame[ZT_SDK_MTU];
|
||||
int len;
|
||||
int err;
|
||||
int err = 0;
|
||||
while (tap->pico_frame_rxbuf_tot > 0 && loop_score > 0) {
|
||||
//DEBUG_FLOW(" [ FBUF -> STACK] Frame buffer SZ=%d", tap->pico_frame_rxbuf_tot);
|
||||
memset(frame, 0, sizeof(frame));
|
||||
@@ -435,13 +450,14 @@ namespace ZeroTier {
|
||||
int err = 0;
|
||||
if(conn->socket_family == AF_INET) {
|
||||
struct pico_ip4 zaddr;
|
||||
memset(&zaddr, 0, sizeof (struct pico_ip4));
|
||||
struct sockaddr_in *in4 = (struct sockaddr_in*)addr;
|
||||
char ipv4_str[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN);
|
||||
pico_string_to_ipv4(ipv4_str, &(zaddr.addr));
|
||||
//DEBUG_ATTN("addr=%s:%d", ipv4_str, Utils::ntoh( in4->sin_port ));
|
||||
uint32_t ipval = 0;
|
||||
pico_string_to_ipv4(ipv4_str, &ipval);
|
||||
zaddr.addr = ipval;
|
||||
err = pico_socket_connect(conn->picosock, &zaddr, in4->sin_port);
|
||||
//DEBUG_INFO("connect_err = %d", err);
|
||||
}
|
||||
if(conn->socket_family == AF_INET6) {
|
||||
struct pico_ip6 zaddr;
|
||||
@@ -449,10 +465,8 @@ namespace ZeroTier {
|
||||
char ipv6_str[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN);
|
||||
pico_string_to_ipv6(ipv6_str, zaddr.addr);
|
||||
//DEBUG_ATTN("addr=%s:%d", ipv6_str, Utils::ntoh(in6->sin6_port));
|
||||
err = pico_socket_connect(conn->picosock, &zaddr, in6->sin6_port);
|
||||
}
|
||||
|
||||
memcpy(&(conn->peer_addr), &addr, sizeof(struct sockaddr_storage));
|
||||
|
||||
if(err == PICO_ERR_EPROTONOSUPPORT)
|
||||
@@ -474,11 +488,13 @@ namespace ZeroTier {
|
||||
int err = 0;
|
||||
if(conn->socket_family == AF_INET) {
|
||||
struct pico_ip4 zaddr;
|
||||
memset(&zaddr, 0, sizeof (struct pico_ip4));
|
||||
struct sockaddr_in *in4 = (struct sockaddr_in*)addr;
|
||||
char ipv4_str[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN);
|
||||
uint32_t ipval = 0;
|
||||
pico_string_to_ipv4(ipv4_str, &(zaddr.addr));
|
||||
// DEBUG_ATTN("addr=%s: %d ntoh()=%d", ipv4_str, in4->sin_port, Utils::ntoh(in4->sin_port));
|
||||
DEBUG_EXTRA("addr=%s:%d", ipv4_str, Utils::ntoh(in4->sin_port));
|
||||
err = pico_socket_bind(conn->picosock, &zaddr, (uint16_t *)&(in4->sin_port));
|
||||
}
|
||||
if(conn->socket_family == AF_INET6) {
|
||||
@@ -488,7 +504,7 @@ namespace ZeroTier {
|
||||
inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN);
|
||||
// TODO: This isn't proper
|
||||
pico_string_to_ipv6("::", pip6.addr);
|
||||
DEBUG_INFO("addr=%s:%d", ipv6_str, Utils::ntoh(in6->sin6_port));
|
||||
DEBUG_EXTRA("addr=%s:%d", ipv6_str, Utils::ntoh(in6->sin6_port));
|
||||
err = pico_socket_bind(conn->picosock, &pip6, (uint16_t *)&(in6->sin6_port));
|
||||
}
|
||||
if(err < 0) {
|
||||
@@ -521,7 +537,7 @@ namespace ZeroTier {
|
||||
DEBUG_ERROR("invalid conn or conn->picosock");
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
int err;
|
||||
int err = 0;
|
||||
if((err = pico_socket_listen(conn->picosock, backlog)) < 0)
|
||||
{
|
||||
if(err == PICO_ERR_EINVAL) {
|
||||
@@ -611,8 +627,7 @@ namespace ZeroTier {
|
||||
if(conn->socket_type==SOCK_STREAM) {
|
||||
#if DEBUG_LEVEL >= MSG_TRANSFER
|
||||
float max = conn->socket_type == SOCK_STREAM ? (float)ZT_TCP_RX_BUF_SZ : (float)ZT_UDP_RX_BUF_SZ;
|
||||
DEBUG_TRANS("[ TCP RX <- STACK] :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
||||
(float)conn->txsz / max, (float)conn->rxsz / max, conn->sock, n);
|
||||
DEBUG_TRANS("[ TCP RX <- STACK] :: conn = %p, len = %d", conn, n);
|
||||
#endif
|
||||
}
|
||||
if(conn->rxsz == 0) {
|
||||
@@ -635,7 +650,11 @@ namespace ZeroTier {
|
||||
|
||||
void picoTCP::pico_Write(Connection *conn, void *data, ssize_t len)
|
||||
{
|
||||
//DEBUG_INFO();
|
||||
Mutex::Lock _l(conn->_tx_m);
|
||||
if(len <= 0) {
|
||||
DEBUG_ERROR("invalid write length");
|
||||
return;
|
||||
}
|
||||
if(conn->picosock->state & PICO_SOCKET_STATE_CLOSED){
|
||||
DEBUG_ERROR("socket is CLOSED, this write() will fail");
|
||||
return;
|
||||
@@ -644,6 +663,12 @@ namespace ZeroTier {
|
||||
DEBUG_ERROR("invalid connection");
|
||||
return;
|
||||
}
|
||||
if(conn->txsz + len >= ZT_TCP_TX_BUF_SZ) {
|
||||
DEBUG_ERROR("TX buffer is too small, try increasing ZT_TCP_TX_BUF_SZ in libzt.h");
|
||||
return;
|
||||
}
|
||||
|
||||
// DEBUG_INFO("conn->txsz = %d, len = %d", conn->txsz, len);
|
||||
unsigned char *buf = (unsigned char*)data;
|
||||
memcpy(conn->txbuf + conn->txsz, buf, len);
|
||||
conn->txsz += len;
|
||||
@@ -661,18 +686,18 @@ namespace ZeroTier {
|
||||
// adjust buffer
|
||||
int sz = (conn->txsz)-r;
|
||||
if(sz)
|
||||
{
|
||||
memmove(&conn->txbuf, (conn->txbuf+r), sz);
|
||||
}
|
||||
conn->txsz -= r;
|
||||
|
||||
if(conn->socket_type == SOCK_STREAM) {
|
||||
max = ZT_TCP_TX_BUF_SZ;
|
||||
DEBUG_TRANS("[ TCP TX -> STACK] :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
||||
(float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r);
|
||||
DEBUG_TRANS("[ TCP TX -> STACK] :: conn = %p, len = %d", conn, r);
|
||||
}
|
||||
if(conn->socket_type == SOCK_DGRAM) {
|
||||
max = ZT_UDP_TX_BUF_SZ;
|
||||
DEBUG_TRANS("[ UDP TX -> STACK] :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
||||
(float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r);
|
||||
DEBUG_TRANS("[ UDP TX -> STACK] :: conn = %p, len = %d", conn, r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -681,12 +706,11 @@ namespace ZeroTier {
|
||||
DEBUG_INFO("conn = %p, picosock=%p, fd = %d", conn, conn->picosock, conn->app_fd);
|
||||
if(!conn || !conn->picosock)
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
int err;
|
||||
int err = 0;
|
||||
Mutex::Lock _l(conn->tap->_tcpconns_m);
|
||||
if(conn->closure_ts != -1) // it was closed at some point in the past, it'll work itself out
|
||||
return ZT_ERR_OK;
|
||||
if((err = pico_socket_close(conn->picosock)) < 0) {
|
||||
DEBUG_ERROR("closing pico_socket...");
|
||||
errno = pico_err;
|
||||
DEBUG_ERROR("error closing pico_socket(%p)", (void*)(conn->picosock));
|
||||
}
|
||||
|
||||
192
test/echo.cpp
Normal file
192
test/echo.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
// Comprehensive stress test for socket-like API
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <ctime>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "libzt.h"
|
||||
|
||||
std::map<std::string, std::string> testConf;
|
||||
|
||||
void loadTestConfigFile(std::string filepath)
|
||||
{
|
||||
std::string key;
|
||||
std::string value;
|
||||
std::ifstream testFile;
|
||||
testFile.open(filepath.c_str());
|
||||
while (testFile >> key >> value) {
|
||||
if(key[0] != '#')
|
||||
testConf[key] = value;
|
||||
}
|
||||
testFile.close();
|
||||
}
|
||||
|
||||
long int get_now_ts()
|
||||
{
|
||||
struct timeval tp;
|
||||
gettimeofday(&tp, NULL);
|
||||
return tp.tv_sec * 1000 + tp.tv_usec / 1000;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* PERFORMANCE */
|
||||
/****************************************************************************/
|
||||
|
||||
// Maintain transfer for n_count OR n_count
|
||||
void start_echo_mode(std::string ipstr, int port)
|
||||
{
|
||||
DEBUG_TEST();
|
||||
/*
|
||||
int w=0, sockfd, err;
|
||||
int total_test_sz = 1024*1024;
|
||||
int arbitrary_chunk_sz_max = 16384;
|
||||
int arbitrary_chunk_sz_min = 512;
|
||||
|
||||
char rbuf[arbitrary_chunk_sz_max];
|
||||
|
||||
for (int i=arbitrary_chunk_sz_min; (i*2) < arbitrary_chunk_sz_max; i*=2) {
|
||||
|
||||
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
DEBUG_ERROR("error creating ZeroTier socket");
|
||||
if((err = connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0)
|
||||
DEBUG_ERROR("error connecting to remote host (%d)\n", err);
|
||||
|
||||
DEBUG_TEST("[TX] Testing (%d) byte chunks: ", i);
|
||||
|
||||
int chunk_sz = i;
|
||||
int iterations = total_test_sz / chunk_sz;
|
||||
|
||||
long int start_time = get_now_ts();
|
||||
w = 0;
|
||||
while(w < total_test_sz)
|
||||
w += write(sockfd, rbuf, chunk_sz);
|
||||
long int end_time = get_now_ts();
|
||||
float ts_delta = (end_time - start_time) / (float)1000;
|
||||
float rate = (float)total_test_sz / (float)ts_delta;
|
||||
DEBUG_TEST("%d total bytes, time = %3f, rate = %3f KB/s", w, ts_delta, (rate / (float)1024) );
|
||||
|
||||
close(sockfd);
|
||||
// let things settle after test
|
||||
sleep(5);
|
||||
}
|
||||
*passed = (w == total_test_sz && !err) ? PASSED : FAILED;
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
Mode 1 (Measure performance of other host's TX):
|
||||
- Receive incoming TX test config (total bytes intended)
|
||||
- Prepare receiver
|
||||
- Record time of first received byte
|
||||
- Record time of last received byte
|
||||
- Send results back to other host's selftest instance
|
||||
|
||||
Mode 2 (Measure performance of other host's RX):
|
||||
- Receive incoming RX test config (total bytes requested)
|
||||
- Prepare transmitter
|
||||
- Send bytes as fast as possible
|
||||
*/
|
||||
|
||||
|
||||
int main(int argc , char *argv[])
|
||||
{
|
||||
if(argc < 1) {
|
||||
fprintf(stderr, "usage: echo <alice|bob>.conf\n");
|
||||
fprintf(stderr, " - Define your test environment in *.conf files.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int err = 0;
|
||||
int type = 0;
|
||||
int protocol = 0;
|
||||
int mode = 0;
|
||||
int port = 0;
|
||||
int start_port = 0;
|
||||
int port_offset = 0;
|
||||
int operation = 0;
|
||||
int n_count = 0;
|
||||
int delay = 0;
|
||||
|
||||
std::string local_echo_ipv4;
|
||||
|
||||
std::string nwid, stype, path = argv[1];
|
||||
std::string ipstr, ipstr6, local_ipstr, local_ipstr6, remote_ipstr, remote_ipstr6;
|
||||
|
||||
// if a test config file was specified:
|
||||
if(path.find(".conf") != std::string::npos) {
|
||||
//printf("\nTest config file contents:\n");
|
||||
loadTestConfigFile(path);
|
||||
nwid = testConf["nwid"];
|
||||
path = testConf["local_path"];
|
||||
stype = testConf["test"];
|
||||
start_port = atoi(testConf["start_port"].c_str());
|
||||
port_offset = atoi(testConf["port_offset"].c_str());
|
||||
local_ipstr = testConf["local_ipv4"];
|
||||
local_ipstr6 = testConf["local_ipv6"];
|
||||
remote_ipstr = testConf["remote_ipv4"];
|
||||
remote_ipstr6 = testConf["remote_ipv6"];
|
||||
std::string smode = testConf["mode"];
|
||||
/*
|
||||
if(strcmp(smode.c_str(), "server") == 0)
|
||||
mode = TEST_MODE_SERVER;
|
||||
else
|
||||
mode = TEST_MODE_CLIENT;
|
||||
*/
|
||||
fprintf(stderr, "\tlocal_ipstr = %s\n", local_ipstr.c_str());
|
||||
fprintf(stderr, "\tremote_ipstr = %s\n", remote_ipstr.c_str());
|
||||
fprintf(stderr, "\tstart_port = %d\n", start_port);
|
||||
fprintf(stderr, "\tport_offset = %d\n", port_offset);
|
||||
fprintf(stderr, "\tlocal_echo_ipv4 = %s\n", local_echo_ipv4.c_str());
|
||||
}
|
||||
|
||||
fprintf(stderr, "\tpath = %s\n", path.c_str());
|
||||
fprintf(stderr, "\tnwid = %s\n", nwid.c_str());
|
||||
fprintf(stderr, "\ttype = %s\n\n", stype.c_str());
|
||||
|
||||
DEBUG_TEST("Starting echo mode...");
|
||||
start_echo_mode(local_echo_ipv4, start_port+port_offset);
|
||||
return 1;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -55,13 +55,13 @@ namespace ZeroTier {
|
||||
|
||||
ZTProxy::ZTProxy(int proxy_listen_port, std::string nwid, std::string path, std::string internal_addr, int internal_port)
|
||||
:
|
||||
_phy(this,false,true),
|
||||
_enabled(true),
|
||||
_run(true),
|
||||
_proxy_listen_port(proxy_listen_port),
|
||||
_internal_port(internal_port),
|
||||
_nwid(nwid),
|
||||
_internal_addr(internal_addr)
|
||||
_internal_addr(internal_addr),
|
||||
_phy(this,false,true)
|
||||
{
|
||||
// Start ZeroTier Node
|
||||
// Join Network which contains resources we need to proxy
|
||||
@@ -220,16 +220,19 @@ namespace ZeroTier {
|
||||
|
||||
void ZTProxy::phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len)
|
||||
{
|
||||
// Not used, connections are handled via user space network stack and SocketTap subsystem
|
||||
DEBUG_INFO("phyOnDatagram");
|
||||
exit(0);
|
||||
}
|
||||
void ZTProxy::phyOnTcpWritable(PhySocket *sock,void **uptr)
|
||||
{
|
||||
// Not used, connections are handled via user space network stack and SocketTap subsystem
|
||||
DEBUG_INFO("phyOnTcpWritable");
|
||||
exit(0);
|
||||
}
|
||||
void ZTProxy::phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable)
|
||||
{
|
||||
// Not used, connections are handled via user space network stack and SocketTap subsystem
|
||||
DEBUG_INFO("phyOnFileDescriptorActivity, sock=%p", sock);
|
||||
exit(0);
|
||||
}
|
||||
@@ -239,6 +242,12 @@ namespace ZeroTier {
|
||||
DEBUG_INFO("phyOnTcpConnect, sock=%p", sock);
|
||||
exit(0);
|
||||
}
|
||||
void ZTProxy::phyOnUnixClose(PhySocket *sock,void **uptr)
|
||||
{
|
||||
// Not used, connections are handled via user space network stack and SocketTap subsystem
|
||||
DEBUG_INFO("phyOnUnixClose, sock=%p", sock);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ZTProxy::phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from)
|
||||
{
|
||||
@@ -256,11 +265,6 @@ namespace ZeroTier {
|
||||
cmap[sockN]=conn; // add new connection
|
||||
}
|
||||
|
||||
void ZTProxy::phyOnUnixClose(PhySocket *sock,void **uptr)
|
||||
{
|
||||
DEBUG_INFO("phyOnUnixClose, sock=%p", sock);
|
||||
exit(0);
|
||||
}
|
||||
void ZTProxy::phyOnUnixData(PhySocket *sock,void **uptr,void *data,ssize_t len)
|
||||
{
|
||||
DEBUG_INFO("phyOnUnixData(sock=%p, len=%lu)", sock, len);
|
||||
@@ -318,7 +322,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
if(argc != 6) {
|
||||
printf("\nZeroTier TCP Proxy Service\n");
|
||||
printf("ztproxy [local port] [network ID]/[ZT internal IP]/port\n");
|
||||
printf("ztproxy [config_file_path] [local_listen_port] [nwid] [zt_host_addr] [zt_resource_port]\n");
|
||||
exit(0);
|
||||
}
|
||||
std::string path = argv[1];
|
||||
@@ -330,9 +334,9 @@ int main(int argc, char **argv)
|
||||
ZeroTier::ZTProxy *proxy = new ZeroTier::ZTProxy(proxy_listen_port, nwid, path, internal_addr, internal_port);
|
||||
|
||||
if(proxy) {
|
||||
printf("ZTProxy started. Listening on %d\n", proxy_listen_port);
|
||||
printf("\nZTProxy started. Listening on %d\n", proxy_listen_port);
|
||||
printf("Traffic will be proxied to and from %s:%d on network %s\n", internal_addr.c_str(), internal_port, nwid.c_str());
|
||||
printf("Proxy Node config files and key stored in: %s/\n", path.c_str());
|
||||
printf("Proxy Node config files and key stored in: %s/\n\n", path.c_str());
|
||||
while(1) {
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user