Update C API: Add functions that simplify wrapper generation
This commit is contained in:
@@ -720,11 +720,11 @@ endif()
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
if(BUILD_HOST_SELFTEST)
|
||||
add_executable(selftest ${PROJ_DIR}/test/selftest.c)
|
||||
target_link_libraries(selftest ${STATIC_LIB_NAME})
|
||||
add_executable(selftest-c-api ${PROJ_DIR}/test/selftest-c-api.c)
|
||||
target_link_libraries(selftest-c-api ${STATIC_LIB_NAME})
|
||||
project(TEST)
|
||||
enable_testing()
|
||||
add_test(NAME selftest COMMAND selftest)
|
||||
add_test(NAME selftest-c-api COMMAND selftest-c-api)
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
@@ -93,7 +93,7 @@ Important directories:
|
||||
|
||||
# Self-hosting (Optional)
|
||||
|
||||
We provide ways for your app or enterprise to function indepenently from any of our services if desired.
|
||||
We provide ways for your app or enterprise to function independently from any of our services if desired.
|
||||
|
||||
While we do operate a global network of redundant root servers, network controllers and an admin API/UI called [Central](https://my.zerotier.com), some use-cases require full control over the infrastructure and we try to make it as easy as possible to set up your own controllers and root servers: See [here](https://github.com/zerotier/ZeroTierOne/tree/master/controller) to learn more about how to set up your own network controller, and [here](https://www.zerotier.com/manual/#4_4) to learn more about setting up your own roots.
|
||||
|
||||
|
||||
94
build.sh
94
build.sh
@@ -89,8 +89,8 @@ gethosttype()
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/apple-xcframework-debug
|
||||
# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist
|
||||
# - Cache : libzt/cache/apple-xcframework-debug
|
||||
# - Build output : libzt/dist
|
||||
#
|
||||
# apple-xcframework-debug
|
||||
# └── pkg
|
||||
@@ -146,10 +146,10 @@ xcframework()
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/iphonesimulator-x64-framework-debug
|
||||
# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist
|
||||
# - Cache : libzt/cache/iphonesimulator-x64-framework-debug
|
||||
# - Build output : libzt/dist
|
||||
#
|
||||
# /Volumes/$USER/zt/libzt/libzt-dev/dist/iphonesimulator-x64-framework-debug
|
||||
# libzt/dist/iphonesimulator-x64-framework-debug
|
||||
# └── pkg
|
||||
# └── zt.framework
|
||||
# ├── Headers
|
||||
@@ -195,10 +195,10 @@ iphonesimulator-framework()
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/macos-x64-framework-debug
|
||||
# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist
|
||||
# - Cache : libzt/cache/macos-x64-framework-debug
|
||||
# - Build output : libzt/dist
|
||||
#
|
||||
# /Volumes/$USER/zt/libzt/libzt-dev/dist/macos-x64-framework-debug
|
||||
# libzt/dist/macos-x64-framework-debug
|
||||
# └── pkg
|
||||
# └── zt.framework
|
||||
# ├── Headers
|
||||
@@ -241,10 +241,10 @@ macos-framework()
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/iphoneos-arm64-framework-debug
|
||||
# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist
|
||||
# - Cache : libzt/cache/iphoneos-arm64-framework-debug
|
||||
# - Build output : libzt/dist
|
||||
#
|
||||
# /Volumes/$USER/zt/libzt/libzt-dev/dist/iphoneos-arm64-framework-debug
|
||||
# libzt/dist/iphoneos-arm64-framework-debug
|
||||
# └── pkg
|
||||
# └── zt.framework
|
||||
# ├── Headers
|
||||
@@ -291,8 +291,8 @@ iphoneos-framework()
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/linux-x64-host-release
|
||||
# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist
|
||||
# - Cache : libzt/cache/linux-x64-host-release
|
||||
# - Build output : libzt/dist
|
||||
#
|
||||
# linux-x64-host-release
|
||||
# ├── bin
|
||||
@@ -307,6 +307,11 @@ host()
|
||||
ARTIFACT="host"
|
||||
# Default to release
|
||||
BUILD_TYPE=${1:-release}
|
||||
if [[ $1 = *"docs"* ]]; then
|
||||
# Generate documentation
|
||||
cd docs/c && doxygen
|
||||
exit 0
|
||||
fi
|
||||
# -DZTS_ENABLE_CENTRAL_API=0
|
||||
VARIANT="-DBUILD_HOST=True"
|
||||
CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE
|
||||
@@ -336,6 +341,29 @@ host-uninstall()
|
||||
cd -
|
||||
}
|
||||
|
||||
# Build C extension module (*.so), python module, package both into wheel
|
||||
#
|
||||
# ./build.sh host-python-wheel "release"
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# libzt/dist/macos-x64-python-debug
|
||||
# └── pkg
|
||||
# └── libzt-1.3.4b1-cp39-cp39-macosx_11_0_x86_64.whl
|
||||
#
|
||||
host-python-wheel()
|
||||
{
|
||||
ARTIFACT="python"
|
||||
# Default to release
|
||||
BUILD_TYPE=${1:-release}
|
||||
CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE
|
||||
TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE
|
||||
PKG_OUTPUT_DIR=$TARGET_BUILD_DIR/pkg
|
||||
mkdir -p $PKG_OUTPUT_DIR
|
||||
# Requires setuptools, etc
|
||||
cd pkg/pypi && ./build.sh wheel && cp -f dist/*.whl $PKG_OUTPUT_DIR
|
||||
}
|
||||
|
||||
# Build shared library with python wrapper symbols exported
|
||||
host-python()
|
||||
{
|
||||
@@ -345,9 +373,8 @@ host-python()
|
||||
VARIANT="-DZTS_ENABLE_PYTHON=True"
|
||||
CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE
|
||||
TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE
|
||||
rm -rf $TARGET_BUILD_DIR
|
||||
LIB_OUTPUT_DIR=$TARGET_BUILD_DIR/lib
|
||||
BIN_OUTPUT_DIR=$TARGET_BUILD_DIR/bin
|
||||
rm -rf $LIB_OUTPUT_DIR
|
||||
mkdir -p $LIB_OUTPUT_DIR
|
||||
# Optional step to generate new SWIG wrapper
|
||||
swig -c++ -python -o src/bindings/python/zt_wrap.cpp -Iinclude src/bindings/python/zt.i
|
||||
@@ -384,6 +411,11 @@ host-jar()
|
||||
ARTIFACT="jar"
|
||||
# Default to release
|
||||
BUILD_TYPE=${1:-release}
|
||||
if [[ $1 = *"docs"* ]]; then
|
||||
# Generate documentation
|
||||
javadoc src/bindings/java/*.java -d docs/java
|
||||
exit 0
|
||||
fi
|
||||
VARIANT="-DZTS_ENABLE_JAVA=True"
|
||||
CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE
|
||||
TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE
|
||||
@@ -402,7 +434,7 @@ host-jar()
|
||||
cp -f $CACHE_DIR/lib/libzt.* $JAVA_JAR_DIR
|
||||
cd $JAVA_JAR_DIR
|
||||
export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8
|
||||
javac com/zerotier/libzt/*.java
|
||||
javac -Xlint:deprecation com/zerotier/libzt/*.java
|
||||
jar cf libzt-"$(git describe --abbrev=0)".jar $SHARED_LIB_NAME com/zerotier/libzt/*.class
|
||||
rm -rf com $SHARED_LIB_NAME
|
||||
cd -
|
||||
@@ -441,8 +473,8 @@ fi
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/android-any-android-release
|
||||
# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist
|
||||
# - Cache : libzt/cache/android-any-android-release
|
||||
# - Build output : libzt/dist
|
||||
#
|
||||
# android-any-android-release
|
||||
# └── libzt-release.aar
|
||||
@@ -496,10 +528,34 @@ test()
|
||||
$TREE $TARGET_BUILD_DIR
|
||||
# Test
|
||||
cd $CACHE_DIR
|
||||
ctest -C release
|
||||
#ctest -C release
|
||||
cd -
|
||||
}
|
||||
|
||||
# Test C API
|
||||
test-c()
|
||||
{
|
||||
if [[ -z "${alice_path}" ]]; then
|
||||
echo "Please set necessary environment variables for test"
|
||||
exit 0
|
||||
fi
|
||||
ARTIFACT="test"
|
||||
# Default to debug so asserts aren't optimized out
|
||||
BUILD_TYPE=${1:-debug}
|
||||
TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE
|
||||
BIN_OUTPUT_DIR=$TARGET_BUILD_DIR/bin
|
||||
rm -rf $TARGET_BUILD_DIR
|
||||
# Build selftest
|
||||
test $1
|
||||
# Ports can be anything we want since they aren't system ports
|
||||
port4=8080
|
||||
port6=8081
|
||||
# Start Alice as server
|
||||
"$BIN_OUTPUT_DIR/selftest-c-api" $alice_path $testnet $port4 $port6 &
|
||||
# Start Bob as client
|
||||
"$BIN_OUTPUT_DIR/selftest-c-api" $bob_path $testnet $port4 $alice_ip4 $port6 $alice_ip6 &
|
||||
}
|
||||
|
||||
# Recursive deep clean
|
||||
clean()
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -70,6 +70,7 @@ namespace ZeroTier
|
||||
jobject objRef = NULL;
|
||||
jmethodID _userCallbackMethodRef = NULL;
|
||||
#endif
|
||||
extern uint8_t _serviceStateFlags;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -421,6 +422,9 @@ JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_restart(
|
||||
|
||||
int zts_free()
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (_getState(ZTS_STATE_FREE_CALLED)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
|
||||
427
src/Sockets.cpp
427
src/Sockets.cpp
@@ -59,12 +59,33 @@ int zts_connect(int fd, const struct zts_sockaddr *addr, zts_socklen_t addrlen)
|
||||
if (!addr) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
if (addrlen > (int)sizeof(struct zts_sockaddr_storage) || addrlen < (int)sizeof(struct zts_sockaddr_in)) {
|
||||
if (addrlen > (int)sizeof(struct zts_sockaddr_storage)
|
||||
|| addrlen < (int)sizeof(struct zts_sockaddr_in)) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return lwip_connect(fd, (sockaddr*)addr, addrlen);
|
||||
}
|
||||
|
||||
int zts_connect_easy(int fd, int family, char *ipstr, int port) {
|
||||
if (family == ZTS_AF_INET) {
|
||||
struct zts_sockaddr_in in4;
|
||||
zts_socklen_t addrlen = sizeof(in4);
|
||||
ipstr2sockaddr(
|
||||
family, ipstr, port, (struct zts_sockaddr *)&in4, &addrlen);
|
||||
struct zts_sockaddr *sa = (struct zts_sockaddr *)&in4;
|
||||
return zts_connect(fd, sa, addrlen);
|
||||
}
|
||||
if (family == ZTS_AF_INET6) {
|
||||
struct zts_sockaddr_in6 in6;
|
||||
zts_socklen_t addrlen = sizeof(in6);
|
||||
ipstr2sockaddr(
|
||||
family, ipstr, port, (struct zts_sockaddr *)&in6, &addrlen);
|
||||
struct zts_sockaddr *sa = (struct zts_sockaddr *)&in6;
|
||||
return zts_connect(fd, sa, addrlen);
|
||||
}
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
|
||||
int zts_bind(int fd, const struct zts_sockaddr *addr, zts_socklen_t addrlen)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
@@ -73,12 +94,33 @@ int zts_bind(int fd, const struct zts_sockaddr *addr, zts_socklen_t addrlen)
|
||||
if (!addr) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
if (addrlen > (int)sizeof(struct zts_sockaddr_storage) || addrlen < (int)sizeof(struct zts_sockaddr_in)) {
|
||||
if (addrlen > (int)sizeof(struct zts_sockaddr_storage)
|
||||
|| addrlen < (int)sizeof(struct zts_sockaddr_in)) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return lwip_bind(fd, (sockaddr*)addr, addrlen);
|
||||
}
|
||||
|
||||
int zts_bind_easy(int fd, int family, char *ipstr, int port) {
|
||||
if (family == ZTS_AF_INET) {
|
||||
struct zts_sockaddr_in in4;
|
||||
zts_socklen_t addrlen = sizeof(in4);
|
||||
ipstr2sockaddr(
|
||||
family, ipstr, port, (struct zts_sockaddr *)&in4, &addrlen);
|
||||
struct zts_sockaddr *sa = (struct zts_sockaddr *)&in4;
|
||||
return zts_bind(fd, sa, addrlen);
|
||||
}
|
||||
if (family == ZTS_AF_INET6) {
|
||||
struct zts_sockaddr_in6 in6;
|
||||
zts_socklen_t addrlen = sizeof(in6);
|
||||
ipstr2sockaddr(
|
||||
family, ipstr, port, (struct zts_sockaddr *)&in6, &addrlen);
|
||||
struct zts_sockaddr *sa = (struct zts_sockaddr *)&in6;
|
||||
return zts_bind(fd, sa, addrlen);
|
||||
}
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
|
||||
int zts_listen(int fd, int backlog)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
@@ -95,7 +137,8 @@ int zts_accept(int fd, struct zts_sockaddr *addr, zts_socklen_t *addrlen)
|
||||
return lwip_accept(fd, (sockaddr*)addr, (socklen_t*)addrlen);
|
||||
}
|
||||
|
||||
int zts_setsockopt(int fd, int level, int optname, const void *optval,zts_socklen_t optlen)
|
||||
int zts_setsockopt(
|
||||
int fd, int level, int optname, const void *optval,zts_socklen_t optlen)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
@@ -103,7 +146,8 @@ int zts_setsockopt(int fd, int level, int optname, const void *optval,zts_sockle
|
||||
return lwip_setsockopt(fd, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int zts_getsockopt(int fd, int level, int optname, void *optval, zts_socklen_t *optlen)
|
||||
int zts_getsockopt(
|
||||
int fd, int level, int optname, void *optval, zts_socklen_t *optlen)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
@@ -119,7 +163,8 @@ int zts_getsockname(int fd, struct zts_sockaddr *addr, zts_socklen_t *addrlen)
|
||||
if (!addr) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
if (*addrlen > (int)sizeof(struct zts_sockaddr_storage) || *addrlen < (int)sizeof(struct zts_sockaddr_in)) {
|
||||
if (*addrlen > (int)sizeof(struct zts_sockaddr_storage)
|
||||
|| *addrlen < (int)sizeof(struct zts_sockaddr_in)) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return lwip_getsockname(fd, (sockaddr*)addr, (socklen_t*)addrlen);
|
||||
@@ -133,7 +178,8 @@ int zts_getpeername(int fd, struct zts_sockaddr *addr, zts_socklen_t *addrlen)
|
||||
if (!addr) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
if (*addrlen > (int)sizeof(struct zts_sockaddr_storage) || *addrlen < (int)sizeof(struct zts_sockaddr_in)) {
|
||||
if (*addrlen > (int)sizeof(struct zts_sockaddr_storage)
|
||||
|| *addrlen < (int)sizeof(struct zts_sockaddr_in)) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return lwip_getpeername(fd, (sockaddr*)addr, (socklen_t*)addrlen);
|
||||
@@ -147,13 +193,15 @@ int zts_close(int fd)
|
||||
return lwip_close(fd);
|
||||
}
|
||||
|
||||
int zts_select(int nfds, zts_fd_set *readfds, zts_fd_set *writefds, zts_fd_set *exceptfds,
|
||||
int zts_select(
|
||||
int nfds, zts_fd_set *readfds, zts_fd_set *writefds, zts_fd_set *exceptfds,
|
||||
struct zts_timeval *timeout)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
return lwip_select(nfds, (fd_set*)readfds, (fd_set*)writefds, (fd_set*)exceptfds, (timeval*)timeout);
|
||||
return lwip_select(
|
||||
nfds, (fd_set*)readfds, (fd_set*)writefds, (fd_set*)exceptfds, (timeval*)timeout);
|
||||
}
|
||||
|
||||
int zts_fcntl(int fd, int cmd, int flags)
|
||||
@@ -203,7 +251,8 @@ ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags,
|
||||
if (!addr || !buf) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
if (addrlen > (int)sizeof(struct zts_sockaddr_storage) || addrlen < (int)sizeof(struct zts_sockaddr_in)) {
|
||||
if (addrlen > (int)sizeof(struct zts_sockaddr_storage)
|
||||
|| addrlen < (int)sizeof(struct zts_sockaddr_in)) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return lwip_sendto(fd, buf, len, flags, (sockaddr*)addr, addrlen);
|
||||
@@ -214,6 +263,7 @@ ssize_t zts_sendmsg(int fd, const struct zts_msghdr *msg, int flags)
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
|
||||
return lwip_sendmsg(fd, (const struct msghdr *)msg, flags);
|
||||
}
|
||||
|
||||
@@ -237,7 +287,8 @@ ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags,
|
||||
if (!buf) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return lwip_recvfrom(fd, buf, len, flags, (sockaddr*)addr, (socklen_t*)addrlen);
|
||||
return lwip_recvfrom(
|
||||
fd, buf, len, flags, (sockaddr*)addr, (socklen_t*)addrlen);
|
||||
}
|
||||
|
||||
ssize_t zts_recvmsg(int fd, struct zts_msghdr *msg, int flags)
|
||||
@@ -262,12 +313,13 @@ ssize_t zts_read(int fd, void *buf, size_t len)
|
||||
return lwip_read(fd, buf, len);
|
||||
}
|
||||
|
||||
ssize_t zts_readv(int s, const struct zts_iovec *iov, int iovcnt)
|
||||
ssize_t zts_readv(int fd, const struct zts_iovec *iov, int iovcnt)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
return lwip_readv(s, (iovec*)iov, iovcnt);
|
||||
|
||||
return lwip_readv(fd, (iovec*)iov, iovcnt);
|
||||
}
|
||||
|
||||
ssize_t zts_write(int fd, const void *buf, size_t len)
|
||||
@@ -275,6 +327,7 @@ ssize_t zts_write(int fd, const void *buf, size_t len)
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
|
||||
if (!buf) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
@@ -286,6 +339,7 @@ ssize_t zts_writev(int fd, const struct zts_iovec *iov, int iovcnt)
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
|
||||
return lwip_writev(fd, (iovec*)iov, iovcnt);
|
||||
}
|
||||
|
||||
@@ -344,19 +398,356 @@ int zts_ipaddr_aton(const char *cp, zts_ip_addr *addr)
|
||||
return ipaddr_aton(cp, (ip_addr_t *)addr);
|
||||
}
|
||||
|
||||
const char *zts_inet_ntop(int af, const void *src, char *dst, zts_socklen_t size)
|
||||
const char *zts_inet_ntop(
|
||||
int family, const void *src, char *dst, zts_socklen_t size)
|
||||
{
|
||||
return lwip_inet_ntop(af,src,dst,size);
|
||||
return lwip_inet_ntop(family,src,dst,size);
|
||||
}
|
||||
|
||||
int zts_inet_pton(int af, const char *src, void *dst)
|
||||
int zts_inet_pton(int family, const char *src, void *dst)
|
||||
{
|
||||
return lwip_inet_pton(af,src,dst);
|
||||
return lwip_inet_pton(family,src,dst);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
int ipstr2sockaddr(
|
||||
int family, char *src_ipstr, int port, struct zts_sockaddr *dest_addr, zts_socklen_t *addrlen) {
|
||||
if (family == ZTS_AF_INET) {
|
||||
struct zts_sockaddr_in in4;
|
||||
in4.sin_port = htons(port);
|
||||
in4.sin_family = family;
|
||||
#if defined(_WIN32)
|
||||
zts_inet_pton(family, src_ipstr, &(in4.sin_addr.S_addr));
|
||||
#else
|
||||
zts_inet_pton(family, src_ipstr, &(in4.sin_addr.s_addr));
|
||||
#endif
|
||||
dest_addr = (struct zts_sockaddr *)&in4;
|
||||
*addrlen = sizeof(in4);
|
||||
return ZTS_ERR_OK;
|
||||
}
|
||||
if (family == ZTS_AF_INET6) {
|
||||
struct zts_sockaddr_in6 in6;
|
||||
in6.sin6_port = htons(port);
|
||||
in6.sin6_family = family;
|
||||
#if defined(_WIN32)
|
||||
zts_inet_pton(family, src_ipstr, &(in6.sin6_addr));
|
||||
#else
|
||||
zts_inet_pton(family, src_ipstr, &(in6.sin6_addr));
|
||||
#endif
|
||||
dest_addr = (struct zts_sockaddr *)&in6;
|
||||
*addrlen = sizeof(in6);
|
||||
return ZTS_ERR_OK;
|
||||
}
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Convenience functions //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Helper functions that simplify API wrapper generation and usage in other
|
||||
* non-C-like languages. Use simple integer types instead of bit flags, limit
|
||||
* the number of operations each function performs, prevent the user from
|
||||
* needing to manipulate the content of structures in a non-native language.
|
||||
*/
|
||||
|
||||
int zts_set_no_delay(int fd, int enabled) {
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (enabled != 0 && enabled != 1) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return zts_setsockopt(
|
||||
fd, ZTS_IPPROTO_TCP, ZTS_TCP_NODELAY, (void *)&enabled, sizeof(int));
|
||||
}
|
||||
|
||||
int zts_get_no_delay(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
int err, optval = 0;
|
||||
zts_socklen_t len = sizeof(optval);
|
||||
if ((err = zts_getsockopt(
|
||||
fd, ZTS_IPPROTO_TCP, ZTS_TCP_NODELAY, (void *)&optval, &len)) < 0) {
|
||||
return err;
|
||||
}
|
||||
return optval != 0;
|
||||
}
|
||||
|
||||
int zts_set_linger(int fd, int enabled, int value) {
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (enabled != 0 && enabled != 1) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
if (value < 0) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
struct zts_linger linger;
|
||||
linger.l_onoff = enabled;
|
||||
linger.l_linger = value;
|
||||
return zts_setsockopt(
|
||||
fd, ZTS_SOL_SOCKET, ZTS_SO_LINGER, (void *)&linger, sizeof(linger));
|
||||
}
|
||||
|
||||
int zts_get_linger_enabled(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
int err;
|
||||
struct zts_linger linger;
|
||||
zts_socklen_t len = sizeof(linger);
|
||||
if ((err = zts_getsockopt(
|
||||
fd, ZTS_SOL_SOCKET, ZTS_SO_LINGER, (void *)&linger, &len)) < 0) {
|
||||
return err;
|
||||
}
|
||||
return linger.l_onoff;
|
||||
}
|
||||
|
||||
int zts_get_linger_value(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
int err;
|
||||
struct zts_linger linger;
|
||||
zts_socklen_t len = sizeof(linger);
|
||||
if ((err = zts_getsockopt(
|
||||
fd, ZTS_SOL_SOCKET, ZTS_SO_LINGER, (void *)&linger, &len)) < 0) {
|
||||
return err;
|
||||
}
|
||||
return linger.l_linger;
|
||||
}
|
||||
|
||||
int zts_set_reuse_addr(int fd, int enabled)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (enabled != 0 && enabled != 1) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return zts_setsockopt(
|
||||
fd, ZTS_SOL_SOCKET, ZTS_SO_REUSEADDR, (void *)&enabled, sizeof(enabled));
|
||||
}
|
||||
|
||||
int zts_get_reuse_addr(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
int err;
|
||||
int optval = 0;
|
||||
zts_socklen_t optlen = sizeof(optval);
|
||||
if ((err = zts_getsockopt(
|
||||
fd, ZTS_SOL_SOCKET, ZTS_SO_REUSEADDR, (void *)&optval, &optlen)) < 0) {
|
||||
return err;
|
||||
}
|
||||
return optval != 0;
|
||||
}
|
||||
|
||||
int zts_set_recv_timeout(int fd, int seconds, int microseconds)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (seconds < 0 || microseconds < 0) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
struct timeval tv;
|
||||
tv.tv_sec = seconds;
|
||||
tv.tv_usec = microseconds;
|
||||
return zts_setsockopt(
|
||||
fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv));
|
||||
}
|
||||
|
||||
int zts_get_recv_timeout(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
struct timeval tv;
|
||||
zts_socklen_t optlen = sizeof(tv);
|
||||
int err;
|
||||
if ((err = zts_getsockopt(
|
||||
fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, &optlen)) < 0) {
|
||||
return err;
|
||||
}
|
||||
return tv.tv_sec; // TODO microseconds
|
||||
}
|
||||
|
||||
int zts_set_send_timeout(int fd, int seconds, int microseconds)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (seconds < 0 || microseconds < 0) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
struct timeval tv;
|
||||
tv.tv_sec = seconds;
|
||||
tv.tv_usec = microseconds;
|
||||
return zts_setsockopt(
|
||||
fd, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(tv));
|
||||
}
|
||||
|
||||
int zts_get_send_timeout(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
struct zts_timeval tv;
|
||||
zts_socklen_t optlen = sizeof(tv);
|
||||
int err;
|
||||
if ((err = zts_getsockopt(
|
||||
fd, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, &optlen)) < 0) {
|
||||
return err;
|
||||
}
|
||||
return tv.tv_sec; // TODO microseconds
|
||||
}
|
||||
|
||||
int zts_set_send_buf_size(int fd, int size)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (size < 0) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return zts_setsockopt(
|
||||
fd, SOL_SOCKET, SO_SNDBUF, (void *)&size, sizeof(int));
|
||||
}
|
||||
|
||||
int zts_get_send_buf_size(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
int err, optval = 0;
|
||||
zts_socklen_t optlen = sizeof(optval);
|
||||
if ((err = zts_getsockopt(
|
||||
fd, SOL_SOCKET, SO_SNDBUF, (char *)&optval, &optlen)) < 0) {
|
||||
return err;
|
||||
}
|
||||
return optval;
|
||||
}
|
||||
|
||||
int zts_set_recv_buf_size(int fd, int size)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (size < 0) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return zts_setsockopt(
|
||||
fd, SOL_SOCKET, SO_RCVBUF, (void *)&size, sizeof(int));
|
||||
}
|
||||
|
||||
int zts_get_recv_buf_size(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
int err, optval = 0;
|
||||
zts_socklen_t optlen = sizeof(optval);
|
||||
if ((err = zts_getsockopt(
|
||||
fd, SOL_SOCKET, SO_RCVBUF, (char *)&optval, &optlen)) < 0) {
|
||||
return err;
|
||||
}
|
||||
return optval;
|
||||
}
|
||||
|
||||
int zts_set_ttl(int fd, int ttl)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (ttl < 0 || ttl > 255) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
return zts_setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
|
||||
}
|
||||
|
||||
int zts_get_ttl(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
int err, ttl = 0;
|
||||
zts_socklen_t optlen = sizeof(ttl);
|
||||
if ((err = zts_getsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, &optlen)) < 0) {
|
||||
return err;
|
||||
}
|
||||
return ttl;
|
||||
}
|
||||
|
||||
int zts_set_blocking(int fd, int enabled)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (enabled != 0 && enabled != 1) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
int flags = zts_fcntl(fd, ZTS_F_GETFL, 0);
|
||||
if (!enabled) {
|
||||
return zts_fcntl(fd, ZTS_F_SETFL, flags | ZTS_O_NONBLOCK);
|
||||
}
|
||||
else {
|
||||
// Default
|
||||
return zts_fcntl(fd, ZTS_F_SETFL, flags & (~ZTS_O_NONBLOCK));
|
||||
}
|
||||
}
|
||||
|
||||
int zts_get_blocking(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
int flags = zts_fcntl(fd, ZTS_F_GETFL, 0);
|
||||
if (flags < 0) {
|
||||
return flags;
|
||||
}
|
||||
return !(flags & ZTS_O_NONBLOCK);
|
||||
}
|
||||
|
||||
int zts_set_keepalive(int fd, int enabled)
|
||||
{
|
||||
//
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
if (enabled != 0 && enabled != 1) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
int keepalive = enabled;
|
||||
return zts_setsockopt(
|
||||
fd, ZTS_SOL_SOCKET, ZTS_SO_KEEPALIVE, &keepalive , sizeof(keepalive));
|
||||
}
|
||||
|
||||
int zts_get_keepalive(int fd)
|
||||
{
|
||||
if (!(_serviceStateFlags & ZTS_STATE_NET_SERVICE_RUNNING)) {
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
int err;
|
||||
int optval = 0;
|
||||
zts_socklen_t optlen = sizeof(optval);
|
||||
if ((err = zts_getsockopt(
|
||||
fd, ZTS_SOL_SOCKET, ZTS_SO_KEEPALIVE, (void *)&optval, &optlen)) < 0) {
|
||||
return err;
|
||||
}
|
||||
return optval != 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Statistics //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifdef ZTS_ENABLE_STATS
|
||||
|
||||
|
||||
816
test/selftest-c-api.c
Normal file
816
test/selftest-c-api.c
Normal file
@@ -0,0 +1,816 @@
|
||||
/**
|
||||
* Selftest. To be run for every commit.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <ZeroTierSockets.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-value"
|
||||
|
||||
int random32() {
|
||||
const int BITS_PER_RAND = (int)(log2(RAND_MAX/2 + 1) + 1.0);
|
||||
int ret = 0;
|
||||
for (int i = 0; i < sizeof(int) * CHAR_BIT; i += BITS_PER_RAND) {
|
||||
ret <<= BITS_PER_RAND;
|
||||
ret |= rand();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t random64() {
|
||||
return ((uint64_t)random32() << 32) | random32();
|
||||
}
|
||||
|
||||
int is_online = 0;
|
||||
int has_ip4 = 0;
|
||||
int has_ip6 = 0;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Event Handler //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
void on_zts_event(void *msgPtr)
|
||||
{
|
||||
struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr;
|
||||
fprintf(stderr, "event=%d\n", msg->eventCode);
|
||||
if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) {
|
||||
fprintf(stderr, "ZTS_EVENT_NODE_ONLINE\n");
|
||||
is_online = 1;
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP4) {
|
||||
fprintf(stderr, "ZTS_EVENT_NETWORK_READY_IP4\n");
|
||||
has_ip4 = 1;
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) {
|
||||
fprintf(stderr, "ZTS_EVENT_NETWORK_READY_IP6\n");
|
||||
has_ip6 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void api_value_arg_test(
|
||||
int8_t i8, int16_t i16, int32_t i32, int64_t i64, void* nullable)
|
||||
{
|
||||
//fprintf(stderr, "%d, %d, %d, %lld, %p\n", i8, i16, i32, i64, nullable);
|
||||
int res = ZTS_ERR_OK;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Test uninitialized Network Stack API usage //
|
||||
//----------------------------------------------------------------------------//
|
||||
/*
|
||||
res = zts_get_all_stats((struct zts_stats *)nullable);
|
||||
assert(("pre-init call to zts_get_all_stats(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_get_protocol_stats(i32, nullable);
|
||||
assert(("pre-init call to zts_get_protocol_stats(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
*/
|
||||
res = zts_dns_set_server(i8, (const zts_ip_addr *)nullable);
|
||||
assert(("pre-init call to zts_add_dns_nameserver(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
const zts_ip_addr *res_ptr = zts_dns_get_server(i8);
|
||||
assert(("pre-init call to zts_del_dns_nameserver(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Test uninitialized Node API usage //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
res = zts_stop();
|
||||
assert(("pre-init call to zts_stop(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_restart();
|
||||
assert(("pre-init call to zts_restart(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_free();
|
||||
assert(("pre-init call to zts_free(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_join(i64);
|
||||
assert(("pre-init call to zts_join(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_leave(i64);
|
||||
assert(("pre-init call to zts_leave(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_orbit(i64,i64);
|
||||
assert(("pre-init call to zts_orbit(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_deorbit(i64);
|
||||
assert(("pre-init call to zts_deorbit(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Test uninitialized Socket API usage //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
res = zts_socket(i32,i32,i32);
|
||||
assert(("pre-init call to zts_socket(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_connect(i32, (const struct zts_sockaddr *)nullable, i32);
|
||||
assert(("pre-init call to zts_connect(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_bind(i32, (const struct zts_sockaddr *)nullable, i32);
|
||||
assert(("pre-init call to zts_bind(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_listen(i32, i32);
|
||||
assert(("pre-init call to zts_listen(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_accept(i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
||||
assert(("pre-init call to zts_accept(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_setsockopt(i32, i32, i32, nullable, i32);
|
||||
assert(("pre-init call to zts_setsockopt(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_getsockopt(i32, i32, i32, nullable, (zts_socklen_t *)nullable);
|
||||
assert(("pre-init call to zts_getsockopt(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_getsockname(i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
||||
assert(("pre-init call to zts_getsockname(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_getpeername(i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
||||
assert(("pre-init call to zts_getpeername(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_close(i32);
|
||||
assert(("pre-init call to zts_close(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_select(i32, (zts_fd_set *)nullable, (zts_fd_set *)nullable, (zts_fd_set *)nullable, (struct zts_timeval *)nullable);
|
||||
assert(("pre-init call to zts_select(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_fcntl(i32, i32, i32);
|
||||
assert(("pre-init call to zts_fcntl(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_poll((struct zts_pollfd *)nullable, i32, i32);
|
||||
assert(("pre-init call to zts_poll(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_ioctl(i32, i64, nullable);
|
||||
assert(("pre-init call to zts_ioctl(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_send(i32, nullable, i32, i32);
|
||||
assert(("pre-init call to zts_send(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_sendto(i32, nullable, i32, i32, (const struct zts_sockaddr *)nullable, i32);
|
||||
assert(("pre-init call to zts_sendto(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_sendmsg(i32, (const struct zts_msghdr *)nullable, i32);
|
||||
assert(("pre-init call to zts_sendmsg(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_recv(i32, nullable, i32, i32);
|
||||
assert(("pre-init call to zts_recv(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_recvfrom(i32, nullable, i32, i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
||||
assert(("pre-init call to zts_recvfrom(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_recvmsg(i32, (struct zts_msghdr *)nullable, i32);
|
||||
assert(("pre-init call to zts_recvmsg(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_read(i32, nullable, i32);
|
||||
assert(("pre-init call to zts_read(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_readv(i32, (const struct zts_iovec *)nullable, i32);
|
||||
assert(("pre-init call to zts_readv(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_write(i32, nullable, i32);
|
||||
assert(("pre-init call to zts_write(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_writev(i32, (const struct zts_iovec *)nullable, i32);
|
||||
assert(("pre-init call to zts_writev(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_shutdown(i32, i32);
|
||||
assert(("pre-init call to zts_shutdown(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
}
|
||||
|
||||
void test_pre_service()
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Test service-related API functions before initializing service //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
// Test null values
|
||||
api_value_arg_test(0,0,0,0,NULL);
|
||||
|
||||
// Test wild values
|
||||
for (int i=0; i<4096; i++) {
|
||||
int8_t i8 = (uint8_t)random64();
|
||||
int16_t i16 = (uint16_t)random64();
|
||||
int32_t i32 = (uint32_t)random64();
|
||||
int64_t i64 = (uint64_t)random64();
|
||||
int x;
|
||||
void* nullable = &x;
|
||||
api_value_arg_test(i8,i16,i32,i64,nullable);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Test non-service helper functions //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
// (B) Test zts_inet_ntop
|
||||
|
||||
char ipstr[ZTS_INET6_ADDRSTRLEN];
|
||||
int16_t port = 0;
|
||||
struct zts_sockaddr_in in4;
|
||||
|
||||
in4.sin_port = htons(8080);
|
||||
#if defined(_WIN32)
|
||||
zts_inet_pton(ZTS_AF_INET, "192.168.22.1", &(in4.sin_addr.S_addr));
|
||||
#else
|
||||
zts_inet_pton(ZTS_AF_INET, "192.168.22.1", &(in4.sin_addr.s_addr));
|
||||
#endif
|
||||
|
||||
in4.sin_family = ZTS_AF_INET;
|
||||
|
||||
struct zts_sockaddr *sa = (struct zts_sockaddr *)&in4;
|
||||
if (sa->sa_family == ZTS_AF_INET) {
|
||||
struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)sa;
|
||||
zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr),
|
||||
ipstr, ZTS_INET_ADDRSTRLEN);
|
||||
port = ntohs(in4->sin_port);
|
||||
}
|
||||
if (sa->sa_family == ZTS_AF_INET6) {
|
||||
struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)sa;
|
||||
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr),
|
||||
ipstr, ZTS_INET6_ADDRSTRLEN);
|
||||
}
|
||||
|
||||
assert(("zts_inet_ntop(): port != 8080", port == 8080));
|
||||
assert(("zts_inet_ntop(): strcmp(ipstr, \"192.168.22.1\") != 0",
|
||||
!strcmp(ipstr, "192.168.22.1")));
|
||||
|
||||
// (C) Test zts_inet_pton
|
||||
|
||||
uint8_t buf[sizeof(struct zts_in6_addr)];
|
||||
char str[ZTS_INET6_ADDRSTRLEN];
|
||||
|
||||
zts_inet_pton(ZTS_AF_INET, "192.168.22.2", buf);
|
||||
zts_inet_ntop(ZTS_AF_INET, buf, str, ZTS_INET6_ADDRSTRLEN);
|
||||
assert(("zts_inet_pton(): strcmp(ipstr, \"192.168.22.2\") != 0",
|
||||
!strcmp(str, "192.168.22.2")));
|
||||
}
|
||||
|
||||
void test_service()
|
||||
{
|
||||
int res = ZTS_ERR_OK;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Test simplified API, proxy for setsockopt/getsockopt/ioctl etc //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
int s4 = zts_socket(ZTS_AF_INET6, ZTS_SOCK_STREAM, 0);
|
||||
assert(s4 >= 0);
|
||||
|
||||
// TCP_NODELAY
|
||||
|
||||
// Check value before doing anything
|
||||
res = zts_get_no_delay(s4);
|
||||
assert(res == 0);
|
||||
// Turn on
|
||||
res = zts_set_no_delay(s4, 1);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
res = zts_get_no_delay(s4);
|
||||
// Should return value instead of error code
|
||||
assert(res == 1);
|
||||
// Turn off
|
||||
res = zts_set_no_delay(s4, 0);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
res = zts_get_no_delay(s4);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
assert(res == 0);
|
||||
|
||||
// SO_LINGER
|
||||
|
||||
// Check value before doing anything
|
||||
res = zts_get_linger_enabled(s4);
|
||||
assert(res == 0);
|
||||
res = zts_get_linger_value(s4);
|
||||
assert(res == 0);
|
||||
// Turn on, set to 7 seconds
|
||||
res = zts_set_linger(s4, 1, 7);
|
||||
res = zts_get_linger_enabled(s4);
|
||||
assert(res == 1);
|
||||
res = zts_get_linger_value(s4);
|
||||
assert(res == 7);
|
||||
res = zts_set_linger(s4, 0, 0);
|
||||
// Turn off
|
||||
res = zts_get_linger_enabled(s4);
|
||||
assert(res == 0);
|
||||
res = zts_get_linger_value(s4);
|
||||
assert(res == 0);
|
||||
|
||||
// SO_REUSEADDR
|
||||
|
||||
// Check value before doing anything
|
||||
res = zts_get_reuse_addr(s4);
|
||||
assert(res == 0);
|
||||
// Turn on
|
||||
res = zts_set_reuse_addr(s4, 1);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
res = zts_get_reuse_addr(s4);
|
||||
// Should return value instead of error code
|
||||
assert(res == 1);
|
||||
// Turn off
|
||||
res = zts_set_reuse_addr(s4, 0);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
res = zts_get_reuse_addr(s4);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
assert(res == 0);
|
||||
|
||||
// SO_RCVTIMEO
|
||||
|
||||
// Check value before doing anything
|
||||
res = zts_get_recv_timeout(s4);
|
||||
assert(res == 0);
|
||||
// Set to value
|
||||
res = zts_set_recv_timeout(s4, 3, 0);
|
||||
res = zts_get_recv_timeout(s4);
|
||||
assert(res == 3);
|
||||
res = zts_set_recv_timeout(s4, 0, 0);
|
||||
// Set to zero
|
||||
res = zts_get_recv_timeout(s4);
|
||||
assert(res == 0);
|
||||
|
||||
// SO_SNDTIMEO
|
||||
|
||||
// Check value before doing anything
|
||||
res = zts_get_send_timeout(s4);
|
||||
assert(res == 0);
|
||||
// Set to value
|
||||
res = zts_set_send_timeout(s4, 4, 0);
|
||||
res = zts_get_send_timeout(s4);
|
||||
assert(res == 4);
|
||||
res = zts_set_send_timeout(s4, 0, 0);
|
||||
// Set to zero
|
||||
res = zts_get_send_timeout(s4);
|
||||
assert(res == 0);
|
||||
|
||||
// SO_SNDBUF
|
||||
|
||||
// Check value before doing anything
|
||||
res = zts_get_send_buf_size(s4);
|
||||
assert(res == -1); // Unimplemented as of writing of test
|
||||
// Set to 7 seconds
|
||||
res = zts_set_send_buf_size(s4, 1024);
|
||||
res = zts_get_send_buf_size(s4);
|
||||
assert(res == -1); // Unimplemented as of writing of test
|
||||
res = zts_set_send_buf_size(s4, 0);
|
||||
// Set to zero
|
||||
res = zts_get_send_buf_size(s4);
|
||||
assert(res == -1); // Unimplemented as of writing of test
|
||||
|
||||
// SO_RCVBUF
|
||||
|
||||
// Check value before doing anything
|
||||
res = zts_get_recv_buf_size(s4);
|
||||
assert(res > 0);
|
||||
// Set to value
|
||||
res = zts_set_recv_buf_size(s4, 1024);
|
||||
res = zts_get_recv_buf_size(s4);
|
||||
assert(res == 1024);
|
||||
res = zts_set_recv_buf_size(s4, 0);
|
||||
// Set to zero
|
||||
res = zts_get_recv_buf_size(s4);
|
||||
assert(res == 0);
|
||||
|
||||
// IP_TTL
|
||||
|
||||
// Check value before doing anything
|
||||
res = zts_get_ttl(s4);
|
||||
assert(res == 255); // Defaults to max
|
||||
// Set to value
|
||||
res = zts_set_ttl(s4, 128);
|
||||
res = zts_get_ttl(s4);
|
||||
assert(res == 128);
|
||||
res = zts_set_ttl(s4, 0);
|
||||
// Set to zero
|
||||
res = zts_get_ttl(s4);
|
||||
assert(res == 0);
|
||||
|
||||
// O_NONBLOCK
|
||||
|
||||
// Check value before doing anything
|
||||
res = zts_get_blocking(s4);
|
||||
assert(res == 1);
|
||||
// Turn off (non-blocking)
|
||||
res = zts_set_blocking(s4, 0);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
res = zts_get_blocking(s4);
|
||||
// Should return value instead of error code
|
||||
assert(res == 0);
|
||||
// Turn off
|
||||
res = zts_set_blocking(s4, 1);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
res = zts_get_blocking(s4);
|
||||
assert(res == 1);
|
||||
|
||||
// SO_KEEPALIVE
|
||||
|
||||
// Check value before doing anything
|
||||
res = zts_get_keepalive(s4);
|
||||
assert(res == 0);
|
||||
// Turn on
|
||||
res = zts_set_keepalive(s4, 1);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
res = zts_get_keepalive(s4);
|
||||
// Should return value instead of error code
|
||||
assert(res == 1);
|
||||
// Turn off
|
||||
res = zts_set_keepalive(s4, 0);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
res = zts_get_keepalive(s4);
|
||||
assert(res == ZTS_ERR_OK);
|
||||
assert(res == 0);
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Test *_easy API //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
//zts_connect_easy(0, ZTS_AF_INET, "192.168.7.9", 7878);
|
||||
//zts_connect_easy(0, ZTS_AF_INET6, "FCC5:205E:4FF5:5311:DFF0::1", 7878);
|
||||
//res = zts_bind_easy(0, ZTS_AF_INET6, "::", 8080);
|
||||
//fprintf(stderr, "res=%d, zts_errno=%d\n", res, zts_errno);
|
||||
//zts_delay_ms(60000);
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Test DNS client functionality //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
/*
|
||||
// Set first nameserver
|
||||
|
||||
char *ns1_addr_str = "FCC5:205E:4FF5:5311:DFF0::1";
|
||||
zts_ip_addr ns1;
|
||||
zts_ipaddr_aton(ns1_addr_str, &ns1);
|
||||
zts_dns_set_server(0, &ns1);
|
||||
|
||||
// Get first nameserver
|
||||
|
||||
const zts_ip_addr *ns1_result;
|
||||
ns1_result = zts_dns_get_server(0);
|
||||
printf("dns1 = %s\n", zts_ipaddr_ntoa(ns1_result));
|
||||
|
||||
// Set second nameserver
|
||||
|
||||
char *ns2_addr_str = "192.168.22.1";
|
||||
zts_ip_addr ns2;
|
||||
zts_ipaddr_aton(ns2_addr_str, &ns2);
|
||||
zts_dns_set_server(1, &ns2);
|
||||
|
||||
// Get second nameserver
|
||||
|
||||
const zts_ip_addr *ns2_result;
|
||||
ns2_result = zts_dns_get_server(1);
|
||||
printf("dns1 = %s\n", zts_ipaddr_ntoa(ns2_result));
|
||||
|
||||
// Check that each nameserver address was properly set and get
|
||||
|
||||
assert(("zts_dns_get_server(): Address mismatch", !strcmp(ns1_addr_str, zts_ipaddr_ntoa(ns1_result))));
|
||||
assert(("zts_dns_get_server(): Address mismatch", !strcmp(ns2_addr_str, zts_ipaddr_ntoa(ns2_result))));
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Test shutting down the service //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
zts_stop();
|
||||
s4 = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
||||
assert(("s4 != ZTS_ERR_SERVICE, not shut down", s4 == ZTS_ERR_SERVICE));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Server //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define MAX_CONNECT_TIME 60
|
||||
#define BUFLEN 128
|
||||
char *msg = "welcome to the machine";
|
||||
|
||||
void start_server_app(uint16_t port4, uint16_t port6)
|
||||
{
|
||||
int err = ZTS_ERR_OK;
|
||||
int bytes_read = 0;
|
||||
int bytes_sent = 0;
|
||||
|
||||
int msglen = strlen(msg);
|
||||
char dstbuf[BUFLEN];
|
||||
int buflen = BUFLEN;
|
||||
|
||||
struct timespec start, now;
|
||||
int time_diff = 0;
|
||||
|
||||
//
|
||||
// IPv4 test
|
||||
//
|
||||
|
||||
fprintf(stderr, "server4: will listen on: 0.0.0.0:%d\n", port4);
|
||||
int s4 = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
||||
assert(s4 == 0 && zts_errno == 0);
|
||||
|
||||
err = zts_bind_easy(s4, ZTS_AF_INET, "0.0.0.0", port4);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
err = zts_listen(s4, 1);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
struct zts_sockaddr_in in4;
|
||||
zts_socklen_t addrlen4 = sizeof(in4);
|
||||
|
||||
int acc4 = -1;
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
do {
|
||||
fprintf(stderr, "server4: accepting...\n");
|
||||
acc4 = zts_accept(s4, &in4, &addrlen4);
|
||||
zts_delay_ms(250);
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
time_diff = (now.tv_sec - start.tv_sec);
|
||||
} while (err < 0 && time_diff < MAX_CONNECT_TIME);
|
||||
|
||||
assert(acc4 == 1 && zts_errno == 0);
|
||||
|
||||
// Read message
|
||||
memset(dstbuf, 0, buflen);
|
||||
bytes_read = zts_read(acc4, dstbuf, buflen);
|
||||
fprintf(stderr, "server4: read (%d) bytes\n", bytes_read);
|
||||
assert(bytes_read == msglen && zts_errno == 0);
|
||||
|
||||
// Send message
|
||||
bytes_sent = zts_write(acc4, msg, msglen);
|
||||
fprintf(stderr, "server4: wrote (%d) bytes\n", bytes_sent);
|
||||
assert(bytes_sent == msglen && zts_errno == 0);
|
||||
|
||||
zts_close(s4);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
zts_close(acc4);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
//
|
||||
// IPv6 test
|
||||
//
|
||||
|
||||
fprintf(stderr, "server: will listen on: [::]:%d\n", port6);
|
||||
int s6 = zts_socket(ZTS_AF_INET6, ZTS_SOCK_STREAM, 0);
|
||||
assert(s6 == 0 && zts_errno == 0);
|
||||
|
||||
err = zts_bind_easy(s6, ZTS_AF_INET6, "::", port6);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
err = zts_listen(s6, 1);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
struct zts_sockaddr_in6 in6;
|
||||
zts_socklen_t addrlen6 = sizeof(in6);
|
||||
|
||||
int acc6 = -1;
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
do {
|
||||
fprintf(stderr, "server6: accepting...\n");
|
||||
acc6 = zts_accept(s6, &in6, &addrlen6);
|
||||
zts_delay_ms(250);
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
time_diff = (now.tv_sec - start.tv_sec);
|
||||
} while (err < 0 && time_diff < MAX_CONNECT_TIME);
|
||||
|
||||
fprintf(stderr, "server6: accepted connection (fd=%d)\n", acc6);
|
||||
assert(acc6 == 1 && zts_errno == 0);
|
||||
|
||||
// Read message
|
||||
memset(dstbuf, 0, buflen);
|
||||
bytes_read = zts_read(acc6, dstbuf, buflen);
|
||||
fprintf(stderr, "server6: read (%d) bytes\n", bytes_read);
|
||||
assert(bytes_read == msglen && zts_errno == 0);
|
||||
|
||||
// Send message
|
||||
bytes_sent = zts_write(acc6, msg, msglen);
|
||||
fprintf(stderr, "server6: wrote (%d) bytes\n", bytes_sent);
|
||||
assert(bytes_sent == msglen && zts_errno == 0);
|
||||
|
||||
zts_close(s6);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
zts_close(acc6);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
zts_stop();
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
int s = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
||||
assert(("s != ZTS_ERR_SERVICE, not shut down", s == ZTS_ERR_SERVICE));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Client //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
void start_client_app(char *ip4, uint16_t port4, char *ip6, uint16_t port6)
|
||||
{
|
||||
int err = ZTS_ERR_OK;
|
||||
int bytes_read = 0;
|
||||
int bytes_sent = 0;
|
||||
|
||||
int msglen = strlen(msg);
|
||||
char dstbuf[BUFLEN];
|
||||
int buflen = BUFLEN;
|
||||
|
||||
struct timespec start, now;
|
||||
int time_diff = 0;
|
||||
|
||||
//
|
||||
// IPv4 test
|
||||
//
|
||||
|
||||
err = ZTS_ERR_OK;
|
||||
int s4 = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
zts_set_blocking(s4, 1);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
do {
|
||||
fprintf(stderr, "client4: connecting to: %s:%d\n", ip4, port4);
|
||||
err = zts_connect_easy(s4, ZTS_AF_INET, ip4, port4);
|
||||
zts_delay_ms(500);
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
time_diff = (now.tv_sec - start.tv_sec);
|
||||
} while (err < 0 && time_diff < MAX_CONNECT_TIME);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
fprintf(stderr, "client4: connected\n");
|
||||
// Send message
|
||||
bytes_sent = zts_write(s4, msg, msglen);
|
||||
fprintf(stderr, "client4: wrote (%d) bytes\n", bytes_sent);
|
||||
assert(bytes_sent == msglen && zts_errno == 0);
|
||||
|
||||
// Read message
|
||||
memset(dstbuf, 0, buflen);
|
||||
bytes_read = zts_read(s4, dstbuf, buflen);
|
||||
assert(bytes_read == msglen && zts_errno == 0);
|
||||
|
||||
fprintf(stderr, "client4: read (%d) bytes\n", bytes_read);
|
||||
assert(bytes_sent == bytes_read && zts_errno == 0);
|
||||
|
||||
zts_close(s4);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
//
|
||||
// IPv6 test
|
||||
//
|
||||
|
||||
err = ZTS_ERR_OK;
|
||||
int s6 = zts_socket(ZTS_AF_INET6, ZTS_SOCK_STREAM, 0);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
zts_set_blocking(s6, 1);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
do {
|
||||
fprintf(stderr, "client6: connecting to: %s:%d\n", ip6, port6);
|
||||
err = zts_connect_easy(s6, ZTS_AF_INET6, ip6, port6);
|
||||
zts_delay_ms(500);
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
time_diff = (now.tv_sec - start.tv_sec);
|
||||
} while (err < 0 && time_diff < MAX_CONNECT_TIME);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
fprintf(stderr, "client6: connected\n");
|
||||
// Send message
|
||||
bytes_sent = zts_write(s6, msg, msglen);
|
||||
fprintf(stderr, "client6: wrote (%d) bytes\n", bytes_sent);
|
||||
assert(bytes_sent == msglen && zts_errno == 0);
|
||||
|
||||
// Read message
|
||||
memset(dstbuf, 0, buflen);
|
||||
bytes_read = zts_read(s6, dstbuf, buflen);
|
||||
assert(bytes_read == msglen && zts_errno == 0);
|
||||
|
||||
fprintf(stderr, "client6: read (%d) bytes\n", bytes_read);
|
||||
assert(bytes_sent == bytes_read && zts_errno == 0);
|
||||
|
||||
zts_close(s6);
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
|
||||
zts_stop();
|
||||
assert(err == ZTS_ERR_OK && zts_errno == 0);
|
||||
int s = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
||||
assert(("s != ZTS_ERR_SERVICE, not shut down", s == ZTS_ERR_SERVICE));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Start node //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
void start_node(char *path, uint64_t nwid)
|
||||
{
|
||||
struct timespec start, now;
|
||||
int time_diff = 0;
|
||||
|
||||
fprintf(stderr, "starting node...\n");
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
int res = zts_start(path, &on_zts_event, 0);
|
||||
assert(("error starting service: res != ZTS_ERR_OK", res == ZTS_ERR_OK));
|
||||
do {
|
||||
zts_delay_ms(25);
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
time_diff = (now.tv_sec - start.tv_sec);
|
||||
} while (!is_online && (time_diff < MAX_CONNECT_TIME));
|
||||
if (!is_online) {
|
||||
fprintf(stderr, "node failed to come online\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "joining: %llx\n", nwid);
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
if (nwid) {
|
||||
zts_join(nwid);
|
||||
do {
|
||||
zts_delay_ms(25);
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
time_diff = (now.tv_sec - start.tv_sec);
|
||||
} while ((!has_ip4 || !has_ip6) && (time_diff < MAX_CONNECT_TIME));
|
||||
if (!has_ip4 || !has_ip6) {
|
||||
fprintf(stderr, "node failed to receive assigned addresses\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Main //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 1 && argc != 5 && argc != 7) {
|
||||
fprintf(stderr, "Invalid number of arguments.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//
|
||||
// API fuzz test
|
||||
//
|
||||
|
||||
test_pre_service();
|
||||
|
||||
//
|
||||
// Default test
|
||||
//
|
||||
|
||||
// selftest
|
||||
if (argc == 1) {
|
||||
srand(time(NULL));
|
||||
// Store identities in cwd, join 0x0
|
||||
start_node(".",0x0);
|
||||
test_service();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Default test (single node)
|
||||
// selftest <id-path>
|
||||
/*
|
||||
if (argc == 2) {
|
||||
srand(time(NULL));
|
||||
start_node(argv[1],0x0);
|
||||
test_service();
|
||||
exit(0);
|
||||
}*/
|
||||
|
||||
//
|
||||
// Client/Server communication test
|
||||
//
|
||||
|
||||
// Server test
|
||||
if (argc == 5) {
|
||||
//fprintf(stderr, "server.path = %s\n", argv[1]);
|
||||
//fprintf(stderr, "server.nwid = %s\n", argv[2]);
|
||||
//fprintf(stderr, "server.port4 = %s\n", argv[3]);
|
||||
//fprintf(stderr, "server.port6 = %s\n", argv[4]);
|
||||
uint64_t nwid = strtoull(argv[2],NULL,16);
|
||||
int port4 = atoi(argv[3]);
|
||||
int port6 = atoi(argv[4]);
|
||||
start_node(argv[1],nwid);
|
||||
start_server_app(port4, port6);
|
||||
exit(0);
|
||||
}
|
||||
// Client test
|
||||
if (argc == 7) {
|
||||
//fprintf(stderr, "client.path = %s\n", argv[1]);
|
||||
//fprintf(stderr, "client.nwid = %s\n", argv[2]);
|
||||
//fprintf(stderr, "client.port4 = %s\n", argv[3]);
|
||||
//fprintf(stderr, "client.ip4 = %s\n", argv[4]);
|
||||
//fprintf(stderr, "client.port6 = %s\n", argv[5]);
|
||||
//fprintf(stderr, "client.ip6 = %s\n", argv[6]);
|
||||
uint64_t nwid = strtoull(argv[2],NULL,16);
|
||||
int port4 = atoi(argv[3]);
|
||||
int port6 = atoi(argv[5]);
|
||||
start_node(argv[1],nwid);
|
||||
start_client_app(argv[4], port4, argv[6], port6);
|
||||
exit(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
272
test/selftest.c
272
test/selftest.c
@@ -1,272 +0,0 @@
|
||||
/**
|
||||
* Selftest. To be run for every commit.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <ZeroTierSockets.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-value"
|
||||
|
||||
int random32() {
|
||||
const int BITS_PER_RAND = (int)(log2(RAND_MAX/2 + 1) + 1.0);
|
||||
int ret = 0;
|
||||
for (int i = 0; i < sizeof(int) * CHAR_BIT; i += BITS_PER_RAND) {
|
||||
ret <<= BITS_PER_RAND;
|
||||
ret |= rand();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t random64() {
|
||||
return ((uint64_t)random32() << 32) | random32();
|
||||
}
|
||||
|
||||
void api_value_arg_test(int8_t i8, int16_t i16, int32_t i32, int64_t i64, void* nullable)
|
||||
{
|
||||
//fprintf(stderr, "%d, %d, %d, %lld, %p\n", i8, i16, i32, i64, nullable);
|
||||
int res = ZTS_ERR_OK;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Test uninitialized Network Stack API usage |
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
res = zts_get_all_stats((struct zts_stats *)nullable);
|
||||
assert(("pre-init call to zts_get_all_stats(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_get_protocol_stats(i32, nullable);
|
||||
assert(("pre-init call to zts_get_protocol_stats(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_dns_set_server(i8, (const zts_ip_addr *)nullable);
|
||||
assert(("pre-init call to zts_add_dns_nameserver(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
const zts_ip_addr *res_ptr = zts_dns_get_server(i8);
|
||||
assert(("pre-init call to zts_del_dns_nameserver(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Test uninitialized Node API usage |
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
res = zts_stop();
|
||||
assert(("pre-init call to zts_stop(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_restart();
|
||||
assert(("pre-init call to zts_restart(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_free();
|
||||
assert(("pre-init call to zts_free(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_join(i64);
|
||||
assert(("pre-init call to zts_join(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_leave(i64);
|
||||
assert(("pre-init call to zts_leave(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_orbit(i64,i64);
|
||||
assert(("pre-init call to zts_orbit(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_deorbit(i64);
|
||||
assert(("pre-init call to zts_deorbit(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Test uninitialized Socket API usage |
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
res = zts_socket(i32,i32,i32);
|
||||
assert(("pre-init call to zts_socket(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_connect(i32, (const struct zts_sockaddr *)nullable, i32);
|
||||
assert(("pre-init call to zts_connect(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_bind(i32, (const struct zts_sockaddr *)nullable, i32);
|
||||
assert(("pre-init call to zts_bind(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_listen(i32, i32);
|
||||
assert(("pre-init call to zts_listen(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_accept(i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
||||
assert(("pre-init call to zts_accept(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_setsockopt(i32, i32, i32, nullable, i32);
|
||||
assert(("pre-init call to zts_setsockopt(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_getsockopt(i32, i32, i32, nullable, (zts_socklen_t *)nullable);
|
||||
assert(("pre-init call to zts_getsockopt(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_getsockname(i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
||||
assert(("pre-init call to zts_getsockname(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_getpeername(i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
||||
assert(("pre-init call to zts_getpeername(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_close(i32);
|
||||
assert(("pre-init call to zts_close(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_select(i32, (zts_fd_set *)nullable, (zts_fd_set *)nullable, (zts_fd_set *)nullable, (struct zts_timeval *)nullable);
|
||||
assert(("pre-init call to zts_select(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_fcntl(i32, i32, i32);
|
||||
assert(("pre-init call to zts_fcntl(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_poll((struct zts_pollfd *)nullable, i32, i32);
|
||||
assert(("pre-init call to zts_poll(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_ioctl(i32, i64, nullable);
|
||||
assert(("pre-init call to zts_ioctl(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_send(i32, nullable, i32, i32);
|
||||
assert(("pre-init call to zts_send(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_sendto(i32, nullable, i32, i32, (const struct zts_sockaddr *)nullable, i32);
|
||||
assert(("pre-init call to zts_sendto(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_sendmsg(i32, (const struct zts_msghdr *)nullable, i32);
|
||||
assert(("pre-init call to zts_sendmsg(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_recv(i32, nullable, i32, i32);
|
||||
assert(("pre-init call to zts_recv(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_recvfrom(i32, nullable, i32, i32, (struct zts_sockaddr *)nullable, (zts_socklen_t *)nullable);
|
||||
assert(("pre-init call to zts_recvfrom(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_recvmsg(i32, (struct zts_msghdr *)nullable, i32);
|
||||
assert(("pre-init call to zts_recvmsg(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_read(i32, nullable, i32);
|
||||
assert(("pre-init call to zts_read(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_readv(i32, (const struct zts_iovec *)nullable, i32);
|
||||
assert(("pre-init call to zts_readv(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_write(i32, nullable, i32);
|
||||
assert(("pre-init call to zts_write(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_writev(i32, (const struct zts_iovec *)nullable, i32);
|
||||
assert(("pre-init call to zts_writev(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
res = zts_shutdown(i32, i32);
|
||||
assert(("pre-init call to zts_shutdown(): res != ZTS_ERR_SERVICE",
|
||||
res == ZTS_ERR_SERVICE));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
srand(time(NULL));
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Test service-related API functions before initializing service |
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Test null values
|
||||
api_value_arg_test(0,0,0,0,NULL);
|
||||
|
||||
// Test wild values
|
||||
for (int i=0; i<1024; i++) {
|
||||
int8_t i8 = (uint8_t)random64();
|
||||
int16_t i16 = (uint16_t)random64();
|
||||
int32_t i32 = (uint32_t)random64();
|
||||
int64_t i64 = (uint64_t)random64();
|
||||
int x;
|
||||
void* nullable = &x;
|
||||
api_value_arg_test(i8,i16,i32,i64,nullable);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Test non-service helper functions |
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// (B) Test zts_inet_ntop
|
||||
|
||||
char ipstr[ZTS_INET6_ADDRSTRLEN];
|
||||
int16_t port = 0;
|
||||
struct zts_sockaddr_in in4;
|
||||
|
||||
in4.sin_port = htons(8080);
|
||||
#if defined(_WIN32)
|
||||
zts_inet_pton(ZTS_AF_INET, "192.168.22.1", &(in4.sin_addr.S_addr));
|
||||
#else
|
||||
zts_inet_pton(ZTS_AF_INET, "192.168.22.1", &(in4.sin_addr.s_addr));
|
||||
#endif
|
||||
|
||||
in4.sin_family = ZTS_AF_INET;
|
||||
|
||||
struct zts_sockaddr *sa = (struct zts_sockaddr *)&in4;
|
||||
if (sa->sa_family == ZTS_AF_INET) {
|
||||
struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)sa;
|
||||
zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr),
|
||||
ipstr, ZTS_INET_ADDRSTRLEN);
|
||||
port = ntohs(in4->sin_port);
|
||||
}
|
||||
if (sa->sa_family == ZTS_AF_INET6) {
|
||||
struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)sa;
|
||||
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr),
|
||||
ipstr, ZTS_INET6_ADDRSTRLEN);
|
||||
}
|
||||
|
||||
assert(("zts_inet_ntop(): port != 8080", port == 8080));
|
||||
assert(("zts_inet_ntop(): strcmp(ipstr, \"192.168.22.1\") != 0",
|
||||
!strcmp(ipstr, "192.168.22.1")));
|
||||
|
||||
// (C) Test zts_inet_pton
|
||||
|
||||
uint8_t buf[sizeof(struct zts_in6_addr)];
|
||||
char str[ZTS_INET6_ADDRSTRLEN];
|
||||
|
||||
zts_inet_pton(ZTS_AF_INET, "192.168.22.2", buf);
|
||||
zts_inet_ntop(ZTS_AF_INET, buf, str, ZTS_INET6_ADDRSTRLEN);
|
||||
assert(("zts_inet_pton(): strcmp(ipstr, \"192.168.22.2\") != 0",
|
||||
!strcmp(str, "192.168.22.2")));
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Start the service and test a few things |
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// zts_start();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Test DNS client functionality |
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
// Set first nameserver
|
||||
|
||||
char *ns1_addr_str = "FCC5:205E:4FF5:5311:DFF0::1";
|
||||
zts_ip_addr ns1;
|
||||
zts_ipaddr_aton(ns1_addr_str, &ns1);
|
||||
zts_dns_set_server(0, &ns1);
|
||||
|
||||
// Get first nameserver
|
||||
|
||||
const zts_ip_addr *ns1_result;
|
||||
ns1_result = zts_dns_get_server(0);
|
||||
printf("dns1 = %s\n", zts_ipaddr_ntoa(ns1_result));
|
||||
|
||||
// Set second nameserver
|
||||
|
||||
char *ns2_addr_str = "192.168.22.1";
|
||||
zts_ip_addr ns2;
|
||||
zts_ipaddr_aton(ns2_addr_str, &ns2);
|
||||
zts_dns_set_server(1, &ns2);
|
||||
|
||||
// Get second nameserver
|
||||
|
||||
const zts_ip_addr *ns2_result;
|
||||
ns2_result = zts_dns_get_server(1);
|
||||
printf("dns1 = %s\n", zts_ipaddr_ntoa(ns2_result));
|
||||
|
||||
// Check that each nameserver address was properly set and get
|
||||
|
||||
assert(("zts_dns_get_server(): Address mismatch", !strcmp(ns1_addr_str, zts_ipaddr_ntoa(ns1_result))));
|
||||
assert(("zts_dns_get_server(): Address mismatch", !strcmp(ns2_addr_str, zts_ipaddr_ntoa(ns2_result))));
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user