From 3052f55d1253b894f90b0f4e4e3a844b785690dc Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Fri, 7 Apr 2017 17:56:05 -0700 Subject: [PATCH] Added SocketTap multiplexing logic --- include/ZeroTierSDK.h | 455 ++++++++++++++++++++++++-------- make-mac.mk | 8 +- src/RPC.c | 8 +- src/RingBuffer.cpp | 0 src/RingBuffer.hpp | 0 src/SDKService.cpp | 524 +++++++++++++++++++++++-------------- src/Socket.c | 143 ++++------ src/SocketTap.cpp | 107 ++++---- src/SocketTap.hpp | 89 +++++-- src/picoTCP.cpp | 145 ++-------- tests/socket/simple.cpp | 137 +++++++++- zto/service/OneService.cpp | 25 ++ zto/service/OneService.hpp | 15 +- 13 files changed, 1049 insertions(+), 607 deletions(-) create mode 100644 src/RingBuffer.cpp create mode 100644 src/RingBuffer.hpp diff --git a/include/ZeroTierSDK.h b/include/ZeroTierSDK.h index a8deaaa..d9f8eaf 100644 --- a/include/ZeroTierSDK.h +++ b/include/ZeroTierSDK.h @@ -29,9 +29,9 @@ /* Defines */ /****************************************************************************/ -#define SDK_MTU 1200 //ZT_MAX_MTU // 2800, usually +#define SDK_MTU 1200 // FIXME: ZT_MAX_MTU, usually #define UNIX_SOCK_BUF_SIZE 1024*1024 -#define ZT_PHY_POLL_INTERVAL 50 // in ms +#define ZT_PHY_POLL_INTERVAL 50 // in ms // picoTCP #define MAX_PICO_FRAME_RX_BUF_SZ ZT_MAX_MTU * 128 // TCP @@ -45,35 +45,46 @@ #define DEFAULT_UDP_TX_BUF_SZ ZT_MAX_MTU #define DEFAULT_UDP_RX_BUF_SZ ZT_MAX_MTU * 10 +#define ZT_SDK_RPC_DIR_PREFIX "rpc.d" + +#define ZT_SDK_VERSION_MAJOR 1 +#define ZT_SDK_VERSION_MINOR 0 +#define ZT_SDK_VERSION_REVISION 0 + +#define ZT_MAX_IPADDR_LEN 64 +#define ZT_ID_LEN 10 +#define ZT_VER_STR_LEN 6 +#define ZT_HOME_PATH_MAX_LEN 128 /****************************************************************************/ /* Socket API Signatures */ /****************************************************************************/ -#define SETSOCKOPT_SIG int fd, int level, int optname, const void *optval, socklen_t optlen -#define GETSOCKOPT_SIG int fd, int level, int optname, void *optval, socklen_t *optlen -#define SENDMSG_SIG int fd, const struct msghdr *msg, int flags -#define SENDTO_SIG int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen -#define RECV_SIG int fd, void *buf, size_t len, int flags -#define RECVFROM_SIG int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen -#define RECVMSG_SIG int fd, struct msghdr *msg,int flags -#define SEND_SIG int fd, const void *buf, size_t len, int flags -#define WRITE_SIG int fd, const void *buf, size_t len -#define READ_SIG int fd, void *buf, size_t len -#define SOCKET_SIG int socket_family, int socket_type, int protocol -#define CONNECT_SIG int fd, const struct sockaddr *addr, socklen_t addrlen -#define BIND_SIG int fd, const struct sockaddr *addr, socklen_t addrlen -#define LISTEN_SIG int fd, int backlog -#define ACCEPT4_SIG int fd, struct sockaddr *addr, socklen_t *addrlen, int flags -#define ACCEPT_SIG int fd, struct sockaddr *addr, socklen_t *addrlen -#define CLOSE_SIG int fd -#define GETSOCKNAME_SIG int fd, struct sockaddr *addr, socklen_t *addrlen -#define GETPEERNAME_SIG int fd, struct sockaddr *addr, socklen_t *addrlen -#define FCNTL_SIG int fd, int cmd, int flags -#define SYSCALL_SIG long number, ... +#define ZT_SETSOCKOPT_SIG int fd, int level, int optname, const void *optval, socklen_t optlen +#define ZT_GETSOCKOPT_SIG int fd, int level, int optname, void *optval, socklen_t *optlen +#define ZT_SENDMSG_SIG int fd, const struct msghdr *msg, int flags +#define ZT_SENDTO_SIG int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen +#define ZT_RECV_SIG int fd, void *buf, size_t len, int flags +#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_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_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_BIND_SIG int fd, const struct sockaddr *addr, socklen_t addrlen +#define ZT_LISTEN_SIG int fd, int backlog +#define ZT_ACCEPT4_SIG int fd, struct sockaddr *addr, socklen_t *addrlen, int flags +#define ZT_ACCEPT_SIG int fd, struct sockaddr *addr, socklen_t *addrlen +#define ZT_CLOSE_SIG int fd +#define ZT_GETSOCKNAME_SIG int fd, struct sockaddr *addr, socklen_t *addrlen +#define ZT_GETPEERNAME_SIG int fd, struct sockaddr *addr, socklen_t *addrlen +#define ZT_FCNTL_SIG int fd, int cmd, int flags +#define ZT_SYSCALL_SIG long number, ... /****************************************************************************/ -/* SDK Socket API */ +/* SDK Socket API (ZeroTier Service Controls) */ +/* Implemented in SDKService.cpp */ /****************************************************************************/ #ifdef __cplusplus @@ -85,47 +96,255 @@ extern "C" { */ void zts_start(const char *path); - -void *zts_start_core_service(void *thread_id); - -char *zts_core_version(); -void zts_stop_service(); +/** + * Stops the core ZeroTier service + */ void zts_stop(); -int zts_service_is_running(); + +/** + * Join a network + */ void zts_join_network(const char * nwid); + +/** + * Join a network - Just create the dir and conf file required, don't instruct the core to do anything + */ void zts_join_network_soft(const char * filepath, const char * nwid); -void zts_leave_network_soft(const char * filepath, const char * nwid); + +/** + * Leave a network + */ void zts_leave_network(const char * nwid); -void zts_get_ipv4_address(const char *nwid, char *addrstr); -void zts_get_ipv6_address(const char *nwid, char *addrstr); -int zts_has_address(const char *nwid); + +/** + * Leave a network - Only delete the .conf file, this will prevent the service from joining upon next startup + */ +void zts_leave_network_soft(const char * filepath, const char * nwid); + +/** + * Return the home path for this instance of ZeroTier + * FIXME: double check this is correct on all platforms + */ +void zts_get_homepath(char *homePath, const int len); + +/** + * Provides core ZeroTier service version + */ +void zts_core_version(char *ver); + +/** + * Provides core SDK service version + */ +void zts_sdk_version(char *ver); + +/** + * Get device ID + * 10-digit hex + NULL byte + */ int zts_get_device_id(char *devID); -int zts_get_device_id_from_file(const char *filepath, char *devID); -int zts_get_peer_address(char *peer, const char *devID); -unsigned long zts_get_peer_count(); -//int zts_get_peer_list(); -char *zts_get_homepath(); + +/** + * Check whether the service is running + */ +int zts_service_running(); + +/** + * Returns whether any IPv6 address has been assigned to the SockTap for this network + * - This is used as an indicator of readiness for service for the ZeroTier core and stack + */ +int zts_has_ipv4_address(const char *nwid); + +/** + * Returns whether any IPv4 address has been assigned to the SockTap for this network + * - This is used as an indicator of readiness for service for the ZeroTier core and stack + */ +int zts_has_ipv6_address(const char *nwid); + +/** + * Returns whether any address has been assigned to the SockTap for this network + * - This is used as an indicator of readiness for service for the ZeroTier core and stack + */ +int zts_has_address(const char *nwid); + +/** + * Get IPV4 Address for this device on a given network + * FIXME: Only returns first address found for given protocol and network (should be enough for now) + */ +void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen); + +/** + * Get IPV6 Address for this device on a given network + * FIXME: Only returns first address found for given protocol and network (should be enough for now) + */ +void zts_get_ipv6_address(const char *nwid, char *addrstr, const int addrlen); + +/** + * Returns a 6PLANE IPv6 address given a network ID and zerotier ID + */ void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID); + +/** + * Returns an RFC 4193 IPv6 address given a network ID and zerotier ID + */ void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID); -// BSD-like socket API -int zts_socket(SOCKET_SIG); -int zts_connect(CONNECT_SIG); -int zts_bind(BIND_SIG); + +/** + * Return the number of peers on this network + */ +unsigned long zts_get_peer_count(); + +/** + * Get the IP address of a peer if a direct path is available + */ +int zts_get_peer_address(char *peer, const char *devID); + +/** + * Enable HTTP control plane (traditionally used by zerotier-cli) + * - Allows one to control the ZeroTier core via HTTP requests + * FIXME: Implement + */ +void zts_enable_http_control_plane(); + +/** + * Disable HTTP control plane (traditionally used by zerotier-cli) + * - Allows one to control the ZeroTier core via HTTP requests + * FIXME: Implement + */ +void zts_disable_http_control_plane(); + +/****************************************************************************/ +/* SDK Socket API (Socket User Controls) */ +/* - These functions are designed to work just like regular socket calls */ +/* but are provisioned and handled by ZeroTier */ +/* Implemented in Socket.c */ +/****************************************************************************/ + +/** + * Creates a socket + */ +int zts_socket(ZT_SOCKET_SIG); + + /** + * Connect a socket to a remote host + */ +int zts_connect(ZT_CONNECT_SIG); + +/** + * Bind a socket to a local address + */ +int zts_bind(ZT_BIND_SIG); + +/** + * Accept a connection + */ #if defined(__linux__) - int zts_accept4(ACCEPT4_SIG); + int zts_accept4(ZT_ACCEPT4_SIG); #endif -int zts_accept(ACCEPT_SIG); -int zts_listen(LISTEN_SIG); -int zts_setsockopt(SETSOCKOPT_SIG); -int zts_getsockopt(GETSOCKOPT_SIG); -int zts_getsockname(GETSOCKNAME_SIG); -int zts_getpeername(GETPEERNAME_SIG); -int zts_close(CLOSE_SIG); -int zts_fcntl(FCNTL_SIG); -ssize_t zts_sendto(SENDTO_SIG); -ssize_t zts_sendmsg(SENDMSG_SIG); -ssize_t zts_recvfrom(RECVFROM_SIG); -ssize_t zts_recvmsg(RECVMSG_SIG); + +/** + * Accept a connection + */ +int zts_accept(ZT_ACCEPT_SIG); + +/** + * Listen for incoming connections + */ +int zts_listen(ZT_LISTEN_SIG); + +/** + * Set socket options + */ +int zts_setsockopt(ZT_SETSOCKOPT_SIG); + +/** + * Get socket options + */ +int zts_getsockopt(ZT_GETSOCKOPT_SIG); + +/** + * Get socket name + */ +int zts_getsockname(ZT_GETSOCKNAME_SIG); + +/** + * Get a peer name + */ +int zts_getpeername(ZT_GETPEERNAME_SIG); + +/** + * Close a socket + */ +int zts_close(ZT_CLOSE_SIG); + +/** + * Issue file control commands on a socket + */ +int zts_fcntl(ZT_FCNTL_SIG); + +/** + * Send data to a remote host + */ +ssize_t zts_sendto(ZT_SENDTO_SIG); + +/** + * Send a message to a remote host + */ +ssize_t zts_sendmsg(ZT_SENDMSG_SIG); + +/** + * Receive data from a remote host + */ +ssize_t zts_recvfrom(ZT_RECVFROM_SIG); + +/** + * Receive a message from a remote host + */ +ssize_t zts_recvmsg(ZT_RECVMSG_SIG); + +/****************************************************************************/ +/* SocketTap Multiplexer Functionality --- 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 +{ + class picoTCP; + struct Connection; + 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()' + */ +void *_start_service(void *thread_id); /****************************************************************************/ /* Debug */ @@ -135,56 +354,55 @@ ssize_t zts_recvmsg(RECVMSG_SIG); #include #include -#define DEBUG_LEVEL 5 // Set this to adjust what you'd like to see in the debug traces +#define ZT_DEBUG_LEVEL 5 // Set this to adjust what you'd like to see in the debug traces -#define MSG_ERROR 1 // Errors -#define MSG_TRANSFER 2 // RX/TX specific statements -#define MSG_INFO 3 // Information which is generally useful to any developer -#define MSG_EXTRA 4 // If nothing in your world makes sense -#define MSG_FLOW 5 // High-level flow messages +#define ZT_MSG_ERROR 1 // Errors +#define ZT_MSG_TRANSFER 2 // RX/TX specific statements +#define ZT_MSG_INFO 3 // Information which is generally useful to any developer +#define ZT_MSG_EXTRA 4 // If nothing in your world makes sense +#define ZT_MSG_FLOW 5 // High-level flow messages +#define ZT_FILENAMES true +#define ZT_COLOR true -#define __SHOW_FILENAMES__ true -#define __SHOW_COLOR__ true - -// Colors +// Debug output colors #if defined(__APPLE__) #include "TargetConditionals.h" #endif -#if defined(__SHOW_COLOR__) && !defined(__ANDROID__) && !defined(TARGET_OS_IPHONE) && !defined(TARGET_IPHONE_SIMULATOR) && !defined(__APP_FRAMEWORK__) - #define RED "\x1B[31m" - #define GRN "\x1B[32m" - #define YEL "\x1B[33m" - #define BLU "\x1B[34m" - #define MAG "\x1B[35m" - #define CYN "\x1B[36m" - #define WHT "\x1B[37m" - #define RESET "\x1B[0m" +#if defined(ZT_COLOR) && !defined(__ANDROID__) && !defined(TARGET_OS_IPHONE) && !defined(TARGET_IPHONE_SIMULATOR) && !defined(__APP_FRAMEWORK__) + #define ZT_RED "\x1B[31m" + #define ZT_GRN "\x1B[32m" + #define ZT_YEL "\x1B[33m" + #define ZT_BLU "\x1B[34m" + #define ZT_MAG "\x1B[35m" + #define ZT_CYN "\x1B[36m" + #define ZT_WHT "\x1B[37m" + #define ZT_RESET "\x1B[0m" #else - #define RED - #define GRN - #define YEL - #define BLU - #define MAG - #define CYN - #define WHT - #define RESET + #define ZT_RED + #define ZT_GRN + #define ZT_YEL + #define ZT_BLU + #define ZT_MAG + #define ZT_CYN + #define ZT_WHT + #define ZT_RESET #endif // filenames -#if __SHOW_FILENAMES__ - #if __SHOW_FULL_FILENAME_PATH__ - #define __FILENAME__ __FILE__ // show the entire mess +#if ZT_FILENAMES + #if ZT_FULL_FILENAME_PATH + #define ZT_FILENAME __FILE__ // show the entire mess #else - #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) // shorten + #define ZT_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) // short #endif #else - #define __FILENAME__ // omit filename + #define ZT_FILENAME // omit filename #endif #ifdef __linux__ - #define THREAD_ID 0 /*(long)getpid()*/ + #define ZT_THREAD_ID 0 // (long)getpid() #elif __APPLE__ - #define THREAD_ID 0 /*(long)syscall(SYS_thread_selfid)*/ + #define ZT_THREAD_ID 0 // (long)syscall(SYS_thread_selfid) #endif #if defined(__JNI_LIB__) @@ -192,26 +410,35 @@ ssize_t zts_recvmsg(RECVMSG_SIG); #endif #if defined(__ANDROID__) #include - #define LOG_TAG "ZTSDK" + #define ZT_LOG_TAG "ZTSDK" #endif - #if DEBUG_LEVEL >= MSG_ERROR - #define DEBUG_ERROR(fmt, args...) fprintf(stderr, RED "ZT_ERROR[%ld] : %14s:%4d:%25s: " fmt "\n" RESET, THREAD_ID, __FILENAME__, __LINE__, __FUNCTION__, ##args) + #if ZT_DEBUG_LEVEL >= ZT_MSG_ERROR + #define DEBUG_ERROR(fmt, args...) fprintf(stderr, ZT_RED "ZT_ERROR[%ld] : %14s:%4d:%25s: " fmt \ + "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #else #define DEBUG_ERROR(fmt, args...) #endif - #if DEBUG_LEVEL >= MSG_INFO + #if ZT_DEBUG_LEVEL >= ZT_MSG_INFO #if defined(__ANDROID__) - #define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "ZT_INFO : %14s:%4d:%20s: " fmt "\n", __FILENAME__, __LINE__, __FUNCTION__, ##args)) - #define DEBUG_BLANK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "ZT_INFO : %14s:%4d:" fmt "\n", __FILENAME__, __LINE__, __FUNCTION__, ##args)) - #define DEBUG_ATTN(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "ZT_INFO : %14s:%4d:%25s: " fmt "\n", __FILENAME__, __LINE__, __FUNCTION__, ##args)) - #define DEBUG_STACK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "ZT_STACK: %14s:%4d:%25s: " fmt "\n", __FILENAME__, __LINE__, __FUNCTION__, ##args)) + #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)) + #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)) + #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)) + #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)) #else - #define DEBUG_INFO(fmt, args...) fprintf(stderr, "ZT_INFO [%ld] : %14s:%4d:%25s: " fmt "\n", THREAD_ID, __FILENAME__, __LINE__, __FUNCTION__, ##args) - #define DEBUG_ATTN(fmt, args...) fprintf(stderr, CYN "ZT_ATTN [%ld] : %14s:%4d:%25s: " fmt "\n" RESET, THREAD_ID, __FILENAME__, __LINE__, __FUNCTION__, ##args) - #define DEBUG_STACK(fmt, args...) fprintf(stderr, YEL "ZT_STACK[%ld] : %14s:%4d:%25s: " fmt "\n" RESET, THREAD_ID, __FILENAME__, __LINE__, __FUNCTION__, ##args) - #define DEBUG_BLANK(fmt, args...) fprintf(stderr, "ZT_INFO [%ld] : %14s:%4d:" fmt "\n", THREAD_ID, __FILENAME__, __LINE__, ##args) + #define DEBUG_INFO(fmt, args...) fprintf(stderr, \ + "ZT_INFO [%ld] : %14s:%4d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) + #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) + #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) + #define DEBUG_BLANK(fmt, args...) fprintf(stderr, \ + "ZT_INFO [%ld] : %14s:%4d:" fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, ##args) #endif #else #define DEBUG_INFO(fmt, args...) @@ -220,31 +447,37 @@ ssize_t zts_recvmsg(RECVMSG_SIG); #define DEBUG_STACK(fmt, args...) #endif - #if DEBUG_LEVEL >= MSG_TRANSFER + #if ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER #if defined(__ANDROID__) - #define DEBUG_TRANS(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "ZT_TRANS : %14s:%4d:%25s: " fmt "\n", __FILENAME__, __LINE__, __FUNCTION__, ##args)) + #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)) #else - #define DEBUG_TRANS(fmt, args...) fprintf(stderr, GRN "ZT_TRANS[%ld] : %14s:%4d:%25s: " fmt "\n" RESET, THREAD_ID, __FILENAME__, __LINE__, __FUNCTION__, ##args) + #define DEBUG_TRANS(fmt, args...) fprintf(stderr, ZT_GRN "ZT_TRANS[%ld] : %14s:%4d:%25s: " fmt \ + "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #endif #else #define DEBUG_TRANS(fmt, args...) #endif - #if DEBUG_LEVEL >= MSG_EXTRA + #if ZT_DEBUG_LEVEL >= ZT_MSG_EXTRA #if defined(__ANDROID__) - #define DEBUG_EXTRA(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "ZT_EXTRA : %14s:%4d:%25s: " fmt "\n", __FILENAME__, __LINE__, __FUNCTION__, ##args)) + #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)) #else - #define DEBUG_EXTRA(fmt, args...) fprintf(stderr, "ZT_EXTRA[%ld] : %14s:%4d:%25s: " fmt "\n", THREAD_ID, __FILENAME__, __LINE__, __FUNCTION__, ##args) + #define DEBUG_EXTRA(fmt, args...) fprintf(stderr, \ + "ZT_EXTRA[%ld] : %14s:%4d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #endif #else #define DEBUG_EXTRA(fmt, args...) #endif -#if DEBUG_LEVEL >= MSG_FLOW +#if ZT_DEBUG_LEVEL >= ZT_MSG_FLOW #if defined(__ANDROID__) - #define DEBUG_FLOW(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "ZT_FLOW : %14s:%4d:%25s: " fmt "\n", __FILENAME__, __LINE__, __FUNCTION__, ##args)) + #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)) #else - #define DEBUG_FLOW(fmt, args...) fprintf(stderr, "ZT_FLOW [%ld] : %14s:%4d:%25s: " fmt "\n", THREAD_ID, __FILENAME__, __LINE__, __FUNCTION__, ##args) + #define DEBUG_FLOW(fmt, args...) fprintf(stderr, "ZT_FLOW [%ld] : %14s:%4d:%25s: " fmt "\n", \ + ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #endif #else #define DEBUG_FLOW(fmt, args...) diff --git a/make-mac.mk b/make-mac.mk index 915d54d..5fed7a9 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -132,7 +132,7 @@ picotcp: ############################################################################## static_lib: picotcp $(ZTO_OBJS) - $(CXX) $(CXXFLAGS) $(SDK_FLAGS) $(RPC_FILES) $(TAP_FILES) $(STACK_DRIVER_FILES) $(SOCKET_API_FILES) -c + $(CXX) $(CXXFLAGS) $(SDK_FLAGS) $(RPC_FILES) $(TAP_FILES) $(STACK_DRIVER_FILES) $(SOCKET_API_FILES) -c -DSDK_STATIC libtool -static -o $(STATIC_LIB) $(ZTO_OBJS) $(SDK_OBJS) $(PICO_LIB) jni_static_lib: picotcp $(ZTO_OBJS) @@ -161,8 +161,4 @@ check: -./check.sh $(ONE_SERVICE) -./check.sh $(SDK_SERVICE) -./check.sh $(STATIC_LIB) - - -#osx_static_lib: pico $(ZTO_OBJS) -# $(CXX) $(CXXFLAGS) $(STACK_FLAGS) $(DEFS) $(INCLUDES) $(ZTFLAGS) -DSDK_SERVICE -DSDK -DSDK_BUNDLED $(PICO_DRIVER_FILES) $(SDK_INTERCEPT_C_FILES) $(SDK_SERVICE_CPP_FILES) src/service.cpp -c -# libtool -static -o build/libzt.a picotcp.o proxy.o tap.o one.o OneService.o service.o sockets.o rpc.o intercept.o $(ZTO_OBJS) \ No newline at end of file + \ No newline at end of file diff --git a/src/RPC.c b/src/RPC.c index e1064f3..ad101c4 100644 --- a/src/RPC.c +++ b/src/RPC.c @@ -42,13 +42,14 @@ #include #include #include +#include #include "ZeroTierSDK.h" #include "RPC.h" // externs common between SDK_Intercept and SDK_Socket from SDK.h -int (*realsocket)(SOCKET_SIG); -int (*realconnect)(CONNECT_SIG); +int (*realsocket)(ZT_SOCKET_SIG); +int (*realconnect)(ZT_CONNECT_SIG); #ifdef __cplusplus extern "C" { @@ -117,7 +118,8 @@ int load_symbols_rpc() int rpc_join(char * sockname) { if(sockname == NULL) { - DEBUG_ERROR("warning, rpc netpath is NULL"); + DEBUG_ERROR("warning, rpc netpath is NULL. Exiting."); + exit(0); } if(!load_symbols_rpc()) return -1; diff --git a/src/RingBuffer.cpp b/src/RingBuffer.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/RingBuffer.hpp b/src/RingBuffer.hpp new file mode 100644 index 0000000..e69de29 diff --git a/src/SDKService.cpp b/src/SDKService.cpp index 2ac4572..c779784 100644 --- a/src/SDKService.cpp +++ b/src/SDKService.cpp @@ -25,10 +25,6 @@ * LLC. Start here: http://www.zerotier.com/ */ -#if defined(__ANDROID__) || defined(__JNI_LIB__) - #include -#endif - #include #include #include @@ -57,58 +53,52 @@ extern "C" { static ZeroTier::OneService *zt1Service; -std::string service_path; std::string localHomeDir; // Local shortened path -std::string givenHomeDir; // What the user/application provides as a suggestion std::string homeDir; // The resultant platform-specific dir we *must* use internally std::string netDir; // Where network .conf files are to be written /****************************************************************************/ -/* SDK Socket API */ +/* SDK Socket API - Language Bindings are written in terms of these */ /****************************************************************************/ void zts_start(const char *path) { + if(zt1Service) + return; + if(ZeroTier::picostack) + return; + + ZeroTier::picostack = new ZeroTier::picoTCP(); + pico_stack_init(); + DEBUG_INFO("path=%s", path); if(path) homeDir = path; - zts_start_core_service(NULL); + pthread_t service_thread; + pthread_create(&service_thread, NULL, _start_service, (void *)(path)); } -// Stop the service, proxy server, stack, etc void zts_stop() { - DEBUG_INFO(); - zts_stop_service(); + if(zt1Service) { + zt1Service->terminate(); + zt1Service->removeNets(); + } } -char *zts_core_version() { - return (char*)"1.2.2"; -} - - // ------------------------------------------------------------------------------ - // --------------------------------- Base zts_* API ----------------------------- - // ------------------------------------------------------------------------------ - -// Prototypes -void *zts_start_core_service(void *thread_id); -void zts_init_rpc(const char * path, const char * nwid); - -// Basic ZT service controls void zts_join_network(const char * nwid) { - DEBUG_ERROR(); - std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf"; - if(!ZeroTier::OSUtils::mkdir(netDir)) { - DEBUG_ERROR("unable to create: %s", netDir.c_str()); + if(zt1Service) { + std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf"; + if(!ZeroTier::OSUtils::mkdir(netDir)) + DEBUG_ERROR("unable to create: %s", netDir.c_str()); + if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), "")) + DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); + zt1Service->join(nwid); + // Provide the API with the RPC information + // zts_init_rpc(homeDir.c_str(), nwid); } - if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), "")) { - DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); - } - zt1Service->join(nwid); - // Provide the API with the RPC information - zts_init_rpc(homeDir.c_str(), nwid); } -// Just create the dir and conf file required, don't instruct the core to do anything + void zts_join_network_soft(const char * filepath, const char * nwid) { std::string net_dir = std::string(filepath) + "/networks.d/"; std::string confFile = net_dir + std::string(nwid) + ".conf"; @@ -121,105 +111,142 @@ void zts_join_network_soft(const char * filepath, const char * nwid) { } } } -// Prevent service from joining network upon startup -void zts_leave_network_soft(const char * filepath, const char * nwid) { - std::string net_dir = std::string(filepath) + "/networks.d/"; - ZeroTier::OSUtils::rm((net_dir + nwid + ".conf").c_str()); -} -// Instruct the service to leave the network + void zts_leave_network(const char * nwid) { if(zt1Service) zt1Service->leave(nwid); } -// Check whether the service is running -int zts_service_is_running() { - return !zt1Service ? false : zt1Service->isRunning(); -} -// Stop the service -void zts_stop_service() { - if(zt1Service) - zt1Service->terminate(); + +void zts_leave_network_soft(const char * filepath, const char * nwid) { + std::string net_dir = std::string(filepath) + "/networks.d/"; + ZeroTier::OSUtils::rm((net_dir + nwid + ".conf").c_str()); } +void zts_get_homepath(char *homePath, int len) { + if(homeDir.length()) + memcpy(homePath, homeDir.c_str(), len < homeDir.length() ? len : homeDir.length()); +} -// FIXME: Re-implemented to make it play nicer with the C-linkage required for Xcode integrations -// Now only returns first assigned address per network. Shouldn't normally be a problem. +void zts_core_version(char *ver) { + int major, minor, revision; + ZT_version(&major, &minor, &revision); + sprintf(ver, "%d.%d.%d", major, minor, revision); +} -// Get IPV4 Address for this device on given network -int zts_has_address(const char *nwid) -{ - char ipv4_addr[64], ipv6_addr[64]; - memset(ipv4_addr, 0, 64); - memset(ipv6_addr, 0, 64); - zts_get_ipv4_address(nwid, ipv4_addr); - zts_get_ipv6_address(nwid, ipv6_addr); - if(!strcmp(ipv4_addr, "-1.-1.-1.-1/-1") && !strcmp(ipv4_addr, "-1.-1.-1.-1/-1")) { - return false; - } - return true; +void zts_sdk_version(char *ver) { + sprintf(ver, "%d.%d.%d", ZT_SDK_VERSION_MAJOR, ZT_SDK_VERSION_MINOR, ZT_SDK_VERSION_REVISION); } -void zts_get_ipv4_address(const char *nwid, char *addrstr) -{ - uint64_t nwid_int = strtoull(nwid, NULL, 16); - ZeroTier::SocketTap *tap = zt1Service->getTap(nwid_int); - if(tap && tap->_ips.size()){ - for(int i=0; i_ips.size(); i++) { - if(tap->_ips[i].isV4()) { - std::string addr = tap->_ips[i].toString(); - // DEBUG_EXTRA("addr=%s, addrlen=%d", addr.c_str(), addr.length()); - memcpy(addrstr, addr.c_str(), addr.length()); // first address found that matches protocol version 4 - return; - } - } - } - else { - memcpy(addrstr, "-1.-1.-1.-1/-1", 14); - } -} -// Get IPV6 Address for this device on given network -void zts_get_ipv6_address(const char *nwid, char *addrstr) -{ - uint64_t nwid_int = strtoull(nwid, NULL, 16); - ZeroTier::SocketTap *tap = zt1Service->getTap(nwid_int); - if(tap && tap->_ips.size()){ - for(int i=0; i_ips.size(); i++) { - if(tap->_ips[i].isV6()) { - std::string addr = tap->_ips[i].toString(); - // DEBUG_EXTRA("addr=%s, addrlen=%d", addr.c_str(), addr.length()); - memcpy(addrstr, addr.c_str(), addr.length()); // first address found that matches protocol version 4 - return; - } - } - } - else { - memcpy(addrstr, "-1.-1.-1.-1/-1", 14); - } -} -// Get device ID (from running service) + int zts_get_device_id(char *devID) { if(zt1Service) { - char id[10]; + char id[ZT_ID_LEN+1]; sprintf(id, "%lx",zt1Service->getNode()->address()); - memcpy(devID, id, 10); + memcpy(devID, id, ZT_ID_LEN+1); return 0; } - else - return -1; -} -// Get device ID (from file) -int zts_get_device_id_from_file(const char *filepath, char *devID) { - std::string fname("identity.public"); - std::string fpath(filepath); + else // Service isn't online, try to read ID from file + { + std::string fname("identity.public"); + std::string fpath(homeDir); - if(ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) { - std::string oldid; - ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid); - memcpy(devID, oldid.c_str(), 10); // first 10 bytes of file - return 0; + if(ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) { + std::string oldid; + ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid); + memcpy(devID, oldid.c_str(), ZT_ID_LEN); // first 10 bytes of file + return 0; + } } return -1; } -// Get the IP address of a peer if a direct path is available + +int zts_service_running() { + return !zt1Service ? false : zt1Service->isRunning(); +} + +int zts_has_ipv4_address(const char *nwid) +{ + char ipv4_addr[ZT_MAX_IPADDR_LEN]; + memset(ipv4_addr, 0, ZT_MAX_IPADDR_LEN); + zts_get_ipv4_address(nwid, ipv4_addr, ZT_MAX_IPADDR_LEN); + return strcmp(ipv4_addr, "\0"); +} + +int zts_has_ipv6_address(const char *nwid) +{ + char ipv6_addr[ZT_MAX_IPADDR_LEN]; + memset(ipv6_addr, 0, ZT_MAX_IPADDR_LEN); + zts_get_ipv6_address(nwid, ipv6_addr, ZT_MAX_IPADDR_LEN); + return strcmp(ipv6_addr, "\0"); +} + +int zts_has_address(const char *nwid) +{ + return zts_has_ipv4_address(nwid) || zts_has_ipv6_address(nwid); +} + +void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen) +{ + if(zt1Service) { + uint64_t nwid_int = strtoull(nwid, NULL, 16); + ZeroTier::SocketTap *tap = zt1Service->getTap(nwid_int); + if(tap && tap->_ips.size()){ + for(int i=0; i_ips.size(); i++) { + if(tap->_ips[i].isV4()) { + std::string addr = tap->_ips[i].toString(); + int len = addrlen < addr.length() ? addrlen : addr.length(); + memset(addrstr, 0, len); + memcpy(addrstr, addr.c_str(), len); + return; + } + } + } + } + else + memcpy(addrstr, "\0", 1); +} + +void zts_get_ipv6_address(const char *nwid, char *addrstr, const int addrlen) +{ + if(zt1Service) { + uint64_t nwid_int = strtoull(nwid, NULL, 16); + ZeroTier::SocketTap *tap = zt1Service->getTap(nwid_int); + if(tap && tap->_ips.size()){ + for(int i=0; i_ips.size(); i++) { + if(tap->_ips[i].isV6()) { + std::string addr = tap->_ips[i].toString(); + int len = addrlen < addr.length() ? addrlen : addr.length(); + memset(addrstr, 0, len); + memcpy(addrstr, addr.c_str(), len); + return; + } + } + } + } + else + memcpy(addrstr, "\0", 1); +} + +void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID) +{ + ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv66plane( + ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); + memcpy(addr, _6planeAddr.toIpString().c_str(), 40); +} + +void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID) +{ + ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv6rfc4193( + ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); + memcpy(addr, _6planeAddr.toIpString().c_str(), 40); +} + +unsigned long zts_get_peer_count() { + if(zt1Service) + return zt1Service->getNode()->peers()->peerCount; + else + return 0; +} + int zts_get_peer_address(char *peer, const char *devID) { if(zt1Service) { ZT_PeerList *pl = zt1Service->getNode()->peers(); @@ -233,49 +260,168 @@ int zts_get_peer_address(char *peer, const char *devID) { else return -1; } -// Return the number of peers on this network -unsigned long zts_get_peer_count() { - if(zt1Service) - return zt1Service->getNode()->peers()->peerCount; - else - return 0; -} -// Return the home path for this instance of ZeroTier -char *zts_get_homepath() { - return (char*)givenHomeDir.c_str(); -} -// Returns a 6PLANE IPv6 address given a network ID and zerotier ID -void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID) + +void zts_enable_http_control_plane() { - ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv66plane(ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); - memcpy(addr, _6planeAddr.toIpString().c_str(), 40); -} -// Returns a RFC 4193 IPv6 address given a network ID and zerotier ID -void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID) -{ - ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv6rfc4193(ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); - memcpy(addr, _6planeAddr.toIpString().c_str(), 40); + } - // ------------------------------------------------------------------------------ - // ------------------------------ EXPORTED JNI METHODS -------------------------- - // ------------------------------------------------------------------------------ - // JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME +void zts_disable_http_control_plane() +{ +} + +/****************************************************************************/ +/* SocketTap Multiplexer Functionality --- 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 +{ + picoTCP *picostack = NULL; + std::map UnassignedConnections; +} + +ZeroTier::Mutex _multiplexer_lock; + +int zts_multiplex_new_socket(ZT_SOCKET_SIG) +{ + DEBUG_INFO(); + _multiplexer_lock.lock(); + ZeroTier::Connection *conn = new ZeroTier::Connection(); + int err; + // set up pico_socket + struct pico_socket * psock; + int pico_protocol, protocol_version; + #if defined(SDK_IPV4) + protocol_version = PICO_PROTO_IPV4; + #elif defined(SDK_IPV6) + protocol_version = PICO_PROTO_IPV6; + #endif + if(socket_type == SOCK_DGRAM) { + pico_protocol = PICO_PROTO_UDP; + psock = pico_socket_open(protocol_version, pico_protocol, &ZeroTier::picoTCP::pico_cb_socket_activity); + } + if(socket_type == SOCK_STREAM) { + pico_protocol = PICO_PROTO_TCP; + psock = pico_socket_open(protocol_version, pico_protocol, &ZeroTier::picoTCP::pico_cb_socket_activity); + } + // set up Unix Domain socket (used for data later on) + 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_type = socket_type; + conn->data_sock = unix_data_sock; + conn->picosock = psock; + memset(conn->rxbuf, 0, DEFAULT_UDP_RX_BUF_SZ); + ZeroTier::UnassignedConnections[unix_data_sock] = conn; + err = unix_data_sock; + } + } + else { + DEBUG_ERROR("failed to create pico_socket"); + err = -1; + } + _multiplexer_lock.unlock(); + return err; +} + +int zts_multiplex_new_connect(ZT_CONNECT_SIG) +{ + DEBUG_INFO(); + if(!zt1Service) { + // errno = ? + return -1; + } + + _multiplexer_lock.lock(); + int err; + ZeroTier::Connection *conn = ZeroTier::UnassignedConnections[fd]; + + if(conn != NULL) { + char ipstr[INET6_ADDRSTRLEN];//, nm_str[INET6_ADDRSTRLEN]; + memset(ipstr, 0, INET6_ADDRSTRLEN); + ZeroTier::InetAddress iaddr; + + 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()); + + ZeroTier::SocketTap *tap = zt1Service->getTap(iaddr); + + if(!tap) { + DEBUG_ERROR("no route to host"); + // errno = ? + err = -1; + } + else { + DEBUG_INFO("found appropriate SocketTap"); + err = 0; + } + } + else { + DEBUG_ERROR("unable to locate connection"); + // errno = ? + err = -1; + } + _multiplexer_lock.unlock(); + return err; +} + +int zts_multiplex_new_bind(ZT_BIND_SIG) +{ + DEBUG_INFO(); + _multiplexer_lock.lock(); + int err; + + // ? + + _multiplexer_lock.unlock(); + return err; +} + +/****************************************************************************/ +/* SDK Socket API (Java Native Interface JNI) */ +/* JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME */ +/****************************************************************************/ #if defined(__ANDROID__) || defined(__JNI_LIB__) // Returns whether the ZeroTier service is running - JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_zt_1service_1is_1running(JNIEnv *env, jobject thisObj) { - if(zt1Service) - return zts_service_is_running(); - return false; + JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_zt_1service_1is_1running( + JNIEnv *env, jobject thisObj) + { + return zts_service_is_running(); } // Returns path for ZT config/data files - JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_zt_1get_1homepath(JNIEnv *env, jobject thisObj) { + JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_zt_1get_1homepath( + JNIEnv *env, jobject thisObj) + { return (*env).NewStringUTF(zts_get_homepath()); } // Join a network - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_zt_1join_1network(JNIEnv *env, jobject thisObj, jstring nwid) { + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_zt_1join_1network( + JNIEnv *env, jobject thisObj, jstring nwid) + { const char *nwidstr; if(nwid) { nwidstr = env->GetStringUTFChars(nwid, NULL); @@ -283,7 +429,9 @@ void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID) } } // Leave a network - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_zt_1leave_1network(JNIEnv *env, jobject thisObj, jstring nwid) { + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_zt_1leave_1network( + JNIEnv *env, jobject thisObj, jstring nwid) + { const char *nwidstr; if(nwid) { nwidstr = env->GetStringUTFChars(nwid, NULL); @@ -292,7 +440,9 @@ void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID) } // FIXME: Re-implemented to make it play nicer with the C-linkage required for Xcode integrations // Now only returns first assigned address per network. Shouldn't normally be a problem - JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_zt_1get_1ipv4_1address(JNIEnv *env, jobject thisObj, jstring nwid) { + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_zt_1get_1ipv4_1address( + JNIEnv *env, jobject thisObj, jstring nwid) + { const char *nwid_str = env->GetStringUTFChars(nwid, NULL); char address_string[32]; memset(address_string, 0, 32); @@ -304,7 +454,9 @@ void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID) return addresses; } - JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_zt_1get_1ipv6_1address(JNIEnv *env, jobject thisObj, jstring nwid) { + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_zt_1get_1ipv6_1address( + JNIEnv *env, jobject thisObj, jstring nwid) + { const char *nwid_str = env->GetStringUTFChars(nwid, NULL); char address_string[32]; memset(address_string, 0, 32); @@ -317,54 +469,25 @@ void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID) } // Returns the device is in integer form - JNIEXPORT jint Java_zerotier_ZeroTier_zt_1get_1device_1id() { + JNIEXPORT jint Java_zerotier_ZeroTier_zt_1get_1device_1id() + { return zts_get_device_id(NULL); // TODO } // Returns whether the path to an endpoint is currently relayed by a root server - JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_zt_1is_1relayed() { + JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_zt_1is_1relayed() + { return 0; // TODO // zts_is_relayed(); } #endif - - // ------------------------------------------------------------------------------ - // --------------------------- zts_start_core_service --------------------------- - // ------------------------------------------------------------------------------ - +/****************************************************************************/ +/* SDK Socket API Helper functions --- DONT CALL THESE DIRECTLY */ +/****************************************************************************/ // Starts a ZeroTier service in the background -void *zts_start_core_service(void *thread_id) { - - #if defined(SDK_BUNDLED) - if(thread_id) - homeDir = std::string((char*)thread_id); - #endif - - #if defined(__IOS__) - char current_dir[MAX_DIR_SZ]; - // Go to the app's data directory so we can shorten the sun_path we bind to - getcwd(current_dir, MAX_DIR_SZ); - std::string targetDir = homeDir; // + "/../../"; - chdir(targetDir.c_str()); - homeDir = localHomeDir; - #endif - - #if defined(__APPLE__) - #include "TargetConditionals.h" - #if TARGET_IPHONE_SIMULATOR - // homeDir = "dont/run/this/in/the/simulator/it/wont/work"; - #elif TARGET_OS_IPHONE - localHomeDir = "ZeroTier/One"; - std::string del = givenHomeDir.length() && givenHomeDir[givenHomeDir.length()-1]!='/' ? "/" : ""; - homeDir = givenHomeDir + del + localHomeDir; - #endif - #endif - - #if defined(__APPLE__) && !defined(__IOS__) - localHomeDir = homeDir; // Used for RPC and *can* differ from homeDir on some platforms - #endif +void *_start_service(void *thread_id) { DEBUG_INFO("homeDir=%s", homeDir.c_str()); // Where network .conf files will be stored @@ -373,7 +496,8 @@ void *zts_start_core_service(void *thread_id) { // Construct path for network config and supporting service files if (homeDir.length()) { - std::vector hpsp(ZeroTier::OSUtils::split(homeDir.c_str(),ZT_PATH_SEPARATOR_S,"","")); + std::vector hpsp(ZeroTier::OSUtils::split(homeDir.c_str(), + ZT_PATH_SEPARATOR_S,"","")); std::string ptmp; if (homeDir[0] == ZT_PATH_SEPARATOR) ptmp.push_back(ZT_PATH_SEPARATOR); @@ -393,18 +517,22 @@ void *zts_start_core_service(void *thread_id) { DEBUG_ERROR("homeDir is empty, could not construct path"); return NULL; } - - DEBUG_INFO("starting service..."); + // rpc dir + if(!ZeroTier::OSUtils::mkdir(homeDir + "/" + ZT_SDK_RPC_DIR_PREFIX)) { + DEBUG_ERROR("unable to create dir: " ZT_SDK_RPC_DIR_PREFIX); + return NULL; + } // Generate random port for new service instance unsigned int randp = 0; ZeroTier::Utils::getSecureRandom(&randp,sizeof(randp)); - int servicePort = 9000 + (randp % 1000); + int servicePort = 9000 + (randp % 10000); + DEBUG_ERROR("servicePort = %d", servicePort); for(;;) { zt1Service = ZeroTier::OneService::newInstance(homeDir.c_str(),servicePort); switch(zt1Service->run()) { - case ZeroTier::OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done + case ZeroTier::OneService::ONE_STILL_RUNNING: case ZeroTier::OneService::ONE_NORMAL_TERMINATION: break; case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR: @@ -414,11 +542,15 @@ void *zts_start_core_service(void *thread_id) { delete zt1Service; zt1Service = (ZeroTier::OneService *)0; std::string oldid; - ZeroTier::OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid); + ZeroTier::OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret").c_str(),oldid); if (oldid.length()) { - ZeroTier::OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid); - ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str()); - ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str()); + ZeroTier::OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret.saved_after_collision").c_str(),oldid); + ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret").c_str()); + ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + + "identity.public").c_str()); } } continue; // restart! diff --git a/src/Socket.c b/src/Socket.c index 3dec023..a18a4d6 100644 --- a/src/Socket.c +++ b/src/Socket.c @@ -21,21 +21,15 @@ #include #include #include - -// For defining the Android direct-call API -#if defined(__ANDROID__) || defined(__JNI_LIB__) - #include -#endif +#include #ifdef __cplusplus extern "C" { #endif - #if defined(__linux__) #define SOCK_MAX (SOCK_PACKET + 1) #endif -#define SOCK_TYPE_MASK 0xf #include "ZeroTierSDK.h" #include "RPC.h" @@ -46,104 +40,73 @@ 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 +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) - 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); } + // 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 } - void get_api_netpath() { zts_init_rpc("",""); } + // 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 socket_family, int socket_type, int protocol - -#if defined(SDK_LANG_JAVA) - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_zt_1socket(JNIEnv *env, jobject thisObj, jint family, jint type, jint protocol) { - return zts_socket(family, type, protocol); - } -#endif - -#ifdef DYNAMIC_LIB - int zt_socket(SOCKET_SIG) -#else - int zts_socket(SOCKET_SIG) -#endif + int zts_socket(ZT_SOCKET_SIG) { - get_api_netpath(); - DEBUG_INFO(""); - // Check that type makes sense -#if defined(__linux__) && !defined(__ANDROID__) - int flags = socket_type & ~SOCK_TYPE_MASK; - if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) { - errno = EINVAL; - return -1; - } + DEBUG_INFO(""); +#ifdef SDK_STATIC + return zts_multiplex_new_socket(socket_family, socket_type, protocol); #endif - socket_type &= SOCK_TYPE_MASK; - // Check protocol is in range -#if defined(__linux__) - if (socket_family < 0 || socket_family >= NPROTO){ - errno = EAFNOSUPPORT; - return -1; - } - if (socket_type < 0 || socket_type >= SOCK_MAX) { - errno = EINVAL; - return -1; - } -#endif - // Assemble and send RPC - struct socket_st rpc_st; - rpc_st.socket_family = socket_family; - rpc_st.socket_type = socket_type; - rpc_st.protocol = protocol; - // -1 is passed since we we're generating the new socket in this call - return rpc_send_command(api_netpath, RPC_SOCKET, -1, &rpc_st, sizeof(struct socket_st)); } - + int zts_connect(ZT_CONNECT_SIG) + { + DEBUG_INFO(""); +#ifdef SDK_STATIC + return zts_multiplex_new_connect(fd, addr, addrlen); +#endif + } diff --git a/src/SocketTap.cpp b/src/SocketTap.cpp index e2bb69b..3c363f9 100644 --- a/src/SocketTap.cpp +++ b/src/SocketTap.cpp @@ -45,13 +45,14 @@ #include "Constants.hpp" #include "Phy.hpp" - namespace ZeroTier { // Ignore these -void SocketTap::phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *local_address, const struct sockaddr *from,void *data,unsigned long len) {} +void SocketTap::phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *local_address, + const struct sockaddr *from,void *data,unsigned long len) {} void SocketTap::phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) {} -void SocketTap::phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) {} +void SocketTap::phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN, + const struct sockaddr *from) {} void SocketTap::phyOnTcpClose(PhySocket *sock,void **uptr) {} void SocketTap::phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) {} void SocketTap::phyOnTcpWritable(PhySocket *sock,void **uptr, bool stack_invoked) {} @@ -90,7 +91,8 @@ SocketTap::SocketTap( unsigned int metric, uint64_t nwid, const char *friendlyName, - void (*handler)(void *,void*,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void (*handler)(void *,void*,uint64_t,const MAC &,const MAC &, + unsigned int,unsigned int,const void *,unsigned int), void *arg) : _homePath(homePath), _mac(mac), @@ -103,28 +105,34 @@ SocketTap::SocketTap( _enabled(true), _run(true) { - char sockPath[4096]; - Utils::snprintf(sockPath,sizeof(sockPath),"%s%snc_%.16llx",homePath,ZT_PATH_SEPARATOR_S,_nwid,ZT_PATH_SEPARATOR_S,(unsigned long long)nwid); - _dev = sockPath; // in SDK mode, set device to be just the network ID - - _unixListenSocket = _phy.unixListen(sockPath,(void *)this); - chmod(sockPath, 0777); // To make the RPC socket available to all users - if (!_unixListenSocket) - DEBUG_ERROR("unable to bind to: path=%s", sockPath); - else - DEBUG_INFO("tap initialized on: path=%s", sockPath); - - picostack = new picoTCP(); - pico_stack_init(); - _thread = Thread::start(this); + char sockPath[4096]; + 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); + _dev = sockPath; + _unixListenSocket = _phy.unixListen(sockPath,(void *)this); + chmod(sockPath, 0777); // make the RPC socket available to all users + if (!_unixListenSocket) + DEBUG_ERROR("unable to bind to: rpc = %s", sockPath); + else + 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); } SocketTap::~SocketTap() { _run = false; _phy.whack(); - _phy.whack(); // FIXME: Remove? Thread::join(_thread); _phy.close(_unixListenSocket,false); } @@ -141,9 +149,9 @@ bool SocketTap::enabled() const bool SocketTap::addIp(const InetAddress &ip) { - // Initialize network stack's interface, assign addresses picotap = this; picostack->pico_init_interface(this, ip); + _ips.push_back(ip); return true; } @@ -155,7 +163,7 @@ bool SocketTap::removeIp(const InetAddress &ip) return false; _ips.erase(i); if (ip.isV4()) { - // TODO: De-register from network stacks + // FIXME: De-register from network stacks } return true; } @@ -166,18 +174,11 @@ std::vector SocketTap::ips() const return _ips; } -// Receive data from ZT tap service (virtual wire) and present it to network stack -// ----------------------------------------- -// | TAP <-> MEM BUFFER <-> STACK <-> APP | -// | |--------------->| | RX -// | APP <-> I/O BUFFER <-> STACK <-> TAP | -// | | -// ----------------------------------------- -void SocketTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) +void SocketTap::put(const MAC &from,const MAC &to,unsigned int etherType, + const void *data,unsigned int len) { - // DEBUG_EXTRA("RX packet: len=%d, etherType=%d", len, etherType); // RX packet - picostack->pico_rx(this, from,to,etherType,data,len); + picostack->pico_rx(this, from,to,etherType,data,len); } @@ -187,9 +188,11 @@ std::string SocketTap::deviceName() const } void SocketTap::setFriendlyName(const char *friendlyName) { + DEBUG_INFO(); } -void SocketTap::scanMulticastGroups(std::vector &added,std::vector &removed) +void SocketTap::scanMulticastGroups(std::vector &added, + std::vector &removed) { std::vector newGroups; Mutex::Lock _l(_multicastGroups_m); @@ -215,9 +218,7 @@ void SocketTap::scanMulticastGroups(std::vector &added,std::vect void SocketTap::threadMain() throw() { - // Enter main thread loop for network stack - picostack->pico_loop(this); - + picostack->pico_loop(this); } Connection *SocketTap::getConnection(PhySocket *sock) @@ -266,16 +267,9 @@ void SocketTap::closeConnection(PhySocket *sock) void SocketTap::phyOnUnixClose(PhySocket *sock,void **uptr) { //Mutex::Lock _l(_tcpconns_m); //closeConnection(sock); + // FIXME: } - -// Receive data from ZT tap service and present it to network stack -// ----------------------------------------- -// | TAP <-> MEM BUFFER <-> STACK <-> APP | -// | |--------------->| | RX -// | APP <-> I/O BUFFER <-> STACK <-> TAP | -// | | -// ----------------------------------------- void SocketTap::handleRead(PhySocket *sock,void **uptr,bool stack_invoked) { picostack->pico_handleRead(sock, uptr, stack_invoked); @@ -367,13 +361,15 @@ void SocketTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t 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) { + 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)) { + 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; @@ -441,7 +437,8 @@ void SocketTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t ----------------------------- RPC Handler functions ---------------------------- ------------------------------------------------------------------------------*/ -void SocketTap::handleGetsockname(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct getsockname_st *getsockname_rpc) +void SocketTap::handleGetsockname(PhySocket *sock, PhySocket *rpcSock, + void **uptr, struct getsockname_st *getsockname_rpc) { Mutex::Lock _l(_tcpconns_m); Connection *conn = getConnection(sock); @@ -455,7 +452,8 @@ void SocketTap::handleGetsockname(PhySocket *sock, PhySocket *rpcSock, void **up write(_phy.getDescriptor(rpcSock), conn->local_addr, sizeof(struct sockaddr_storage)); } -void SocketTap::handleGetpeername(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct getsockname_st *getsockname_rpc) +void SocketTap::handleGetpeername(PhySocket *sock, PhySocket *rpcSock, + void **uptr, struct getsockname_st *getsockname_rpc) { Mutex::Lock _l(_tcpconns_m); Connection *conn = getConnection(sock); @@ -469,24 +467,24 @@ void SocketTap::handleGetpeername(PhySocket *sock, PhySocket *rpcSock, void **up write(_phy.getDescriptor(rpcSock), conn->peer_addr, sizeof(struct sockaddr_storage)); } -Connection * SocketTap::handleSocket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc) +Connection * SocketTap::handleSocket(PhySocket *sock, void **uptr, + struct socket_st* socket_rpc) { return picostack->pico_handleSocket(sock, uptr, socket_rpc); } - -// Connect a stack's PCB/socket/Connection object to a remote host -void SocketTap::handleConnect(PhySocket *sock, PhySocket *rpcSock, Connection *conn, struct connect_st* connect_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) +void SocketTap::handleBind(PhySocket *sock, PhySocket *rpcSock, void **uptr, + struct bind_st *bind_rpc) { Mutex::Lock _l(_tcpconns_m); if(!_ips.size()) { - // We haven't been given an address yet. Binding at this stage is premature DEBUG_ERROR("cannot bind yet. ZT address hasn't been provided"); sendReturnValue(_phy.getDescriptor(rpcSock), -1, ENOMEM); return; @@ -494,7 +492,8 @@ void SocketTap::handleBind(PhySocket *sock, PhySocket *rpcSock, void **uptr, str picostack->pico_handleBind(sock,rpcSock,uptr,bind_rpc); } -void SocketTap::handleListen(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct listen_st *listen_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); diff --git a/src/SocketTap.hpp b/src/SocketTap.hpp index 5326a04..904867f 100644 --- a/src/SocketTap.hpp +++ b/src/SocketTap.hpp @@ -74,12 +74,12 @@ namespace ZeroTier { extern SocketTap *picotap; /* - * TCP connection + * Connection object */ struct Connection { bool listening, probation, disabled; - int pid, txsz, rxsz, type; + int pid, txsz, rxsz; PhySocket *rpcSock, *sock; struct tcp_pcb *TCP_pcb; struct udp_pcb *UDP_pcb; @@ -88,12 +88,14 @@ namespace ZeroTier { unsigned short port; unsigned char txbuf[DEFAULT_TCP_TX_BUF_SZ]; unsigned char rxbuf[DEFAULT_TCP_RX_BUF_SZ]; - // pico struct pico_socket *picosock; + + int data_sock; + int socket_family, socket_type; }; /* - * A helper for passing a reference to _phy to LWIP callbacks as a "state" + * A helper for passing a reference to _phy to stackrpc callbacks as a "state" */ struct Larg { @@ -103,7 +105,7 @@ namespace ZeroTier { }; /* - * Network Containers instance -- emulates an Ethernet tap device as far as OneService knows + * Socket Tap -- emulates an Ethernet tap device */ class SocketTap { @@ -124,19 +126,54 @@ namespace ZeroTier { void setEnabled(bool en); bool enabled() const; + + /* + * + */ bool addIp(const InetAddress &ip); + + /* + * + */ bool removeIp(const InetAddress &ip); std::vector ips() const; std::vector _ips; + + /* + * + */ + void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data, + unsigned int len); - void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + /* + * + */ std::string deviceName() const; + + /* + * + */ void setFriendlyName(const char *friendlyName); + + /* + * + */ void scanMulticastGroups(std::vector &added,std::vector &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); - + + /* + * + */ + void unloadRPC(void *data, pid_t &pid, pid_t &tid, char (timestamp[RPC_TIMESTAMP_SZ]), + char (CANARY[sizeof(uint64_t)]), char &cmd, void* &payload); + + /* + * + */ void threadMain() throw(); @@ -144,7 +181,13 @@ namespace ZeroTier { MAC _mac; unsigned int _mtu; uint64_t _nwid; - void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); + + /* + * + */ + void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int, + const void *,unsigned int); + void *_arg; Phy _phy; PhySocket *_unixListenSocket; @@ -157,11 +200,11 @@ namespace ZeroTier { 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); + 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, struct connect_st* connect_rpc); - - // void handleIsConnected(); + void handleConnect(PhySocket *sock, PhySocket *rpcsock, Connection *conn, + struct connect_st* connect_rpc); /* * Return the address that the socket is bound to @@ -179,13 +222,18 @@ namespace ZeroTier { void handleWrite(Connection *conn); // Unused -- no UDP or TCP from this thread/Phy<> - void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *local_address, const struct sockaddr *from,void *data,unsigned long len); + void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *local_address, + const struct sockaddr *from,void *data,unsigned long len); void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success); - void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from); + void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN, + const struct sockaddr *from); void phyOnTcpClose(PhySocket *sock,void **uptr); void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len); void phyOnTcpWritable(PhySocket *sock,void **uptr, bool stack_invoked); + /* + * + */ void handleRead(PhySocket *sock,void **uptr,bool stack_invoked); /* @@ -214,16 +262,11 @@ namespace ZeroTier { Connection *getConnection(struct pico_socket *socket); /* - * Closes a TcpConnection, associated LWIP PCB strcuture, + * Closes a TcpConnection, associated connection strcuture, * PhySocket, and underlying file descriptor */ void closeConnection(PhySocket *sock); - - - picoTCP *picostack; - - std::vector _Connections; std::map > jobmap; @@ -236,9 +279,7 @@ namespace ZeroTier { Mutex _multicastGroups_m; Mutex _ips_m, _tcpconns_m, _rx_buf_m, _close_m; - }; - } // namespace ZeroTier #endif diff --git a/src/picoTCP.cpp b/src/picoTCP.cpp index 6687c3c..47a4962 100644 --- a/src/picoTCP.cpp +++ b/src/picoTCP.cpp @@ -25,8 +25,6 @@ * LLC. Start here: http://www.zerotier.com/ */ - - #include "pico_eth.h" #include "pico_stack.h" #include "pico_ipv4.h" @@ -98,7 +96,6 @@ namespace ZeroTier { int pico_eth_send(struct pico_device *dev, void *buf, int len); int pico_eth_poll(struct pico_device *dev, int loop_score); - // Initialize network stack's interfaces and assign addresses void picoTCP::pico_init_interface(SocketTap *tap, const InetAddress &ip) { if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) { @@ -117,7 +114,7 @@ namespace ZeroTier { picodev.poll = pico_eth_poll; // rx picodev.mtu = tap->_mtu; if( 0 != pico_device_init(&(picodev), "p0", mac)) { - DEBUG_ERROR("device init failed"); + DEBUG_ERROR("dev init failed"); return; } pico_ipv4_link_add(&(picodev), ipaddr, netmask); @@ -140,10 +137,10 @@ namespace ZeroTier { tap->_mac.copyTo(mac, PICO_SIZE_ETH); DEBUG_ATTN("mac = %s", tap->_mac.toString().c_str()); if( 0 != pico_device_init(&(picodev), "p0", mac)) { - DEBUG_ERROR("device init failed"); + DEBUG_ERROR("dev init failed"); return; } - DEBUG_ATTN("device initialized as ipv6_addr = %s", ipv6_str); + DEBUG_ATTN("addr = %s", ipv6_str); } #endif } @@ -159,16 +156,6 @@ namespace ZeroTier { } } - // RX packets from [ZT->STACK] onto RXBUF - // Also notify the tap service that data can be read: - // [RXBUF -> (ZTSOCK->APP)] - // ----------------------------------------- - // | TAP <-> MEM BUFFER <-> STACK <-> APP | - // | | - // | APP <-> I/O BUFFER <-> STACK <-> TAP | - // | |<-----------------| | RX - // ----------------------------------------- - // After this step, buffer will be emptied periodically by pico_handleRead() void picoTCP::pico_cb_tcp_read(ZeroTier::SocketTap *tap, struct pico_socket *s) { Connection *conn = tap->getConnection(s); @@ -179,12 +166,11 @@ namespace ZeroTier { struct pico_ip4 ip4; struct pico_ip6 ip6; } peer; - do { int avail = DEFAULT_TCP_RX_BUF_SZ - conn->rxsz; if(avail) { - r = pico_socket_recvfrom(s, conn->rxbuf + (conn->rxsz), SDK_MTU, (void *)&peer.ip4.addr, &port); - // DEBUG_ATTN("received packet (%d byte) from %08X:%u", r, long_be2(peer.ip4.addr), short_be(port)); + r = pico_socket_recvfrom(s, conn->rxbuf + (conn->rxsz), SDK_MTU, + (void *)&peer.ip4.addr, &port); tap->_phy.setNotifyWritable(conn->sock, true); if (r > 0) conn->rxsz += r; @@ -198,19 +184,6 @@ namespace ZeroTier { DEBUG_ERROR("invalid connection"); } - // RX packets from the stack onto internal buffer - // Also notifies the tap service that data can be read - // ----------------------------------------- - // | TAP <-> MEM BUFFER <-> STACK <-> APP | - // | | - // | APP <-> I/O BUFFER <-> STACK <-> TAP | - // | |<-----------------| | RX - // ----------------------------------------- - // After this step, buffer will be emptied periodically by pico_handleRead() - // Read payload is encapsulated as such: - // - // [addr|payload_len|payload] - // void picoTCP::pico_cb_udp_read(SocketTap *tap, struct pico_socket *s) { Connection *conn = tap->getConnection(s); @@ -272,7 +245,6 @@ namespace ZeroTier { } } - // TX packets from internal buffer to network void picoTCP::pico_cb_tcp_write(SocketTap *tap, struct pico_socket *s) { Connection *conn = tap->getConnection(s); @@ -293,7 +265,7 @@ namespace ZeroTier { conn->txsz -= r; #if DEBUG_LEVEL >= MSG_TRANSFER - int max = conn->type == SOCK_STREAM ? DEFAULT_TCP_TX_BUF_SZ : DEFAULT_UDP_TX_BUF_SZ; + int max = conn->socket_type == SOCK_STREAM ? DEFAULT_TCP_TX_BUF_SZ : DEFAULT_UDP_TX_BUF_SZ; DEBUG_TRANS("[TCP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes", (float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r); #endif @@ -302,7 +274,6 @@ namespace ZeroTier { } } - // Main callback for TCP connections void picoTCP::pico_cb_socket_activity(uint16_t ev, struct pico_socket *s) { int err; @@ -311,7 +282,7 @@ namespace ZeroTier { if(!conn) { DEBUG_ERROR("invalid connection"); } - // Accept connection (analogous to lwip_nc_accept) + // accept() if (ev & PICO_SOCK_EV_CONN) { DEBUG_INFO("connection established with server, picosock=%p",(conn->picosock)); uint32_t peer; @@ -331,7 +302,7 @@ namespace ZeroTier { } Connection *newTcpConn = new Connection(); picotap->_Connections.push_back(newTcpConn); - newTcpConn->type = SOCK_STREAM; + newTcpConn->socket_type = SOCK_STREAM; newTcpConn->sock = picotap->_phy.wrapSocket(fds[0], newTcpConn); newTcpConn->picosock = client; int fd = picotap->_phy.getDescriptor(conn->sock); @@ -357,15 +328,14 @@ namespace ZeroTier { } // Read from picoTCP socket if (ev & PICO_SOCK_EV_RD) { - if(conn->type==SOCK_STREAM) + if(conn->socket_type==SOCK_STREAM) pico_cb_tcp_read(picotap, s); - if(conn->type==SOCK_DGRAM) + if(conn->socket_type==SOCK_DGRAM) pico_cb_udp_read(picotap, s); } // Write to picoTCP socket - if (ev & PICO_SOCK_EV_WR) { + if (ev & PICO_SOCK_EV_WR) pico_cb_tcp_write(picotap, s); - } } // Called when an incoming ping is received @@ -383,38 +353,22 @@ namespace ZeroTier { } } */ - - // Called from the stack, sends data to the tap device (in our case, the ZeroTier service) - // ----------------------------------------- - // | TAP <-> MEM BUFFER <-> STACK <-> APP | - // | |<-------------------------| | TX - // | APP <-> I/O BUFFER <-> STACK <-> TAP | - // | | - // ----------------------------------------- + int pico_eth_send(struct pico_device *dev, void *buf, int len) { struct pico_eth_hdr *ethhdr; ethhdr = (struct pico_eth_hdr *)buf; - MAC src_mac; MAC dest_mac; src_mac.setTo(ethhdr->saddr, 6); dest_mac.setTo(ethhdr->daddr, 6); - picotap->_handler(picotap->_arg,NULL,picotap->_nwid,src_mac,dest_mac, Utils::ntoh((uint16_t)ethhdr->proto),0, ((char*)buf) + sizeof(struct pico_eth_hdr),len - sizeof(struct pico_eth_hdr)); return len; } - // Receives data from the tap device and encapsulates it into a ZeroTier ethernet frame and places it in a locked memory buffer - // ----------------------------------------- - // | TAP <-> MEM BUFFER <-> STACK <-> APP | - // | |--------------->| | RX - // | APP <-> I/O BUFFER <-> STACK <-> TAP | - // | | - // ----------------------------------------- - // It will then periodically be transfered into the network stack via pico_eth_poll() - void picoTCP::pico_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) + void picoTCP::pico_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType, + const void *data,unsigned int len) { // 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 @@ -447,14 +401,6 @@ namespace ZeroTier { DEBUG_FLOW(" [ ZTWIRE -> FBUF ] Move FRAME(sz=%d) into FBUF(sz=%d), data_len=%d", newlen, picotap->pico_frame_rxbuf_tot, len); } - // Called periodically by the stack, this removes data from the locked memory buffer (FBUF) and feeds it into the stack. - // A maximum of 'loop_score' frames can be processed in each call - // ----------------------------------------- - // | TAP <-> MEM BUFFER <-> STACK <-> APP | - // | |----------------->| | RX - // | APP <-> I/O BUFFER <-> STACK <-> TAP | - // | | - // ----------------------------------------- int pico_eth_poll(struct pico_device *dev, int loop_score) { // OPTIMIZATION: The copy logic and/or buffer structure should be reworked for better performance after the BETA @@ -475,7 +421,7 @@ namespace ZeroTier { picotap->pico_frame_rxbuf_tot-=len; } else { - DEBUG_ERROR("Skipping frame of size (%d)",len); + DEBUG_ERROR("Invalid frame size (%d). Exiting.",len); exit(0); } loop_score--; @@ -483,8 +429,10 @@ namespace ZeroTier { return loop_score; } - // Creates a new pico_socket and Connection object to represent a new connection to be. - Connection *picoTCP::pico_handleSocket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc) + // 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; @@ -507,27 +455,8 @@ namespace ZeroTier { DEBUG_ATTN("physock=%p, picosock=%p", sock, psock); Connection * newConn = new Connection(); *uptr = newConn; - newConn->type = socket_rpc->socket_type; - newConn->sock = sock; - - /* - int res = 0; - int sendbuff = UNIX_SOCK_BUF_SIZE; - socklen_t optlen = sizeof(sendbuff); - - res = setsockopt(picotap->_phy.getDescriptor(sock), SOL_SOCKET, SO_RCVBUF, &sendbuff, sizeof(sendbuff)); - if(res == -1) - //DEBUG_ERROR("Error while setting RX buffer limits"); - res = setsockopt(picotap->_phy.getDescriptor(sock), SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)); - if(res == -1) - //DEBUG_ERROR("Error while setting TX buffer limits"); - - // Get buffer size - // optlen = sizeof(sendbuff); - // res = getsockopt(picotap->_phy.getDescriptor(sock), SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen); - // DEBUG_INFO("buflen=%d", sendbuff); - */ - + newConn->socket_type = socket_rpc->socket_type; + newConn->sock = sock; newConn->local_addr = NULL; newConn->picosock = psock; picotap->_Connections.push_back(newConn); @@ -539,13 +468,6 @@ namespace ZeroTier { return NULL; } - // Writes data from the I/O buffer to the network stack - // ----------------------------------------- - // | TAP <-> MEM BUFFER <-> STACK <-> APP | - // | | - // | APP <-> I/O BUFFER <-> STACK <-> TAP | - // | |----------------->| | TX - // ----------------------------------------- void picoTCP::pico_handleWrite(Connection *conn) { if(!conn || !conn->picosock) { @@ -586,19 +508,18 @@ namespace ZeroTier { memmove(&conn->txbuf, (conn->txbuf+r), sz); conn->txsz -= r; - if(conn->type == SOCK_STREAM) { + if(conn->socket_type == SOCK_STREAM) { max = DEFAULT_TCP_TX_BUF_SZ; DEBUG_TRANS("[TCP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes", (float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r); } - if(conn->type == SOCK_DGRAM) { + if(conn->socket_type == SOCK_DGRAM) { max = DEFAULT_UDP_TX_BUF_SZ; DEBUG_TRANS("[UDP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes", (float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r); } } - // Instructs the stack to connect to a remote host void picoTCP::pico_handleConnect(PhySocket *sock, PhySocket *rpcSock, Connection *conn, struct connect_st* connect_rpc) { if(conn->picosock) { @@ -631,12 +552,10 @@ namespace ZeroTier { DEBUG_ERROR("PICO_ERR_EINVAL"); if(ret == PICO_ERR_EHOSTUNREACH) DEBUG_ERROR("PICO_ERR_EHOSTUNREACH"); - picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), 0, ERR_OK); } } - // Instructs the stack to bind to a given address void picoTCP::pico_handleBind(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct bind_st *bind_rpc) { Connection *conn = picotap->getConnection(sock); @@ -682,7 +601,6 @@ namespace ZeroTier { picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), ERR_OK, ERR_OK); // success } - // Puts a pico_socket into a listening state to receive incoming connection requests void picoTCP::pico_handleListen(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct listen_st *listen_rpc) { Connection *conn = picotap->getConnection(sock); @@ -706,14 +624,6 @@ namespace ZeroTier { picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), ERR_OK, ERR_OK); // success } - // Feeds data into the local app socket from the I/O buffer associated with the "connection" - // [ (APP<-ZTSOCK) <- RXBUF ] - // ----------------------------------------- - // | TAP <-> MEM BUFFER <-> STACK <-> APP | - // | | - // | APP <-> I/O BUFFER <-> STACK <-> TAP | - // | |<---------------| | RX - // ----------------------------------------- void picoTCP::pico_handleRead(PhySocket *sock,void **uptr,bool lwip_invoked) { if(!lwip_invoked) { @@ -727,7 +637,7 @@ namespace ZeroTier { if(conn && conn->rxsz) { // - if(conn->type==SOCK_DGRAM) { + if(conn->socket_type==SOCK_DGRAM) { // Try to write SDK_MTU-sized chunk to app socket while(tot < SDK_MTU) { write_attempts++; @@ -757,7 +667,7 @@ namespace ZeroTier { conn->rxsz -= SDK_MTU; } // - if(conn->type==SOCK_STREAM) { + if(conn->socket_type==SOCK_STREAM) { n = picotap->_phy.streamSend(conn->sock, conn->rxbuf, conn->rxsz); if(conn->rxsz-n > 0) // If more remains on buffer memcpy(conn->rxbuf, conn->rxbuf+n, conn->rxsz - n); @@ -765,10 +675,10 @@ namespace ZeroTier { } // Notify ZT I/O loop that it has new buffer contents if(n) { - if(conn->type==SOCK_STREAM) { + if(conn->socket_type==SOCK_STREAM) { #if DEBUG_LEVEL >= MSG_TRANSFER - float max = conn->type == SOCK_STREAM ? (float)DEFAULT_TCP_RX_BUF_SZ : (float)DEFAULT_UDP_RX_BUF_SZ; + float max = conn->socket_type == SOCK_STREAM ? (float)DEFAULT_TCP_RX_BUF_SZ : (float)DEFAULT_UDP_RX_BUF_SZ; DEBUG_TRANS("[TCP RX] <--- :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes", (float)conn->txsz / max, (float)conn->rxsz / max, conn->sock, n); #endif @@ -791,7 +701,6 @@ namespace ZeroTier { DEBUG_FLOW(" [ ZTSOCK <- RXBUF] Emitted (%d) from RXBUF(%d) to socket", tot, conn->rxsz); } - // Closes a pico_socket void picoTCP::pico_handleClose(PhySocket *sock) { /* diff --git a/tests/socket/simple.cpp b/tests/socket/simple.cpp index 6821d4a..6b7b425 100644 --- a/tests/socket/simple.cpp +++ b/tests/socket/simple.cpp @@ -1,16 +1,149 @@ // Comprehensive stress test for socket-like API #include +#include +#include +#include +#include +#include + +#include +#include #include "ZeroTierSDK.h" int main() { - printf("zts_core_version = %s\n", zts_core_version()); + char *nwid = "e5cd7a9e1c0fd272"; - zts_start("./ztsdk"); // starts ZeroTier core, generates id in ./zt + // Get ZeroTier core version + char ver[ZT_VER_STR_LEN]; + zts_core_version(ver); + printf("zts_core_version = %s\n", ver); + + // Get SDK version + zts_sdk_version(ver); + printf("zts_sdk_version = %s\n", ver); + + // Spawns a couple threads to support ZeroTier core, userspace network stack, and generates ID in ./zt + zts_start("./zt"); + + // Print the device/app ID (this is also the ID you'd see in ZeroTier Central) + char id[ZT_ID_LEN + 1]; + zts_get_device_id(id); + printf("id = %s\n", id); + + // Get the home path of this ZeroTier instance, where we store identity keys, conf files, etc + char homePath[ZT_HOME_PATH_MAX_LEN]; + zts_get_homepath(homePath, ZT_HOME_PATH_MAX_LEN); + printf("homePath = %s\n", homePath); + + // Wait for ZeroTier service to start + while(!zts_service_running()) { + printf("wating for service to start\n"); + sleep(1); + } + + // Join a network + zts_join_network(nwid); + + // Wait for ZeroTier service to issue an address to the device on the given network + while(!zts_has_address("e5cd7a9e1c0fd272")) { + printf("waiting for service to issue an address\n"); + sleep(1); + } + + // Begin Socket API calls + + int err; + int sockfd; + int port = 5555; + struct sockaddr_in addr; + + // socket() + if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) + printf("error creating ZeroTier socket"); + else + printf("sockfd = %d\n", sockfd); + + // connect() IPv6 + struct hostent *server = gethostbyname2("fde5:cd7a:9e1c:fd2:7299:932e:e35a:9a03",AF_INET6); + struct sockaddr_in6 serv_addr; + 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( port ); + + if((err = zts_connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) < 0) + printf("error connecting to remote host (%d)\n", err); + else + printf("connected\n"); + + // connect() IPv4 + addr.sin_addr.s_addr = inet_addr("10.9.9.4"); + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + + if((err = zts_connect(sockfd, (const struct sockaddr *)&addr, sizeof(addr))) < 0) + printf("error connecting to remote host (%d)\n", err); + else + printf("connected\n"); + + // End Socket API calls + // Get the ipv4 address assigned for this network + char addr_str[ZT_MAX_IPADDR_LEN]; + zts_get_ipv4_address(nwid, addr_str, ZT_MAX_IPADDR_LEN); + printf("ipv4 = %s\n", addr_str); + + zts_get_ipv6_address(nwid, addr_str, ZT_MAX_IPADDR_LEN); + printf("ipv6 = %s\n", addr_str); + + printf("peer_count = %lu\n", zts_get_peer_count()); + + // --- + + /* + + "Tap Multiplexer" + - socket() [BEFORE JOIN]: take requests for new sockets + - Create them, and store them in a temporary holding space until we find out where we should assign them + + - connect(): + - Search SocketTaps for tap with a relevant route + - None? -> ENETUNREACH + - Found? + - Assign previously-held socket to this tap + - Attempt connection + + - bind(): + - bind on all Interfaces? + + + Join Semantics + - Create : SocketTap + - Create : rpc.d/nwid unix domain socket (if intercept mode?) + - Create : Stack Interface + - Provide : IPs to Interface + + + /--- int0: 10. 9.0.0 + stack ---- int1: 172.27.0.0 + \--- int2: ? + */ + + // zts_join("other_network"); // 10.9.0.0 + // zts_join("whatever"); // 172.27.0.0 + + //zts_socket(AF, STREAM, 0); + //zts_connect("10.9.9.5"); + + + // --- + + // Stop service, delete tap interfaces, and network stack zts_stop(); return 0; } \ No newline at end of file diff --git a/zto/service/OneService.cpp b/zto/service/OneService.cpp index f0de485..f28d966 100644 --- a/zto/service/OneService.cpp +++ b/zto/service/OneService.cpp @@ -998,10 +998,35 @@ public: return n->second.tap; } + virtual EthernetTap *getTap(InetAddress &addr) + { + Mutex::Lock _l(_nets_m); + std::map::iterator it; + for(it = _nets.begin(); it != _nets.end(); it++) { + if(it->second.tap) { + for(int j=0; jsecond.tap->_ips.size(); j++) { + if(it->second.tap->_ips[j].containsAddress(addr)) { + return it->second.tap; + } + } + } + } + return NULL; + } + virtual Node * getNode() { return _node; } + + virtual void removeNets() + { + Mutex::Lock _l(_nets_m); + std::map::iterator i; + for(i = _nets.begin(); i != _nets.end(); i++) { + delete i->second.tap; + } + } #endif // ZT_SDK virtual void terminate() diff --git a/zto/service/OneService.hpp b/zto/service/OneService.hpp index 21804c4..ed3008a 100644 --- a/zto/service/OneService.hpp +++ b/zto/service/OneService.hpp @@ -152,19 +152,28 @@ public: /** * Returns the homePath given by the client application - * - Used for SDK mode */ virtual std::string givenHomePath() = 0; /* - * + * Returns a SocketTap that is associated with the given nwid */ virtual EthernetTap * getTap(uint64_t nwid) = 0; /* - * + * Returns a SocketTap that cant function as a route to the specified host + */ + virtual EthernetTap * getTap(InetAddress &addr) = 0; + + /* + * Returns a pointer to the Node */ virtual Node * getNode() = 0; + + /* + * Delete all SocketTap interfaces + */ + virtual void removeNets() = 0; #endif /**