Improve Central API

This commit is contained in:
Joseph Henry
2021-03-14 01:01:04 -08:00
parent 26454d2939
commit c220bb7d2f
6 changed files with 220 additions and 175 deletions

View File

@@ -87,18 +87,19 @@ include_directories(${LWIP_PORT_DIR}/include)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Defaults # Defaults
set(ALLOW_INSTALL_TARGET TRUE) set(ALLOW_INSTALL_TARGET TRUE)
set(BUILD_STATIC_LIB TRUE) set(BUILD_STATIC_LIB TRUE)
set(BUILD_SHARED_LIB TRUE) set(BUILD_SHARED_LIB TRUE)
set(BUILD_HOST_SELFTEST TRUE)
# C# language bindings (libzt.dll/dylib/so) # C# language bindings (libzt.dll/dylib/so)
if (ZTS_ENABLE_PINVOKE) if (ZTS_ENABLE_PINVOKE)
# Features # Features
set(BUILD_STATIC_LIB FALSE) set(BUILD_STATIC_LIB FALSE)
set(BUILD_SHARED_LIB TRUE) set(BUILD_SHARED_LIB TRUE)
set(BUILD_EXAMPLES FALSE) set(BUILD_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE) set(ALLOW_INSTALL_TARGET FALSE)
set(BUILD_HOST_SELFTEST FALSE) set(BUILD_HOST_SELFTEST FALSE)
# Sources and libraries # Sources and libraries
set(ZTS_SWIG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/csharp/*.cpp) set(ZTS_SWIG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/csharp/*.cpp)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_PINVOKE=1") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_PINVOKE=1")
@@ -107,14 +108,14 @@ endif()
# Python language bindings (_libzt.so) # Python language bindings (_libzt.so)
if (ZTS_ENABLE_PYTHON) if (ZTS_ENABLE_PYTHON)
# Features # Features
set(ZTS_ENABLE_PYTHON TRUE) set(ZTS_ENABLE_PYTHON TRUE)
#set(ZTS_ENABLE_STATS FALSE) #set(ZTS_ENABLE_STATS FALSE)
# Targets # Targets
set(BUILD_STATIC_LIB FALSE) set(BUILD_STATIC_LIB FALSE)
set(BUILD_SHARED_LIB TRUE) set(BUILD_SHARED_LIB TRUE)
set(BUILD_EXAMPLES FALSE) set(BUILD_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE) set(ALLOW_INSTALL_TARGET FALSE)
set(BUILD_HOST_SELFTEST FALSE) set(BUILD_HOST_SELFTEST FALSE)
# Sources and libraries # Sources and libraries
find_package(PythonLibs REQUIRED) find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS}) include_directories(${PYTHON_INCLUDE_DIRS})
@@ -124,51 +125,52 @@ endif()
# Java language bindings # Java language bindings
if (ZTS_ENABLE_JAVA) if (ZTS_ENABLE_JAVA)
set(BUILD_STATIC_LIB FALSE) set(BUILD_STATIC_LIB FALSE)
set(BUILD_SHARED_LIB TRUE) set(BUILD_SHARED_LIB TRUE)
set(BUILD_HOST_EXAMPLES FALSE) set(BUILD_HOST_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE) set(ALLOW_INSTALL_TARGET FALSE)
set(BUILD_HOST_SELFTEST FALSE) set(BUILD_HOST_SELFTEST FALSE)
set(ZTS_ENABLE_STATS FALSE) set(ZTS_ENABLE_STATS FALSE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_JAVA=1") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_JAVA=1")
endif() endif()
# All native targets for this host # All native targets for this host
if(BUILD_HOST) if(BUILD_HOST)
set(BUILD_STATIC_LIB TRUE) set(BUILD_STATIC_LIB TRUE)
set(BUILD_SHARED_LIB TRUE) set(BUILD_SHARED_LIB TRUE)
set(BUILD_HOST_EXAMPLES TRUE) set(BUILD_HOST_EXAMPLES TRUE)
set(ALLOW_INSTALL_TARGET TRUE) set(ALLOW_INSTALL_TARGET TRUE)
set(BUILD_HOST_SELFTEST TRUE) set(BUILD_HOST_SELFTEST FALSE)
set(ZTS_ENABLE_STATS TRUE) set(ZTS_ENABLE_STATS TRUE)
set(ZTS_ENABLE_CENTRAL_API FALSE)
endif() endif()
# CI # CI
if(BUILD_HOST_SELFTEST_ONLY) if(BUILD_HOST_SELFTEST_ONLY)
set(BUILD_STATIC_LIB TRUE) set(BUILD_STATIC_LIB TRUE)
set(BUILD_SHARED_LIB FALSE) set(BUILD_SHARED_LIB FALSE)
set(BUILD_HOST_EXAMPLES FALSE) set(BUILD_HOST_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE) set(ALLOW_INSTALL_TARGET FALSE)
set(BUILD_HOST_SELFTEST TRUE) set(BUILD_HOST_SELFTEST TRUE)
set(ZTS_ENABLE_STATS FALSE) set(ZTS_ENABLE_STATS FALSE)
endif() endif()
# Android AAR containing libzt.so # Android AAR containing libzt.so
if(${CMAKE_SYSTEM_NAME} MATCHES "Android") if(${CMAKE_SYSTEM_NAME} MATCHES "Android")
set(BUILD_ANDROID TRUE) set(BUILD_ANDROID TRUE)
set(BUILD_STATIC_LIB FALSE) set(BUILD_STATIC_LIB FALSE)
set(BUILD_SHARED_LIB TRUE) set(BUILD_SHARED_LIB TRUE)
set(BUILD_SELFTEST FALSE) set(BUILD_SELFTEST FALSE)
set(BUILD_EXAMPLES FALSE) set(BUILD_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE) set(ALLOW_INSTALL_TARGET FALSE)
endif() endif()
if(BUILD_MACOS_FRAMEWORK) if(BUILD_MACOS_FRAMEWORK)
set(BUILD_STATIC_LIB TRUE) set(BUILD_STATIC_LIB TRUE)
set(BUILD_SHARED_LIB TRUE) set(BUILD_SHARED_LIB TRUE)
set(BUILD_SELFTEST FALSE) set(BUILD_SELFTEST FALSE)
set(BUILD_EXAMPLES FALSE) set(BUILD_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE) set(ALLOW_INSTALL_TARGET FALSE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOMIT_JSON_SUPPORT=1") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOMIT_JSON_SUPPORT=1")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOMIT_JSON_SUPPORT=1") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOMIT_JSON_SUPPORT=1")
set(CMAKE_XCODE_ATTRIBUTE_ARCHS "$(ARCHS_STANDARD)") set(CMAKE_XCODE_ATTRIBUTE_ARCHS "$(ARCHS_STANDARD)")
@@ -178,11 +180,11 @@ if(BUILD_MACOS_FRAMEWORK)
endif() endif()
if(BUILD_IOS_FRAMEWORK) if(BUILD_IOS_FRAMEWORK)
set(BUILD_STATIC_LIB TRUE) set(BUILD_STATIC_LIB TRUE)
set(BUILD_SHARED_LIB TRUE) set(BUILD_SHARED_LIB TRUE)
set(BUILD_SELFTEST FALSE) set(BUILD_SELFTEST FALSE)
set(BUILD_EXAMPLES FALSE) set(BUILD_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE) set(ALLOW_INSTALL_TARGET FALSE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOMIT_JSON_SUPPORT=1") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOMIT_JSON_SUPPORT=1")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOMIT_JSON_SUPPORT=1") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOMIT_JSON_SUPPORT=1")
set(DEVROOT set(DEVROOT
@@ -204,10 +206,24 @@ if(BUILD_IOS_FRAMEWORK)
endif() endif()
endif() endif()
# -----------------------------------------------------------------------------
# | TESTING (and) FEATURE FLAGS |
# -----------------------------------------------------------------------------
if(BUILD_HOST_SELFTEST)
set(ZTS_ENABLE_STATS TRUE)
set(ZTS_ENABLE_CENTRAL_API TRUE)
endif()
# Enable specific features (eventually these will be enabled by default)
if(ZTS_ENABLE_STATS) if(ZTS_ENABLE_STATS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_STATS=1") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_STATS=1")
endif() endif()
if(ZTS_ENABLE_CENTRAL_API)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_CENTRAL_API=1")
endif()
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# | HACKS TO GET THIS TO WORK ON WINDOWS | # | HACKS TO GET THIS TO WORK ON WINDOWS |
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
@@ -279,7 +295,7 @@ if(BUILD_HOST_EXAMPLES)
${PROJ_DIR}/examples/cpp/keymanagement.cpp) ${PROJ_DIR}/examples/cpp/keymanagement.cpp)
target_link_libraries(keymanagement ${STATIC_LIB_NAME}) target_link_libraries(keymanagement ${STATIC_LIB_NAME})
if(CENTRAL_API) if(ZTS_ENABLE_CENTRAL_API)
add_executable(centralapi ${PROJ_DIR}/examples/cpp/centralapi.cpp) add_executable(centralapi ${PROJ_DIR}/examples/cpp/centralapi.cpp)
target_link_libraries(centralapi ${STATIC_LIB_NAME}) target_link_libraries(centralapi ${STATIC_LIB_NAME})
endif() endif()
@@ -378,7 +394,7 @@ endif()
# | OPTIONAL FEATURES | # | OPTIONAL FEATURES |
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
if(CENTRAL_API) if(ZTS_ENABLE_CENTRAL_API)
set(requiredlibs) set(requiredlibs)
find_package(CURL) find_package(CURL)
if(CURL_FOUND) if(CURL_FOUND)
@@ -605,12 +621,13 @@ if(BUILD_STATIC_LIB)
if(BUILD_WIN) if(BUILD_WIN)
target_link_libraries(${STATIC_LIB_NAME} ${ws2_32_LIBRARY_PATH} target_link_libraries(${STATIC_LIB_NAME} ${ws2_32_LIBRARY_PATH}
${shlwapi_LIBRARY_PATH} ${iphlpapi_LIBRARY_PATH}) ${shlwapi_LIBRARY_PATH} ${iphlpapi_LIBRARY_PATH})
endif() # BUILD_STATIC_LIB endif()
endif() if(ZTS_ENABLE_CENTRAL_API)
target_link_libraries(${STATIC_LIB_NAME} ${CURL_LIBRARIES})
endif()
endif() # BUILD_STATIC_LIB
if(CENTRAL_API)
# target_link_libraries(${STATIC_LIB_NAME} ${CURL_LIBRARIES})
endif()
@@ -642,7 +659,7 @@ if(BUILD_SHARED_LIB)
natpmp_pic natpmp_pic
miniupnpc_pic) miniupnpc_pic)
if(CENTRAL_API) if(ZTS_ENABLE_CENTRAL_API)
target_link_libraries(${DYNAMIC_LIB_NAME} ${CURL_LIBRARIES}) target_link_libraries(${DYNAMIC_LIB_NAME} ${CURL_LIBRARIES})
endif() endif()
@@ -651,6 +668,9 @@ if(BUILD_SHARED_LIB)
if(BUILD_ANDROID) if(BUILD_ANDROID)
target_link_libraries(${DYNAMIC_LIB_NAME} android log) target_link_libraries(${DYNAMIC_LIB_NAME} android log)
endif() endif()
if(ZTS_ENABLE_CENTRAL_API)
target_link_libraries(${DYNAMIC_LIB_NAME} ${CURL_LIBRARIES})
endif()
endif() # BUILD_SHARED_LIB endif() # BUILD_SHARED_LIB
# xcode framework # xcode framework

View File

@@ -48,8 +48,8 @@ int main()
{ {
zts_start(...) zts_start(...)
zts_join(networkId); zts_join(networkId);
zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0); int fd = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
zts_connect(...); zts_connect(fd, ...);
... ...
} }
``` ```
@@ -68,7 +68,7 @@ This project uses [CMake](https://cmake.org/download/) as a build system generat
|macOS | `./build.sh host "release"`| [build.sh](./build.sh) | |macOS | `./build.sh host "release"`| [build.sh](./build.sh) |
|Windows | `. .\build.ps1; Build-Host -BuildType "Release"`| [build.ps1](./build.ps1), *Requires [PowerShell](https://github.com/powershell/powershell)*| |Windows | `. .\build.ps1; Build-Host -BuildType "Release"`| [build.ps1](./build.ps1), *Requires [PowerShell](https://github.com/powershell/powershell)*|
Using the `host` keyword will automatically detect the current machine type and build standard libzt for use in C/C++ (no additional language bindings.) See `./build.sh list` for additional target options. Using the `host` keyword will automatically detect the current machine type and build standard libzt for use in C/C++ (no additional language bindings.) See `./build.sh list` for additional target options. `libzt` depends on [cURL](https://github.com/curl/curl) for the optional portion of the API that interfaces with our hosted web offering ([my.zerotier.com](my.zerotier.com)). If you do not need this functionality you can omit it by passing `-DZTS_ENABLE_CENTRAL_API=0` to CMake.
Example output: Example output:

View File

@@ -307,6 +307,7 @@ host()
ARTIFACT="host" ARTIFACT="host"
# Default to release # Default to release
BUILD_TYPE=${1:-release} BUILD_TYPE=${1:-release}
# -DZTS_ENABLE_CENTRAL_API=0
VARIANT="-DBUILD_HOST=True" VARIANT="-DBUILD_HOST=True"
CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE
TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE

View File

@@ -39,7 +39,7 @@ int main(int argc, char **argv)
} }
std::string central_url = argv[1]; // API endpoint std::string central_url = argv[1]; // API endpoint
std::string api_token = argv[2]; // User token (generate at my.zerotier.com) std::string api_token = argv[2]; // User token (generate at my.zerotier.com)
/** /**
* This example demonstrates how to use the ZeroTier Central API to: * This example demonstrates how to use the ZeroTier Central API to:
* *
@@ -55,7 +55,7 @@ int main(int argc, char **argv)
* Error Codes: * Error Codes:
* -2 : [ZTS_ERR_SERVICE] The API may not have been initialized properly * -2 : [ZTS_ERR_SERVICE] The API may not have been initialized properly
* -3 : [ZTS_ERR_ARG] Invalid argument * -3 : [ZTS_ERR_ARG] Invalid argument
* [100-500] : Standard HTTP error codes * [100-500] : Standard HTTP error codes
* *
* Usage example: centralapi https://my.zerotier.com e7no7nVRFItge7no7cVR5Ibge7no8nV1 * Usage example: centralapi https://my.zerotier.com e7no7nVRFItge7no7cVR5Ibge7no8nV1
* *
@@ -63,23 +63,23 @@ int main(int argc, char **argv)
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
// Buffer to store server response as JSON string blobs // Buffer to store server response as JSON string blobs
char rbuf[CENTRAL_API_RESP_BUF_DEFAULT_SZ]; char rbuf[ZTS_CENTRAL_RESP_BUF_DEFAULT_SZ];
// Provide URL to Central API server and user API token generated at https://my.zerotier.com // Provide URL to Central API server and user API token generated at https://my.zerotier.com
printf("Initializing Central API client...\n"); printf("Initializing Central API client...\n");
if ((err = zts_central_api_init(central_url.c_str(), api_token.c_str(), rbuf, CENTRAL_API_RESP_BUF_DEFAULT_SZ)) != ZTS_ERR_OK) { if ((err = zts_central_init(central_url.c_str(), api_token.c_str(), rbuf, ZTS_CENTRAL_RESP_BUF_DEFAULT_SZ)) != ZTS_ERR_OK) {
fprintf(stderr, "Error while initializing client's Central API parameters\n"); fprintf(stderr, "Error while initializing client's Central API parameters\n");
return 0; return 0;
} }
zts_central_api_set_verbose(false); // (optiona) Turn on reporting from libcurl zts_central_set_verbose(false); // (optiona) Turn on reporting from libcurl
zts_central_api_set_access(ZTS_CENTRAL_READ | ZTS_CENTRAL_WRITE); zts_central_set_access_mode(ZTS_CENTRAL_READ | ZTS_CENTRAL_WRITE);
int http_res_code = 0; int http_res_code = 0;
// Get hosted service status // Get hosted service status
printf("Requesting Central API server status (/api/status):\n"); printf("Requesting Central API server status (/api/status):\n");
if ((err = zts_central_api_get_status(&http_res_code)) != ZTS_ERR_OK) { if ((err = zts_central_get_status(&http_res_code)) != ZTS_ERR_OK) {
fprintf(stderr, "Error (%d) making the request.\n", err); fprintf(stderr, "Error (%d) making the request.\n", err);
} else { } else {
process_response(rbuf, http_res_code); process_response(rbuf, http_res_code);
@@ -87,7 +87,7 @@ int main(int argc, char **argv)
// Get network config // Get network config
int64_t nwid = 0x1234567890abcdef; int64_t nwid = 0x1234567890abcdef;
printf("Requesting network config: /api/network/%llx\n", nwid); printf("Requesting network config: /api/network/%llx\n", nwid);
if ((err = zts_central_api_get_network(&http_res_code, nwid)) != ZTS_ERR_OK) { if ((err = zts_central_get_network(&http_res_code, nwid)) != ZTS_ERR_OK) {
fprintf(stderr, "Error (%d) making the request.\n", err); fprintf(stderr, "Error (%d) making the request.\n", err);
} else { } else {
process_response(rbuf, http_res_code); process_response(rbuf, http_res_code);
@@ -95,11 +95,11 @@ int main(int argc, char **argv)
// Authorize a node on a network // Authorize a node on a network
int64_t nodeid = 0x9934343434; int64_t nodeid = 0x9934343434;
printf("Authorizing: /api/network/%llx/member/%llx\n", nwid, nodeid); printf("Authorizing: /api/network/%llx/member/%llx\n", nwid, nodeid);
if ((err = zts_set_node_auth(&http_res_code, nwid, nodeid, ZTS_CENTRAL_NODE_AUTH_TRUE)) != ZTS_ERR_OK) { if ((err = zts_central_set_node_auth(&http_res_code, nwid, nodeid, ZTS_CENTRAL_NODE_AUTH_TRUE)) != ZTS_ERR_OK) {
fprintf(stderr, "Error (%d) making the request.\n", err); fprintf(stderr, "Error (%d) making the request.\n", err);
} else { } else {
process_response(rbuf, http_res_code); process_response(rbuf, http_res_code);
} }
return 0; return 0;
} }

View File

@@ -903,14 +903,14 @@ int zts_py_getblocking(int fd);
#ifdef ZTS_ENABLE_CENTRAL_API #ifdef ZTS_ENABLE_CENTRAL_API
#define CENTRAL_API_DEFAULT_URL "https://my.zerotier.com" #define ZTS_CENTRAL_DEFAULT_URL "https://my.zerotier.com"
#define CENRTAL_API_MAX_URL_LEN 128 #define ZTS_CENRTAL_MAX_URL_LEN 128
#define CENTRAL_API_TOKEN_LEN 32 #define ZTS_CENTRAL_TOKEN_LEN 32
#define CENTRAL_API_RESP_BUF_DEFAULT_SZ (128*1024) #define ZTS_CENTRAL_RESP_BUF_DEFAULT_SZ (128*1024)
#define HTTP_GET 0 #define ZTS_HTTP_GET 0
#define HTTP_POST 1 #define ZTS_HTTP_POST 1
#define HTTP_DELETE 2 #define ZTS_HTTP_DELETE 2
#define ZTS_CENTRAL_NODE_AUTH_FALSE 0 #define ZTS_CENTRAL_NODE_AUTH_FALSE 0
#define ZTS_CENTRAL_NODE_AUTH_TRUE 1 #define ZTS_CENTRAL_NODE_AUTH_TRUE 1
@@ -924,71 +924,77 @@ int zts_py_getblocking(int fd);
* *
* @param modes Whether the API allows read, write, or both * @param modes Whether the API allows read, write, or both
*/ */
ZTS_API void ZTCALL zts_central_api_set_access(int8_t modes); ZTS_API void ZTCALL zts_central_set_access_mode(int8_t modes);
/** /**
* @brief Enables or disables libcurl verbosity * @brief Enables or disables libcurl verbosity
* *
* @param is_verbose Whether debug information is desired * @param is_verbose Whether debug information is desired
*/ */
ZTS_API void ZTCALL zts_central_api_set_verbose(int8_t is_verbose); ZTS_API void ZTCALL zts_central_set_verbose(int8_t is_verbose);
ZTS_API void ZTCALL zts_central_api_clear_response_buffer(); ZTS_API void ZTCALL zts_central_clear_resp_buf();
/** /**
* @brief Set the Central API URL and user API token. * @brief Set the Central API URL and user API token.
* *
* @param url_str The URL to the Central API server * @param url_str The URL to the Central API server
* @param token_str User API token * @param token_str User API token
* @param response_buffer Destination buffer for raw JSON output * @param resp_buf Destination buffer for raw JSON output
* @param buffer_len Size of buffer for server response (specify 0 for default size) * @param buf_len Size of buffer for server response (specify 0 for default size)
* @return ZTS_ERR_OK on success. ZTS_ERR_ARG if invalid arguments provided. * @return ZTS_ERR_OK on success. ZTS_ERR_ARG if invalid arguments provided.
*/ */
ZTS_API int ZTCALL zts_central_api_init(const char *url_str, const char *token_str, char *response_buffer, uint32_t buffer_len); ZTS_API int ZTCALL zts_central_init(
const char *url_str, const char *token_str, char *resp_buf, uint32_t buf_len);
ZTS_API void ZTCALL zts_central_api_cleanup(); ZTS_API void ZTCALL zts_central_cleanup();
/** /**
* @brief Copies the JSON-formatted string buffer from the last request into a user-provided buffer. * @brief Copies the JSON-formatted string buffer from the last request into
* a user-provided buffer.
* *
* @param dest_buffer User-provided destination buffer * @param dest_buffer User-provided destination buffer
* @param dest_buffer_len Length of aforementioned buffer * @param dest_buf_len Length of aforementioned buffer
* @return ZTS_ERR_OK if all contents were copied successfully. ZTS_ERR_ARG if provided buffer was too small. * @return ZTS_ERR_OK if all contents were copied successfully.
* ZTS_ERR_ARG if provided buffer was too small.
*/ */
ZTS_API int ZTCALL zts_get_last_response_buffer(char *dest_buffer, int dest_buffer_len); ZTS_API int ZTCALL zts_central_get_last_response_buf(
char *dest_buffer, int dest_buf_len);
/** /**
* @brief Get the status of the Central API server. * @brief Get the status of the Central API server.
* *
* @return Standard HTTP response codes. * @return Standard HTTP response codes.
*/ */
ZTS_API int ZTCALL zts_central_api_get_status(int *http_response_code); ZTS_API int ZTCALL zts_central_get_status(int *http_response_code);
/** /**
* @brief Get the currently authenticated users user record. * @brief Get the currently authenticated users user record.
* *
* @return Standard HTTP response codes. * @return Standard HTTP response codes.
*/ */
ZTS_API int ZTCALL zts_central_api_get_self(int *http_response_code); ZTS_API int ZTCALL zts_central_get_self(int *http_response_code);
/** /**
* @brief Retrieve a Network. * @brief Retrieve a Network.
* *
* @return Standard HTTP response codes. * @return Standard HTTP response codes.
*/ */
ZTS_API int ZTCALL zts_central_api_get_network(int *http_response_code, uint64_t nwid); ZTS_API int ZTCALL zts_central_get_network(
int *http_response_code, uint64_t nwid);
/** /**
* @brief Update or create a Network. * @brief Update or create a Network.
* *
* Only fields marked as [rw] can be directly modified. If other fields are * Only fields marked as [rw] can be directly modified. If other fields are
* present in the posted request they are ignored. New networks can be created by POSTing * present in the posted request they are ignored. New networks can be
* to /api/network with no networkId parameter. The server will create a random unused * created by POSTing to /api/network with no networkId parameter. The server
* network ID and return the new network record. * will create a random unused network ID and return the new network record.
* *
* @return Standard HTTP response codes. * @return Standard HTTP response codes.
*/ */
ZTS_API int ZTCALL zts_central_api_update_network(int *http_response_code, uint64_t nwid); ZTS_API int ZTCALL zts_central_update_network(
int *http_response_code, uint64_t nwid);
/** /**
* @brief Delete a Network. * @brief Delete a Network.
@@ -998,7 +1004,8 @@ ZTS_API int ZTCALL zts_central_api_update_network(int *http_response_code, uint6
* *
* @return Standard HTTP response codes. * @return Standard HTTP response codes.
*/ */
ZTS_API int ZTCALL zts_central_api_delete_network(int *http_response_code, uint64_t nwid); ZTS_API int ZTCALL zts_central_delete_network(
int *http_response_code, uint64_t nwid);
/** /**
* @brief Get All Viewable Networks. * @brief Get All Viewable Networks.
@@ -1007,13 +1014,14 @@ ZTS_API int ZTCALL zts_central_api_delete_network(int *http_response_code, uint6
* *
* @return Standard HTTP response codes. * @return Standard HTTP response codes.
*/ */
ZTS_API int ZTCALL zts_central_api_get_networks(int *http_response_code); ZTS_API int ZTCALL zts_central_get_networks(int *http_response_code);
/** /**
* @brief Retrieve a Member. * @brief Retrieve a Member.
* *
* @return Standard HTTP response codes. * @return Standard HTTP response codes.
*/ */
ZTS_API int ZTCALL zts_central_api_get_member(int *http_response_code, int64_t nwid, uint64_t nodeid); ZTS_API int ZTCALL zts_central_get_member(
int *http_response_code, uint64_t nwid, uint64_t nodeid);
/** /**
* @brief Update or add a Member. * @brief Update or add a Member.
@@ -1022,17 +1030,20 @@ ZTS_API int ZTCALL zts_central_api_get_member(int *http_response_code, int64_t n
* *
* @return Standard HTTP response codes. * @return Standard HTTP response codes.
*/ */
ZTS_API int ZTCALL zts_central_api_update_member(int *http_response_code, uint64_t nwid, uint64_t nodeid, char *post_data); ZTS_API int ZTCALL zts_central_update_member(
int *http_response_code, uint64_t nwid, uint64_t nodeid, char *post_data);
/** /**
* @brief Authorize or (De)authorize a node on a network. This operation is idempotent. * @brief Authorize or (De)authorize a node on a network. This operation
* is idempotent.
* *
* @param nwid The network ID * @param nwid The network ID
* @param nodeid The node ID * @param nodeid The node ID
* @param is_authed Boolean value for whether this node should be authorized * @param is_authed Boolean value for whether this node should be authorized
* @return Standard HTTP response codes. ZTS_ERR_ARG invalid argument specified. * @return Standard HTTP response codes. ZTS_ERR_ARG invalid argument specified.
*/ */
ZTS_API int ZTCALL zts_set_node_auth(int *http_response_code, uint64_t nwid, uint64_t nodeid, uint64_t is_authed); ZTS_API int ZTCALL zts_central_set_node_auth(
int *http_response_code, uint64_t nwid, uint64_t nodeid, uint8_t is_authed);
/** /**
* @brief Get All Members of a Network. * @brief Get All Members of a Network.
@@ -1041,7 +1052,8 @@ ZTS_API int ZTCALL zts_set_node_auth(int *http_response_code, uint64_t nwid, uin
* *
* @return Standard HTTP response codes. * @return Standard HTTP response codes.
*/ */
ZTS_API int ZTCALL zts_central_api_get_members_of_network(int *http_response_code, uint64_t nwid); ZTS_API int ZTCALL zts_central_get_members_of_network(
int *http_response_code, uint64_t nwid);
#endif // NO_CENTRAL_API #endif // NO_CENTRAL_API

View File

@@ -26,14 +26,14 @@
#include "Debug.hpp" #include "Debug.hpp"
#include "ZeroTierSockets.h" #include "ZeroTierSockets.h"
char central_api_url[CENRTAL_API_MAX_URL_LEN]; char api_url[ZTS_CENRTAL_MAX_URL_LEN];
char central_api_token[CENTRAL_API_TOKEN_LEN+1]; char api_token[ZTS_CENTRAL_TOKEN_LEN+1];
char *_response_buffer; char *_resp_buf;
int _response_buffer_len; int _resp_buf_len;
int _response_buffer_offset; int _resp_buf_offset;
static int8_t _api_access_modes; static int8_t _access_modes;
static int8_t _bIsVerbose; static int8_t _bIsVerbose;
static int8_t _bInit; static int8_t _bInit;
@@ -47,100 +47,101 @@ extern "C" {
size_t on_data(void *buffer, size_t size, size_t nmemb, void *userp) size_t on_data(void *buffer, size_t size, size_t nmemb, void *userp)
{ {
DEBUG_INFO("buffer=%p, size=%zu, nmemb=%zu, userp=%p", buffer, size, nmemb, userp); DEBUG_INFO("buf=%p,size=%zu,nmemb=%zu,userp=%p", buffer, size, nmemb, userp);
int byte_count = (size * nmemb); int byte_count = (size * nmemb);
if (_response_buffer_offset + byte_count >= _response_buffer_len) { if (_resp_buf_offset + byte_count >= _resp_buf_len) {
DEBUG_ERROR("Out of buffer space. Cannot store response from server"); DEBUG_ERROR("Out of buffer space. Cannot store response from server");
return 0; // Signal to libcurl that our buffer is full (triggers a write error.) return 0; // Signal to libcurl that our buffer is full (triggers a write error.)
} }
memcpy(_response_buffer+_response_buffer_offset, buffer, byte_count); memcpy(_resp_buf+_resp_buf_offset, buffer, byte_count);
_response_buffer_offset += byte_count; _resp_buf_offset += byte_count;
return byte_count; return byte_count;
} }
void zts_central_api_set_access(int8_t modes) void zts_central_set_access_mode(int8_t modes)
{ {
_api_access_modes = modes; _access_modes = modes;
} }
void zts_central_api_set_verbose(int8_t is_verbose) void zts_central_set_verbose(int8_t is_verbose)
{ {
_bIsVerbose = is_verbose; _bIsVerbose = is_verbose;
} }
void zts_central_api_clear_response_buffer() void zts_central_clear_resp_buf()
{ {
Mutex::Lock _l(_responseBuffer_m); Mutex::Lock _l(_responseBuffer_m);
memset(_response_buffer, 0, _response_buffer_len); memset(_resp_buf, 0, _resp_buf_len);
_response_buffer_offset = 0; _resp_buf_offset = 0;
} }
int zts_central_api_init(const char *url_str, const char *token_str, char *response_buffer, uint32_t response_buffer_len) int zts_central_init(
const char *url_str, const char *token_str, char *resp_buf, uint32_t resp_buf_len)
{ {
_api_access_modes = ZTS_CENTRAL_READ; // Defauly read-only _access_modes = ZTS_CENTRAL_READ; // Defauly read-only
_bIsVerbose = 0; // Default disable libcurl verbose output _bIsVerbose = 0; // Default disable libcurl verbose output
Mutex::Lock _l(_responseBuffer_m); Mutex::Lock _l(_responseBuffer_m);
if (response_buffer_len == 0) { if (resp_buf_len == 0) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
_response_buffer = response_buffer; _resp_buf = resp_buf;
_response_buffer_len = response_buffer_len; _resp_buf_len = resp_buf_len;
_response_buffer_offset = 0; _resp_buf_offset = 0;
// Initialize all curl internal submodules // Initialize all curl internal submodules
curl_global_init(CURL_GLOBAL_ALL); curl_global_init(CURL_GLOBAL_ALL);
int url_len = strlen(url_str); int url_len = strlen(url_str);
if (url_len < 3 || url_len > CENRTAL_API_MAX_URL_LEN) { if (url_len < 3 || url_len > ZTS_CENRTAL_MAX_URL_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} else { } else {
memset(central_api_url, 0, CENRTAL_API_MAX_URL_LEN); memset(api_url, 0, ZTS_CENRTAL_MAX_URL_LEN);
memcpy(central_api_url, url_str, url_len); memcpy(api_url, url_str, url_len);
} }
int token_len = strlen(token_str); int token_len = strlen(token_str);
if (token_len != CENTRAL_API_TOKEN_LEN) { if (token_len != ZTS_CENTRAL_TOKEN_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} else { } else {
memset(central_api_token, 0, CENTRAL_API_TOKEN_LEN); memset(api_token, 0, ZTS_CENTRAL_TOKEN_LEN);
memcpy(central_api_token, token_str, token_len); memcpy(api_token, token_str, token_len);
} }
_bInit = true; _bInit = true;
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
void zts_central_api_cleanup() void zts_central_cleanup()
{ {
curl_global_cleanup(); curl_global_cleanup();
} }
int _central_req(int request_type, char *central_api_str, int _central_req(int request_type, char *central_str,
char *api_route_str, char *token_str, int *response_code, char *post_data) char *api_route_str, char *token_str, int *response_code, char *post_data)
{ {
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
if (!_bInit) { if (!_bInit) {
DEBUG_ERROR("Error: Central API must be initialized first. Call zts_central_api_init()"); DEBUG_ERROR("Error: Central API must be initialized first. Call zts_central_init()");
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
if (request_type == HTTP_GET && !(_api_access_modes & ZTS_CENTRAL_READ)) { if (request_type == ZTS_HTTP_GET && !(_access_modes & ZTS_CENTRAL_READ)) {
DEBUG_ERROR("Error: Incorrect access mode. Need (ZTS_CENTRAL_READ) permission"); DEBUG_ERROR("Error: Incorrect access mode. Need (ZTS_CENTRAL_READ) permission");
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
if (request_type == HTTP_POST && !(_api_access_modes & ZTS_CENTRAL_WRITE)) { if (request_type == ZTS_HTTP_POST && !(_access_modes & ZTS_CENTRAL_WRITE)) {
DEBUG_ERROR("Error: Incorrect access mode. Need (ZTS_CENTRAL_WRITE) permission"); DEBUG_ERROR("Error: Incorrect access mode. Need (ZTS_CENTRAL_WRITE) permission");
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
zts_central_api_clear_response_buffer(); zts_central_clear_resp_buf();
int central_api_strlen = strlen(central_api_str); int central_strlen = strlen(central_str);
int api_route_strlen = strlen(api_route_str); int api_route_strlen = strlen(api_route_str);
int token_strlen = strlen(token_str); int token_strlen = strlen(token_str);
int url_len = central_api_strlen + api_route_strlen; int url_len = central_strlen + api_route_strlen;
if (token_strlen > CENTRAL_API_TOKEN_LEN) { if (token_strlen > ZTS_CENTRAL_TOKEN_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
if (url_len > CENRTAL_API_MAX_URL_LEN) { if (url_len > ZTS_CENRTAL_MAX_URL_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
char req_url[CENRTAL_API_MAX_URL_LEN]; char req_url[ZTS_CENRTAL_MAX_URL_LEN];
strcpy(req_url, central_api_str); strcpy(req_url, central_str);
strcat(req_url, api_route_str); strcat(req_url, api_route_str);
CURL *curl; CURL *curl;
@@ -151,9 +152,9 @@ int _central_req(int request_type, char *central_api_str,
} }
struct curl_slist *hs=NULL; struct curl_slist *hs=NULL;
char auth_str[CENTRAL_API_TOKEN_LEN + 32]; char auth_str[ZTS_CENTRAL_TOKEN_LEN + 32];
if (token_strlen == CENTRAL_API_TOKEN_LEN) { if (token_strlen == ZTS_CENTRAL_TOKEN_LEN) {
memset(auth_str, 0, CENTRAL_API_TOKEN_LEN + 32); memset(auth_str, 0, ZTS_CENTRAL_TOKEN_LEN + 32);
sprintf(auth_str, "Authorization: Bearer %s", token_str); sprintf(auth_str, "Authorization: Bearer %s", token_str);
} }
@@ -161,7 +162,7 @@ int _central_req(int request_type, char *central_api_str,
hs = curl_slist_append(hs, "Content-Type: application/json"); hs = curl_slist_append(hs, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hs); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hs);
curl_easy_setopt(curl, CURLOPT_URL, req_url); curl_easy_setopt(curl, CURLOPT_URL, req_url);
// example.com is redirected, so we tell libcurl to follow redirection // example.com is redirected, so we tell libcurl to follow redirection
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
if (_bIsVerbose) { if (_bIsVerbose) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
@@ -169,18 +170,18 @@ int _central_req(int request_type, char *central_api_str,
// Tell curl to use our write function // Tell curl to use our write function
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, on_data); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, on_data);
if (request_type == HTTP_GET) { if (request_type == ZTS_HTTP_GET) {
// Nothing // Nothing
DEBUG_INFO("Request (GET) = %s", api_route_str); DEBUG_INFO("Request (GET) = %s", api_route_str);
} }
if (request_type == HTTP_POST) { if (request_type == ZTS_HTTP_POST) {
DEBUG_INFO("Request (POST) = %s", api_route_str); DEBUG_INFO("Request (POST) = %s", api_route_str);
if (post_data) { if (post_data) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
} }
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
} }
if (request_type == HTTP_DELETE) { if (request_type == ZTS_HTTP_DELETE) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
} }
//curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); // Consider 400-500 series code as failures //curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); // Consider 400-500 series code as failures
@@ -192,7 +193,7 @@ int _central_req(int request_type, char *central_api_str,
long hrc = 0; long hrc = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &hrc); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &hrc);
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &elapsed_time); curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &elapsed_time);
DEBUG_INFO("Request took %f second(s). HTTP code (%ld)", elapsed_time, hrc); DEBUG_INFO("Req. took %f second(s). HTTP code (%ld)", elapsed_time, hrc);
*response_code = hrc; *response_code = hrc;
//curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url); //curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
} else { } else {
@@ -203,73 +204,83 @@ int _central_req(int request_type, char *central_api_str,
return err; return err;
} }
int zts_get_last_response_buffer(char *dest_buffer, int dest_buffer_len) int zts_get_last_resp_buf(char *dest_buffer, int dest_buf_len)
{ {
if (dest_buffer_len <= _response_buffer_offset) { if (dest_buf_len <= _resp_buf_offset) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
int amount_to_copy = dest_buffer_len < _response_buffer_len ? dest_buffer_len : _response_buffer_len; int sz = dest_buf_len < _resp_buf_len ? dest_buf_len : _resp_buf_len;
memcpy(dest_buffer, _response_buffer, amount_to_copy); memcpy(dest_buffer, _resp_buf, sz);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_central_api_get_status(int *http_response_code) int zts_central_get_status(int *resp_code)
{ {
return _central_req(HTTP_GET, central_api_url, (char*)"/api/status", central_api_token, http_response_code, NULL); return _central_req(
ZTS_HTTP_GET, api_url, (char*)"/api/status", api_token, resp_code, NULL);
} }
int zts_central_api_get_self(int *http_response_code) int zts_central_get_self(int *resp_code)
{ {
return _central_req(HTTP_GET, central_api_url, (char*)"/api/self", central_api_token, http_response_code, NULL); return _central_req(
ZTS_HTTP_GET, api_url, (char*)"/api/self", api_token, resp_code, NULL);
} }
int zts_central_api_get_network(int *http_response_code, uint64_t nwid) int zts_central_get_network(int *resp_code, uint64_t nwid)
{ {
char req[64]; char req[64];
sprintf(req, "/api/network/%llx", nwid); sprintf(req, "/api/network/%llx", nwid);
return _central_req(HTTP_GET, central_api_url, req, central_api_token, http_response_code, NULL); return _central_req(
ZTS_HTTP_GET, api_url, req, api_token, resp_code, NULL);
} }
int zts_central_api_update_network(int *http_response_code, uint64_t nwid) int zts_central_update_network(int *resp_code, uint64_t nwid)
{ {
char req[64]; char req[64];
sprintf(req, "/api/network/%llx", nwid); sprintf(req, "/api/network/%llx", nwid);
return _central_req(HTTP_POST, central_api_url, req, central_api_token, http_response_code, NULL); return _central_req(
ZTS_HTTP_POST, api_url, req, api_token, resp_code, NULL);
} }
int zts_central_api_delete_network(int *http_response_code, uint64_t nwid) int zts_central_delete_network(int *resp_code, uint64_t nwid)
{ {
char req[64]; char req[64];
sprintf(req, "/api/network/%llx", nwid); sprintf(req, "/api/network/%llx", nwid);
return _central_req(HTTP_DELETE, central_api_url, req, central_api_token, http_response_code, NULL); return _central_req(
ZTS_HTTP_DELETE, api_url, req, api_token, resp_code, NULL);
} }
int zts_central_api_get_networks(int *http_response_code) int zts_central_get_networks(int *resp_code)
{ {
return _central_req(HTTP_GET, central_api_url, (char*)"/api/network", central_api_token, http_response_code, NULL); return _central_req(
ZTS_HTTP_GET, api_url, (char*)"/api/network", api_token, resp_code, NULL);
} }
int zts_central_api_get_member(int *http_response_code, uint64_t nwid, uint64_t nodeid) int zts_central_get_member(int *resp_code, uint64_t nwid, uint64_t nodeid)
{ {
if (nwid == 0 || nodeid == 0) { if (nwid == 0 || nodeid == 0) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
char req[64]; char req[64];
sprintf(req, "/api/network/%llx/member/%llx", nwid, nodeid); sprintf(req, "/api/network/%llx/member/%llx", nwid, nodeid);
return _central_req(HTTP_GET, central_api_url, req, central_api_token, http_response_code, NULL); return _central_req(
ZTS_HTTP_GET, api_url, req, api_token, resp_code, NULL);
} }
int zts_central_api_update_member(int *http_response_code, uuint64_t nwid, uuint64_t nodeid, char *post_data) int zts_central_update_member(
int *resp_code, uint64_t nwid, uint64_t nodeid, char *post_data)
{ {
if (nwid == 0 || nodeid == 0 || post_data == NULL) { if (nwid == 0 || nodeid == 0 || post_data == NULL) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
char req[64]; char req[64];
sprintf(req, "/api/network/%llx/member/%llx", nwid, nodeid); sprintf(req, "/api/network/%llx/member/%llx", nwid, nodeid);
return _central_req(HTTP_POST, central_api_url, req, central_api_token, http_response_code, post_data); return _central_req(
ZTS_HTTP_POST, api_url, req, api_token, resp_code, post_data);
} }
int zts_set_node_auth(int *http_response_code, uint64_t nwid, uint64_t nodeid, int8_t is_authed) int zts_central_set_node_auth(
int *resp_code, uint64_t nwid, uint64_t nodeid, uint8_t is_authed)
{ {
if (is_authed != 0 && is_authed != 1) { if (is_authed != 0 && is_authed != 1) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
@@ -281,19 +292,20 @@ int zts_set_node_auth(int *http_response_code, uint64_t nwid, uint64_t nodeid, i
if (is_authed == ZTS_CENTRAL_NODE_AUTH_FALSE) { if (is_authed == ZTS_CENTRAL_NODE_AUTH_FALSE) {
sprintf(config_data, "{\"config\": {\"authorized\": false} }"); sprintf(config_data, "{\"config\": {\"authorized\": false} }");
} }
return zts_central_api_update_member(http_response_code, nwid, nodeid, config_data); return zts_central_update_member(resp_code, nwid, nodeid, config_data);
} }
int zts_central_api_get_members_of_network(int *http_response_code, uint64_t nwid) int zts_central_get_members_of_network(int *resp_code, uint64_t nwid)
{ {
char req[64]; char req[64];
sprintf(req, "/api/network/%llx/member", nwid); sprintf(req, "/api/network/%llx/member", nwid);
return _central_req(HTTP_GET, central_api_url, req, central_api_token, http_response_code, NULL); return _central_req(
ZTS_HTTP_GET, api_url, req, api_token, resp_code, NULL);
} }
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif
#endif // NO_CENTRAL_API #endif // ZTS_ENABLE_CENTRAL_API
#endif // _H #endif // _H