mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-07 13:03:45 +02:00
Some cleanup, revision to Endpoint string format, stub out HTTP API callbacks.
This commit is contained in:
parent
016d85b169
commit
40d48c969c
7 changed files with 243 additions and 128 deletions
|
@ -30,14 +30,14 @@ char *Endpoint::toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept
|
||||||
break;
|
break;
|
||||||
case ZT_ENDPOINT_TYPE_ZEROTIER:
|
case ZT_ENDPOINT_TYPE_ZEROTIER:
|
||||||
s[0] = s_endpointTypeChars[ZT_ENDPOINT_TYPE_ZEROTIER];
|
s[0] = s_endpointTypeChars[ZT_ENDPOINT_TYPE_ZEROTIER];
|
||||||
s[1] = '=';
|
s[1] = '/';
|
||||||
zt().toString(s + 2);
|
zt().toString(s + 2);
|
||||||
break;
|
break;
|
||||||
case ZT_ENDPOINT_TYPE_ETHERNET:
|
case ZT_ENDPOINT_TYPE_ETHERNET:
|
||||||
case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
|
case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
|
||||||
case ZT_ENDPOINT_TYPE_BLUETOOTH:
|
case ZT_ENDPOINT_TYPE_BLUETOOTH:
|
||||||
s[0] = s_endpointTypeChars[this->type];
|
s[0] = s_endpointTypeChars[this->type];
|
||||||
s[1] = '=';
|
s[1] = '/';
|
||||||
eth().toString(s + 2);
|
eth().toString(s + 2);
|
||||||
break;
|
break;
|
||||||
case ZT_ENDPOINT_TYPE_IP:
|
case ZT_ENDPOINT_TYPE_IP:
|
||||||
|
@ -45,7 +45,7 @@ char *Endpoint::toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept
|
||||||
case ZT_ENDPOINT_TYPE_IP_TCP:
|
case ZT_ENDPOINT_TYPE_IP_TCP:
|
||||||
case ZT_ENDPOINT_TYPE_IP_HTTP:
|
case ZT_ENDPOINT_TYPE_IP_HTTP:
|
||||||
s[0] = s_endpointTypeChars[this->type];
|
s[0] = s_endpointTypeChars[this->type];
|
||||||
s[1] = '=';
|
s[1] = '/';
|
||||||
ip().toString(s + 2);
|
ip().toString(s + 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -59,13 +59,32 @@ bool Endpoint::fromString(const char *s) noexcept
|
||||||
if ((!s) || (!*s))
|
if ((!s) || (!*s))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const char *start = strchr(s, '=');
|
// Locate first slash, colon, and dot to help classify input.
|
||||||
if (start++ != nullptr) {
|
const char *slash = nullptr, *colon = nullptr, *dot = nullptr;
|
||||||
// Parse a fully qualified type-address format Endpoint.
|
for(const char *p=s;;++p) {
|
||||||
|
const char c = *p;
|
||||||
|
if (c != 0) {
|
||||||
|
switch (c) {
|
||||||
|
case '/':
|
||||||
|
slash = p;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
colon = p;
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
dot = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((slash != nullptr) && (((colon == nullptr) && (dot == nullptr)) || (colon > slash) || (dot > slash))) {
|
||||||
|
// Detect a fully specified endpoint of the form type/ip/port or type/other,
|
||||||
|
// but don't detect ip/port as a fully specified endpoint.
|
||||||
char tmp[16];
|
char tmp[16];
|
||||||
for (unsigned int i=0;i<16;++i) {
|
for (unsigned int i=0;i<16;++i) {
|
||||||
char ss = s[i];
|
const char ss = s[i];
|
||||||
if (ss == '-') {
|
if (ss == '/') {
|
||||||
tmp[i] = 0;
|
tmp[i] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -74,32 +93,33 @@ bool Endpoint::fromString(const char *s) noexcept
|
||||||
tmp[15] = 0;
|
tmp[15] = 0;
|
||||||
this->type = (ZT_EndpointType)Utils::strToUInt(tmp);
|
this->type = (ZT_EndpointType)Utils::strToUInt(tmp);
|
||||||
|
|
||||||
Fingerprint tmpfp;
|
++slash;
|
||||||
MAC tmpmac;
|
|
||||||
switch (this->type) {
|
switch (this->type) {
|
||||||
case ZT_ENDPOINT_TYPE_NIL:
|
case ZT_ENDPOINT_TYPE_NIL:
|
||||||
break;
|
break;
|
||||||
case ZT_ENDPOINT_TYPE_ZEROTIER:
|
case ZT_ENDPOINT_TYPE_ZEROTIER: {
|
||||||
if (!tmpfp.fromString(start))
|
Fingerprint tmpfp;
|
||||||
|
if (!tmpfp.fromString(slash))
|
||||||
return false;
|
return false;
|
||||||
this->value.fp = tmpfp;
|
this->value.fp = tmpfp;
|
||||||
break;
|
} break;
|
||||||
case ZT_ENDPOINT_TYPE_ETHERNET:
|
case ZT_ENDPOINT_TYPE_ETHERNET:
|
||||||
case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
|
case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
|
||||||
case ZT_ENDPOINT_TYPE_BLUETOOTH:
|
case ZT_ENDPOINT_TYPE_BLUETOOTH: {
|
||||||
tmpmac.fromString(start);
|
MAC tmpmac;
|
||||||
|
tmpmac.fromString(slash);
|
||||||
this->value.mac = tmpmac.toInt();
|
this->value.mac = tmpmac.toInt();
|
||||||
break;
|
} break;
|
||||||
case ZT_ENDPOINT_TYPE_IP:
|
case ZT_ENDPOINT_TYPE_IP:
|
||||||
case ZT_ENDPOINT_TYPE_IP_UDP:
|
case ZT_ENDPOINT_TYPE_IP_UDP:
|
||||||
case ZT_ENDPOINT_TYPE_IP_TCP:
|
case ZT_ENDPOINT_TYPE_IP_TCP:
|
||||||
case ZT_ENDPOINT_TYPE_IP_HTTP:
|
case ZT_ENDPOINT_TYPE_IP_HTTP:
|
||||||
if (!asInetAddress(this->value.ss).fromString(start))
|
if (!asInetAddress(this->value.ss).fromString(slash))
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if ((strchr(s, ':')) || (strchr(s, '.'))) {
|
} else if (((colon != nullptr) || (dot != nullptr)) && (slash != nullptr)) {
|
||||||
// Parse raw IP/port strings as IP_UDP endpoints.
|
// Parse raw IP/port strings as IP_UDP endpoints.
|
||||||
this->type = ZT_ENDPOINT_TYPE_IP_UDP;
|
this->type = ZT_ENDPOINT_TYPE_IP_UDP;
|
||||||
if (!asInetAddress(this->value.ss).fromString(s))
|
if (!asInetAddress(this->value.ss).fromString(s))
|
||||||
|
|
|
@ -86,7 +86,9 @@ struct p_CompareLittleEndian
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
ZT_INLINE bool operator()(const uint64_t a,const uint64_t b) const noexcept { return Utils::swapBytes(a) < Utils::swapBytes(b); }
|
ZT_INLINE bool operator()(const uint64_t a,const uint64_t b) const noexcept { return Utils::swapBytes(a) < Utils::swapBytes(b); }
|
||||||
#else
|
#else
|
||||||
ZT_INLINE bool operator()(const uint64_t a,const uint64_t b) const noexcept { return a < b; }
|
ZT_INLINE bool operator()(const uint64_t a, const uint64_t b) const noexcept
|
||||||
|
{ return a < b; }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -159,7 +161,8 @@ bool Identity::generate(const Type t)
|
||||||
delete[] genmem;
|
delete[] genmem;
|
||||||
m_fp.address = address; // address comes from PoW hash for type 0 identities
|
m_fp.address = address; // address comes from PoW hash for type 0 identities
|
||||||
m_computeHash();
|
m_computeHash();
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case P384: {
|
case P384: {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -185,7 +188,8 @@ bool Identity::generate(const Type t)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -225,14 +229,13 @@ void Identity::hashWithPrivate(uint8_t h[ZT_FINGERPRINT_HASH_SIZE]) const
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case C25519:
|
case C25519:
|
||||||
SHA384(h, m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
SHA384(h, m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||||
break;
|
return;
|
||||||
case P384:
|
case P384:
|
||||||
SHA384(h, m_pub, sizeof(m_pub), m_priv, sizeof(m_priv));
|
SHA384(h, m_pub, sizeof(m_pub), m_priv, sizeof(m_priv));
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Utils::zero<48>(h);
|
}
|
||||||
|
Utils::zero< ZT_FINGERPRINT_HASH_SIZE >(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Identity::sign(const void *data, unsigned int len, void *sig, unsigned int siglen) const
|
unsigned int Identity::sign(const void *data, unsigned int len, void *sig, unsigned int siglen) const
|
||||||
|
@ -276,20 +279,16 @@ bool Identity::verify(const void *data, unsigned int len, const void *sig, unsig
|
||||||
|
|
||||||
bool Identity::agree(const Identity &id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) const
|
bool Identity::agree(const Identity &id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) const
|
||||||
{
|
{
|
||||||
uint8_t rawkey[128];
|
uint8_t rawkey[128], h[64];
|
||||||
uint8_t h[64];
|
if (likely(m_hasPrivate)) {
|
||||||
if (m_hasPrivate) {
|
if ((m_type == C25519) || (id.m_type == C25519)) {
|
||||||
if (m_type == C25519) {
|
|
||||||
if ((id.m_type == C25519) || (id.m_type == P384)) {
|
|
||||||
// If we are a C25519 key we can agree with another C25519 key or with only the
|
// If we are a C25519 key we can agree with another C25519 key or with only the
|
||||||
// C25519 portion of a type 1 P-384 key.
|
// C25519 portion of a type 1 P-384 key.
|
||||||
C25519::agree(m_priv, id.m_pub, rawkey);
|
C25519::agree(m_priv, id.m_pub, rawkey);
|
||||||
SHA512(h, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
SHA512(h, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||||
Utils::copy< ZT_SYMMETRIC_KEY_SIZE >(key, h);
|
Utils::copy< ZT_SYMMETRIC_KEY_SIZE >(key, h);
|
||||||
return true;
|
return true;
|
||||||
}
|
} else if ((m_type == P384) && (id.m_type == P384)) {
|
||||||
} else if (m_type == P384) {
|
|
||||||
if (id.m_type == P384) {
|
|
||||||
// For another P384 identity we execute DH agreement with BOTH keys and then
|
// For another P384 identity we execute DH agreement with BOTH keys and then
|
||||||
// hash the results together. For those (cough FIPS cough) who only consider
|
// hash the results together. For those (cough FIPS cough) who only consider
|
||||||
// P384 to be kosher, the C25519 secret can be considered a "salt"
|
// P384 to be kosher, the C25519 secret can be considered a "salt"
|
||||||
|
@ -297,16 +296,8 @@ bool Identity::agree(const Identity &id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) con
|
||||||
// your traffic is also protected by C25519.
|
// your traffic is also protected by C25519.
|
||||||
C25519::agree(m_priv, id.m_pub, rawkey);
|
C25519::agree(m_priv, id.m_pub, rawkey);
|
||||||
ECC384ECDH(id.m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE, rawkey + ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
ECC384ECDH(id.m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE, rawkey + ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||||
SHA384(h, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE + ZT_ECC384_SHARED_SECRET_SIZE);
|
SHA384(key, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE + ZT_ECC384_SHARED_SECRET_SIZE);
|
||||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key, h);
|
|
||||||
return true;
|
return true;
|
||||||
} else if (id.m_type == C25519) {
|
|
||||||
// If the other identity is a C25519 identity we can agree using only that type.
|
|
||||||
C25519::agree(m_priv, id.m_pub, rawkey);
|
|
||||||
SHA512(h, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
|
||||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key, h);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -190,7 +190,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_INLINE String toString() const
|
ZT_INLINE String toString() const
|
||||||
{ char tmp[18]; return String(toString(tmp)); }
|
{
|
||||||
|
char tmp[18];
|
||||||
|
return String(toString(tmp));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a MAC address in hex format with or without : separators and ignoring non-hex characters.
|
* Parse a MAC address in hex format with or without : separators and ignoring non-hex characters.
|
||||||
|
|
|
@ -214,6 +214,20 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZT_ResultCode Node::processHTTPResponse(
|
||||||
|
void *tptr,
|
||||||
|
int64_t now,
|
||||||
|
void *requestId,
|
||||||
|
int responseCode,
|
||||||
|
const char **headerNames,
|
||||||
|
const char **headerValues,
|
||||||
|
const void *body,
|
||||||
|
unsigned int bodySize,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
return ZT_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
ZT_ResultCode Node::processBackgroundTasks(
|
ZT_ResultCode Node::processBackgroundTasks(
|
||||||
void *tPtr,
|
void *tPtr,
|
||||||
int64_t now,
|
int64_t now,
|
||||||
|
@ -899,6 +913,27 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ZT_ResultCode ZT_Node_processHTTPResponse(
|
||||||
|
ZT_Node *node,
|
||||||
|
void *tptr,
|
||||||
|
int64_t now,
|
||||||
|
void *requestId,
|
||||||
|
int responseCode,
|
||||||
|
const char **headerNames,
|
||||||
|
const char **headerValues,
|
||||||
|
const void *body,
|
||||||
|
unsigned int bodySize,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return reinterpret_cast<ZeroTier::Node *>(node)->processHTTPResponse(tptr, now, requestId, responseCode, headerNames, headerValues, body, bodySize, flags);
|
||||||
|
} catch (std::bad_alloc &exc) {
|
||||||
|
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||||
|
} catch (...) {
|
||||||
|
return ZT_RESULT_ERROR_INTERNAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node, void *tptr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline)
|
enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node, void *tptr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -71,6 +71,17 @@ public:
|
||||||
unsigned int frameLength,
|
unsigned int frameLength,
|
||||||
volatile int64_t *nextBackgroundTaskDeadline);
|
volatile int64_t *nextBackgroundTaskDeadline);
|
||||||
|
|
||||||
|
ZT_ResultCode processHTTPResponse(
|
||||||
|
void *tptr,
|
||||||
|
int64_t now,
|
||||||
|
void *requestId,
|
||||||
|
int responseCode,
|
||||||
|
const char **headerNames,
|
||||||
|
const char **headerValues,
|
||||||
|
const void *body,
|
||||||
|
unsigned int bodySize,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
ZT_ResultCode processBackgroundTasks(
|
ZT_ResultCode processBackgroundTasks(
|
||||||
void *tPtr,
|
void *tPtr,
|
||||||
int64_t now,
|
int64_t now,
|
||||||
|
|
|
@ -53,11 +53,9 @@ namespace Utils {
|
||||||
#define ZT_ROL32(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
|
#define ZT_ROL32(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
|
||||||
|
|
||||||
#ifdef ZT_ARCH_X64
|
#ifdef ZT_ARCH_X64
|
||||||
|
|
||||||
struct CPUIDRegisters
|
struct CPUIDRegisters
|
||||||
{
|
{
|
||||||
CPUIDRegisters() noexcept;
|
CPUIDRegisters() noexcept;
|
||||||
|
|
||||||
bool rdrand;
|
bool rdrand;
|
||||||
bool aes;
|
bool aes;
|
||||||
bool avx;
|
bool avx;
|
||||||
|
@ -68,7 +66,6 @@ struct CPUIDRegisters
|
||||||
bool sha;
|
bool sha;
|
||||||
bool fsrm;
|
bool fsrm;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const CPUIDRegisters CPUID;
|
extern const CPUIDRegisters CPUID;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -285,10 +282,22 @@ static ZT_INLINE uint32_t hash32(uint32_t x) noexcept
|
||||||
*/
|
*/
|
||||||
static ZT_INLINE bool allZero(const void *const b, unsigned int l) noexcept
|
static ZT_INLINE bool allZero(const void *const b, unsigned int l) noexcept
|
||||||
{
|
{
|
||||||
|
const uint8_t *p = reinterpret_cast<const uint8_t *>(b);
|
||||||
|
|
||||||
|
#ifndef ZT_NO_UNALIGNED_ACCESS
|
||||||
|
while (l >= 8) {
|
||||||
|
if (*reinterpret_cast<const uint64_t *>(p) != 0)
|
||||||
|
return false;
|
||||||
|
p += 8;
|
||||||
|
l -= 8;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (unsigned int i = 0; i < l; ++i) {
|
for (unsigned int i = 0; i < l; ++i) {
|
||||||
if (reinterpret_cast<const uint8_t *>(b)[i] != 0)
|
if (reinterpret_cast<const uint8_t *>(p)[i] != 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1459,15 +1459,6 @@ typedef int (*ZT_StateGetFunction)(
|
||||||
/**
|
/**
|
||||||
* Function to send a ZeroTier packet out over the physical wire (L2/L3)
|
* Function to send a ZeroTier packet out over the physical wire (L2/L3)
|
||||||
*
|
*
|
||||||
* Parameters:
|
|
||||||
* (1) Node
|
|
||||||
* (2) User pointer
|
|
||||||
* (3) Local socket or -1 for "all" or "any"
|
|
||||||
* (4) Remote address
|
|
||||||
* (5) Packet data
|
|
||||||
* (6) Packet length
|
|
||||||
* (7) Desired IP TTL or 0 to use default
|
|
||||||
*
|
|
||||||
* If there is only one local socket, the local socket can be ignored.
|
* If there is only one local socket, the local socket can be ignored.
|
||||||
* If the local socket is -1, the packet should be sent out from all
|
* If the local socket is -1, the packet should be sent out from all
|
||||||
* bound local sockets or a random bound local socket.
|
* bound local sockets or a random bound local socket.
|
||||||
|
@ -1490,6 +1481,29 @@ typedef int (*ZT_WirePacketSendFunction)(
|
||||||
unsigned int, /* Packet length */
|
unsigned int, /* Packet length */
|
||||||
unsigned int); /* TTL or 0 to use default */
|
unsigned int); /* TTL or 0 to use default */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to initiate HTTP requests
|
||||||
|
*
|
||||||
|
* The supplied HTTP request identifier is an opaque pointer that must
|
||||||
|
* be returned via ZT_Node_processHttpResponse(). If this handler is
|
||||||
|
* implemented then ZT_Node_processHttpResponse() must be called for
|
||||||
|
* each call made by the core to this. This function itself does not
|
||||||
|
* return any error code; use processHttpResponse() for that. It may
|
||||||
|
* be called directly from inside the implementation of this.
|
||||||
|
*/
|
||||||
|
typedef void (*ZT_HTTPRequestFunction)(
|
||||||
|
ZT_Node *, /* Node */
|
||||||
|
void *, /* User ptr */
|
||||||
|
void *, /* Thread ptr */
|
||||||
|
void *, /* HTTP request identifier */
|
||||||
|
const char *, /* HTTP method (GET, HEAD, etc.) */
|
||||||
|
const char *, /* URL */
|
||||||
|
const char **, /* Header names, NULL terminated */
|
||||||
|
const char **, /* Header values, NULL terminated */
|
||||||
|
const void *, /* Request body or NULL if none */
|
||||||
|
unsigned int, /* Length of request body in bytes */
|
||||||
|
unsigned int); /* Flags */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to check whether a path should be used for ZeroTier traffic
|
* Function to check whether a path should be used for ZeroTier traffic
|
||||||
*
|
*
|
||||||
|
@ -1568,6 +1582,11 @@ struct ZT_Node_Callbacks
|
||||||
*/
|
*/
|
||||||
ZT_WirePacketSendFunction wirePacketSendFunction;
|
ZT_WirePacketSendFunction wirePacketSendFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RECOMMENDED: Function to initiate HTTP requests
|
||||||
|
*/
|
||||||
|
ZT_HTTPRequestFunction httpRequestFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* REQUIRED: Function to inject frames into a virtual network's TAP
|
* REQUIRED: Function to inject frames into a virtual network's TAP
|
||||||
*/
|
*/
|
||||||
|
@ -1718,6 +1737,33 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
||||||
int isZtBuffer,
|
int isZtBuffer,
|
||||||
volatile int64_t *nextBackgroundTaskDeadline);
|
volatile int64_t *nextBackgroundTaskDeadline);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a response from HTTP requests initiated via API callback
|
||||||
|
*
|
||||||
|
* @param node Node instance
|
||||||
|
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||||
|
* @param now Current clock in milliseconds
|
||||||
|
* @param requestId Opaque pointer provided via the requesting callback
|
||||||
|
* @param responseCode HTTP response code (e.g. 200, 500)
|
||||||
|
* @param headerNames HTTP header names, terminated by a NULL pointer
|
||||||
|
* @param headerValues HTTP header values corresponding with each name
|
||||||
|
* @param body Response body or NULL if none
|
||||||
|
* @param bodySize Size of response body in bytes
|
||||||
|
* @param flags Response flags
|
||||||
|
* @return OK (0) or error code if a fatal error condition has occurred
|
||||||
|
*/
|
||||||
|
ZT_SDK_API enum ZT_ResultCode ZT_Node_processHTTPResponse(
|
||||||
|
ZT_Node *node,
|
||||||
|
void *tptr,
|
||||||
|
int64_t now,
|
||||||
|
void *requestId,
|
||||||
|
int responseCode,
|
||||||
|
const char **headerNames,
|
||||||
|
const char **headerValues,
|
||||||
|
const void *body,
|
||||||
|
unsigned int bodySize,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform periodic background operations
|
* Perform periodic background operations
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue