spring cleaning
This commit is contained in:
@@ -1568,7 +1568,7 @@ int pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int pico_socket_connect(struct pico_socket *s, const void *remote_addr, uint16_t remote_port)
|
extern int pico_socket_connect(struct pico_socket *s, const void *remote_addr, uint16_t remote_port)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
pico_err = PICO_ERR_EPROTONOSUPPORT;
|
pico_err = PICO_ERR_EPROTONOSUPPORT;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* ZeroTier One - Network Virtualization Everywhere
|
* ZeroTier SDK - Network Virtualization Everywhere
|
||||||
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@@ -16,10 +16,6 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* This defines the external C++ API for the ZeroTier SDK's service
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ZT_ZEROTIERSDK_H
|
#ifndef ZT_ZEROTIERSDK_H
|
||||||
#define ZT_ZEROTIERSDK_H
|
#define ZT_ZEROTIERSDK_H
|
||||||
|
|
||||||
@@ -29,21 +25,21 @@
|
|||||||
/* Defines */
|
/* Defines */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
#define SDK_MTU 1200 // FIXME: ZT_MAX_MTU, usually
|
#define ZT_SDK_MTU ZT_MAX_MTU
|
||||||
#define UNIX_SOCK_BUF_SIZE 1024*1024
|
#define ZT_PHY_POLL_INTERVAL 50 // ms
|
||||||
#define ZT_PHY_POLL_INTERVAL 50 // in ms
|
#define ZT_ACCEPT_RECHECK_DELAY 250 // ms (for blocking zts_accept() calls)
|
||||||
// picoTCP
|
// picoTCP
|
||||||
#define MAX_PICO_FRAME_RX_BUF_SZ ZT_MAX_MTU * 128
|
#define MAX_PICO_FRAME_RX_BUF_SZ ZT_MAX_MTU * 128
|
||||||
// TCP
|
// TCP
|
||||||
#define DEFAULT_TCP_TX_BUF_SZ 1024 * 1024
|
#define ZT_TCP_TX_BUF_SZ 1024 * 1024
|
||||||
#define DEFAULT_TCP_RX_BUF_SZ 1024 * 1024
|
#define ZT_TCP_RX_BUF_SZ 1024 * 1024
|
||||||
#define DEFAULT_TCP_TX_BUF_SOFTMAX DEFAULT_TCP_TX_BUF_SZ * 0.80
|
#define ZT_TCP_TX_BUF_SOFTMAX ZT_TCP_TX_BUF_SZ * 0.80
|
||||||
#define DEFAULT_TCP_TX_BUF_SOFTMIN DEFAULT_TCP_TX_BUF_SZ * 0.20
|
#define ZT_TCP_TX_BUF_SOFTMIN ZT_TCP_TX_BUF_SZ * 0.20
|
||||||
#define DEFAULT_TCP_RX_BUF_SOFTMAX DEFAULT_TCP_RX_BUF_SZ * 0.80
|
#define ZT_TCP_RX_BUF_SOFTMAX ZT_TCP_RX_BUF_SZ * 0.80
|
||||||
#define DEFAULT_TCP_RX_BUF_SOFTMIN DEFAULT_TCP_RX_BUF_SZ * 0.20
|
#define ZT_TCP_RX_BUF_SOFTMIN ZT_TCP_RX_BUF_SZ * 0.20
|
||||||
// UDP
|
// UDP
|
||||||
#define DEFAULT_UDP_TX_BUF_SZ ZT_MAX_MTU
|
#define ZT_UDP_TX_BUF_SZ ZT_MAX_MTU
|
||||||
#define DEFAULT_UDP_RX_BUF_SZ ZT_MAX_MTU * 10
|
#define ZT_UDP_RX_BUF_SZ ZT_MAX_MTU * 10
|
||||||
|
|
||||||
#define ZT_SDK_RPC_DIR_PREFIX "rpc.d"
|
#define ZT_SDK_RPC_DIR_PREFIX "rpc.d"
|
||||||
|
|
||||||
@@ -56,6 +52,8 @@
|
|||||||
#define ZT_VER_STR_LEN 6
|
#define ZT_VER_STR_LEN 6
|
||||||
#define ZT_HOME_PATH_MAX_LEN 128
|
#define ZT_HOME_PATH_MAX_LEN 128
|
||||||
|
|
||||||
|
#define ZT_ERR_OK 0
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* Socket API Signatures */
|
/* Socket API Signatures */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
@@ -68,8 +66,8 @@
|
|||||||
#define ZT_RECVFROM_SIG int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen
|
#define ZT_RECVFROM_SIG int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen
|
||||||
#define ZT_RECVMSG_SIG int fd, struct msghdr *msg,int flags
|
#define ZT_RECVMSG_SIG int fd, struct msghdr *msg,int flags
|
||||||
#define ZT_SEND_SIG int fd, const void *buf, size_t len, int flags
|
#define ZT_SEND_SIG int fd, const void *buf, size_t len, int flags
|
||||||
#define ZT_WRITE_SIG int fd, const void *buf, size_t len
|
|
||||||
#define ZT_READ_SIG int fd, void *buf, size_t len
|
#define ZT_READ_SIG int fd, void *buf, size_t len
|
||||||
|
#define ZT_WRITE_SIG int fd, const void *buf, size_t len
|
||||||
#define ZT_SOCKET_SIG int socket_family, int socket_type, int protocol
|
#define ZT_SOCKET_SIG int socket_family, int socket_type, int protocol
|
||||||
#define ZT_CONNECT_SIG int fd, const struct sockaddr *addr, socklen_t addrlen
|
#define ZT_CONNECT_SIG int fd, const struct sockaddr *addr, socklen_t addrlen
|
||||||
#define ZT_BIND_SIG int fd, const struct sockaddr *addr, socklen_t addrlen
|
#define ZT_BIND_SIG int fd, const struct sockaddr *addr, socklen_t addrlen
|
||||||
@@ -230,16 +228,23 @@ int zts_socket(ZT_SOCKET_SIG);
|
|||||||
int zts_connect(ZT_CONNECT_SIG);
|
int zts_connect(ZT_CONNECT_SIG);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind a socket to a local address
|
* Binds a socket to a specific address
|
||||||
|
* - To accept connections on a specific ZeroTier network you must
|
||||||
|
* use this bind call with an address which is associated with that network
|
||||||
|
*
|
||||||
|
* For instance, given the following networks:
|
||||||
|
* - nwid = 97afaf1963cc6a90 (10.9.0.0/24)
|
||||||
|
* - nwid = 23bfae5663c8b188 (192.168.0.0/24)
|
||||||
|
*
|
||||||
|
* In order to accept a connection on 97afaf1963cc6a90, you
|
||||||
|
* should bind to 10.9.0.0
|
||||||
*/
|
*/
|
||||||
int zts_bind(ZT_BIND_SIG);
|
int zts_bind(ZT_BIND_SIG);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accept a connection
|
* Listen for incoming connections
|
||||||
*/
|
*/
|
||||||
#if defined(__linux__)
|
int zts_listen(ZT_LISTEN_SIG);
|
||||||
int zts_accept4(ZT_ACCEPT4_SIG);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accept a connection
|
* Accept a connection
|
||||||
@@ -247,9 +252,11 @@ int zts_bind(ZT_BIND_SIG);
|
|||||||
int zts_accept(ZT_ACCEPT_SIG);
|
int zts_accept(ZT_ACCEPT_SIG);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen for incoming connections
|
* Accept a connection
|
||||||
*/
|
*/
|
||||||
int zts_listen(ZT_LISTEN_SIG);
|
#if defined(__linux__)
|
||||||
|
int zts_accept4(ZT_ACCEPT4_SIG);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set socket options
|
* Set socket options
|
||||||
@@ -301,46 +308,32 @@ ssize_t zts_recvfrom(ZT_RECVFROM_SIG);
|
|||||||
*/
|
*/
|
||||||
ssize_t zts_recvmsg(ZT_RECVMSG_SIG);
|
ssize_t zts_recvmsg(ZT_RECVMSG_SIG);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read bytes from socket onto buffer
|
||||||
|
* - Note, this function isn't strictly necessary, you can
|
||||||
|
* use a regular read() call as long as the socket fd was
|
||||||
|
* created via a zts_socket() call.
|
||||||
|
*/
|
||||||
|
int zts_read(ZT_READ_SIG);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write bytes from buffer to socket
|
||||||
|
* - Note, this function isn't strictly necessary, you can
|
||||||
|
* use a regular write() call as long as the socket fd was
|
||||||
|
* created via a zts_socket() call.
|
||||||
|
*/
|
||||||
|
int zts_write(ZT_WRITE_SIG);
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* SocketTap Multiplexer Functionality --- DONT CALL THESE DIRECTLY */
|
/* SDK Socket API Helper functions/objects --- DONT CALL THESE DIRECTLY */
|
||||||
/* - This section of the API is used to implement the general socket */
|
|
||||||
/* controls. Basically this is designed to handle socket provisioning */
|
|
||||||
/* requests when no SocketTap is yet initialized, and as a way to */
|
|
||||||
/* determine which SocketTap is to be used for a particular connect() or */
|
|
||||||
/* bind() call */
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
namespace ZeroTier
|
namespace ZeroTier
|
||||||
{
|
{
|
||||||
class picoTCP;
|
class picoTCP;
|
||||||
struct Connection;
|
|
||||||
extern ZeroTier::picoTCP *picostack;
|
extern ZeroTier::picoTCP *picostack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Connection objects and keeps it in UnassignedConnections
|
|
||||||
* until a connect() or bind() call is made, at which point it is assigned
|
|
||||||
* to the appropriate SocketTap.
|
|
||||||
*/
|
|
||||||
int zts_multiplex_new_socket(ZT_SOCKET_SIG);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a file descriptor, looks up the relevant Connection object and then
|
|
||||||
* searches for a SocketTap with an appropriate route. Once found, the
|
|
||||||
* Connection object will be assigned to that SocketTap and a connection
|
|
||||||
* to the remote host will be attempted.
|
|
||||||
*/
|
|
||||||
int zts_multiplex_new_connect(ZT_CONNECT_SIG);
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int zts_multiplex_new_bind(ZT_BIND_SIG);
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* SDK Socket API Helper functions --- DONT CALL THESE DIRECTLY */
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Don't call this directly, use 'zts_start()'
|
* Don't call this directly, use 'zts_start()'
|
||||||
*/
|
*/
|
||||||
@@ -423,22 +416,22 @@ void *_start_service(void *thread_id);
|
|||||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_INFO
|
#if ZT_DEBUG_LEVEL >= ZT_MSG_INFO
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
#define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
#define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||||
"ZT_INFO : %14s:%4d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
"ZT_INFO : %16s:%4d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||||
#define DEBUG_BLANK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
#define DEBUG_BLANK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||||
"ZT_INFO : %14s:%4d:" fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
"ZT_INFO : %16s:%4d:" fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||||
#define DEBUG_ATTN(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
#define DEBUG_ATTN(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||||
"ZT_INFO : %14s:%4d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
"ZT_INFO : %16s:%4d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||||
#define DEBUG_STACK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
#define DEBUG_STACK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||||
"ZT_STACK: %14s:%4d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
"ZT_STACK: %16s:%4d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||||
#else
|
#else
|
||||||
#define DEBUG_INFO(fmt, args...) fprintf(stderr, \
|
#define DEBUG_INFO(fmt, args...) fprintf(stderr, \
|
||||||
"ZT_INFO [%ld] : %14s:%4d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
"ZT_INFO [%ld] : %16s:%4d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||||
#define DEBUG_ATTN(fmt, args...) fprintf(stderr, ZT_CYN \
|
#define DEBUG_ATTN(fmt, args...) fprintf(stderr, ZT_CYN \
|
||||||
"ZT_ATTN [%ld] : %14s:%4d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
"ZT_ATTN [%ld] : %16s:%4d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||||
#define DEBUG_STACK(fmt, args...) fprintf(stderr, ZT_YEL \
|
#define DEBUG_STACK(fmt, args...) fprintf(stderr, ZT_YEL \
|
||||||
"ZT_STACK[%ld] : %14s:%4d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
"ZT_STACK[%ld] : %16s:%4d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||||
#define DEBUG_BLANK(fmt, args...) fprintf(stderr, \
|
#define DEBUG_BLANK(fmt, args...) fprintf(stderr, \
|
||||||
"ZT_INFO [%ld] : %14s:%4d:" fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, ##args)
|
"ZT_INFO [%ld] : %16s:%4d:" fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, ##args)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define DEBUG_INFO(fmt, args...)
|
#define DEBUG_INFO(fmt, args...)
|
||||||
@@ -450,9 +443,9 @@ void *_start_service(void *thread_id);
|
|||||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER
|
#if ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
#define DEBUG_TRANS(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
#define DEBUG_TRANS(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||||
"ZT_TRANS : %14s:%4d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
"ZT_TRANS : %16s:%4d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||||
#else
|
#else
|
||||||
#define DEBUG_TRANS(fmt, args...) fprintf(stderr, ZT_GRN "ZT_TRANS[%ld] : %14s:%4d:%25s: " fmt \
|
#define DEBUG_TRANS(fmt, args...) fprintf(stderr, ZT_GRN "ZT_TRANS[%ld] : %16s:%4d:%25s: " fmt \
|
||||||
"\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
"\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
@@ -462,10 +455,10 @@ void *_start_service(void *thread_id);
|
|||||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_EXTRA
|
#if ZT_DEBUG_LEVEL >= ZT_MSG_EXTRA
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
#define DEBUG_EXTRA(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
#define DEBUG_EXTRA(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||||
"ZT_EXTRA : %14s:%4d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
"ZT_EXTRA : %16s:%4d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||||
#else
|
#else
|
||||||
#define DEBUG_EXTRA(fmt, args...) fprintf(stderr, \
|
#define DEBUG_EXTRA(fmt, args...) fprintf(stderr, \
|
||||||
"ZT_EXTRA[%ld] : %14s:%4d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
"ZT_EXTRA[%ld] : %16s:%4d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define DEBUG_EXTRA(fmt, args...)
|
#define DEBUG_EXTRA(fmt, args...)
|
||||||
@@ -474,9 +467,9 @@ void *_start_service(void *thread_id);
|
|||||||
#if ZT_DEBUG_LEVEL >= ZT_MSG_FLOW
|
#if ZT_DEBUG_LEVEL >= ZT_MSG_FLOW
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
#define DEBUG_FLOW(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
#define DEBUG_FLOW(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||||
"ZT_FLOW : %14s:%4d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
"ZT_FLOW : %16s:%4d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||||
#else
|
#else
|
||||||
#define DEBUG_FLOW(fmt, args...) fprintf(stderr, "ZT_FLOW [%ld] : %14s:%4d:%25s: " fmt "\n", \
|
#define DEBUG_FLOW(fmt, args...) fprintf(stderr, "ZT_FLOW [%ld] : %16s:%4d:%25s: " fmt "\n", \
|
||||||
ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
|
|||||||
183
make-linux.mk
183
make-linux.mk
@@ -8,8 +8,189 @@ ifeq ($(origin CXX),default)
|
|||||||
CXX=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi)
|
CXX=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## VARIABLES ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
include objects.mk
|
||||||
|
|
||||||
|
# Target output filenames
|
||||||
|
STATIC_LIB_NAME = libzt.a
|
||||||
|
INTERCEPT_NAME = libztintercept.so
|
||||||
|
SDK_SERVICE_NAME = zerotier-sdk-service
|
||||||
|
ONE_SERVICE_NAME = zerotier-one
|
||||||
|
PICO_LIB_NAME = libpicotcp.a
|
||||||
|
#
|
||||||
|
STATIC_LIB = $(BUILD)/$(STATIC_LIB_NAME)
|
||||||
|
SDK_INTERCEPT = $(BUILD)/$(INTERCEPT_NAME)
|
||||||
|
SDK_SERVICE = $(BUILD)/$(SDK_SERVICE_NAME)
|
||||||
|
ONE_SERVICE = $(BUILD)/$(ONE_SERVICE_NAME)
|
||||||
|
PICO_LIB = ext/picotcp/build/lib/$(PICO_LIB_NAME)
|
||||||
|
|
||||||
|
TEST_BUILD_DIR = build/test
|
||||||
|
UNIT_TEST_SRC_DIR = test/unit
|
||||||
|
DUMB_TEST_SRC_DIR = test/dumb
|
||||||
|
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## General Configuration ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Debug output for ZeroTier service
|
||||||
|
ifeq ($(ZT_DEBUG),1)
|
||||||
|
DEFS+=-DZT_TRACE
|
||||||
|
#CFLAGS+=-Wall -fPIE -fvisibility=hidden -pthread $(INCLUDES) $(DEFS)
|
||||||
|
CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
|
||||||
|
STRIP=echo
|
||||||
|
# The following line enables optimization for the crypto code, since
|
||||||
|
# C25519 in particular is almost UNUSABLE in heavy testing without it.
|
||||||
|
#ext/lz4/lz4.o node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CFLAGS = -Wall -O2 -g -pthread $(INCLUDES) $(DEFS)
|
||||||
|
else
|
||||||
|
CFLAGS?=-Ofast -fstack-protector
|
||||||
|
CFLAGS+=-Wall -fPIE -fvisibility=hidden -pthread $(INCLUDES) $(DEFS)
|
||||||
|
#CFLAGS+=$(ARCH_FLAGS) -Wall -flto -fPIC -pthread -mmacosx-version-min=10.7 -DNDEBUG -Wno-unused-private-field $(INCLUDES) $(DEFS)
|
||||||
|
STRIP=strip
|
||||||
|
endif
|
||||||
|
|
||||||
|
CXXFLAGS=$(CFLAGS) -Wno-format -fno-rtti -std=c++11 -DZT_SDK
|
||||||
|
|
||||||
|
INCLUDES+= -Iext \
|
||||||
|
-I$(ZTO)/osdep \
|
||||||
|
-I$(ZTO)/node \
|
||||||
|
-I$(ZTO)/service \
|
||||||
|
-I$(ZTO)/include \
|
||||||
|
-I../$(ZTO)/osdep \
|
||||||
|
-I../$(ZTO)/node \
|
||||||
|
-I../$(ZTO)/service \
|
||||||
|
-I. \
|
||||||
|
-Isrc \
|
||||||
|
-Iinclude \
|
||||||
|
-Iext/picotcp/include \
|
||||||
|
-Iext/picotcp/build/include
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## User Build Flags ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Debug option, prints filenames, lines, functions, arguments, etc
|
||||||
|
# Also enables debug symbols for debugging with tools like gdb, etc
|
||||||
|
ifeq ($(SDK_DEBUG),1)
|
||||||
|
SDK_FLAGS+=-DSDK_PICOTCP
|
||||||
|
CXXFLAGS+=-g
|
||||||
|
INCLUDES+= -I$(PICOTCP_DIR)/include \
|
||||||
|
-I$(PICOTCP_DIR)/build/include \
|
||||||
|
-Isrc/stack_drivers/picotcp
|
||||||
|
endif
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## Stack Configuration ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Stack config flags
|
||||||
|
ifeq ($(SDK_PICOTCP),1)
|
||||||
|
SDK_FLAGS+=-DSDK_PICOTCP
|
||||||
|
INCLUDES+= -I$(PICOTCP_DIR)/include \
|
||||||
|
-I$(PICOTCP_DIR)/build/include \
|
||||||
|
-Isrc/stack_drivers/picotcp
|
||||||
|
endif
|
||||||
|
ifeq ($(SDK_IPV4),1)
|
||||||
|
SDK_FLAGS+=-DSDK_IPV4
|
||||||
|
endif
|
||||||
|
ifeq ($(SDK_IPV6),1)
|
||||||
|
SDK_FLAGS+=-DSDK_IPV6
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## Files ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
STACK_DRIVER_FILES:=src/picoTCP.cpp
|
||||||
|
TAP_FILES:=src/SocketTap.cpp \
|
||||||
|
src/ZeroTierSDK.cpp
|
||||||
|
|
||||||
|
SDK_OBJS+= SocketTap.o \
|
||||||
|
Socket.o \
|
||||||
|
picoTCP.o \
|
||||||
|
ZeroTierSDK.o
|
||||||
|
|
||||||
|
PICO_OBJS+= ext/picotcp/build/lib/pico_device.o \
|
||||||
|
ext/picotcp/build/lib/pico_frame.o \
|
||||||
|
ext/picotcp/build/lib/pico_md5.o \
|
||||||
|
ext/picotcp/build/lib/pico_protocol.o \
|
||||||
|
ext/picotcp/build/lib/pico_socket_multicast.o \
|
||||||
|
ext/picotcp/build/lib/pico_socket.o \
|
||||||
|
ext/picotcp/build/lib/pico_stack.o \
|
||||||
|
ext/picotcp/build/lib/pico_tree.o
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
|
||||||
static_lib: $(OBJS)
|
tests: dumb_tests unit_tests
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## User-Space Stack ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
picotcp:
|
||||||
|
cd ext/picotcp; make lib ARCH=shared IPV4=1 IPV6=1
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## Static Libraries ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
static_lib: picotcp $(ZTO_OBJS)
|
||||||
|
$(CXX) $(CXXFLAGS) $(SDK_FLAGS) $(TAP_FILES) $(STACK_DRIVER_FILES) -c -DSDK_STATIC
|
||||||
|
libtool -static -o $(STATIC_LIB) $(ZTO_OBJS) $(SDK_OBJS) $(PICO_LIB)
|
||||||
|
|
||||||
|
jni_static_lib: picotcp $(ZTO_OBJS)
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## Unit Tests ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
UNIT_TEST_SRC_FILES:=$(wildcard $(UNIT_TEST_SRC_DIR)/*.cpp)
|
||||||
|
UNIT_TEST_OBJ_FILES:=$(addprefix $(TEST_BUILD_DIR)/,$(notdir $(UNIT_TEST_SRC_FILES:.cpp=.out)))
|
||||||
|
UNIT_TEST_INCLUDES:=-Iinclude
|
||||||
|
UNIT_TEST_LIBS:=-Lbuild -lzt
|
||||||
|
|
||||||
|
$(TEST_BUILD_DIR)/%.out: $(UNIT_TEST_SRC_DIR)/%.cpp
|
||||||
|
@mkdir -p $(TEST_BUILD_DIR)
|
||||||
|
@-$(CXX) $(UNIT_TEST_INCLUDES) -o $@ $< $(UNIT_TEST_LIBS)
|
||||||
|
@-./check.sh $@
|
||||||
|
|
||||||
|
unit_tests: $(UNIT_TEST_OBJ_FILES)
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## Non-ZT Client/Server Tests ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
DUMB_TEST_SRC_FILES=$(wildcard $(DUMB_TEST_SRC_DIR)/*.c)
|
||||||
|
DUMB_TEST_OBJ_FILES := $(addprefix $(TEST_BUILD_DIR)/,$(notdir $(DUMB_TEST_SRC_FILES:.c=.out)))
|
||||||
|
|
||||||
|
$(TEST_BUILD_DIR)/%.out: $(DUMB_TEST_SRC_DIR)/%.c
|
||||||
|
@mkdir -p $(TEST_BUILD_DIR)
|
||||||
|
@-$(CC) -o $@ $<
|
||||||
|
@-./check.sh $@
|
||||||
|
|
||||||
|
dumb_tests: $(DUMB_TEST_OBJ_FILES)
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## Misc ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -rf $(BUILD)/*
|
||||||
|
-rm -rf zerotier-cli zerotier-idtool
|
||||||
|
-find . -type f \( -name $(ONE_SERVICE_NAME) -o -name $(SDK_SERVICE_NAME) \) -delete
|
||||||
|
-find . -type f \( -name '*.o' -o -name '*.so' -o -name '*.o.d' -o -name '*.out' -o -name '*.log' -o -name '*.dSYM' \) -delete
|
||||||
|
|
||||||
|
# Check for the presence of built frameworks/bundles/libaries
|
||||||
|
check:
|
||||||
|
-./check.sh $(PICO_LIB)
|
||||||
|
-./check.sh $(SDK_INTERCEPT)
|
||||||
|
-./check.sh $(ONE_SERVICE)
|
||||||
|
-./check.sh $(SDK_SERVICE)
|
||||||
|
-./check.sh $(STATIC_LIB)
|
||||||
|
-./check.sh $(STATIC_LIB)
|
||||||
|
|
||||||
|
|
||||||
69
make-mac.mk
69
make-mac.mk
@@ -9,7 +9,7 @@ ifeq ($(origin CXX),default)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
## General Configuration ##
|
## VARIABLES ##
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
include objects.mk
|
include objects.mk
|
||||||
@@ -27,6 +27,15 @@ SDK_SERVICE = $(BUILD)/$(SDK_SERVICE_NAME)
|
|||||||
ONE_SERVICE = $(BUILD)/$(ONE_SERVICE_NAME)
|
ONE_SERVICE = $(BUILD)/$(ONE_SERVICE_NAME)
|
||||||
PICO_LIB = ext/picotcp/build/lib/$(PICO_LIB_NAME)
|
PICO_LIB = ext/picotcp/build/lib/$(PICO_LIB_NAME)
|
||||||
|
|
||||||
|
TEST_BUILD_DIR = build/test
|
||||||
|
UNIT_TEST_SRC_DIR = test/unit
|
||||||
|
DUMB_TEST_SRC_DIR = test/dumb
|
||||||
|
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## General Configuration ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
# Debug output for ZeroTier service
|
# Debug output for ZeroTier service
|
||||||
ifeq ($(ZT_DEBUG),1)
|
ifeq ($(ZT_DEBUG),1)
|
||||||
DEFS+=-DZT_TRACE
|
DEFS+=-DZT_TRACE
|
||||||
@@ -98,28 +107,25 @@ endif
|
|||||||
|
|
||||||
STACK_DRIVER_FILES:=src/picoTCP.cpp
|
STACK_DRIVER_FILES:=src/picoTCP.cpp
|
||||||
TAP_FILES:=src/SocketTap.cpp \
|
TAP_FILES:=src/SocketTap.cpp \
|
||||||
src/SDKService.cpp
|
src/ZeroTierSDK.cpp \
|
||||||
|
|
||||||
RPC_FILES:=src/RPC.c
|
SDK_OBJS+= SocketTap.o \
|
||||||
SOCKET_API_FILES:=src/Socket.c
|
|
||||||
|
|
||||||
SDK_OBJS+= RPC.o \
|
|
||||||
SocketTap.o \
|
|
||||||
Socket.o \
|
|
||||||
picoTCP.o \
|
picoTCP.o \
|
||||||
SDKService.o
|
ZeroTierSDK.o
|
||||||
|
|
||||||
PICO_OBJS+= ext/picotcp/build/lib/pico_device.o \
|
PICO_OBJS+= ext/picotcp/build/lib/pico_device.o \
|
||||||
ext/picotcp/build/lib/pico_frame.o \
|
ext/picotcp/build/lib/pico_frame.o \
|
||||||
ext/picotcp/build/lib/pico_md5.o \
|
ext/picotcp/build/lib/pico_md5.o \
|
||||||
ext/picotcp/build/lib/pico_protocol.o \
|
ext/picotcp/build/lib/pico_protocol.o \
|
||||||
ext/picotcp/build/lib/pico_socket_multicast.o \
|
ext/picotcp/build/lib/pico_socket_multicast.o \
|
||||||
ext/picotcp/build/lib/pico_socket.o \
|
ext/picotcp/build/lib/pico_socket.o \
|
||||||
ext/picotcp/build/lib/pico_stack.o \
|
ext/picotcp/build/lib/pico_stack.o \
|
||||||
ext/picotcp/build/lib/pico_tree.o
|
ext/picotcp/build/lib/pico_tree.o
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
|
||||||
|
tests: dumb_tests unit_tests
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
## User-Space Stack ##
|
## User-Space Stack ##
|
||||||
##############################################################################
|
##############################################################################
|
||||||
@@ -132,7 +138,7 @@ picotcp:
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
static_lib: picotcp $(ZTO_OBJS)
|
static_lib: picotcp $(ZTO_OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $(SDK_FLAGS) $(RPC_FILES) $(TAP_FILES) $(STACK_DRIVER_FILES) $(SOCKET_API_FILES) -c -DSDK_STATIC
|
$(CXX) $(CXXFLAGS) $(SDK_FLAGS) $(TAP_FILES) $(STACK_DRIVER_FILES) -c -DSDK_STATIC
|
||||||
libtool -static -o $(STATIC_LIB) $(ZTO_OBJS) $(SDK_OBJS) $(PICO_LIB)
|
libtool -static -o $(STATIC_LIB) $(ZTO_OBJS) $(SDK_OBJS) $(PICO_LIB)
|
||||||
|
|
||||||
jni_static_lib: picotcp $(ZTO_OBJS)
|
jni_static_lib: picotcp $(ZTO_OBJS)
|
||||||
@@ -141,8 +147,31 @@ jni_static_lib: picotcp $(ZTO_OBJS)
|
|||||||
## Unit Tests ##
|
## Unit Tests ##
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
static_lib_test:
|
UNIT_TEST_SRC_FILES:=$(wildcard $(UNIT_TEST_SRC_DIR)/*.cpp)
|
||||||
$(CXX) -Iinclude tests/socket/simple.cpp -o build/simple.out -Lbuild -lzt
|
UNIT_TEST_OBJ_FILES:=$(addprefix $(TEST_BUILD_DIR)/,$(notdir $(UNIT_TEST_SRC_FILES:.cpp=.out)))
|
||||||
|
UNIT_TEST_INCLUDES:=-Iinclude
|
||||||
|
UNIT_TEST_LIBS:=-Lbuild -lzt
|
||||||
|
|
||||||
|
$(TEST_BUILD_DIR)/%.out: $(UNIT_TEST_SRC_DIR)/%.cpp
|
||||||
|
@mkdir -p $(TEST_BUILD_DIR)
|
||||||
|
@-$(CXX) $(UNIT_TEST_INCLUDES) -o $@ $< $(UNIT_TEST_LIBS)
|
||||||
|
@-./check.sh $@
|
||||||
|
|
||||||
|
unit_tests: $(UNIT_TEST_OBJ_FILES)
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
## Non-ZT Client/Server Tests ##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
DUMB_TEST_SRC_FILES=$(wildcard $(DUMB_TEST_SRC_DIR)/*.c)
|
||||||
|
DUMB_TEST_OBJ_FILES := $(addprefix $(TEST_BUILD_DIR)/,$(notdir $(DUMB_TEST_SRC_FILES:.c=.out)))
|
||||||
|
|
||||||
|
$(TEST_BUILD_DIR)/%.out: $(DUMB_TEST_SRC_DIR)/%.c
|
||||||
|
@mkdir -p $(TEST_BUILD_DIR)
|
||||||
|
@-$(CC) -o $@ $<
|
||||||
|
@-./check.sh $@
|
||||||
|
|
||||||
|
dumb_tests: $(DUMB_TEST_OBJ_FILES)
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
## Misc ##
|
## Misc ##
|
||||||
@@ -161,4 +190,6 @@ check:
|
|||||||
-./check.sh $(ONE_SERVICE)
|
-./check.sh $(ONE_SERVICE)
|
||||||
-./check.sh $(SDK_SERVICE)
|
-./check.sh $(SDK_SERVICE)
|
||||||
-./check.sh $(STATIC_LIB)
|
-./check.sh $(STATIC_LIB)
|
||||||
|
-./check.sh $(STATIC_LIB)
|
||||||
|
|
||||||
|
|
||||||
73
src/Connection.hpp
Normal file
73
src/Connection.hpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* ZeroTier SDK - Network Virtualization Everywhere
|
||||||
|
* Copyright (C) 2011-2016 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZT_CONNECTION_HPP
|
||||||
|
#define ZT_CONNECTION_HPP
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include "pico_socket.h"
|
||||||
|
|
||||||
|
#include "Phy.hpp"
|
||||||
|
|
||||||
|
#include "ZeroTierSDK.h"
|
||||||
|
#include "SocketTap.hpp"
|
||||||
|
|
||||||
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Connection object
|
||||||
|
*/
|
||||||
|
struct Connection
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
PhySocket *sock;
|
||||||
|
struct pico_socket *picosock;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// RX/TX buffers
|
||||||
|
int txsz, rxsz;
|
||||||
|
unsigned char txbuf[ZT_TCP_TX_BUF_SZ];
|
||||||
|
unsigned char rxbuf[ZT_TCP_RX_BUF_SZ];
|
||||||
|
|
||||||
|
int data_sock;
|
||||||
|
int socket_family, socket_type;
|
||||||
|
|
||||||
|
int app_fd; // provided to app for I/O
|
||||||
|
int sdk_fd; // provided to SDK for I/O
|
||||||
|
|
||||||
|
std::queue<Connection*> _AcceptedConnections;
|
||||||
|
SocketTap *tap; // Reference to SocketTap
|
||||||
|
|
||||||
|
Connection() {
|
||||||
|
ZT_PHY_SOCKFD_TYPE fdpair[2];
|
||||||
|
if(socketpair(PF_LOCAL, SOCK_STREAM, 0, fdpair) < 0) {
|
||||||
|
if(errno < 0) {
|
||||||
|
DEBUG_ERROR("unable to create socketpair");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sdk_fd = fdpair[0];
|
||||||
|
app_fd = fdpair[1];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
345
src/RPC.c
345
src/RPC.c
@@ -1,345 +0,0 @@
|
|||||||
/*
|
|
||||||
* ZeroTier One - Network Virtualization Everywhere
|
|
||||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*
|
|
||||||
* --
|
|
||||||
*
|
|
||||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which
|
|
||||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
*
|
|
||||||
* If you would like to embed ZeroTier into a commercial application or
|
|
||||||
* redistribute it in a modified binary form, please contact ZeroTier Networks
|
|
||||||
* LLC. Start here: http://www.zerotier.com/
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef USE_GNU_SOURCE
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "ZeroTierSDK.h"
|
|
||||||
#include "RPC.h"
|
|
||||||
|
|
||||||
// externs common between SDK_Intercept and SDK_Socket from SDK.h
|
|
||||||
int (*realsocket)(ZT_SOCKET_SIG);
|
|
||||||
int (*realconnect)(ZT_CONNECT_SIG);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SERVICE_CONNECT_ATTEMPTS 30
|
|
||||||
|
|
||||||
ssize_t sock_fd_write(int sock, int fd);
|
|
||||||
ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
|
|
||||||
|
|
||||||
static int rpc_count;
|
|
||||||
|
|
||||||
static pthread_mutex_t lock;
|
|
||||||
void rpc_mutex_init() {
|
|
||||||
if(pthread_mutex_init(&lock, NULL) != 0) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void rpc_mutex_destroy() {
|
|
||||||
pthread_mutex_destroy(&lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reads a new file descriptor from the service
|
|
||||||
*/
|
|
||||||
int get_new_fd(int sock)
|
|
||||||
{
|
|
||||||
char buf[BUF_SZ];
|
|
||||||
int newfd;
|
|
||||||
ssize_t size = sock_fd_read(sock, buf, sizeof(buf), &newfd);
|
|
||||||
if(size > 0)
|
|
||||||
return newfd;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reads a return value from the service and sets errno (if applicable)
|
|
||||||
*/
|
|
||||||
int get_retval(int rpc_sock)
|
|
||||||
{
|
|
||||||
if(rpc_sock >= 0) {
|
|
||||||
int retval;
|
|
||||||
int sz = sizeof(char) + sizeof(retval) + sizeof(errno);
|
|
||||||
char retbuf[BUF_SZ];
|
|
||||||
memset(&retbuf, 0, sz);
|
|
||||||
long n_read = read(rpc_sock, &retbuf, sz);
|
|
||||||
if(n_read > 0) {
|
|
||||||
memcpy(&retval, &retbuf[1], sizeof(retval));
|
|
||||||
memcpy(&errno, &retbuf[1+sizeof(retval)], sizeof(errno));
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int load_symbols_rpc()
|
|
||||||
{
|
|
||||||
#if defined(__IOS__) || defined(__UNITY_3D__)
|
|
||||||
realsocket = dlsym(RTLD_NEXT, "socket");
|
|
||||||
realconnect = dlsym(RTLD_NOW, "connect");
|
|
||||||
if(!realconnect || !realsocket)
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rpc_join(char * sockname)
|
|
||||||
{
|
|
||||||
if(sockname == NULL) {
|
|
||||||
DEBUG_ERROR("warning, rpc netpath is NULL. Exiting.");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
if(!load_symbols_rpc())
|
|
||||||
return -1;
|
|
||||||
struct sockaddr_un addr;
|
|
||||||
int conn_err = -1, attempts = 0;
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
strncpy(addr.sun_path, sockname, sizeof(addr.sun_path)-1);
|
|
||||||
int sock;
|
|
||||||
|
|
||||||
#if defined(SDK_INTERCEPT)
|
|
||||||
if((sock = realsocket(AF_UNIX, SOCK_STREAM, 0)) < 0){
|
|
||||||
#else
|
|
||||||
if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
|
|
||||||
#endif
|
|
||||||
DEBUG_ERROR("error creating RPC socket");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
while((conn_err != 0) /* && (attempts < SERVICE_CONNECT_ATTEMPTS) */){
|
|
||||||
#if defined(SDK_INTERCEPT)
|
|
||||||
if((conn_err = realconnect(sock, (struct sockaddr*)&addr, sizeof(addr))) != 0) {
|
|
||||||
#else
|
|
||||||
if((conn_err = connect(sock, (struct sockaddr*)&addr, sizeof(addr))) != 0) {
|
|
||||||
#endif
|
|
||||||
DEBUG_ERROR("error connecting to RPC socket (%s). Re-attempting...", sockname);
|
|
||||||
usleep(100000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return sock;
|
|
||||||
attempts++;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send a command to the service
|
|
||||||
*/
|
|
||||||
int rpc_send_command(char *path, int cmd, int forfd, void *data, int len)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&lock);
|
|
||||||
char c, padding[] = {PADDING};
|
|
||||||
char cmdbuf[BUF_SZ], CANARY[CANARY_SZ+PADDING_SZ], metabuf[BUF_SZ];
|
|
||||||
|
|
||||||
memcpy(CANARY+CANARY_SZ, padding, sizeof(padding));
|
|
||||||
uint64_t canary_num;
|
|
||||||
// ephemeral RPC socket used only for this command
|
|
||||||
int rpc_sock = rpc_join(path);
|
|
||||||
|
|
||||||
// Generate token
|
|
||||||
int fdrand = open("/dev/urandom", O_RDONLY);
|
|
||||||
if(read(fdrand, &CANARY, CANARY_SZ) < 0) {
|
|
||||||
DEBUG_ERROR("unable to read from /dev/urandom for RPC canary data");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fdrand);
|
|
||||||
memcpy(&canary_num, CANARY, CANARY_SZ);
|
|
||||||
cmdbuf[CMD_ID_IDX] = cmd;
|
|
||||||
memcpy(&cmdbuf[CANARY_IDX], &canary_num, CANARY_SZ);
|
|
||||||
memcpy(&cmdbuf[STRUCT_IDX], data, len);
|
|
||||||
|
|
||||||
rpc_count++;
|
|
||||||
memset(metabuf, 0, BUF_SZ);
|
|
||||||
#if defined(__linux__)
|
|
||||||
#if !defined(__ANDROID__)
|
|
||||||
pid_t pid = 5; //syscall(SYS_getpid);
|
|
||||||
pid_t tid = 4;//syscall(SYS_gettid);
|
|
||||||
#else
|
|
||||||
// Dummy values
|
|
||||||
pid_t pid = 5;
|
|
||||||
pid_t tid = gettid();
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
char timestring[20];
|
|
||||||
time_t timestamp;
|
|
||||||
timestamp = time(NULL);
|
|
||||||
strftime(timestring, sizeof(timestring), "%H:%M:%S", localtime(×tamp));
|
|
||||||
#if defined(__linux__)
|
|
||||||
memcpy(&metabuf[IDX_PID], &pid, sizeof(pid_t) ); /* pid */
|
|
||||||
memcpy(&metabuf[IDX_TID], &tid, sizeof(pid_t) ); /* tid */
|
|
||||||
#endif
|
|
||||||
memcpy(&metabuf[IDX_TIME], ×tring, 20 ); /* timestamp */
|
|
||||||
|
|
||||||
/* Combine command flag+payload with RPC metadata */
|
|
||||||
memcpy(metabuf, RPC_PHRASE, RPC_PHRASE_SZ); // Write signal phrase
|
|
||||||
memcpy(&metabuf[IDX_PAYLOAD], cmdbuf, len + 1 + CANARY_SZ);
|
|
||||||
|
|
||||||
// Write RPC
|
|
||||||
long n_write = write(rpc_sock, &metabuf, BUF_SZ);
|
|
||||||
if(n_write < 0) {
|
|
||||||
DEBUG_ERROR("error writing command to service (CMD = %d)", cmdbuf[CMD_ID_IDX]);
|
|
||||||
errno = 0;
|
|
||||||
}
|
|
||||||
// Write token to corresponding data stream
|
|
||||||
if(read(rpc_sock, &c, 1) < 0) {
|
|
||||||
DEBUG_ERROR("unable to read RPC ACK byte from service.");
|
|
||||||
close(rpc_sock);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(c == 'z' && n_write > 0 && forfd > -1){
|
|
||||||
if(send(forfd, &CANARY, CANARY_SZ+PADDING_SZ, 0) < 0) {
|
|
||||||
perror("send: \n");
|
|
||||||
DEBUG_ERROR("unable to write canary to stream (fd=%d)", forfd);
|
|
||||||
close(rpc_sock);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Process response from service
|
|
||||||
int ret = ERR_OK;
|
|
||||||
if(n_write > 0) {
|
|
||||||
if(cmdbuf[CMD_ID_IDX]==RPC_SOCKET) {
|
|
||||||
pthread_mutex_unlock(&lock);
|
|
||||||
return rpc_sock; // Used as new socket
|
|
||||||
}
|
|
||||||
if(cmdbuf[CMD_ID_IDX]==RPC_CONNECT
|
|
||||||
|| cmdbuf[CMD_ID_IDX]==RPC_BIND
|
|
||||||
|| cmdbuf[CMD_ID_IDX]==RPC_LISTEN) {
|
|
||||||
ret = get_retval(rpc_sock);
|
|
||||||
}
|
|
||||||
if(cmdbuf[CMD_ID_IDX]==RPC_GETSOCKNAME || cmdbuf[CMD_ID_IDX]==RPC_GETPEERNAME) {
|
|
||||||
pthread_mutex_unlock(&lock);
|
|
||||||
return rpc_sock; // Don't close rpc here, we'll use it to read getsockopt_st
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ret = -1;
|
|
||||||
close(rpc_sock); // We're done with this RPC socket, close it (if type-R)
|
|
||||||
pthread_mutex_unlock(&lock);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send file descriptor
|
|
||||||
*/
|
|
||||||
ssize_t sock_fd_write(int sock, int fd)
|
|
||||||
{
|
|
||||||
ssize_t size;
|
|
||||||
struct msghdr msg;
|
|
||||||
struct iovec iov;
|
|
||||||
char buf = '\0';
|
|
||||||
int buflen = 1;
|
|
||||||
union {
|
|
||||||
struct cmsghdr cmsghdr;
|
|
||||||
char control[CMSG_SPACE(sizeof (int))];
|
|
||||||
} cmsgu;
|
|
||||||
struct cmsghdr *cmsg;
|
|
||||||
iov.iov_base = &buf;
|
|
||||||
iov.iov_len = buflen;
|
|
||||||
msg.msg_name = NULL;
|
|
||||||
msg.msg_namelen = 0;
|
|
||||||
msg.msg_iov = &iov;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
if (fd != -1) {
|
|
||||||
msg.msg_control = cmsgu.control;
|
|
||||||
msg.msg_controllen = sizeof(cmsgu.control);
|
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
|
||||||
cmsg->cmsg_len = CMSG_LEN(sizeof (int));
|
|
||||||
cmsg->cmsg_level = SOL_SOCKET;
|
|
||||||
cmsg->cmsg_type = SCM_RIGHTS;
|
|
||||||
*((int *) CMSG_DATA(cmsg)) = fd;
|
|
||||||
} else {
|
|
||||||
msg.msg_control = NULL;
|
|
||||||
msg.msg_controllen = 0;
|
|
||||||
}
|
|
||||||
size = sendmsg(sock, &msg, 0);
|
|
||||||
if (size < 0)
|
|
||||||
perror ("sendmsg");
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Read a file descriptor
|
|
||||||
*/
|
|
||||||
ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
|
|
||||||
{
|
|
||||||
ssize_t size;
|
|
||||||
if (fd) {
|
|
||||||
struct msghdr msg;
|
|
||||||
struct iovec iov;
|
|
||||||
union {
|
|
||||||
struct cmsghdr cmsghdr;
|
|
||||||
char control[CMSG_SPACE(sizeof (int))];
|
|
||||||
} cmsgu;
|
|
||||||
|
|
||||||
struct cmsghdr *cmsg;
|
|
||||||
iov.iov_base = buf;
|
|
||||||
iov.iov_len = bufsize;
|
|
||||||
msg.msg_name = NULL;
|
|
||||||
msg.msg_namelen = 0;
|
|
||||||
|
|
||||||
msg.msg_iov = &iov;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
msg.msg_control = cmsgu.control;
|
|
||||||
msg.msg_controllen = sizeof(cmsgu.control);
|
|
||||||
size = recvmsg (sock, &msg, 0);
|
|
||||||
|
|
||||||
if (size < 0)
|
|
||||||
return -1;
|
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
|
||||||
if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
|
|
||||||
if (cmsg->cmsg_level != SOL_SOCKET) {
|
|
||||||
DEBUG_ERROR("invalid cmsg_level %d",cmsg->cmsg_level);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (cmsg->cmsg_type != SCM_RIGHTS) {
|
|
||||||
DEBUG_ERROR("invalid cmsg_type %d",cmsg->cmsg_type);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*fd = *((int *) CMSG_DATA(cmsg));
|
|
||||||
} else {
|
|
||||||
*fd = -1;}
|
|
||||||
} else {
|
|
||||||
size = read (sock, buf, bufsize);
|
|
||||||
if (size < 0) {
|
|
||||||
DEBUG_ERROR("sock_fd_read(): read: Error");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
144
src/RPC.h
144
src/RPC.h
@@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* ZeroTier One - Network Virtualization Everywhere
|
|
||||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*
|
|
||||||
* --
|
|
||||||
*
|
|
||||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which
|
|
||||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
*
|
|
||||||
* If you would like to embed ZeroTier into a commercial application or
|
|
||||||
* redistribute it in a modified binary form, please contact ZeroTier Networks
|
|
||||||
* LLC. Start here: http://www.zerotier.com/
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __RPCLIB_H_
|
|
||||||
#define __RPCLIB_H_
|
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#define CANARY_SZ sizeof(uint64_t)
|
|
||||||
#define PADDING_SZ 12
|
|
||||||
#define PADDING 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
|
|
||||||
|
|
||||||
#define RPC_PHRASE "zerotier\0"
|
|
||||||
#define RPC_PHRASE_SZ 9
|
|
||||||
#define RPC_TIMESTAMP_SZ 20
|
|
||||||
// 1st RPC section (metdata)
|
|
||||||
#define IDX_SIGNAL_PHRASE 0
|
|
||||||
#define IDX_PID IDX_SIGNAL_PHRASE + RPC_PHRASE_SZ
|
|
||||||
#define IDX_TID sizeof(pid_t) + IDX_PID
|
|
||||||
#define IDX_TIME IDX_TID + sizeof(int)
|
|
||||||
#define IDX_PAYLOAD IDX_TIME + RPC_TIMESTAMP_SZ
|
|
||||||
// 2nd RPC section (payload and canary)
|
|
||||||
#define CMD_ID_IDX 0
|
|
||||||
#define CANARY_IDX 1
|
|
||||||
#define STRUCT_IDX CANARY_IDX+CANARY_SZ
|
|
||||||
|
|
||||||
#define BUF_SZ 512
|
|
||||||
|
|
||||||
#define ERR_OK 0
|
|
||||||
|
|
||||||
/* RPC codes */
|
|
||||||
#define RPC_UNDEFINED 0
|
|
||||||
#define RPC_CONNECT 1
|
|
||||||
#define RPC_CONNECT_SOCKARG 2
|
|
||||||
#define RPC_CLOSE 3
|
|
||||||
#define RPC_READ 4
|
|
||||||
#define RPC_WRITE 5
|
|
||||||
#define RPC_BIND 6
|
|
||||||
#define RPC_ACCEPT 7
|
|
||||||
#define RPC_LISTEN 8
|
|
||||||
#define RPC_SOCKET 9
|
|
||||||
#define RPC_SHUTDOWN 10
|
|
||||||
#define RPC_GETSOCKNAME 11
|
|
||||||
#define RPC_GETPEERNAME 12
|
|
||||||
#define RPC_RETVAL 13
|
|
||||||
#define RPC_IS_CONNECTED 14
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int get_retval(int);
|
|
||||||
int rpc_join( char * sockname);
|
|
||||||
int rpc_send_command(char *path, int cmd, int forfd, void *data, int len);
|
|
||||||
|
|
||||||
int get_new_fd(int sock);
|
|
||||||
ssize_t sock_fd_write(int sock, int fd);
|
|
||||||
ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
|
|
||||||
|
|
||||||
void rpc_mutex_destroy();
|
|
||||||
void rpc_mutex_init();
|
|
||||||
|
|
||||||
|
|
||||||
/* Structures used for sending commands via RPC mechanism */
|
|
||||||
|
|
||||||
struct bind_st {
|
|
||||||
int fd;
|
|
||||||
struct sockaddr_storage addr;
|
|
||||||
socklen_t addrlen;
|
|
||||||
int tid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct connect_st {
|
|
||||||
int fd;
|
|
||||||
struct sockaddr_storage addr;
|
|
||||||
socklen_t addrlen;
|
|
||||||
int tid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct close_st {
|
|
||||||
int fd;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct listen_st {
|
|
||||||
int fd;
|
|
||||||
int backlog;
|
|
||||||
int tid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct socket_st {
|
|
||||||
int socket_family;
|
|
||||||
int socket_type;
|
|
||||||
int protocol;
|
|
||||||
int tid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct accept_st {
|
|
||||||
int fd;
|
|
||||||
struct sockaddr_storage addr;
|
|
||||||
socklen_t addrlen;
|
|
||||||
int tid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct shutdown_st {
|
|
||||||
int socket;
|
|
||||||
int how;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct getsockname_st {
|
|
||||||
int fd;
|
|
||||||
struct sockaddr_storage addr;
|
|
||||||
socklen_t addrlen;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
115
src/Socket.c
115
src/Socket.c
@@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* ZeroTier One - Network Virtualization Everywhere
|
|
||||||
* Copyright (C) 2011-2016 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
#define SOCK_MAX (SOCK_PACKET + 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "ZeroTierSDK.h"
|
|
||||||
#include "RPC.h"
|
|
||||||
|
|
||||||
char *api_netpath;
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* zts_init_rpc() */
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
int service_initialized = 0;
|
|
||||||
|
|
||||||
// Assembles (and/or) sets the RPC path for communication with the ZeroTier service
|
|
||||||
void zts_init_rpc(const char *path, const char *nwid)
|
|
||||||
{
|
|
||||||
// If no path, construct one or get it fron system env vars
|
|
||||||
if(!api_netpath) {
|
|
||||||
rpc_mutex_init();
|
|
||||||
// Provided by user
|
|
||||||
#if defined(SDK_BUNDLED)
|
|
||||||
// Get the path/nwid from the user application
|
|
||||||
// netpath = [path + "/nc_" + nwid]
|
|
||||||
char *fullpath = (char *)malloc(strlen(path)+strlen(nwid)+1+4);
|
|
||||||
if(fullpath) {
|
|
||||||
zts_join_network_soft(path, nwid);
|
|
||||||
strcpy(fullpath, path);
|
|
||||||
strcat(fullpath, "/nc_");
|
|
||||||
strcat(fullpath, nwid);
|
|
||||||
api_netpath = fullpath;
|
|
||||||
}
|
|
||||||
// Provided by Env
|
|
||||||
#else
|
|
||||||
// Get path/nwid from environment variables
|
|
||||||
if (!api_netpath) {
|
|
||||||
api_netpath = getenv("ZT_NC_NETWORK");
|
|
||||||
DEBUG_INFO("$ZT_NC_NETWORK=%s", api_netpath);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// start the SDK service if this is bundled
|
|
||||||
#if defined(SDK_BUNDLED)
|
|
||||||
if(!service_initialized) {
|
|
||||||
DEBUG_ATTN("api_netpath = %s", api_netpath);
|
|
||||||
pthread_t service_thread;
|
|
||||||
pthread_create(&service_thread, NULL, zts_start_core_service, (void *)(path));
|
|
||||||
service_initialized = 1;
|
|
||||||
DEBUG_ATTN("waiting for service to assign address to network stack");
|
|
||||||
// wait for zt service to assign the network stack an address
|
|
||||||
sleep(1);
|
|
||||||
while(!zts_has_address(nwid)) { usleep(1000); }
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_api_netpath() { zts_init_rpc("",""); }
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* socket() */
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
int zts_socket(ZT_SOCKET_SIG)
|
|
||||||
{
|
|
||||||
DEBUG_INFO("");
|
|
||||||
#ifdef SDK_STATIC
|
|
||||||
return zts_multiplex_new_socket(socket_family, socket_type, protocol);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int zts_connect(ZT_CONNECT_SIG)
|
|
||||||
{
|
|
||||||
DEBUG_INFO("");
|
|
||||||
#ifdef SDK_STATIC
|
|
||||||
return zts_multiplex_new_connect(fd, addr, addrlen);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* ZeroTier One - Network Virtualization Everywhere
|
* ZeroTier SDK - Network Virtualization Everywhere
|
||||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -14,15 +14,6 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
* --
|
|
||||||
*
|
|
||||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which
|
|
||||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
*
|
|
||||||
* If you would like to embed ZeroTier into a commercial application or
|
|
||||||
* redistribute it in a modified binary form, please contact ZeroTier Networks
|
|
||||||
* LLC. Start here: http://www.zerotier.com/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -37,7 +28,6 @@
|
|||||||
|
|
||||||
#include "SocketTap.hpp"
|
#include "SocketTap.hpp"
|
||||||
#include "ZeroTierSDK.h"
|
#include "ZeroTierSDK.h"
|
||||||
#include "RPC.h"
|
|
||||||
#include "picoTCP.hpp"
|
#include "picoTCP.hpp"
|
||||||
|
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
@@ -57,32 +47,11 @@ void SocketTap::phyOnTcpClose(PhySocket *sock,void **uptr) {}
|
|||||||
void SocketTap::phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
|
void SocketTap::phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
|
||||||
void SocketTap::phyOnTcpWritable(PhySocket *sock,void **uptr, bool stack_invoked) {}
|
void SocketTap::phyOnTcpWritable(PhySocket *sock,void **uptr, bool stack_invoked) {}
|
||||||
|
|
||||||
int SocketTap::sendReturnValue(int fd, int retval, int _errno)
|
/****************************************************************************/
|
||||||
{
|
/* SocketTap Service */
|
||||||
//DEBUG_INFO("fd=%d, retval=%d, errno=%d", fd, retval, _errno);
|
/* - For each joined network a SocketTap will be created to administer I/O */
|
||||||
int sz = sizeof(char) + sizeof(retval) + sizeof(errno);
|
/* calls to the stack and the ZT virtual wire */
|
||||||
char retmsg[sz];
|
/****************************************************************************/
|
||||||
memset(&retmsg, 0, sizeof(retmsg));
|
|
||||||
retmsg[0]=RPC_RETVAL;
|
|
||||||
memcpy(&retmsg[1], &retval, sizeof(retval));
|
|
||||||
memcpy(&retmsg[1]+sizeof(retval), &_errno, sizeof(_errno));
|
|
||||||
return write(fd, &retmsg, sz);
|
|
||||||
}
|
|
||||||
// Unpacks the buffer from an RPC command
|
|
||||||
void SocketTap::unloadRPC(void *data, pid_t &pid, pid_t &tid,
|
|
||||||
char (timestamp[RPC_TIMESTAMP_SZ]), char (CANARY[sizeof(uint64_t)]), char &cmd, void* &payload)
|
|
||||||
{
|
|
||||||
unsigned char *buf = (unsigned char*)data;
|
|
||||||
memcpy(&pid, &buf[IDX_PID], sizeof(pid_t));
|
|
||||||
memcpy(&tid, &buf[IDX_TID], sizeof(pid_t));
|
|
||||||
memcpy(timestamp, &buf[IDX_TIME], RPC_TIMESTAMP_SZ);
|
|
||||||
memcpy(&cmd, &buf[IDX_PAYLOAD], sizeof(char));
|
|
||||||
memcpy(CANARY, &buf[IDX_PAYLOAD+1], CANARY_SZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
|
||||||
-------------------------------- Tap Service ----------------------------------
|
|
||||||
------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SocketTap::SocketTap(
|
SocketTap::SocketTap(
|
||||||
const char *homePath,
|
const char *homePath,
|
||||||
@@ -105,7 +74,7 @@ SocketTap::SocketTap(
|
|||||||
_enabled(true),
|
_enabled(true),
|
||||||
_run(true)
|
_run(true)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
char sockPath[4096];
|
char sockPath[4096];
|
||||||
Utils::snprintf(sockPath,sizeof(sockPath),"%s%s" ZT_SDK_RPC_DIR_PREFIX "/%.16llx",
|
Utils::snprintf(sockPath,sizeof(sockPath),"%s%s" ZT_SDK_RPC_DIR_PREFIX "/%.16llx",
|
||||||
homePath,ZT_PATH_SEPARATOR_S,_nwid,ZT_PATH_SEPARATOR_S,(unsigned long long)nwid);
|
homePath,ZT_PATH_SEPARATOR_S,_nwid,ZT_PATH_SEPARATOR_S,(unsigned long long)nwid);
|
||||||
@@ -116,21 +85,13 @@ SocketTap::SocketTap(
|
|||||||
DEBUG_ERROR("unable to bind to: rpc = %s", sockPath);
|
DEBUG_ERROR("unable to bind to: rpc = %s", sockPath);
|
||||||
else
|
else
|
||||||
DEBUG_INFO("rpc = %s", sockPath);
|
DEBUG_INFO("rpc = %s", sockPath);
|
||||||
|
*/
|
||||||
char ver[6];
|
|
||||||
zts_core_version(ver);
|
|
||||||
DEBUG_INFO("zts_core_version = %s", ver);
|
|
||||||
zts_sdk_version(ver);
|
|
||||||
DEBUG_INFO("zts_sdk_version = %s", ver);
|
|
||||||
char id[11];
|
|
||||||
zts_get_device_id(id);
|
|
||||||
DEBUG_INFO("id = %s", id);
|
|
||||||
|
|
||||||
_thread = Thread::start(this);
|
_thread = Thread::start(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketTap::~SocketTap()
|
SocketTap::~SocketTap()
|
||||||
{
|
{
|
||||||
|
// TODO: Verify deletion of all objects
|
||||||
_run = false;
|
_run = false;
|
||||||
_phy.whack();
|
_phy.whack();
|
||||||
Thread::join(_thread);
|
Thread::join(_thread);
|
||||||
@@ -149,6 +110,7 @@ bool SocketTap::enabled() const
|
|||||||
|
|
||||||
bool SocketTap::addIp(const InetAddress &ip)
|
bool SocketTap::addIp(const InetAddress &ip)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
picotap = this;
|
picotap = this;
|
||||||
picostack->pico_init_interface(this, ip);
|
picostack->pico_init_interface(this, ip);
|
||||||
_ips.push_back(ip);
|
_ips.push_back(ip);
|
||||||
@@ -157,6 +119,7 @@ bool SocketTap::addIp(const InetAddress &ip)
|
|||||||
|
|
||||||
bool SocketTap::removeIp(const InetAddress &ip)
|
bool SocketTap::removeIp(const InetAddress &ip)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
Mutex::Lock _l(_ips_m);
|
Mutex::Lock _l(_ips_m);
|
||||||
std::vector<InetAddress>::iterator i(std::find(_ips.begin(),_ips.end(),ip));
|
std::vector<InetAddress>::iterator i(std::find(_ips.begin(),_ips.end(),ip));
|
||||||
if (i == _ips.end())
|
if (i == _ips.end())
|
||||||
@@ -177,6 +140,7 @@ std::vector<InetAddress> SocketTap::ips() const
|
|||||||
void SocketTap::put(const MAC &from,const MAC &to,unsigned int etherType,
|
void SocketTap::put(const MAC &from,const MAC &to,unsigned int etherType,
|
||||||
const void *data,unsigned int len)
|
const void *data,unsigned int len)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
// RX packet
|
// RX packet
|
||||||
picostack->pico_rx(this, from,to,etherType,data,len);
|
picostack->pico_rx(this, from,to,etherType,data,len);
|
||||||
|
|
||||||
@@ -223,6 +187,7 @@ void SocketTap::threadMain()
|
|||||||
|
|
||||||
Connection *SocketTap::getConnection(PhySocket *sock)
|
Connection *SocketTap::getConnection(PhySocket *sock)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
for(size_t i=0;i<_Connections.size();++i) {
|
for(size_t i=0;i<_Connections.size();++i) {
|
||||||
if(_Connections[i]->sock == sock)
|
if(_Connections[i]->sock == sock)
|
||||||
return _Connections[i];
|
return _Connections[i];
|
||||||
@@ -232,6 +197,7 @@ Connection *SocketTap::getConnection(PhySocket *sock)
|
|||||||
|
|
||||||
Connection *SocketTap::getConnection(struct pico_socket *sock)
|
Connection *SocketTap::getConnection(struct pico_socket *sock)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
for(size_t i=0;i<_Connections.size();++i) {
|
for(size_t i=0;i<_Connections.size();++i) {
|
||||||
if(_Connections[i]->picosock == sock)
|
if(_Connections[i]->picosock == sock)
|
||||||
return _Connections[i];
|
return _Connections[i];
|
||||||
@@ -241,6 +207,7 @@ Connection *SocketTap::getConnection(struct pico_socket *sock)
|
|||||||
|
|
||||||
void SocketTap::closeConnection(PhySocket *sock)
|
void SocketTap::closeConnection(PhySocket *sock)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
Mutex::Lock _l(_close_m);
|
Mutex::Lock _l(_close_m);
|
||||||
// Here we assume _tcpconns_m is already locked by caller
|
// Here we assume _tcpconns_m is already locked by caller
|
||||||
if(!sock) {
|
if(!sock) {
|
||||||
@@ -265,6 +232,7 @@ void SocketTap::closeConnection(PhySocket *sock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::phyOnUnixClose(PhySocket *sock,void **uptr) {
|
void SocketTap::phyOnUnixClose(PhySocket *sock,void **uptr) {
|
||||||
|
DEBUG_INFO();
|
||||||
//Mutex::Lock _l(_tcpconns_m);
|
//Mutex::Lock _l(_tcpconns_m);
|
||||||
//closeConnection(sock);
|
//closeConnection(sock);
|
||||||
// FIXME:
|
// FIXME:
|
||||||
@@ -272,167 +240,57 @@ void SocketTap::phyOnUnixClose(PhySocket *sock,void **uptr) {
|
|||||||
|
|
||||||
void SocketTap::handleRead(PhySocket *sock,void **uptr,bool stack_invoked)
|
void SocketTap::handleRead(PhySocket *sock,void **uptr,bool stack_invoked)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
picostack->pico_handleRead(sock, uptr, stack_invoked);
|
picostack->pico_handleRead(sock, uptr, stack_invoked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::phyOnUnixWritable(PhySocket *sock,void **uptr,bool stack_invoked)
|
void SocketTap::phyOnUnixWritable(PhySocket *sock,void **uptr,bool stack_invoked)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
handleRead(sock,uptr,stack_invoked);
|
handleRead(sock,uptr,stack_invoked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len)
|
void SocketTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len)
|
||||||
{
|
{
|
||||||
//DEBUG_INFO("physock=%p, len=%d", sock, (int)len);
|
DEBUG_INFO();
|
||||||
uint64_t CANARY_num;
|
Connection *conn = getConnection(sock);
|
||||||
pid_t pid, tid;
|
|
||||||
ssize_t wlen = len;
|
|
||||||
char tmpbuf[SDK_MTU];
|
|
||||||
char cmd, timestamp[20], CANARY[CANARY_SZ], padding[] = {PADDING};
|
|
||||||
void *payload;
|
|
||||||
unsigned char *buf = (unsigned char*)data;
|
|
||||||
std::pair<PhySocket*, void*> sockdata;
|
|
||||||
PhySocket *rpcSock;
|
|
||||||
bool foundJob = false, detected_rpc = false;
|
|
||||||
Connection *conn;
|
|
||||||
// RPC
|
|
||||||
char phrase[RPC_PHRASE_SZ];
|
|
||||||
memset(phrase, 0, RPC_PHRASE_SZ);
|
|
||||||
if(len == BUF_SZ) {
|
|
||||||
memcpy(phrase, buf, RPC_PHRASE_SZ);
|
|
||||||
if(strcmp(phrase, RPC_PHRASE) == 0)
|
|
||||||
detected_rpc = true;
|
|
||||||
}
|
|
||||||
if(detected_rpc) {
|
|
||||||
unloadRPC(data, pid, tid, timestamp, CANARY, cmd, payload);
|
|
||||||
memcpy(&CANARY_num, CANARY, CANARY_SZ);
|
|
||||||
// DEBUG_EXTRA(" RPC: physock=%p, (pid=%d, tid=%d, timestamp=%s, cmd=%d)", sock, pid, tid, timestamp, cmd);
|
|
||||||
|
|
||||||
if(cmd == RPC_SOCKET) {
|
|
||||||
// DEBUG_INFO("RPC_SOCKET, physock=%p", sock);
|
|
||||||
// Create new stack socket and associate it with this sock
|
|
||||||
struct socket_st socket_rpc;
|
|
||||||
memcpy(&socket_rpc, &buf[IDX_PAYLOAD+STRUCT_IDX], sizeof(struct socket_st));
|
|
||||||
Connection * new_conn;
|
|
||||||
if((new_conn = handleSocket(sock, uptr, &socket_rpc))) {
|
|
||||||
new_conn->pid = pid; // Merely kept to look up application path/names later, not strictly necessary
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
memcpy(&tmpbuf,data,len);
|
|
||||||
jobmap[CANARY_num] = std::pair<PhySocket*, void*>(sock, tmpbuf);
|
|
||||||
|
|
||||||
}
|
|
||||||
write(_phy.getDescriptor(sock), "z", 1); // RPC ACK byte to maintain order
|
|
||||||
}
|
|
||||||
// STREAM
|
|
||||||
else {
|
|
||||||
int data_start = -1, data_end = -1, canary_pos = -1, padding_pos = -1;
|
|
||||||
// Look for padding
|
|
||||||
std::string padding_pattern(padding, padding+PADDING_SZ);
|
|
||||||
std::string buffer(buf, buf + len);
|
|
||||||
padding_pos = buffer.find(padding_pattern);
|
|
||||||
canary_pos = padding_pos-CANARY_SZ;
|
|
||||||
// Grab token, next we'll use it to look up an RPC job
|
|
||||||
if(canary_pos > -1) {
|
|
||||||
memcpy(&CANARY_num, buf+canary_pos, CANARY_SZ);
|
|
||||||
if(CANARY_num != 0) {
|
|
||||||
// Find job
|
|
||||||
sockdata = jobmap[CANARY_num];
|
|
||||||
if(!sockdata.first) {
|
|
||||||
return;
|
|
||||||
} else
|
|
||||||
foundJob = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conn = getConnection(sock);
|
|
||||||
if(!conn)
|
if(!conn)
|
||||||
return;
|
return;
|
||||||
|
if(len) {
|
||||||
if(padding_pos == -1) { // [DATA]
|
conn->txsz += len;
|
||||||
memcpy(&conn->txbuf[conn->txsz], buf, wlen);
|
|
||||||
} else { // Padding found, implies a canary is present
|
|
||||||
// [CANARY]
|
|
||||||
if(len == CANARY_SZ+PADDING_SZ && canary_pos == 0) {
|
|
||||||
wlen = 0; // Nothing to write
|
|
||||||
} else {
|
|
||||||
// [CANARY] + [DATA]
|
|
||||||
if(len > CANARY_SZ+PADDING_SZ && canary_pos == 0) {
|
|
||||||
wlen = len - CANARY_SZ+PADDING_SZ;
|
|
||||||
data_start = padding_pos+PADDING_SZ;
|
|
||||||
memcpy((&conn->txbuf)+conn->txsz, buf+data_start, wlen);
|
|
||||||
}
|
|
||||||
// [DATA] + [CANARY]
|
|
||||||
if(len > CANARY_SZ+PADDING_SZ && canary_pos > 0
|
|
||||||
&& canary_pos == len - CANARY_SZ+PADDING_SZ) {
|
|
||||||
wlen = len - CANARY_SZ+PADDING_SZ;
|
|
||||||
data_start = 0;
|
|
||||||
memcpy((&conn->txbuf)+conn->txsz, buf+data_start, wlen);
|
|
||||||
}
|
|
||||||
// [DATA] + [CANARY] + [DATA]
|
|
||||||
if(len > CANARY_SZ+PADDING_SZ && canary_pos > 0
|
|
||||||
&& len > (canary_pos + CANARY_SZ+PADDING_SZ)) {
|
|
||||||
wlen = len - CANARY_SZ+PADDING_SZ;
|
|
||||||
data_start = 0;
|
|
||||||
data_end = padding_pos-CANARY_SZ;
|
|
||||||
memcpy((&conn->txbuf)+conn->txsz, buf+data_start, (data_end-data_start)+1);
|
|
||||||
memcpy((&conn->txbuf)+conn->txsz, buf+(padding_pos+PADDING_SZ), len-(canary_pos+CANARY_SZ+PADDING_SZ));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write data from stream
|
|
||||||
if(wlen) {
|
|
||||||
conn->txsz += wlen;
|
|
||||||
handleWrite(conn);
|
handleWrite(conn);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Process RPC if we have a corresponding jobmap entry
|
|
||||||
if(foundJob) {
|
|
||||||
rpcSock = sockdata.first;
|
|
||||||
buf = (unsigned char*)sockdata.second;
|
|
||||||
unloadRPC(buf, pid, tid, timestamp, CANARY, cmd, payload);
|
|
||||||
//DEBUG_ERROR(" RPC: physock=%p, (pid=%d, tid=%d, timestamp=%s, cmd=%d)", sock, pid, tid, timestamp, cmd);
|
|
||||||
switch(cmd) {
|
|
||||||
case RPC_BIND:
|
|
||||||
//DEBUG_INFO("RPC_BIND, physock=%p", sock);
|
|
||||||
struct bind_st bind_rpc;
|
|
||||||
memcpy(&bind_rpc, &buf[IDX_PAYLOAD+STRUCT_IDX], sizeof(struct bind_st));
|
|
||||||
handleBind(sock, rpcSock, uptr, &bind_rpc);
|
|
||||||
break;
|
|
||||||
case RPC_LISTEN:
|
|
||||||
//DEBUG_INFO("RPC_LISTEN, physock=%p", sock);
|
|
||||||
struct listen_st listen_rpc;
|
|
||||||
memcpy(&listen_rpc, &buf[IDX_PAYLOAD+STRUCT_IDX], sizeof(struct listen_st));
|
|
||||||
handleListen(sock, rpcSock, uptr, &listen_rpc);
|
|
||||||
break;
|
|
||||||
case RPC_GETSOCKNAME:
|
|
||||||
//DEBUG_INFO("RPC_GETSOCKNAME, physock=%p", sock);
|
|
||||||
struct getsockname_st getsockname_rpc;
|
|
||||||
memcpy(&getsockname_rpc, &buf[IDX_PAYLOAD+STRUCT_IDX], sizeof(struct getsockname_st));
|
|
||||||
handleGetsockname(sock, rpcSock, uptr, &getsockname_rpc);
|
|
||||||
break;
|
|
||||||
case RPC_GETPEERNAME:
|
|
||||||
//DEBUG_INFO("RPC_GETPEERNAME, physock=%p", sock);
|
|
||||||
struct getsockname_st getpeername_rpc;
|
|
||||||
memcpy(&getpeername_rpc, &buf[IDX_PAYLOAD+STRUCT_IDX], sizeof(struct getsockname_st));
|
|
||||||
handleGetpeername(sock, rpcSock, uptr, &getpeername_rpc);
|
|
||||||
break;
|
|
||||||
case RPC_CONNECT:
|
|
||||||
//DEBUG_INFO("RPC_CONNECT, physock=%p", sock);
|
|
||||||
struct connect_st connect_rpc;
|
|
||||||
memcpy(&connect_rpc, &buf[IDX_PAYLOAD+STRUCT_IDX], sizeof(struct connect_st));
|
|
||||||
handleConnect(sock, rpcSock, conn, &connect_rpc);
|
|
||||||
jobmap.erase(CANARY_num);
|
|
||||||
return; // Keep open RPC, we'll use it once in nc_connected to send retval
|
|
||||||
default:
|
|
||||||
return;
|
return;
|
||||||
break;
|
|
||||||
}
|
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
|
||||||
closeConnection(sockdata.first); // close RPC after sending retval, no longer needed
|
|
||||||
jobmap.erase(CANARY_num);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* SDK Socket API */
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
int SocketTap::Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||||
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
|
return picostack->pico_Connect(conn, fd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SocketTap::Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||||
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
|
return picostack->pico_Bind(conn, fd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketTap::Listen(Connection *conn, int fd, int backlog) {
|
||||||
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
|
picostack->pico_Listen(conn, fd, backlog);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SocketTap::Accept(Connection *conn) {
|
||||||
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
|
return picostack->pico_Accept(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
----------------------------- RPC Handler functions ----------------------------
|
----------------------------- RPC Handler functions ----------------------------
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
@@ -440,6 +298,7 @@ void SocketTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t
|
|||||||
void SocketTap::handleGetsockname(PhySocket *sock, PhySocket *rpcSock,
|
void SocketTap::handleGetsockname(PhySocket *sock, PhySocket *rpcSock,
|
||||||
void **uptr, struct getsockname_st *getsockname_rpc)
|
void **uptr, struct getsockname_st *getsockname_rpc)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
Connection *conn = getConnection(sock);
|
Connection *conn = getConnection(sock);
|
||||||
if(conn->local_addr == NULL){
|
if(conn->local_addr == NULL){
|
||||||
@@ -455,6 +314,7 @@ void SocketTap::handleGetsockname(PhySocket *sock, PhySocket *rpcSock,
|
|||||||
void SocketTap::handleGetpeername(PhySocket *sock, PhySocket *rpcSock,
|
void SocketTap::handleGetpeername(PhySocket *sock, PhySocket *rpcSock,
|
||||||
void **uptr, struct getsockname_st *getsockname_rpc)
|
void **uptr, struct getsockname_st *getsockname_rpc)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
Connection *conn = getConnection(sock);
|
Connection *conn = getConnection(sock);
|
||||||
if(conn->peer_addr == NULL){
|
if(conn->peer_addr == NULL){
|
||||||
@@ -467,41 +327,10 @@ void SocketTap::handleGetpeername(PhySocket *sock, PhySocket *rpcSock,
|
|||||||
write(_phy.getDescriptor(rpcSock), conn->peer_addr, sizeof(struct sockaddr_storage));
|
write(_phy.getDescriptor(rpcSock), conn->peer_addr, sizeof(struct sockaddr_storage));
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection * SocketTap::handleSocket(PhySocket *sock, void **uptr,
|
|
||||||
struct socket_st* socket_rpc)
|
|
||||||
{
|
|
||||||
return picostack->pico_handleSocket(sock, uptr, socket_rpc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SocketTap::handleConnect(PhySocket *sock, PhySocket *rpcSock, Connection *conn,
|
|
||||||
struct connect_st* connect_rpc)
|
|
||||||
{
|
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
|
||||||
picostack->pico_handleConnect(sock, rpcSock, conn, connect_rpc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SocketTap::handleBind(PhySocket *sock, PhySocket *rpcSock, void **uptr,
|
|
||||||
struct bind_st *bind_rpc)
|
|
||||||
{
|
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
|
||||||
if(!_ips.size()) {
|
|
||||||
DEBUG_ERROR("cannot bind yet. ZT address hasn't been provided");
|
|
||||||
sendReturnValue(_phy.getDescriptor(rpcSock), -1, ENOMEM);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
picostack->pico_handleBind(sock,rpcSock,uptr,bind_rpc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SocketTap::handleListen(PhySocket *sock, PhySocket *rpcSock, void **uptr,
|
|
||||||
struct listen_st *listen_rpc)
|
|
||||||
{
|
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
|
||||||
picostack->pico_handleListen(sock, rpcSock, uptr, listen_rpc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write to the network stack (and thus out onto the network)
|
// Write to the network stack (and thus out onto the network)
|
||||||
void SocketTap::handleWrite(Connection *conn)
|
void SocketTap::handleWrite(Connection *conn)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
picostack->pico_handleWrite(conn);
|
picostack->pico_handleWrite(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* ZeroTier One - Network Virtualization Everywhere
|
* ZeroTier SDK - Network Virtualization Everywhere
|
||||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -14,24 +14,16 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
* --
|
|
||||||
*
|
|
||||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which
|
|
||||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
*
|
|
||||||
* If you would like to embed ZeroTier into a commercial application or
|
|
||||||
* redistribute it in a modified binary form, please contact ZeroTier Networks
|
|
||||||
* LLC. Start here: http://www.zerotier.com/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ZT_SocketTap_HPP
|
#ifndef ZT_SOCKETTAP_HPP
|
||||||
#define ZT_SocketTap_HPP
|
#define ZT_SOCKETTAP_HPP
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <queue>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -44,8 +36,8 @@
|
|||||||
#include "Phy.hpp"
|
#include "Phy.hpp"
|
||||||
|
|
||||||
#include "ZeroTierSDK.h"
|
#include "ZeroTierSDK.h"
|
||||||
#include "RPC.h"
|
|
||||||
#include "picoTCP.hpp"
|
#include "picoTCP.hpp"
|
||||||
|
#include "Connection.hpp"
|
||||||
|
|
||||||
#include "pico_protocol.h"
|
#include "pico_protocol.h"
|
||||||
#include "pico_stack.h"
|
#include "pico_stack.h"
|
||||||
@@ -69,31 +61,8 @@ struct pico_socket;
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class SocketTap;
|
|
||||||
|
|
||||||
extern SocketTap *picotap;
|
extern SocketTap *picotap;
|
||||||
|
|
||||||
/*
|
|
||||||
* Connection object
|
|
||||||
*/
|
|
||||||
struct Connection
|
|
||||||
{
|
|
||||||
bool listening, probation, disabled;
|
|
||||||
int pid, txsz, rxsz;
|
|
||||||
PhySocket *rpcSock, *sock;
|
|
||||||
struct tcp_pcb *TCP_pcb;
|
|
||||||
struct udp_pcb *UDP_pcb;
|
|
||||||
struct sockaddr_storage *local_addr; // Address we've bound to locally
|
|
||||||
struct sockaddr_storage *peer_addr; // Address of connection call to remote host
|
|
||||||
unsigned short port;
|
|
||||||
unsigned char txbuf[DEFAULT_TCP_TX_BUF_SZ];
|
|
||||||
unsigned char rxbuf[DEFAULT_TCP_RX_BUF_SZ];
|
|
||||||
struct pico_socket *picosock;
|
|
||||||
|
|
||||||
int data_sock;
|
|
||||||
int socket_family, socket_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A helper for passing a reference to _phy to stackrpc callbacks as a "state"
|
* A helper for passing a reference to _phy to stackrpc callbacks as a "state"
|
||||||
*/
|
*/
|
||||||
@@ -160,17 +129,6 @@ namespace ZeroTier {
|
|||||||
*/
|
*/
|
||||||
void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int sendReturnValue(int fd, int retval, int _errno);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void unloadRPC(void *data, pid_t &pid, pid_t &tid, char (timestamp[RPC_TIMESTAMP_SZ]),
|
|
||||||
char (CANARY[sizeof(uint64_t)]), char &cmd, void* &payload);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -199,12 +157,20 @@ namespace ZeroTier {
|
|||||||
int pico_frame_rxbuf_tot;
|
int pico_frame_rxbuf_tot;
|
||||||
Mutex _pico_frame_rxbuf_m;
|
Mutex _pico_frame_rxbuf_m;
|
||||||
|
|
||||||
void handleBind(PhySocket *sock, PhySocket *rpcsock, void **uptr, struct bind_st *bind_rpc);
|
|
||||||
void handleListen(PhySocket *sock, PhySocket *rpcsock, void **uptr,
|
|
||||||
struct listen_st *listen_rpc);
|
|
||||||
Connection * handleSocket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc);
|
/****************************************************************************/
|
||||||
void handleConnect(PhySocket *sock, PhySocket *rpcsock, Connection *conn,
|
/* In these, we will call the stack's corresponding functions, this is *
|
||||||
struct connect_st* connect_rpc);
|
* where one would put logic to select between different stacks */
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
int Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
int Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
void Listen(Connection *conn, int fd, int backlog);
|
||||||
|
int Accept(Connection *conn);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the address that the socket is bound to
|
* Return the address that the socket is bound to
|
||||||
@@ -269,15 +235,11 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
std::vector<Connection*> _Connections;
|
std::vector<Connection*> _Connections;
|
||||||
|
|
||||||
std::map<uint64_t, std::pair<PhySocket*, void*> > jobmap;
|
|
||||||
pid_t rpcCounter;
|
|
||||||
|
|
||||||
Thread _thread;
|
Thread _thread;
|
||||||
std::string _dev; // path to Unix domain socket
|
std::string _dev; // path to Unix domain socket
|
||||||
|
|
||||||
std::vector<MulticastGroup> _multicastGroups;
|
std::vector<MulticastGroup> _multicastGroups;
|
||||||
Mutex _multicastGroups_m;
|
Mutex _multicastGroups_m;
|
||||||
|
|
||||||
Mutex _ips_m, _tcpconns_m, _rx_buf_m, _close_m;
|
Mutex _ips_m, _tcpconns_m, _rx_buf_m, _close_m;
|
||||||
};
|
};
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* ZeroTier One - Network Virtualization Everywhere
|
* ZeroTier SDK - Network Virtualization Everywhere
|
||||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -14,15 +14,6 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
* --
|
|
||||||
*
|
|
||||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which
|
|
||||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
*
|
|
||||||
* If you would like to embed ZeroTier into a commercial application or
|
|
||||||
* redistribute it in a modified binary form, please contact ZeroTier Networks
|
|
||||||
* LLC. Start here: http://www.zerotier.com/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
@@ -53,10 +44,16 @@ extern "C" {
|
|||||||
|
|
||||||
static ZeroTier::OneService *zt1Service;
|
static ZeroTier::OneService *zt1Service;
|
||||||
|
|
||||||
std::string localHomeDir; // Local shortened path
|
namespace ZeroTier {
|
||||||
std::string homeDir; // The resultant platform-specific dir we *must* use internally
|
std::string homeDir; // The resultant platform-specific dir we *must* use internally
|
||||||
std::string netDir; // Where network .conf files are to be written
|
std::string netDir; // Where network .conf files are to be written
|
||||||
|
|
||||||
|
picoTCP *picostack = NULL;
|
||||||
|
std::map<int, Connection*> UnassignedConnections;
|
||||||
|
std::map<int, std::pair<Connection*,SocketTap*>*> AssignedFileDescriptors;
|
||||||
|
Mutex _multiplexer_lock;
|
||||||
|
Mutex _accepted_connection_lock;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* SDK Socket API - Language Bindings are written in terms of these */
|
/* SDK Socket API - Language Bindings are written in terms of these */
|
||||||
@@ -74,7 +71,7 @@ void zts_start(const char *path)
|
|||||||
|
|
||||||
DEBUG_INFO("path=%s", path);
|
DEBUG_INFO("path=%s", path);
|
||||||
if(path)
|
if(path)
|
||||||
homeDir = path;
|
ZeroTier::homeDir = path;
|
||||||
pthread_t service_thread;
|
pthread_t service_thread;
|
||||||
pthread_create(&service_thread, NULL, _start_service, (void *)(path));
|
pthread_create(&service_thread, NULL, _start_service, (void *)(path));
|
||||||
}
|
}
|
||||||
@@ -89,13 +86,11 @@ void zts_stop() {
|
|||||||
void zts_join_network(const char * nwid) {
|
void zts_join_network(const char * nwid) {
|
||||||
if(zt1Service) {
|
if(zt1Service) {
|
||||||
std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf";
|
std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf";
|
||||||
if(!ZeroTier::OSUtils::mkdir(netDir))
|
if(!ZeroTier::OSUtils::mkdir(ZeroTier::netDir))
|
||||||
DEBUG_ERROR("unable to create: %s", netDir.c_str());
|
DEBUG_ERROR("unable to create: %s", ZeroTier::netDir.c_str());
|
||||||
if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), ""))
|
if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), ""))
|
||||||
DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str());
|
DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str());
|
||||||
zt1Service->join(nwid);
|
zt1Service->join(nwid);
|
||||||
// Provide the API with the RPC information
|
|
||||||
// zts_init_rpc(homeDir.c_str(), nwid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,8 +118,10 @@ void zts_leave_network_soft(const char * filepath, const char * nwid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void zts_get_homepath(char *homePath, int len) {
|
void zts_get_homepath(char *homePath, int len) {
|
||||||
if(homeDir.length())
|
if(ZeroTier::homeDir.length()) {
|
||||||
memcpy(homePath, homeDir.c_str(), len < homeDir.length() ? len : homeDir.length());
|
memset(homePath, 0, len);
|
||||||
|
memcpy(homePath, ZeroTier::homeDir.c_str(), len < ZeroTier::homeDir.length() ? len : ZeroTier::homeDir.length());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void zts_core_version(char *ver) {
|
void zts_core_version(char *ver) {
|
||||||
@@ -147,7 +144,7 @@ int zts_get_device_id(char *devID) {
|
|||||||
else // Service isn't online, try to read ID from file
|
else // Service isn't online, try to read ID from file
|
||||||
{
|
{
|
||||||
std::string fname("identity.public");
|
std::string fname("identity.public");
|
||||||
std::string fpath(homeDir);
|
std::string fpath(ZeroTier::homeDir);
|
||||||
|
|
||||||
if(ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) {
|
if(ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) {
|
||||||
std::string oldid;
|
std::string oldid;
|
||||||
@@ -272,111 +269,98 @@ void zts_disable_http_control_plane()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* SocketTap Multiplexer Functionality --- DONT CALL THESE DIRECTLY */
|
/* SocketTap Multiplexer Functionality */
|
||||||
/* - This section of the API is used to implement the general socket */
|
/* - This section of the API is used to implement the general socket */
|
||||||
/* controls. Basically this is designed to handle socket provisioning */
|
/* controls. Basically this is designed to handle socket provisioning */
|
||||||
/* requests when no SocketTap is yet initialized, and as a way to */
|
/* requests when no SocketTap is yet initialized, and as a way to */
|
||||||
/* determine which SocketTap is to be used for a particular connect() or */
|
/* determine which SocketTap is to be used for a particular connect() or */
|
||||||
/* bind() call */
|
/* bind() call. This enables multi-network support */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
namespace ZeroTier
|
int zts_socket(ZT_SOCKET_SIG) {
|
||||||
{
|
|
||||||
picoTCP *picostack = NULL;
|
|
||||||
std::map<int, Connection*> UnassignedConnections;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZeroTier::Mutex _multiplexer_lock;
|
|
||||||
|
|
||||||
int zts_multiplex_new_socket(ZT_SOCKET_SIG)
|
|
||||||
{
|
|
||||||
DEBUG_INFO();
|
DEBUG_INFO();
|
||||||
_multiplexer_lock.lock();
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
||||||
int err;
|
int err, protocol_version;
|
||||||
// set up pico_socket
|
// set up pico_socket
|
||||||
struct pico_socket * psock;
|
struct pico_socket * psock;
|
||||||
int pico_protocol, protocol_version;
|
|
||||||
#if defined(SDK_IPV4)
|
#if defined(SDK_IPV4)
|
||||||
protocol_version = PICO_PROTO_IPV4;
|
protocol_version = PICO_PROTO_IPV4;
|
||||||
#elif defined(SDK_IPV6)
|
#elif defined(SDK_IPV6)
|
||||||
protocol_version = PICO_PROTO_IPV6;
|
protocol_version = PICO_PROTO_IPV6;
|
||||||
#endif
|
#endif
|
||||||
if(socket_type == SOCK_DGRAM) {
|
if(socket_type == SOCK_DGRAM) {
|
||||||
pico_protocol = PICO_PROTO_UDP;
|
psock = pico_socket_open(
|
||||||
psock = pico_socket_open(protocol_version, pico_protocol, &ZeroTier::picoTCP::pico_cb_socket_activity);
|
protocol_version, PICO_PROTO_UDP, &ZeroTier::picoTCP::pico_cb_socket_activity);
|
||||||
}
|
}
|
||||||
if(socket_type == SOCK_STREAM) {
|
if(socket_type == SOCK_STREAM) {
|
||||||
pico_protocol = PICO_PROTO_TCP;
|
psock = pico_socket_open(
|
||||||
psock = pico_socket_open(protocol_version, pico_protocol, &ZeroTier::picoTCP::pico_cb_socket_activity);
|
protocol_version, PICO_PROTO_TCP, &ZeroTier::picoTCP::pico_cb_socket_activity);
|
||||||
}
|
}
|
||||||
// set up Unix Domain socket (used for data later on)
|
// set up Unix Domain socketpair (used for data later on)
|
||||||
if(psock) {
|
if(psock) {
|
||||||
int unix_data_sock;
|
|
||||||
if((unix_data_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
|
||||||
DEBUG_ERROR("unable to create unix domain socket for data");
|
|
||||||
// errno = ?
|
|
||||||
err = -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
conn->socket_family = socket_family;
|
conn->socket_family = socket_family;
|
||||||
conn->socket_type = socket_type;
|
conn->socket_type = socket_type;
|
||||||
conn->data_sock = unix_data_sock;
|
|
||||||
conn->picosock = psock;
|
conn->picosock = psock;
|
||||||
memset(conn->rxbuf, 0, DEFAULT_UDP_RX_BUF_SZ);
|
memset(conn->rxbuf, 0, ZT_UDP_RX_BUF_SZ);
|
||||||
ZeroTier::UnassignedConnections[unix_data_sock] = conn;
|
ZeroTier::UnassignedConnections[conn->app_fd] = conn;
|
||||||
err = unix_data_sock;
|
err = conn->app_fd; // return one end of the socketpair
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG_ERROR("failed to create pico_socket");
|
DEBUG_ERROR("failed to create pico_socket");
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
_multiplexer_lock.unlock();
|
ZeroTier::_multiplexer_lock.unlock();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int zts_multiplex_new_connect(ZT_CONNECT_SIG)
|
int zts_connect(ZT_CONNECT_SIG) {
|
||||||
{
|
|
||||||
DEBUG_INFO();
|
|
||||||
if(!zt1Service) {
|
if(!zt1Service) {
|
||||||
|
DEBUG_ERROR("zt1Service = NULL");
|
||||||
// errno = ?
|
// errno = ?
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
_multiplexer_lock.lock();
|
|
||||||
int err;
|
int err;
|
||||||
ZeroTier::Connection *conn = ZeroTier::UnassignedConnections[fd];
|
ZeroTier::Connection *conn = ZeroTier::UnassignedConnections[fd];
|
||||||
|
ZeroTier::SocketTap *tap;
|
||||||
|
|
||||||
if(conn != NULL) {
|
if(conn) {
|
||||||
char ipstr[INET6_ADDRSTRLEN];//, nm_str[INET6_ADDRSTRLEN];
|
char ipstr[INET6_ADDRSTRLEN];//, nm_str[INET6_ADDRSTRLEN];
|
||||||
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||||
ZeroTier::InetAddress iaddr;
|
ZeroTier::InetAddress iaddr;
|
||||||
|
|
||||||
if(conn->socket_family == AF_INET) {
|
if(conn->socket_family == AF_INET) {
|
||||||
// FIXME: Fix this typecast mess
|
// FIXME: Fix this typecast mess
|
||||||
inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
inet_ntop(AF_INET,
|
||||||
|
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
if(conn->socket_family == AF_INET6) {
|
if(conn->socket_family == AF_INET6) {
|
||||||
// FIXME: Fix this typecast mess
|
// FIXME: Fix this typecast mess
|
||||||
inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
inet_ntop(AF_INET6,
|
||||||
|
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
iaddr.fromString(ipstr);
|
iaddr.fromString(ipstr);
|
||||||
|
|
||||||
DEBUG_INFO("ipstr= %s", ipstr);
|
DEBUG_INFO("ipstr= %s", ipstr);
|
||||||
DEBUG_INFO("iaddr= %s", iaddr.toString().c_str());
|
DEBUG_INFO("iaddr= %s", iaddr.toString().c_str());
|
||||||
|
|
||||||
ZeroTier::SocketTap *tap = zt1Service->getTap(iaddr);
|
tap = zt1Service->getTap(iaddr);
|
||||||
|
|
||||||
if(!tap) {
|
if(!tap) {
|
||||||
|
// TODO: More canonical error?
|
||||||
DEBUG_ERROR("no route to host");
|
DEBUG_ERROR("no route to host");
|
||||||
// errno = ?
|
// errno = ?
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
conn->sock = tap->_phy.wrapSocket(conn->sdk_fd, conn); // wrap the socketpair we created earlier
|
||||||
|
conn->picosock->priv = new ZeroTier::Larg(tap, conn); // pointer to tap we use in callbacks from the stack
|
||||||
DEBUG_INFO("found appropriate SocketTap");
|
DEBUG_INFO("found appropriate SocketTap");
|
||||||
err = 0;
|
// TODO: Perhaps move this connect call outside of the lock
|
||||||
|
tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on
|
||||||
|
err = tap->Connect(conn, fd, addr, addrlen); // Semantically: tap->stack->connect
|
||||||
|
conn->tap = tap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -384,22 +368,178 @@ int zts_multiplex_new_connect(ZT_CONNECT_SIG)
|
|||||||
// errno = ?
|
// errno = ?
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
_multiplexer_lock.unlock();
|
ZeroTier::AssignedFileDescriptors[fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(conn, tap);
|
||||||
|
ZeroTier::_multiplexer_lock.unlock();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int zts_multiplex_new_bind(ZT_BIND_SIG)
|
int zts_bind(ZT_BIND_SIG) {
|
||||||
{
|
if(!zt1Service) {
|
||||||
DEBUG_INFO();
|
DEBUG_ERROR("zt1Service = NULL");
|
||||||
_multiplexer_lock.lock();
|
// errno = ?
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
int err;
|
int err;
|
||||||
|
ZeroTier::Connection *conn = ZeroTier::UnassignedConnections[fd];
|
||||||
|
ZeroTier::SocketTap *tap;
|
||||||
|
|
||||||
// ?
|
if(conn) {
|
||||||
|
char ipstr[INET6_ADDRSTRLEN];//, nm_str[INET6_ADDRSTRLEN];
|
||||||
|
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||||
|
ZeroTier::InetAddress iaddr;
|
||||||
|
|
||||||
_multiplexer_lock.unlock();
|
if(conn->socket_family == AF_INET) {
|
||||||
|
// FIXME: Fix this typecast mess
|
||||||
|
inet_ntop(AF_INET,
|
||||||
|
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
if(conn->socket_family == AF_INET6) {
|
||||||
|
// FIXME: Fix this typecast mess
|
||||||
|
inet_ntop(AF_INET6,
|
||||||
|
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
iaddr.fromString(ipstr);
|
||||||
|
|
||||||
|
DEBUG_INFO("ipstr= %s", ipstr);
|
||||||
|
DEBUG_INFO("iaddr= %s", iaddr.toString().c_str());
|
||||||
|
|
||||||
|
tap = zt1Service->getTap(iaddr);
|
||||||
|
|
||||||
|
if(!tap) {
|
||||||
|
// TODO: More canonical error?
|
||||||
|
DEBUG_ERROR("no appropriate interface to bind to");
|
||||||
|
// errno = ?
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DEBUG_INFO("found appropriate SocketTap");
|
||||||
|
DEBUG_INFO("conn->picosock = %p", conn->picosock);
|
||||||
|
conn->picosock->priv = new ZeroTier::Larg(tap, conn);
|
||||||
|
// TODO: Perhaps move this connect call outside of the lock
|
||||||
|
tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on
|
||||||
|
err = tap->Bind(conn, fd, addr, addrlen); // Semantically: tap->stack->connect
|
||||||
|
conn->tap = tap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DEBUG_ERROR("unable to locate connection");
|
||||||
|
// errno = ?
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
ZeroTier::AssignedFileDescriptors[fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(conn, tap);
|
||||||
|
ZeroTier::_multiplexer_lock.unlock();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zts_listen(ZT_LISTEN_SIG) {
|
||||||
|
if(!zt1Service) {
|
||||||
|
DEBUG_ERROR("zt1Service = NULL");
|
||||||
|
// errno = ?
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int err;
|
||||||
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
|
ZeroTier::Connection *conn = ZeroTier::AssignedFileDescriptors[fd]->first;
|
||||||
|
ZeroTier::SocketTap *tap = ZeroTier::AssignedFileDescriptors[fd]->second;
|
||||||
|
|
||||||
|
if(!tap || !conn) {
|
||||||
|
DEBUG_ERROR("unable to locate tap interface for file descriptor");
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
tap->Listen(conn, fd, backlog);
|
||||||
|
err = 0;
|
||||||
|
DEBUG_INFO("put %p into LISTENING state", conn);
|
||||||
|
ZeroTier::_multiplexer_lock.unlock();
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zts_accept(ZT_ACCEPT_SIG) {
|
||||||
|
int err;
|
||||||
|
ZeroTier::Connection *conn = ZeroTier::AssignedFileDescriptors[fd]->first;
|
||||||
|
ZeroTier::SocketTap *tap = ZeroTier::AssignedFileDescriptors[fd]->second;
|
||||||
|
// BLOCKING: loop and keep checking until we find a newly accepted connection
|
||||||
|
if(true) {
|
||||||
|
while(true) {
|
||||||
|
usleep(ZT_ACCEPT_RECHECK_DELAY * 1000);
|
||||||
|
err = tap->Accept(conn);
|
||||||
|
if(err >= 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// NON-BLOCKING: only check for a new connection once
|
||||||
|
else
|
||||||
|
err = tap->Accept(conn);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
int zts_accept4(ZT_ACCEPT4_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int zts_setsockopt(ZT_SETSOCKOPT_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zts_getsockopt(ZT_GETSOCKOPT_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zts_getsockname(ZT_GETSOCKNAME_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zts_getpeername(ZT_GETPEERNAME_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zts_close(ZT_CLOSE_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zts_fcntl(ZT_FCNTL_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t zts_sendmsg(ZT_SENDMSG_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t zts_recvfrom(ZT_RECVFROM_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t zts_recvmsg(ZT_RECVMSG_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zts_read(ZT_READ_SIG) {
|
||||||
|
return read(fd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int zts_write(ZT_WRITE_SIG) {
|
||||||
|
return write(fd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* SDK Socket API (Java Native Interface JNI) */
|
/* SDK Socket API (Java Native Interface JNI) */
|
||||||
/* JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME */
|
/* JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME */
|
||||||
@@ -489,17 +629,17 @@ int zts_multiplex_new_bind(ZT_BIND_SIG)
|
|||||||
// Starts a ZeroTier service in the background
|
// Starts a ZeroTier service in the background
|
||||||
void *_start_service(void *thread_id) {
|
void *_start_service(void *thread_id) {
|
||||||
|
|
||||||
DEBUG_INFO("homeDir=%s", homeDir.c_str());
|
DEBUG_INFO("homeDir=%s", ZeroTier::homeDir.c_str());
|
||||||
// Where network .conf files will be stored
|
// Where network .conf files will be stored
|
||||||
netDir = homeDir + "/networks.d";
|
ZeroTier::netDir = ZeroTier::homeDir + "/networks.d";
|
||||||
zt1Service = (ZeroTier::OneService *)0;
|
zt1Service = (ZeroTier::OneService *)0;
|
||||||
|
|
||||||
// Construct path for network config and supporting service files
|
// Construct path for network config and supporting service files
|
||||||
if (homeDir.length()) {
|
if (ZeroTier::homeDir.length()) {
|
||||||
std::vector<std::string> hpsp(ZeroTier::OSUtils::split(homeDir.c_str(),
|
std::vector<std::string> hpsp(ZeroTier::OSUtils::split(ZeroTier::homeDir.c_str(),
|
||||||
ZT_PATH_SEPARATOR_S,"",""));
|
ZT_PATH_SEPARATOR_S,"",""));
|
||||||
std::string ptmp;
|
std::string ptmp;
|
||||||
if (homeDir[0] == ZT_PATH_SEPARATOR)
|
if (ZeroTier::homeDir[0] == ZT_PATH_SEPARATOR)
|
||||||
ptmp.push_back(ZT_PATH_SEPARATOR);
|
ptmp.push_back(ZT_PATH_SEPARATOR);
|
||||||
for(std::vector<std::string>::iterator pi(hpsp.begin());pi!=hpsp.end();++pi) {
|
for(std::vector<std::string>::iterator pi(hpsp.begin());pi!=hpsp.end();++pi) {
|
||||||
if (ptmp.length() > 0)
|
if (ptmp.length() > 0)
|
||||||
@@ -518,7 +658,7 @@ void *_start_service(void *thread_id) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// rpc dir
|
// rpc dir
|
||||||
if(!ZeroTier::OSUtils::mkdir(homeDir + "/" + ZT_SDK_RPC_DIR_PREFIX)) {
|
if(!ZeroTier::OSUtils::mkdir(ZeroTier::homeDir + "/" + ZT_SDK_RPC_DIR_PREFIX)) {
|
||||||
DEBUG_ERROR("unable to create dir: " ZT_SDK_RPC_DIR_PREFIX);
|
DEBUG_ERROR("unable to create dir: " ZT_SDK_RPC_DIR_PREFIX);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -530,7 +670,7 @@ void *_start_service(void *thread_id) {
|
|||||||
DEBUG_ERROR("servicePort = %d", servicePort);
|
DEBUG_ERROR("servicePort = %d", servicePort);
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
zt1Service = ZeroTier::OneService::newInstance(homeDir.c_str(),servicePort);
|
zt1Service = ZeroTier::OneService::newInstance(ZeroTier::homeDir.c_str(),servicePort);
|
||||||
switch(zt1Service->run()) {
|
switch(zt1Service->run()) {
|
||||||
case ZeroTier::OneService::ONE_STILL_RUNNING:
|
case ZeroTier::OneService::ONE_STILL_RUNNING:
|
||||||
case ZeroTier::OneService::ONE_NORMAL_TERMINATION:
|
case ZeroTier::OneService::ONE_NORMAL_TERMINATION:
|
||||||
@@ -542,14 +682,14 @@ void *_start_service(void *thread_id) {
|
|||||||
delete zt1Service;
|
delete zt1Service;
|
||||||
zt1Service = (ZeroTier::OneService *)0;
|
zt1Service = (ZeroTier::OneService *)0;
|
||||||
std::string oldid;
|
std::string oldid;
|
||||||
ZeroTier::OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S
|
ZeroTier::OSUtils::readFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S
|
||||||
+ "identity.secret").c_str(),oldid);
|
+ "identity.secret").c_str(),oldid);
|
||||||
if (oldid.length()) {
|
if (oldid.length()) {
|
||||||
ZeroTier::OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S
|
ZeroTier::OSUtils::writeFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S
|
||||||
+ "identity.secret.saved_after_collision").c_str(),oldid);
|
+ "identity.secret.saved_after_collision").c_str(),oldid);
|
||||||
ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S
|
ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S
|
||||||
+ "identity.secret").c_str());
|
+ "identity.secret").c_str());
|
||||||
ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S
|
ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S
|
||||||
+ "identity.public").c_str());
|
+ "identity.public").c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
370
src/picoTCP.cpp
370
src/picoTCP.cpp
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* ZeroTier One - Network Virtualization Everywhere
|
* ZeroTier SDK - Network Virtualization Everywhere
|
||||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -14,15 +14,6 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
* --
|
|
||||||
*
|
|
||||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which
|
|
||||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
*
|
|
||||||
* If you would like to embed ZeroTier into a commercial application or
|
|
||||||
* redistribute it in a modified binary form, please contact ZeroTier Networks
|
|
||||||
* LLC. Start here: http://www.zerotier.com/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pico_eth.h"
|
#include "pico_eth.h"
|
||||||
@@ -70,7 +61,7 @@ int pico_socket_recv(PICO_SOCKET_RECV_SIG);
|
|||||||
extern "C" int pico_socket_recvfrom(PICO_SOCKET_RECVFROM_SIG);
|
extern "C" int pico_socket_recvfrom(PICO_SOCKET_RECVFROM_SIG);
|
||||||
extern "C" struct pico_socket * pico_socket_open(PICO_SOCKET_OPEN_SIG);
|
extern "C" struct pico_socket * pico_socket_open(PICO_SOCKET_OPEN_SIG);
|
||||||
int pico_socket_bind(PICO_SOCKET_BIND_SIG);
|
int pico_socket_bind(PICO_SOCKET_BIND_SIG);
|
||||||
int pico_socket_connect(PICO_SOCKET_CONNECT_SIG);
|
extern "C" int pico_socket_connect(PICO_SOCKET_CONNECT_SIG);
|
||||||
extern "C" int pico_socket_listen(PICO_SOCKET_LISTEN_SIG);
|
extern "C" int pico_socket_listen(PICO_SOCKET_LISTEN_SIG);
|
||||||
int pico_socket_read(PICO_SOCKET_READ_SIG);
|
int pico_socket_read(PICO_SOCKET_READ_SIG);
|
||||||
extern "C" int pico_socket_write(PICO_SOCKET_WRITE_SIG);
|
extern "C" int pico_socket_write(PICO_SOCKET_WRITE_SIG);
|
||||||
@@ -98,6 +89,7 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
void picoTCP::pico_init_interface(SocketTap *tap, const InetAddress &ip)
|
void picoTCP::pico_init_interface(SocketTap *tap, const InetAddress &ip)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) {
|
if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) {
|
||||||
tap->_ips.push_back(ip);
|
tap->_ips.push_back(ip);
|
||||||
std::sort(tap->_ips.begin(),tap->_ips.end());
|
std::sort(tap->_ips.begin(),tap->_ips.end());
|
||||||
@@ -158,7 +150,8 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
void picoTCP::pico_cb_tcp_read(ZeroTier::SocketTap *tap, struct pico_socket *s)
|
void picoTCP::pico_cb_tcp_read(ZeroTier::SocketTap *tap, struct pico_socket *s)
|
||||||
{
|
{
|
||||||
Connection *conn = tap->getConnection(s);
|
DEBUG_INFO();
|
||||||
|
Connection *conn = (Connection*)((Larg*)(s->priv))->conn;
|
||||||
if(conn) {
|
if(conn) {
|
||||||
int r;
|
int r;
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
@@ -167,9 +160,9 @@ namespace ZeroTier {
|
|||||||
struct pico_ip6 ip6;
|
struct pico_ip6 ip6;
|
||||||
} peer;
|
} peer;
|
||||||
do {
|
do {
|
||||||
int avail = DEFAULT_TCP_RX_BUF_SZ - conn->rxsz;
|
int avail = ZT_TCP_RX_BUF_SZ - conn->rxsz;
|
||||||
if(avail) {
|
if(avail) {
|
||||||
r = pico_socket_recvfrom(s, conn->rxbuf + (conn->rxsz), SDK_MTU,
|
r = pico_socket_recvfrom(s, conn->rxbuf + (conn->rxsz), ZT_SDK_MTU,
|
||||||
(void *)&peer.ip4.addr, &port);
|
(void *)&peer.ip4.addr, &port);
|
||||||
tap->_phy.setNotifyWritable(conn->sock, true);
|
tap->_phy.setNotifyWritable(conn->sock, true);
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
@@ -186,7 +179,8 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
void picoTCP::pico_cb_udp_read(SocketTap *tap, struct pico_socket *s)
|
void picoTCP::pico_cb_udp_read(SocketTap *tap, struct pico_socket *s)
|
||||||
{
|
{
|
||||||
Connection *conn = tap->getConnection(s);
|
DEBUG_INFO();
|
||||||
|
Connection *conn = (Connection*)((Larg*)(s->priv))->conn;
|
||||||
if(conn) {
|
if(conn) {
|
||||||
|
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
@@ -195,14 +189,14 @@ namespace ZeroTier {
|
|||||||
struct pico_ip6 ip6;
|
struct pico_ip6 ip6;
|
||||||
} peer;
|
} peer;
|
||||||
|
|
||||||
char tmpbuf[SDK_MTU];
|
char tmpbuf[ZT_SDK_MTU];
|
||||||
unsigned char *addr_pos, *sz_pos, *payload_pos;
|
unsigned char *addr_pos, *sz_pos, *payload_pos;
|
||||||
struct sockaddr_in addr_in;
|
struct sockaddr_in addr_in;
|
||||||
addr_in.sin_addr.s_addr = peer.ip4.addr;
|
addr_in.sin_addr.s_addr = peer.ip4.addr;
|
||||||
addr_in.sin_port = port;
|
addr_in.sin_port = port;
|
||||||
|
|
||||||
// RX
|
// RX
|
||||||
int r = pico_socket_recvfrom(s, tmpbuf, SDK_MTU, (void *)&peer.ip4.addr, &port);
|
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);
|
//DEBUG_FLOW(" [ RXBUF <- STACK] Receiving (%d) from stack, copying to receving buffer", r);
|
||||||
|
|
||||||
// Mutex::Lock _l2(tap->_rx_buf_m);
|
// Mutex::Lock _l2(tap->_rx_buf_m);
|
||||||
@@ -211,12 +205,12 @@ namespace ZeroTier {
|
|||||||
// addr_in6.sin6_port = Utils::ntoh(s->remote_port);
|
// addr_in6.sin6_port = Utils::ntoh(s->remote_port);
|
||||||
// DEBUG_ATTN("remote_port=%d, local_port=%d", s->remote_port, Utils::ntoh(s->local_port));
|
// DEBUG_ATTN("remote_port=%d, local_port=%d", s->remote_port, Utils::ntoh(s->local_port));
|
||||||
tap->_rx_buf_m.lock();
|
tap->_rx_buf_m.lock();
|
||||||
if(conn->rxsz == DEFAULT_UDP_RX_BUF_SZ) { // if UDP buffer full
|
if(conn->rxsz == ZT_UDP_RX_BUF_SZ) { // if UDP buffer full
|
||||||
//DEBUG_FLOW(" [ RXBUF <- STACK] UDP RX buffer full. Discarding oldest payload segment");
|
//DEBUG_FLOW(" [ RXBUF <- STACK] UDP RX buffer full. Discarding oldest payload segment");
|
||||||
memmove(conn->rxbuf, conn->rxbuf + SDK_MTU, DEFAULT_UDP_RX_BUF_SZ - SDK_MTU);
|
memmove(conn->rxbuf, conn->rxbuf + ZT_SDK_MTU, ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU);
|
||||||
addr_pos = conn->rxbuf + (DEFAULT_UDP_RX_BUF_SZ - SDK_MTU); // TODO:
|
addr_pos = conn->rxbuf + (ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU); // TODO:
|
||||||
sz_pos = addr_pos + sizeof(struct sockaddr_storage);
|
sz_pos = addr_pos + sizeof(struct sockaddr_storage);
|
||||||
conn->rxsz -= SDK_MTU;
|
conn->rxsz -= ZT_SDK_MTU;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addr_pos = conn->rxbuf + conn->rxsz; // where we'll prepend the size of the address
|
addr_pos = conn->rxbuf + conn->rxsz; // where we'll prepend the size of the address
|
||||||
@@ -229,7 +223,7 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
// Adjust buffer size
|
// Adjust buffer size
|
||||||
if(r) {
|
if(r) {
|
||||||
conn->rxsz += SDK_MTU;
|
conn->rxsz += ZT_SDK_MTU;
|
||||||
memcpy(sz_pos, &r, sizeof(r));
|
memcpy(sz_pos, &r, sizeof(r));
|
||||||
}
|
}
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@@ -247,14 +241,18 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
void picoTCP::pico_cb_tcp_write(SocketTap *tap, struct pico_socket *s)
|
void picoTCP::pico_cb_tcp_write(SocketTap *tap, struct pico_socket *s)
|
||||||
{
|
{
|
||||||
Connection *conn = tap->getConnection(s);
|
DEBUG_INFO();
|
||||||
if(!conn)
|
Connection *conn = (Connection*)((Larg*)(s->priv))->conn;
|
||||||
|
|
||||||
|
if(!conn) {
|
||||||
DEBUG_ERROR("invalid connection");
|
DEBUG_ERROR("invalid connection");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(!conn->txsz)
|
if(!conn->txsz)
|
||||||
return;
|
return;
|
||||||
// Only called from a locked context, no need to lock anything
|
// Only called from a locked context, no need to lock anything
|
||||||
if(conn->txsz > 0) {
|
if(conn->txsz > 0) {
|
||||||
int r, max_write_len = conn->txsz < SDK_MTU ? conn->txsz : SDK_MTU;
|
int r, max_write_len = conn->txsz < ZT_SDK_MTU ? conn->txsz : ZT_SDK_MTU;
|
||||||
if((r = pico_socket_write(s, &conn->txbuf, max_write_len)) < 0) {
|
if((r = pico_socket_write(s, &conn->txbuf, max_write_len)) < 0) {
|
||||||
DEBUG_ERROR("unable to write to picosock=%p", s);
|
DEBUG_ERROR("unable to write to picosock=%p", s);
|
||||||
return;
|
return;
|
||||||
@@ -265,7 +263,7 @@ namespace ZeroTier {
|
|||||||
conn->txsz -= r;
|
conn->txsz -= r;
|
||||||
|
|
||||||
#if DEBUG_LEVEL >= MSG_TRANSFER
|
#if DEBUG_LEVEL >= MSG_TRANSFER
|
||||||
int max = conn->socket_type == SOCK_STREAM ? DEFAULT_TCP_TX_BUF_SZ : DEFAULT_UDP_TX_BUF_SZ;
|
int max = conn->socket_type == SOCK_STREAM ? ZT_TCP_TX_BUF_SZ : ZT_UDP_TX_BUF_SZ;
|
||||||
DEBUG_TRANS("[TCP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
DEBUG_TRANS("[TCP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
||||||
(float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r);
|
(float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r);
|
||||||
#endif
|
#endif
|
||||||
@@ -276,40 +274,43 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
void picoTCP::pico_cb_socket_activity(uint16_t ev, struct pico_socket *s)
|
void picoTCP::pico_cb_socket_activity(uint16_t ev, struct pico_socket *s)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
|
// TODO: Test API out of order so this check isn't necessary
|
||||||
|
if(!(SocketTap*)((Larg*)(s->priv)))
|
||||||
|
return;
|
||||||
|
SocketTap *tap = (SocketTap*)((Larg*)(s->priv))->tap;
|
||||||
|
Connection *conn = (Connection*)((Larg*)(s->priv))->conn;
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
Mutex::Lock _l(picotap->_tcpconns_m);
|
Mutex::Lock _l(tap->_tcpconns_m);
|
||||||
Connection *conn = picotap->getConnection(s);
|
|
||||||
if(!conn) {
|
if(!conn) {
|
||||||
DEBUG_ERROR("invalid connection");
|
DEBUG_ERROR("invalid connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
// accept()
|
// accept()
|
||||||
if (ev & PICO_SOCK_EV_CONN) {
|
if (ev & PICO_SOCK_EV_CONN) {
|
||||||
DEBUG_INFO("connection established with server, picosock=%p",(conn->picosock));
|
|
||||||
uint32_t peer;
|
uint32_t peer;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
struct pico_socket *client = pico_socket_accept(s, &peer, &port);
|
struct pico_socket *client_psock = pico_socket_accept(s, &peer, &port);
|
||||||
if(!client) {
|
DEBUG_INFO("accepted (pico_sock=%p) on (pico_sock=%p)", client_psock, conn->picosock);
|
||||||
|
if(!client_psock) {
|
||||||
DEBUG_EXTRA("unable to accept conn. (event might not be incoming, not necessarily an error), picosock=%p", (conn->picosock));
|
DEBUG_EXTRA("unable to accept conn. (event might not be incoming, not necessarily an error), picosock=%p", (conn->picosock));
|
||||||
}
|
}
|
||||||
ZT_PHY_SOCKFD_TYPE fds[2];
|
|
||||||
if(socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0) {
|
// Create a new Connection and add it to the queue,
|
||||||
if(errno < 0) {
|
// some time in the future a call to zts_multiplex_accept() will pick up
|
||||||
// FIXME: Return a value to the client
|
// this new connection, add it to the connection list and return its
|
||||||
//tap->sendReturnValue(conn, -1, errno);
|
// Connection->sock to the application
|
||||||
DEBUG_ERROR("unable to create socketpair");
|
|
||||||
return;
|
Connection *newConn = new Connection();
|
||||||
}
|
newConn->socket_type = SOCK_STREAM;
|
||||||
}
|
newConn->sock = tap->_phy.wrapSocket(newConn->sdk_fd, newConn);
|
||||||
Connection *newTcpConn = new Connection();
|
newConn->picosock = client_psock;
|
||||||
picotap->_Connections.push_back(newTcpConn);
|
newConn->tap = tap;
|
||||||
newTcpConn->socket_type = SOCK_STREAM;
|
newConn->picosock->priv = new Larg(tap,newConn);
|
||||||
newTcpConn->sock = picotap->_phy.wrapSocket(fds[0], newTcpConn);
|
|
||||||
newTcpConn->picosock = client;
|
tap->_Connections.push_back(newConn);
|
||||||
int fd = picotap->_phy.getDescriptor(conn->sock);
|
conn->_AcceptedConnections.push(newConn);
|
||||||
if(sock_fd_write(fd, fds[1]) < 0) {
|
|
||||||
DEBUG_ERROR("error sending new fd to client application");
|
|
||||||
}
|
|
||||||
DEBUG_EXTRA("conn=%p, physock=%p, listen_picosock=%p, new_picosock=%p, fd=%d", newTcpConn, newTcpConn->sock, s, client, fds[1]);
|
|
||||||
}
|
}
|
||||||
if (ev & PICO_SOCK_EV_FIN) {
|
if (ev & PICO_SOCK_EV_FIN) {
|
||||||
DEBUG_INFO("socket closed. exit normally. picosock=%p\n\n", s);
|
DEBUG_INFO("socket closed. exit normally. picosock=%p\n\n", s);
|
||||||
@@ -322,7 +323,7 @@ namespace ZeroTier {
|
|||||||
err = pico_socket_close(s);
|
err = pico_socket_close(s);
|
||||||
DEBUG_INFO("socket closure = %d, picosock=%p", err, s);
|
DEBUG_INFO("socket closure = %d, picosock=%p", err, s);
|
||||||
if(err==0) {
|
if(err==0) {
|
||||||
picotap->closeConnection(conn->sock);
|
tap->closeConnection(conn->sock);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -356,6 +357,7 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
int pico_eth_send(struct pico_device *dev, void *buf, int len)
|
int pico_eth_send(struct pico_device *dev, void *buf, int len)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
struct pico_eth_hdr *ethhdr;
|
struct pico_eth_hdr *ethhdr;
|
||||||
ethhdr = (struct pico_eth_hdr *)buf;
|
ethhdr = (struct pico_eth_hdr *)buf;
|
||||||
MAC src_mac;
|
MAC src_mac;
|
||||||
@@ -370,6 +372,7 @@ namespace ZeroTier {
|
|||||||
void picoTCP::pico_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,
|
void picoTCP::pico_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,
|
||||||
const void *data,unsigned int len)
|
const void *data,unsigned int len)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
// Since picoTCP only allows the reception of frames from within the polling function, we
|
// 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
|
// must enqueue each frame into a memory structure shared by both threads. This structure will
|
||||||
Mutex::Lock _l(tap->_pico_frame_rxbuf_m);
|
Mutex::Lock _l(tap->_pico_frame_rxbuf_m);
|
||||||
@@ -406,7 +409,7 @@ namespace ZeroTier {
|
|||||||
// OPTIMIZATION: The copy logic and/or buffer structure should be reworked for better performance after the BETA
|
// OPTIMIZATION: The copy logic and/or buffer structure should be reworked for better performance after the BETA
|
||||||
// SocketTap *tap = (SocketTap*)netif->state;
|
// SocketTap *tap = (SocketTap*)netif->state;
|
||||||
Mutex::Lock _l(picotap->_pico_frame_rxbuf_m);
|
Mutex::Lock _l(picotap->_pico_frame_rxbuf_m);
|
||||||
unsigned char frame[SDK_MTU];
|
unsigned char frame[ZT_SDK_MTU];
|
||||||
int len;
|
int len;
|
||||||
while (picotap->pico_frame_rxbuf_tot > 0 && loop_score > 0) {
|
while (picotap->pico_frame_rxbuf_tot > 0 && loop_score > 0) {
|
||||||
//DEBUG_FLOW(" [ FBUF -> STACK] Frame buffer SZ=%d", picotap->pico_frame_rxbuf_tot);
|
//DEBUG_FLOW(" [ FBUF -> STACK] Frame buffer SZ=%d", picotap->pico_frame_rxbuf_tot);
|
||||||
@@ -429,79 +432,20 @@ namespace ZeroTier {
|
|||||||
return loop_score;
|
return loop_score;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This function's contents should be retired
|
|
||||||
// More or less duplicated in zts_multiplex_new_socket()
|
|
||||||
Connection *picoTCP::pico_handleSocket(PhySocket *sock, void **uptr,
|
|
||||||
struct socket_st* socket_rpc)
|
|
||||||
{
|
|
||||||
struct pico_socket * psock;
|
|
||||||
int protocol, protocol_version;
|
|
||||||
|
|
||||||
#if defined(SDK_IPV4)
|
|
||||||
protocol_version = PICO_PROTO_IPV4;
|
|
||||||
#elif defined(SDK_IPV6)
|
|
||||||
protocol_version = PICO_PROTO_IPV6;
|
|
||||||
#endif
|
|
||||||
if(socket_rpc->socket_type == SOCK_DGRAM) {
|
|
||||||
protocol = PICO_PROTO_UDP;
|
|
||||||
psock = pico_socket_open(protocol_version, protocol, &pico_cb_socket_activity);
|
|
||||||
}
|
|
||||||
if(socket_rpc->socket_type == SOCK_STREAM) {
|
|
||||||
protocol = PICO_PROTO_TCP;
|
|
||||||
psock = pico_socket_open(protocol_version, protocol, &pico_cb_socket_activity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(psock) {
|
|
||||||
DEBUG_ATTN("physock=%p, picosock=%p", sock, psock);
|
|
||||||
Connection * newConn = new Connection();
|
|
||||||
*uptr = newConn;
|
|
||||||
newConn->socket_type = socket_rpc->socket_type;
|
|
||||||
newConn->sock = sock;
|
|
||||||
newConn->local_addr = NULL;
|
|
||||||
newConn->picosock = psock;
|
|
||||||
picotap->_Connections.push_back(newConn);
|
|
||||||
memset(newConn->rxbuf, 0, DEFAULT_UDP_RX_BUF_SZ);
|
|
||||||
return newConn;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
DEBUG_ERROR("failed to create pico_socket");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void picoTCP::pico_handleWrite(Connection *conn)
|
void picoTCP::pico_handleWrite(Connection *conn)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
if(!conn || !conn->picosock) {
|
if(!conn || !conn->picosock) {
|
||||||
DEBUG_ERROR(" invalid connection");
|
DEBUG_ERROR(" invalid connection");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int max, r, max_write_len = conn->txsz < SDK_MTU ? conn->txsz : SDK_MTU;
|
int max, r, max_write_len = conn->txsz < ZT_SDK_MTU ? conn->txsz : ZT_SDK_MTU;
|
||||||
if((r = pico_socket_write(conn->picosock, &conn->txbuf, max_write_len)) < 0) {
|
if((r = pico_socket_write(conn->picosock, &conn->txbuf, max_write_len)) < 0) {
|
||||||
DEBUG_ERROR("unable to write to picosock=%p, r=%d", (conn->picosock), r);
|
DEBUG_ERROR("unable to write to picosock=%p, r=%d", (conn->picosock), r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Errors
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(pico_err == PICO_ERR_EINVAL)
|
|
||||||
DEBUG_ERROR("PICO_ERR_EINVAL - invalid argument");
|
|
||||||
if(pico_err == PICO_ERR_EIO)
|
|
||||||
DEBUG_ERROR("PICO_ERR_EIO - input/output error");
|
|
||||||
if(pico_err == PICO_ERR_ENOTCONN)
|
|
||||||
DEBUG_ERROR("PICO_ERR_ENOTCONN - the socket is not connected");
|
|
||||||
if(pico_err == PICO_ERR_ESHUTDOWN)
|
|
||||||
DEBUG_ERROR("PICO_ERR_ESHUTDOWN - cannot send after transport endpoint shutdown");
|
|
||||||
if(pico_err == PICO_ERR_EADDRNOTAVAIL)
|
|
||||||
DEBUG_ERROR("PICO_ERR_EADDRNOTAVAIL - address not available");
|
|
||||||
if(pico_err == PICO_ERR_EHOSTUNREACH)
|
|
||||||
DEBUG_ERROR("PICO_ERR_EHOSTUNREACH - host is unreachable");
|
|
||||||
if(pico_err == PICO_ERR_ENOMEM)
|
|
||||||
DEBUG_ERROR("PICO_ERR_ENOMEM - not enough space");
|
|
||||||
if(pico_err == PICO_ERR_EAGAIN)
|
|
||||||
DEBUG_ERROR("PICO_ERR_EAGAIN - resource temporarily unavailable");
|
|
||||||
*/
|
|
||||||
|
|
||||||
// adjust buffer
|
// adjust buffer
|
||||||
int sz = (conn->txsz)-r;
|
int sz = (conn->txsz)-r;
|
||||||
if(sz)
|
if(sz)
|
||||||
@@ -509,123 +453,130 @@ namespace ZeroTier {
|
|||||||
conn->txsz -= r;
|
conn->txsz -= r;
|
||||||
|
|
||||||
if(conn->socket_type == SOCK_STREAM) {
|
if(conn->socket_type == SOCK_STREAM) {
|
||||||
max = DEFAULT_TCP_TX_BUF_SZ;
|
max = ZT_TCP_TX_BUF_SZ;
|
||||||
DEBUG_TRANS("[TCP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
DEBUG_TRANS("[TCP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
||||||
(float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r);
|
(float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r);
|
||||||
}
|
}
|
||||||
if(conn->socket_type == SOCK_DGRAM) {
|
if(conn->socket_type == SOCK_DGRAM) {
|
||||||
max = DEFAULT_UDP_TX_BUF_SZ;
|
max = ZT_UDP_TX_BUF_SZ;
|
||||||
DEBUG_TRANS("[UDP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
DEBUG_TRANS("[UDP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
||||||
(float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r);
|
(float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void picoTCP::pico_handleConnect(PhySocket *sock, PhySocket *rpcSock, Connection *conn, struct connect_st* connect_rpc)
|
int picoTCP::pico_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
if(conn->picosock) {
|
int err;
|
||||||
struct sockaddr_in *addr = (struct sockaddr_in *) &connect_rpc->addr;
|
|
||||||
int ret;
|
|
||||||
// TODO: Rewrite this
|
|
||||||
#if defined(SDK_IPV4)
|
#if defined(SDK_IPV4)
|
||||||
struct pico_ip4 zaddr;
|
struct pico_ip4 zaddr;
|
||||||
struct sockaddr_in *in4 = (struct sockaddr_in*)&connect_rpc->addr;
|
struct sockaddr_in *in4 = (struct sockaddr_in*)addr;
|
||||||
char ipv4_str[INET_ADDRSTRLEN];
|
char ipv4_str[INET_ADDRSTRLEN];
|
||||||
inet_ntop(AF_INET, &(in4->sin_addr), 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));
|
pico_string_to_ipv4(ipv4_str, &(zaddr.addr));
|
||||||
//DEBUG_ATTN("addr=%s:%d", ipv4_str, Utils::ntoh(addr->sin_port));
|
DEBUG_ATTN("addr=%s:%d", ipv4_str, Utils::ntoh( in4->sin_port ));
|
||||||
ret = pico_socket_connect(conn->picosock, &zaddr, addr->sin_port);
|
err = pico_socket_connect(conn->picosock, &zaddr, in4->sin_port);
|
||||||
#elif defined(SDK_IPV6) // "fd56:5799:d8f6:1238:8c99:9322:30ce:418a"
|
DEBUG_INFO("connect_err = %d", err);
|
||||||
struct pico_ip6 zaddr;
|
|
||||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&connect_rpc->addr;
|
|
||||||
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(addr->sin_port));
|
|
||||||
ret = pico_socket_connect(conn->picosock, &zaddr, addr->sin_port);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memcpy(&(conn->peer_addr), &connect_rpc->addr, sizeof(struct sockaddr_storage));
|
|
||||||
|
|
||||||
if(ret == PICO_ERR_EPROTONOSUPPORT)
|
|
||||||
DEBUG_ERROR("PICO_ERR_EPROTONOSUPPORT");
|
|
||||||
if(ret == PICO_ERR_EINVAL)
|
|
||||||
DEBUG_ERROR("PICO_ERR_EINVAL");
|
|
||||||
if(ret == PICO_ERR_EHOSTUNREACH)
|
|
||||||
DEBUG_ERROR("PICO_ERR_EHOSTUNREACH");
|
|
||||||
picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), 0, ERR_OK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void picoTCP::pico_handleBind(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct bind_st *bind_rpc)
|
|
||||||
{
|
|
||||||
Connection *conn = picotap->getConnection(sock);
|
|
||||||
if(!sock) {
|
|
||||||
DEBUG_ERROR("invalid connection");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct sockaddr_in *addr = (struct sockaddr_in *) &bind_rpc->addr;
|
|
||||||
int ret;
|
|
||||||
// TODO: Rewrite this
|
|
||||||
#if defined(SDK_IPV4)
|
|
||||||
struct pico_ip4 zaddr;
|
|
||||||
struct sockaddr_in *in4 = (struct sockaddr_in*)&bind_rpc->addr;
|
|
||||||
char ipv4_str[INET_ADDRSTRLEN];
|
|
||||||
inet_ntop(AF_INET, &(in4->sin_addr), ipv4_str, INET_ADDRSTRLEN);
|
|
||||||
pico_string_to_ipv4(ipv4_str, &(zaddr.addr));
|
|
||||||
DEBUG_ATTN("addr=%s:%d, physock=%p, picosock=%p", ipv4_str, Utils::ntoh(addr->sin_port), sock, (conn->picosock));
|
|
||||||
ret = pico_socket_bind(conn->picosock, &zaddr, (uint16_t*)&(addr->sin_port));
|
|
||||||
#elif defined(SDK_IPV6)
|
#elif defined(SDK_IPV6)
|
||||||
struct pico_ip6 zaddr;
|
struct pico_ip6 zaddr;
|
||||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&bind_rpc->addr;
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
||||||
char ipv6_str[INET6_ADDRSTRLEN];
|
char ipv6_str[INET6_ADDRSTRLEN];
|
||||||
inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN);
|
inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN);
|
||||||
pico_string_to_ipv6(ipv6_str, zaddr.addr);
|
pico_string_to_ipv6(ipv6_str, zaddr.addr);
|
||||||
DEBUG_ATTN("addr=%s:%d, physock=%p, picosock=%p", ipv6_str, Utils::ntoh(addr->sin_port), sock, (conn->picosock));
|
DEBUG_ATTN("addr=%s:%d", ipv6_str, Utils::ntoh(addr->sin_port));
|
||||||
ret = pico_socket_bind(conn->picosock, &zaddr, (uint16_t*)&(addr->sin_port));
|
err = pico_socket_connect(conn->picosock, &zaddr, (struct sockaddr_in *)&addr->sin_port);
|
||||||
#endif
|
#endif
|
||||||
if(ret < 0) {
|
|
||||||
DEBUG_ERROR("unable to bind pico_socket(%p), err=%d", (conn->picosock), ret);
|
memcpy(&(conn->peer_addr), &addr, sizeof(struct sockaddr_storage));
|
||||||
if(ret == PICO_ERR_EINVAL) {
|
|
||||||
DEBUG_ERROR("PICO_ERR_EINVAL - invalid argument");
|
if(err == PICO_ERR_EPROTONOSUPPORT)
|
||||||
picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), -1, EINVAL);
|
DEBUG_ERROR("PICO_ERR_EPROTONOSUPPORT");
|
||||||
}
|
if(err == PICO_ERR_EINVAL)
|
||||||
if(ret == PICO_ERR_ENOMEM) {
|
DEBUG_ERROR("PICO_ERR_EINVAL");
|
||||||
DEBUG_ERROR("PICO_ERR_ENOMEM - not enough space");
|
if(err == PICO_ERR_EHOSTUNREACH)
|
||||||
picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), -1, ENOMEM);
|
DEBUG_ERROR("PICO_ERR_EHOSTUNREACH");
|
||||||
}
|
return err;
|
||||||
if(ret == PICO_ERR_ENXIO) {
|
|
||||||
DEBUG_ERROR("PICO_ERR_ENXIO - no such device or address");
|
|
||||||
picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), -1, ENXIO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), ERR_OK, ERR_OK); // success
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void picoTCP::pico_handleListen(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct listen_st *listen_rpc)
|
int picoTCP::pico_Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
Connection *conn = picotap->getConnection(sock);
|
int err;
|
||||||
DEBUG_ATTN("physock=%p, conn=%p, picosock=%p", sock, conn, conn->picosock);
|
#if defined(SDK_IPV4)
|
||||||
if(!sock || !conn) {
|
struct pico_ip4 zaddr;
|
||||||
DEBUG_ERROR("invalid connection");
|
struct sockaddr_in *in4 = (struct sockaddr_in*)addr;
|
||||||
return;
|
char ipv4_str[INET_ADDRSTRLEN];
|
||||||
}
|
inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN);
|
||||||
int ret, backlog = 100;
|
pico_string_to_ipv4(ipv4_str, &(zaddr.addr));
|
||||||
if((ret = pico_socket_listen(conn->picosock, backlog)) < 0)
|
//DEBUG_ATTN("addr=%s:%d, physock=%p, picosock=%p", ipv4_str, Utils::ntoh(addr->sin_port), sock, (conn->picosock));
|
||||||
{
|
err = pico_socket_bind(conn->picosock, &zaddr, (uint16_t *)&(in4->sin_port));
|
||||||
if(ret == PICO_ERR_EINVAL) {
|
#elif defined(SDK_IPV6)
|
||||||
|
struct pico_ip6 zaddr;
|
||||||
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
||||||
|
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, physock=%p, picosock=%p", ipv6_str, Utils::ntoh(addr->sin_port), sock, (conn->picosock));
|
||||||
|
err = pico_socket_bind(conn->picosock, &zaddr, (struct sockaddr_in *)&addr->sin_port);
|
||||||
|
#endif
|
||||||
|
if(err < 0) {
|
||||||
|
DEBUG_ERROR("unable to bind pico_socket(%p), err=%d", (conn->picosock), err);
|
||||||
|
if(err == PICO_ERR_EINVAL) {
|
||||||
DEBUG_ERROR("PICO_ERR_EINVAL - invalid argument");
|
DEBUG_ERROR("PICO_ERR_EINVAL - invalid argument");
|
||||||
picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), -1, EINVAL);
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if(ret == PICO_ERR_EISCONN) {
|
if(err == PICO_ERR_ENOMEM) {
|
||||||
|
DEBUG_ERROR("PICO_ERR_ENOMEM - not enough space");
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(err == PICO_ERR_ENXIO) {
|
||||||
|
DEBUG_ERROR("PICO_ERR_ENXIO - no such device or address");
|
||||||
|
errno = ENXIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int picoTCP::pico_Listen(Connection *conn, int fd, int backlog)
|
||||||
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
|
int err;
|
||||||
|
if((err = pico_socket_listen(conn->picosock, backlog)) < 0)
|
||||||
|
{
|
||||||
|
if(err == PICO_ERR_EINVAL) {
|
||||||
|
DEBUG_ERROR("PICO_ERR_EINVAL - invalid argument");
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(err == PICO_ERR_EISCONN) {
|
||||||
DEBUG_ERROR("PICO_ERR_EISCONN - socket is connected");
|
DEBUG_ERROR("PICO_ERR_EISCONN - socket is connected");
|
||||||
picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), -1, EISCONN);
|
errno = EISCONN;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), ERR_OK, ERR_OK); // success
|
return ZT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int picoTCP::pico_Accept(Connection *conn)
|
||||||
|
{
|
||||||
|
// Retreive queued Connections from parent connection
|
||||||
|
int err;
|
||||||
|
if(!conn->_AcceptedConnections.size()) {
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Connection *new_conn = conn->_AcceptedConnections.front();
|
||||||
|
conn->_AcceptedConnections.pop();
|
||||||
|
err = new_conn->app_fd;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void picoTCP::pico_handleRead(PhySocket *sock,void **uptr,bool lwip_invoked)
|
void picoTCP::pico_handleRead(PhySocket *sock,void **uptr,bool lwip_invoked)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
if(!lwip_invoked) {
|
if(!lwip_invoked) {
|
||||||
// The stack thread writes to RXBUF as well
|
// The stack thread writes to RXBUF as well
|
||||||
picotap->_tcpconns_m.lock();
|
picotap->_tcpconns_m.lock();
|
||||||
@@ -638,17 +589,17 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
//
|
//
|
||||||
if(conn->socket_type==SOCK_DGRAM) {
|
if(conn->socket_type==SOCK_DGRAM) {
|
||||||
// Try to write SDK_MTU-sized chunk to app socket
|
// Try to write ZT_SDK_MTU-sized chunk to app socket
|
||||||
while(tot < SDK_MTU) {
|
while(tot < ZT_SDK_MTU) {
|
||||||
write_attempts++;
|
write_attempts++;
|
||||||
n = picotap->_phy.streamSend(conn->sock, (conn->rxbuf)+tot, SDK_MTU);
|
n = picotap->_phy.streamSend(conn->sock, (conn->rxbuf)+tot, ZT_SDK_MTU);
|
||||||
tot += n;
|
tot += n;
|
||||||
DEBUG_FLOW(" [ ZTSOCK <- RXBUF] wrote = %d, errno=%d", n, errno);
|
DEBUG_FLOW(" [ ZTSOCK <- RXBUF] wrote = %d, errno=%d", n, errno);
|
||||||
// If socket is unavailable, attempt to write N times before giving up
|
// If socket is unavailable, attempt to write N times before giving up
|
||||||
if(errno==35) {
|
if(errno==35) {
|
||||||
if(write_attempts == 1024) {
|
if(write_attempts == 1024) {
|
||||||
n = SDK_MTU; // say we wrote it, even though we didn't (drop packet)
|
n = ZT_SDK_MTU; // say we wrote it, even though we didn't (drop packet)
|
||||||
tot = SDK_MTU;
|
tot = ZT_SDK_MTU;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -659,15 +610,16 @@ namespace ZeroTier {
|
|||||||
// adjust buffer
|
// adjust buffer
|
||||||
//DEBUG_FLOW(" [ ZTSOCK <- RXBUF] Copying data from receiving buffer to ZT-controlled app socket (n=%d, payload_sz=%d)", n, payload_sz);
|
//DEBUG_FLOW(" [ ZTSOCK <- RXBUF] Copying data from receiving buffer to ZT-controlled app socket (n=%d, payload_sz=%d)", n, payload_sz);
|
||||||
if(conn->rxsz-n > 0) { // If more remains on buffer
|
if(conn->rxsz-n > 0) { // If more remains on buffer
|
||||||
memcpy(conn->rxbuf, conn->rxbuf+SDK_MTU, conn->rxsz - SDK_MTU);
|
memcpy(conn->rxbuf, conn->rxbuf+ZT_SDK_MTU, conn->rxsz - ZT_SDK_MTU);
|
||||||
//DEBUG_FLOW(" [ ZTSOCK <- RXBUF] Data(%d) still on buffer, moving it up by one MTU", conn->rxsz-n);
|
//DEBUG_FLOW(" [ ZTSOCK <- RXBUF] Data(%d) still on buffer, moving it up by one MTU", conn->rxsz-n);
|
||||||
////memset(conn->rxbuf, 0, DEFAULT_UDP_RX_BUF_SZ);
|
////memset(conn->rxbuf, 0, ZT_UDP_RX_BUF_SZ);
|
||||||
////conn->rxsz=SDK_MTU;
|
////conn->rxsz=ZT_SDK_MTU;
|
||||||
}
|
}
|
||||||
conn->rxsz -= SDK_MTU;
|
conn->rxsz -= ZT_SDK_MTU;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if(conn->socket_type==SOCK_STREAM) {
|
if(conn->socket_type==SOCK_STREAM) {
|
||||||
|
DEBUG_TRANS("writing to conn->sock = %p", conn->sock);
|
||||||
n = picotap->_phy.streamSend(conn->sock, conn->rxbuf, conn->rxsz);
|
n = picotap->_phy.streamSend(conn->sock, conn->rxbuf, conn->rxsz);
|
||||||
if(conn->rxsz-n > 0) // If more remains on buffer
|
if(conn->rxsz-n > 0) // If more remains on buffer
|
||||||
memcpy(conn->rxbuf, conn->rxbuf+n, conn->rxsz - n);
|
memcpy(conn->rxbuf, conn->rxbuf+n, conn->rxsz - n);
|
||||||
@@ -678,7 +630,7 @@ namespace ZeroTier {
|
|||||||
if(conn->socket_type==SOCK_STREAM) {
|
if(conn->socket_type==SOCK_STREAM) {
|
||||||
|
|
||||||
#if DEBUG_LEVEL >= MSG_TRANSFER
|
#if DEBUG_LEVEL >= MSG_TRANSFER
|
||||||
float max = conn->socket_type == SOCK_STREAM ? (float)DEFAULT_TCP_RX_BUF_SZ : (float)DEFAULT_UDP_RX_BUF_SZ;
|
float max = conn->socket_type == SOCK_STREAM ? (float)ZT_TCP_RX_BUF_SZ : (float)ZT_UDP_RX_BUF_SZ;
|
||||||
DEBUG_TRANS("[TCP RX] <--- :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
DEBUG_TRANS("[TCP RX] <--- :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
|
||||||
(float)conn->txsz / max, (float)conn->rxsz / max, conn->sock, n);
|
(float)conn->txsz / max, (float)conn->rxsz / max, conn->sock, n);
|
||||||
#endif
|
#endif
|
||||||
@@ -698,11 +650,13 @@ namespace ZeroTier {
|
|||||||
picotap->_tcpconns_m.unlock();
|
picotap->_tcpconns_m.unlock();
|
||||||
picotap->_rx_buf_m.unlock();
|
picotap->_rx_buf_m.unlock();
|
||||||
}
|
}
|
||||||
|
// FIXME: Re-write debug traces
|
||||||
DEBUG_FLOW(" [ ZTSOCK <- RXBUF] Emitted (%d) from RXBUF(%d) to socket", tot, conn->rxsz);
|
DEBUG_FLOW(" [ ZTSOCK <- RXBUF] Emitted (%d) from RXBUF(%d) to socket", tot, conn->rxsz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void picoTCP::pico_handleClose(PhySocket *sock)
|
void picoTCP::pico_handleClose(PhySocket *sock)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO();
|
||||||
/*
|
/*
|
||||||
int ret;
|
int ret;
|
||||||
if(conn && conn->picosock) {
|
if(conn && conn->picosock) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* ZeroTier One - Network Virtualization Everywhere
|
* ZeroTier SDK - Network Virtualization Everywhere
|
||||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -14,21 +14,11 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
* --
|
|
||||||
*
|
|
||||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which
|
|
||||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
*
|
|
||||||
* If you would like to embed ZeroTier into a commercial application or
|
|
||||||
* redistribute it in a modified binary form, please contact ZeroTier Networks
|
|
||||||
* LLC. Start here: http://www.zerotier.com/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ZT_PICOTCP_HPP
|
#ifndef ZT_PICOTCP_HPP
|
||||||
#define ZT_PICOTCP_HPP
|
#define ZT_PICOTCP_HPP
|
||||||
|
|
||||||
|
|
||||||
#include "pico_eth.h"
|
#include "pico_eth.h"
|
||||||
#include "pico_stack.h"
|
#include "pico_stack.h"
|
||||||
#include "pico_ipv4.h"
|
#include "pico_ipv4.h"
|
||||||
@@ -79,26 +69,50 @@ namespace ZeroTier
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up an interface in the network stack for the SocketTap
|
||||||
|
*/
|
||||||
void pico_init_interface(ZeroTier::SocketTap *tap, const ZeroTier::InetAddress &ip);
|
void pico_init_interface(ZeroTier::SocketTap *tap, const ZeroTier::InetAddress &ip);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main stack loop
|
||||||
|
*/
|
||||||
void pico_loop(SocketTap *tap);
|
void pico_loop(SocketTap *tap);
|
||||||
|
|
||||||
//int pico_eth_send(struct pico_device *dev, void *buf, int len);
|
/*
|
||||||
//int pico_eth_poll(struct pico_device *dev, int loop_score);
|
* Read bytes from the stack to the RX buffer (prepare to be read by app)
|
||||||
|
*/
|
||||||
static void pico_cb_tcp_read(SocketTap *tap, struct pico_socket *s);
|
static void pico_cb_tcp_read(SocketTap *tap, struct pico_socket *s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read bytes from the stack to the RX buffer (prepare to be read by app)
|
||||||
|
*/
|
||||||
static void pico_cb_udp_read(SocketTap *tap, struct pico_socket *s);
|
static void pico_cb_udp_read(SocketTap *tap, struct pico_socket *s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire)
|
||||||
|
*/
|
||||||
static void pico_cb_tcp_write(SocketTap *tap, struct pico_socket *s);
|
static void pico_cb_tcp_write(SocketTap *tap, struct pico_socket *s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire)
|
||||||
|
*/
|
||||||
static void pico_cb_socket_activity(uint16_t ev, struct pico_socket *s);
|
static void pico_cb_socket_activity(uint16_t ev, struct pico_socket *s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Where packets enter the stack
|
||||||
|
*/
|
||||||
void pico_rx(SocketTap *tap, const ZeroTier::MAC &from,const ZeroTier::MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
void pico_rx(SocketTap *tap, const ZeroTier::MAC &from,const ZeroTier::MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||||
Connection *pico_handleSocket(ZeroTier::PhySocket *sock, void **uptr, struct socket_st* socket_rpc);
|
|
||||||
void pico_handleWrite(Connection *conn);
|
|
||||||
void pico_handleConnect(ZeroTier::PhySocket *sock, ZeroTier::PhySocket *rpcSock, Connection *conn, struct connect_st* connect_rpc);
|
|
||||||
void pico_handleBind(ZeroTier::PhySocket *sock, ZeroTier::PhySocket *rpcSock, void **uptr, struct bind_st *bind_rpc);
|
|
||||||
void pico_handleListen(ZeroTier::PhySocket *sock, ZeroTier::PhySocket *rpcSock, void **uptr, struct listen_st *listen_rpc);
|
|
||||||
void pico_handleRead(ZeroTier::PhySocket *sock,void **uptr,bool lwip_invoked);
|
void pico_handleRead(ZeroTier::PhySocket *sock,void **uptr,bool lwip_invoked);
|
||||||
void pico_handleClose(ZeroTier::PhySocket *sock);
|
void pico_handleClose(ZeroTier::PhySocket *sock);
|
||||||
|
void pico_handleWrite(Connection *conn);
|
||||||
|
|
||||||
|
// common socket operations
|
||||||
|
int pico_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
int pico_Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
int pico_Listen(Connection *conn, int fd, int backlog);
|
||||||
|
int pico_Accept(Connection *conn);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
62
test/dumb/tcpclient4.c
Normal file
62
test/dumb/tcpclient4.c
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// TCP Client test program
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int atoi(const char *str);
|
||||||
|
int close(int filedes);
|
||||||
|
|
||||||
|
#define MSG_SZ 128
|
||||||
|
|
||||||
|
int main(int argc , char *argv[])
|
||||||
|
{
|
||||||
|
if(argc < 3) {
|
||||||
|
printf("usage: client <addr> <port>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock, port = atoi(argv[2]);
|
||||||
|
struct sockaddr_in server;
|
||||||
|
char message[MSG_SZ] , server_reply[MSG_SZ];
|
||||||
|
|
||||||
|
sock = socket(AF_INET , SOCK_STREAM , 0);
|
||||||
|
if (sock == -1) {
|
||||||
|
printf("could not create socket");
|
||||||
|
}
|
||||||
|
server.sin_addr.s_addr = inet_addr(argv[1]);
|
||||||
|
server.sin_family = AF_INET;
|
||||||
|
server.sin_port = htons( port );
|
||||||
|
|
||||||
|
printf("connecting...\n");
|
||||||
|
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0) {
|
||||||
|
perror("connect failed. Error");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("connected\n");
|
||||||
|
|
||||||
|
char *msg = "welcome to the machine!";
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// TX
|
||||||
|
if(send(sock, msg, strlen(msg), 0) < 0) {
|
||||||
|
printf("send failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("TX: %s\n", msg);
|
||||||
|
printf("len = %ld\n", strlen(msg));
|
||||||
|
|
||||||
|
int bytes_read = read(sock, server_reply, MSG_SZ);
|
||||||
|
if(bytes_read < 0)
|
||||||
|
printf("\tRX: Nothing\n");
|
||||||
|
else
|
||||||
|
printf("\tRX = (%d bytes): %s\n", bytes_read, server_reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(sock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
72
test/dumb/tcpclient6.c
Normal file
72
test/dumb/tcpclient6.c
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
void error(char *msg) {
|
||||||
|
perror(msg);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int sockfd, portno, n;
|
||||||
|
struct sockaddr_in6 serv_addr;
|
||||||
|
struct hostent *server;
|
||||||
|
char buffer[256] = "This is a string from client!";
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf(stderr, "Usage: %s \n", argv[0]);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
portno = atoi(argv[2]);
|
||||||
|
|
||||||
|
printf("\nIPv6 TCP Client Started...\n");
|
||||||
|
|
||||||
|
//Sockets Layer Call: socket()
|
||||||
|
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
|
if (sockfd < 0)
|
||||||
|
error("ERROR opening socket");
|
||||||
|
|
||||||
|
//Sockets Layer Call: gethostbyname2()
|
||||||
|
server = gethostbyname2(argv[1],AF_INET6);
|
||||||
|
if (server == NULL) {
|
||||||
|
fprintf(stderr, "ERROR, no such host\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset((char *) &serv_addr, 0, sizeof(serv_addr));
|
||||||
|
serv_addr.sin6_flowinfo = 0;
|
||||||
|
serv_addr.sin6_family = AF_INET6;
|
||||||
|
memmove((char *) &serv_addr.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length);
|
||||||
|
serv_addr.sin6_port = htons(portno);
|
||||||
|
|
||||||
|
//Sockets Layer Call: connect()
|
||||||
|
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
|
||||||
|
error("ERROR connecting");
|
||||||
|
|
||||||
|
|
||||||
|
//Sockets Layer Call: send()
|
||||||
|
n = send(sockfd,buffer, strlen(buffer)+1, 0);
|
||||||
|
if (n < 0)
|
||||||
|
error("ERROR writing to socket");
|
||||||
|
|
||||||
|
printf("sent %d bytes\n", n);
|
||||||
|
memset(buffer, 0, 256);
|
||||||
|
|
||||||
|
//Sockets Layer Call: recv()
|
||||||
|
printf("reading...\n");
|
||||||
|
n = recv(sockfd, buffer, 255, 0);
|
||||||
|
if (n < 0)
|
||||||
|
error("ERROR reading from socket");
|
||||||
|
printf("Message from server: %s\n", buffer);
|
||||||
|
|
||||||
|
//Sockets Layer Call: close()
|
||||||
|
close(sockfd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
61
test/dumb/tcpserver4.c
Normal file
61
test/dumb/tcpserver4.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int atoi(const char *str);
|
||||||
|
|
||||||
|
int main(int argc , char *argv[])
|
||||||
|
{
|
||||||
|
if(argc < 2) {
|
||||||
|
printf("usage: tcp_server <port>\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int comm_fd, sock, client_sock, c, read_size, port = atoi(argv[1]);
|
||||||
|
char client_message[2000];
|
||||||
|
|
||||||
|
struct sockaddr_in servaddr;
|
||||||
|
struct sockaddr_in client;
|
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
bzero( &servaddr, sizeof(servaddr));
|
||||||
|
|
||||||
|
servaddr.sin_family = AF_INET;
|
||||||
|
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
|
||||||
|
servaddr.sin_port = htons(port);
|
||||||
|
bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
|
||||||
|
|
||||||
|
printf("listening\n");
|
||||||
|
listen(sock , 3);
|
||||||
|
printf("waiting to accept\n");
|
||||||
|
c = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
client_sock = accept(sock, (struct sockaddr *)&client, (socklen_t*)&c);
|
||||||
|
if (client_sock < 0) {
|
||||||
|
perror("accept failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf("connection accepted\n reading...\n");
|
||||||
|
|
||||||
|
// RX
|
||||||
|
|
||||||
|
int msglen = 1024;
|
||||||
|
unsigned long count = 0;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
int bytes_read = read(client_sock, client_message, msglen);
|
||||||
|
printf("[%lu] RX = (%d): ", count, bytes_read);
|
||||||
|
for(int i=0; i<bytes_read; i++) {
|
||||||
|
printf("%c", client_message[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TX
|
||||||
|
int bytes_written = write(client_sock, "Server here!", 12);
|
||||||
|
printf("\t\nTX = %d\n", bytes_written);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
83
test/dumb/tcpserver6.c
Normal file
83
test/dumb/tcpserver6.c
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
void error(char *msg) {
|
||||||
|
perror(msg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int sockfd, newsockfd, portno;
|
||||||
|
socklen_t clilen;
|
||||||
|
char buffer[256];
|
||||||
|
struct sockaddr_in6 serv_addr, cli_addr;
|
||||||
|
int n;
|
||||||
|
char client_addr_ipv6[100];
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
fprintf(stderr, "Usage: %s \n", argv[0]);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nIPv6 TCP Server Started...\n");
|
||||||
|
|
||||||
|
//Sockets Layer Call: socket()
|
||||||
|
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
|
if (sockfd < 0)
|
||||||
|
error("ERROR opening socket");
|
||||||
|
|
||||||
|
bzero((char *) &serv_addr, sizeof(serv_addr));
|
||||||
|
portno = atoi(argv[1]);
|
||||||
|
serv_addr.sin6_flowinfo = 0;
|
||||||
|
serv_addr.sin6_family = AF_INET6;
|
||||||
|
serv_addr.sin6_addr = in6addr_any;
|
||||||
|
serv_addr.sin6_port = htons(portno);
|
||||||
|
|
||||||
|
|
||||||
|
//Sockets Layer Call: bind()
|
||||||
|
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
|
||||||
|
error("ERROR on binding");
|
||||||
|
|
||||||
|
//Sockets Layer Call: listen()
|
||||||
|
listen(sockfd, 5);
|
||||||
|
clilen = sizeof(cli_addr);
|
||||||
|
|
||||||
|
//Sockets Layer Call: accept()
|
||||||
|
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
|
||||||
|
if (newsockfd < 0)
|
||||||
|
error("ERROR on accept");
|
||||||
|
|
||||||
|
//Sockets Layer Call: inet_ntop()
|
||||||
|
inet_ntop(AF_INET6, &(cli_addr.sin6_addr),client_addr_ipv6, 100);
|
||||||
|
printf("Incoming connection from client having IPv6 address: %s\n",client_addr_ipv6);
|
||||||
|
|
||||||
|
memset(buffer,0, 256);
|
||||||
|
|
||||||
|
//Sockets Layer Call: recv()
|
||||||
|
n = recv(newsockfd, buffer, 255, 0);
|
||||||
|
if (n < 0)
|
||||||
|
error("ERROR reading from socket");
|
||||||
|
|
||||||
|
printf("Message from client: %s\n", buffer);
|
||||||
|
|
||||||
|
//Sockets Layer Call: send()
|
||||||
|
printf("sending...\n");
|
||||||
|
n = send(newsockfd, "Server got your message", 23+1, 0);
|
||||||
|
if (n < 0)
|
||||||
|
error("ERROR writing to socket");
|
||||||
|
|
||||||
|
//Sockets Layer Call: close()
|
||||||
|
close(sockfd);
|
||||||
|
close(newsockfd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
88
test/dumb/udpclient4.c
Executable file
88
test/dumb/udpclient4.c
Executable file
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* udpclient.c - A simple UDP client
|
||||||
|
* usage: udpclient <host> <port>
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#define BUFSIZE 1024
|
||||||
|
|
||||||
|
/*
|
||||||
|
* error - wrapper for perror
|
||||||
|
*/
|
||||||
|
void error(char *msg) {
|
||||||
|
perror(msg);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int sock, portno, n;
|
||||||
|
int serverlen;
|
||||||
|
struct sockaddr_in serveraddr;
|
||||||
|
struct hostent *server;
|
||||||
|
char *hostname;
|
||||||
|
char buf[BUFSIZE];
|
||||||
|
|
||||||
|
/* check command line arguments */
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr,"usage: %s <hostname> <port>\n", argv[0]);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
hostname = argv[1];
|
||||||
|
portno = atoi(argv[2]);
|
||||||
|
|
||||||
|
/* socket: create the socket */
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock < 0)
|
||||||
|
error("ERROR opening socket");
|
||||||
|
|
||||||
|
/* gethostbyname: get the server's DNS entry */
|
||||||
|
server = gethostbyname(hostname);
|
||||||
|
if (server == NULL) {
|
||||||
|
fprintf(stderr,"ERROR, no such host as %s\n", hostname);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build the server's Internet address */
|
||||||
|
bzero((char *) &serveraddr, sizeof(serveraddr));
|
||||||
|
serveraddr.sin_family = AF_INET;
|
||||||
|
bcopy((char *)server->h_addr,
|
||||||
|
(char *)&serveraddr.sin_addr.s_addr, server->h_length);
|
||||||
|
serveraddr.sin_port = htons(portno);
|
||||||
|
|
||||||
|
/* get a message from the user */
|
||||||
|
char *msg = "A message to the server!\0";
|
||||||
|
fcntl(sock, F_SETFL, O_NONBLOCK);
|
||||||
|
long count = 0;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
printf("\n\n\nTX(%lu)...\n", count);
|
||||||
|
sleep(1);
|
||||||
|
//usleep(10000);
|
||||||
|
//bzero(buf, BUFSIZE);
|
||||||
|
//printf("\nPlease enter msg: ");
|
||||||
|
//fgets(buf, BUFSIZE, stdin);
|
||||||
|
|
||||||
|
/* send the message to the server */
|
||||||
|
serverlen = sizeof(serveraddr);
|
||||||
|
n = sendto(sock, msg, strlen(msg), 0, (struct sockaddr *)&serveraddr, serverlen);
|
||||||
|
//if (n < 0)
|
||||||
|
// error("ERROR in sendto");
|
||||||
|
|
||||||
|
/* print the server's reply */
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
n = recvfrom(sock, buf, BUFSIZE, 0, (struct sockaddr *)&serveraddr, (socklen_t *)&serverlen);
|
||||||
|
//if (n < 0)
|
||||||
|
// printf("ERROR in recvfrom: %d", n);
|
||||||
|
printf("Echo from server: %s", buf);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
43
test/dumb/udpclient6.c
Executable file
43
test/dumb/udpclient6.c
Executable file
@@ -0,0 +1,43 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAXBUF 65536
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct addrinfo sainfo, *psinfo;
|
||||||
|
struct hostent *server;
|
||||||
|
char buffer[MAXBUF];
|
||||||
|
|
||||||
|
int sock, portno, n;
|
||||||
|
struct sockaddr_in6 serv_addr;
|
||||||
|
|
||||||
|
if(argc < 2)
|
||||||
|
printf("Specify a port number\n"), exit(1);
|
||||||
|
|
||||||
|
sock = socket(PF_INET6, SOCK_DGRAM,0);
|
||||||
|
|
||||||
|
portno = atoi(argv[2]);
|
||||||
|
server = gethostbyname2(argv[1],AF_INET6);
|
||||||
|
memset((char *) &serv_addr, 0, sizeof(serv_addr));
|
||||||
|
serv_addr.sin6_flowinfo = 0;
|
||||||
|
serv_addr.sin6_family = AF_INET6;
|
||||||
|
memmove((char *) &serv_addr.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length);
|
||||||
|
serv_addr.sin6_port = htons(portno);
|
||||||
|
|
||||||
|
sprintf(buffer,"Ciao");
|
||||||
|
|
||||||
|
status = sendto(sock, buffer, strlen(buffer), 0, (const struct sockaddr *)&serv_addr, sizeof(serv_addr));
|
||||||
|
printf("buffer : %s \t%d\n", buffer, status);
|
||||||
|
|
||||||
|
close(sock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
86
test/dumb/udpserver4.c
Executable file
86
test/dumb/udpserver4.c
Executable file
@@ -0,0 +1,86 @@
|
|||||||
|
// UDP Server test program
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
#define MAXBUF 1024*1024
|
||||||
|
|
||||||
|
void echo(int sock) {
|
||||||
|
char bufin[MAXBUF];
|
||||||
|
struct sockaddr_in remote;
|
||||||
|
int n;
|
||||||
|
socklen_t len = sizeof(remote);
|
||||||
|
long count = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
sleep(1);
|
||||||
|
//usleep(50);
|
||||||
|
count++;
|
||||||
|
// read a datagram from the socket (put result in bufin)
|
||||||
|
n=recvfrom(sock,bufin,MAXBUF,0,(struct sockaddr *)&remote,&len);
|
||||||
|
// print out the address of the sender
|
||||||
|
printf("DGRAM from %s:%d\n", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));
|
||||||
|
|
||||||
|
if (n<0) {
|
||||||
|
perror("Error receiving data");
|
||||||
|
} else {
|
||||||
|
printf("GOT %d BYTES (count = %ld)\n", n, count);
|
||||||
|
// Got something, just send it back
|
||||||
|
// sendto(sock,bufin,n,0,(struct sockaddr *)&remote,len);
|
||||||
|
printf("RX = %s\n", bufin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
if(argc < 2) {
|
||||||
|
printf("usage: udp_server <port>\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int sock, port = atoi(argv[1]);
|
||||||
|
socklen_t len;
|
||||||
|
struct sockaddr_in skaddr;
|
||||||
|
struct sockaddr_in skaddr2;
|
||||||
|
|
||||||
|
// Create socket
|
||||||
|
if ((sock = socket( PF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||||
|
printf("error creating socket\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Create address
|
||||||
|
skaddr.sin_family = AF_INET;
|
||||||
|
skaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
skaddr.sin_port = htons(port);
|
||||||
|
// Bind to address
|
||||||
|
if (bind(sock, (struct sockaddr *) &skaddr, sizeof(skaddr))<0) {
|
||||||
|
printf("error binding\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// find out what port we were assigned
|
||||||
|
len = sizeof( skaddr2 );
|
||||||
|
//if (getsockname(sock, (struct sockaddr *) &skaddr2, &len)<0) {
|
||||||
|
// printf("error getsockname\n");
|
||||||
|
// return 0;
|
||||||
|
//}
|
||||||
|
// Display address:port to verify it was sent over RPC correctly
|
||||||
|
/*
|
||||||
|
port = ntohs(skaddr2.sin_port);
|
||||||
|
int ip = skaddr2.sin_addr.s_addr;
|
||||||
|
unsigned char d[4];
|
||||||
|
d[0] = ip & 0xFF;
|
||||||
|
d[1] = (ip >> 8) & 0xFF;
|
||||||
|
d[2] = (ip >> 16) & 0xFF;
|
||||||
|
d[3] = (ip >> 24) & 0xFF;
|
||||||
|
printf("bound to address: %d.%d.%d.%d : %d\n", d[0],d[1],d[2],d[3], port);
|
||||||
|
*/
|
||||||
|
// RX
|
||||||
|
echo(sock);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
44
test/dumb/udpserver6.c
Executable file
44
test/dumb/udpserver6.c
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAXBUF 65536
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int sock;
|
||||||
|
int n;
|
||||||
|
struct sockaddr_in6 sin6;
|
||||||
|
socklen_t sin6len;
|
||||||
|
char buffer[MAXBUF];
|
||||||
|
|
||||||
|
sock = socket(PF_INET6, SOCK_DGRAM,0);
|
||||||
|
sin6len = sizeof(struct sockaddr_in6);
|
||||||
|
memset(&sin6, 0, sin6len);
|
||||||
|
|
||||||
|
sin6.sin6_port = htons(atoi(argv[1]));
|
||||||
|
sin6.sin6_family = AF_INET6;
|
||||||
|
sin6.sin6_addr = in6addr_any;
|
||||||
|
|
||||||
|
n = bind(sock, (struct sockaddr *)&sin6, sin6len);
|
||||||
|
if(-1 == n)
|
||||||
|
perror("bind"), exit(1);
|
||||||
|
|
||||||
|
//n = getsockname(sock, (struct sockaddr *)&sin6, &sin6len);
|
||||||
|
//printf("%d\n", ntohs(sin6.sin6_port));
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
sleep(1);
|
||||||
|
n = recvfrom(sock, buffer, MAXBUF, 0, (struct sockaddr *)&sin6, &sin6len);
|
||||||
|
printf("n = %d, buffer : %s\n", n, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdown(sock, 2);
|
||||||
|
close(sock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
64
test/unit/client.cpp
Normal file
64
test/unit/client.cpp
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// Comprehensive stress test for socket-like API
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* Test Functions */
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
int test_for_correctness()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipv4_udp_client()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipv6_udp_client()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipv4_tcp_client()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipv6_tcp_client()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* main */
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int test_all = 1;
|
||||||
|
|
||||||
|
if(test_all)
|
||||||
|
{
|
||||||
|
printf("Testing API calls for correctness\n");
|
||||||
|
test_for_correctness();
|
||||||
|
|
||||||
|
printf("Testing as IPv4 UDP Client\n");
|
||||||
|
ipv4_udp_client();
|
||||||
|
|
||||||
|
printf("Testing as IPv6 UDP Client\n");
|
||||||
|
ipv6_udp_client();
|
||||||
|
|
||||||
|
printf("Testing as IPv4 TCP Client\n");
|
||||||
|
ipv4_udp_client();
|
||||||
|
|
||||||
|
printf("Testing as IPv6 TCP Client\n");
|
||||||
|
ipv6_udp_client();
|
||||||
|
|
||||||
|
printf("Testing \n");
|
||||||
|
printf("\n");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
char *nwid = "e5cd7a9e1c0fd272";
|
char *nwid = (char *)"e5cd7a9e1c0fd272";
|
||||||
|
|
||||||
// Get ZeroTier core version
|
// Get ZeroTier core version
|
||||||
char ver[ZT_VER_STR_LEN];
|
char ver[ZT_VER_STR_LEN];
|
||||||
@@ -34,7 +34,7 @@ int main()
|
|||||||
printf("id = %s\n", id);
|
printf("id = %s\n", id);
|
||||||
|
|
||||||
// Get the home path of this ZeroTier instance, where we store identity keys, conf files, etc
|
// Get the home path of this ZeroTier instance, where we store identity keys, conf files, etc
|
||||||
char homePath[ZT_HOME_PATH_MAX_LEN];
|
char homePath[ZT_HOME_PATH_MAX_LEN+1];
|
||||||
zts_get_homepath(homePath, ZT_HOME_PATH_MAX_LEN);
|
zts_get_homepath(homePath, ZT_HOME_PATH_MAX_LEN);
|
||||||
printf("homePath = %s\n", homePath);
|
printf("homePath = %s\n", homePath);
|
||||||
|
|
||||||
@@ -67,6 +67,8 @@ int main()
|
|||||||
printf("sockfd = %d\n", sockfd);
|
printf("sockfd = %d\n", sockfd);
|
||||||
|
|
||||||
// connect() IPv6
|
// connect() IPv6
|
||||||
|
if(false)
|
||||||
|
{
|
||||||
struct hostent *server = gethostbyname2("fde5:cd7a:9e1c:fd2:7299:932e:e35a:9a03",AF_INET6);
|
struct hostent *server = gethostbyname2("fde5:cd7a:9e1c:fd2:7299:932e:e35a:9a03",AF_INET6);
|
||||||
struct sockaddr_in6 serv_addr;
|
struct sockaddr_in6 serv_addr;
|
||||||
memset((char *) &serv_addr, 0, sizeof(serv_addr));
|
memset((char *) &serv_addr, 0, sizeof(serv_addr));
|
||||||
@@ -74,21 +76,45 @@ int main()
|
|||||||
serv_addr.sin6_family = AF_INET6;
|
serv_addr.sin6_family = AF_INET6;
|
||||||
memmove((char *) &serv_addr.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length);
|
memmove((char *) &serv_addr.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length);
|
||||||
serv_addr.sin6_port = htons( port );
|
serv_addr.sin6_port = htons( port );
|
||||||
|
if((err = zts_connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) < 0) {
|
||||||
if((err = zts_connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) < 0)
|
|
||||||
printf("error connecting to remote host (%d)\n", err);
|
printf("error connecting to remote host (%d)\n", err);
|
||||||
else
|
return -1;
|
||||||
printf("connected\n");
|
}
|
||||||
|
}
|
||||||
// connect() IPv4
|
// connect() IPv4
|
||||||
addr.sin_addr.s_addr = inet_addr("10.9.9.4");
|
if(true)
|
||||||
|
{
|
||||||
|
addr.sin_addr.s_addr = inet_addr("10.9.9.20");
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons( port );
|
addr.sin_port = htons( port );
|
||||||
|
if((err = zts_connect(sockfd, (const struct sockaddr *)&addr, sizeof(addr))) < 0) {
|
||||||
if((err = zts_connect(sockfd, (const struct sockaddr *)&addr, sizeof(addr))) < 0)
|
|
||||||
printf("error connecting to remote host (%d)\n", err);
|
printf("error connecting to remote host (%d)\n", err);
|
||||||
else
|
return -1;
|
||||||
printf("connected\n");
|
}
|
||||||
|
}
|
||||||
|
// bind() ipv4
|
||||||
|
if(false)
|
||||||
|
{
|
||||||
|
//addr.sin_addr.s_addr = INADDR_ANY; // TODO: Requires significant socket multiplexer work
|
||||||
|
addr.sin_addr.s_addr = inet_addr("10.9.9.40");
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons( port );
|
||||||
|
if((err = zts_bind(sockfd, (const struct sockaddr *)&addr, sizeof(addr))) < 0) {
|
||||||
|
printf("error binding to interface (%d)\n", err);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
zts_listen(sockfd, 1);
|
||||||
|
struct sockaddr_in client;
|
||||||
|
int c = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
int accept_fd = zts_accept(sockfd, (struct sockaddr *)&client, (socklen_t*)&c);
|
||||||
|
|
||||||
|
printf("reading from buffer\n");
|
||||||
|
char newbuf[32];
|
||||||
|
memset(newbuf, 0, 32);
|
||||||
|
read(accept_fd, newbuf, 20);
|
||||||
|
printf("newbuf = %s\n", newbuf);
|
||||||
|
}
|
||||||
|
|
||||||
// End Socket API calls
|
// End Socket API calls
|
||||||
|
|
||||||
@@ -103,6 +129,13 @@ int main()
|
|||||||
|
|
||||||
printf("peer_count = %lu\n", zts_get_peer_count());
|
printf("peer_count = %lu\n", zts_get_peer_count());
|
||||||
|
|
||||||
|
/*
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Reference in New Issue
Block a user