Commit f73f9b5c authored by Kai Vehmanen's avatar Kai Vehmanen

Convert indentation from tabs to spaces.

darcs-hash:20070918150713-77cd4-7bdd3f21524c846c1bf0c2c8cb96eb6104c96ad8.gz
parent d3e16af2
......@@ -59,7 +59,7 @@
struct stun_bind_s
{
stun_trans_t trans;
stun_trans_t trans;
};
......@@ -81,37 +81,37 @@ static int
stun_bind_alloc (stun_bind_t **restrict context, int fd,
const struct sockaddr *restrict srv, socklen_t srvlen)
{
int val;
int val;
stun_bind_t *ctx = malloc (sizeof (*ctx));
if (ctx == NULL)
return ENOMEM;
stun_bind_t *ctx = malloc (sizeof (*ctx));
if (ctx == NULL)
return ENOMEM;
memset (ctx, 0, sizeof (*ctx));
*context = ctx;
memset (ctx, 0, sizeof (*ctx));
*context = ctx;
val = (fd != -1)
? stun_trans_init (&ctx->trans, fd, srv, srvlen)
: stun_trans_create (&ctx->trans, SOCK_DGRAM, 0, srv, srvlen);
val = (fd != -1)
? stun_trans_init (&ctx->trans, fd, srv, srvlen)
: stun_trans_create (&ctx->trans, SOCK_DGRAM, 0, srv, srvlen);
if (val)
{
free (ctx);
return val;
}
if (val)
{
free (ctx);
return val;
}
stun_init_request (ctx->trans.msg.buf, STUN_BINDING);
return 0;
stun_init_request (ctx->trans.msg.buf, STUN_BINDING);
return 0;
}
static int
stun_bind_launch (stun_bind_t *ctx)
{
int val = stun_trans_start (&ctx->trans);
if (val)
stun_bind_cancel (ctx);
return val;
int val = stun_trans_start (&ctx->trans);
if (val)
stun_bind_cancel (ctx);
return val;
}
......@@ -119,30 +119,30 @@ int stun_bind_start (stun_bind_t **restrict context, int fd,
const struct sockaddr *restrict srv,
socklen_t srvlen)
{
stun_bind_t *ctx;
stun_bind_t *ctx;
int val = stun_bind_alloc (context, fd, srv, srvlen);
if (val)
return val;
int val = stun_bind_alloc (context, fd, srv, srvlen);
if (val)
return val;
ctx = *context;
ctx = *context;
ctx->trans.msg.length = sizeof (ctx->trans.msg.buf);
val = stun_finish (ctx->trans.msg.buf, &ctx->trans.msg.length);
if (val)
{
stun_bind_cancel (ctx);
return val;
}
ctx->trans.msg.length = sizeof (ctx->trans.msg.buf);
val = stun_finish (ctx->trans.msg.buf, &ctx->trans.msg.length);
if (val)
{
stun_bind_cancel (ctx);
return val;
}
return stun_bind_launch (ctx);
return stun_bind_launch (ctx);
}
void stun_bind_cancel (stun_bind_t *context)
{
stun_trans_deinit (&context->trans);
free (context);
stun_trans_deinit (&context->trans);
free (context);
}
......@@ -150,17 +150,17 @@ void stun_bind_cancel (stun_bind_t *context)
unsigned stun_bind_timeout (const stun_bind_t *context)
{
assert (context != NULL);
return stun_trans_timeout (&context->trans);
assert (context != NULL);
return stun_trans_timeout (&context->trans);
}
int stun_bind_elapse (stun_bind_t *context)
{
int val = stun_trans_tick (&context->trans);
if (val != EAGAIN)
stun_bind_cancel (context);
return val;
int val = stun_trans_tick (&context->trans);
if (val != EAGAIN)
stun_bind_cancel (context);
return val;
}
......@@ -170,40 +170,40 @@ int stun_bind_process (stun_bind_t *restrict ctx,
const void *restrict buf, size_t len,
struct sockaddr *restrict addr, socklen_t *addrlen)
{
int val, code;
assert (ctx != NULL);
val = stun_trans_preprocess (&ctx->trans, &code, buf, len);
switch (val)
{
case EAGAIN:
return EAGAIN;
case 0:
break;
default:
if (code == STUN_ROLE_CONFLICT)
val = ECONNRESET;
stun_bind_cancel (ctx);
return val;
}
val = stun_find_xor_addr (buf, STUN_XOR_MAPPED_ADDRESS, addr, addrlen);
if (val)
{
DBG (" No XOR-MAPPED-ADDRESS: %s\n", strerror (val));
val = stun_find_addr (buf, STUN_MAPPED_ADDRESS, addr, addrlen);
if (val)
{
DBG (" No MAPPED-ADDRESS: %s\n", strerror (val));
stun_bind_cancel (ctx);
return val;
}
}
DBG (" Mapped address found!\n");
stun_bind_cancel (ctx);
return 0;
int val, code;
assert (ctx != NULL);
val = stun_trans_preprocess (&ctx->trans, &code, buf, len);
switch (val)
{
case EAGAIN:
return EAGAIN;
case 0:
break;
default:
if (code == STUN_ROLE_CONFLICT)
val = ECONNRESET;
stun_bind_cancel (ctx);
return val;
}
val = stun_find_xor_addr (buf, STUN_XOR_MAPPED_ADDRESS, addr, addrlen);
if (val)
{
DBG (" No XOR-MAPPED-ADDRESS: %s\n", strerror (val));
val = stun_find_addr (buf, STUN_MAPPED_ADDRESS, addr, addrlen);
if (val)
{
DBG (" No MAPPED-ADDRESS: %s\n", strerror (val));
stun_bind_cancel (ctx);
return val;
}
}
DBG (" Mapped address found!\n");
stun_bind_cancel (ctx);
return 0;
}
......@@ -213,28 +213,28 @@ int stun_bind_run (int fd,
const struct sockaddr *restrict srv, socklen_t srvlen,
struct sockaddr *restrict addr, socklen_t *addrlen)
{
stun_bind_t *ctx;
uint8_t buf[STUN_MAXMSG];
ssize_t val;
val = stun_bind_start (&ctx, fd, srv, srvlen);
if (val)
return val;
do
{
val = stun_trans_recv (&ctx->trans, buf, sizeof (buf));
if (val == -1)
{
val = errno;
continue;
}
val = stun_bind_process (ctx, buf, val, addr, addrlen);
}
while (val == EAGAIN);
return val;
stun_bind_t *ctx;
uint8_t buf[STUN_MAXMSG];
ssize_t val;
val = stun_bind_start (&ctx, fd, srv, srvlen);
if (val)
return val;
do
{
val = stun_trans_recv (&ctx->trans, buf, sizeof (buf));
if (val == -1)
{
val = errno;
continue;
}
val = stun_bind_process (ctx, buf, val, addr, addrlen);
}
while (val == EAGAIN);
return val;
}
......@@ -244,19 +244,19 @@ int
stun_bind_keepalive (int fd, const struct sockaddr *restrict srv,
socklen_t srvlen)
{
uint8_t buf[28];
size_t len = sizeof (buf);
int val;
stun_init_indication (buf, STUN_BINDING);
val = stun_finish (buf, &len);
assert (val == 0);
(void)val;
/* NOTE: hopefully, this is only needed for non-stream sockets */
if (stun_sendto (fd, buf, len, srv, srvlen) == -1)
return errno;
return 0;
uint8_t buf[28];
size_t len = sizeof (buf);
int val;
stun_init_indication (buf, STUN_BINDING);
val = stun_finish (buf, &len);
assert (val == 0);
(void)val;
/* NOTE: hopefully, this is only needed for non-stream sockets */
if (stun_sendto (fd, buf, len, srv, srvlen) == -1)
return errno;
return 0;
}
......@@ -270,58 +270,58 @@ stun_conncheck_start (stun_bind_t **restrict context, int fd,
bool cand_use, bool controlling, uint32_t priority,
uint64_t tie)
{
int val;
stun_bind_t *ctx;
assert (username != NULL);
assert (password != NULL);
val = stun_bind_alloc (&ctx, fd, srv, srvlen);
if (val)
return val;
ctx->trans.key.length = strlen (password);
ctx->trans.key.value = malloc (ctx->trans.key.length);
if (ctx->trans.key.value == NULL)
{
val = ENOMEM;
goto error;
}
*context = ctx;
memcpy (ctx->trans.key.value, password, ctx->trans.key.length);
if (cand_use)
{
val = stun_append_flag (ctx->trans.msg.buf,
sizeof (ctx->trans.msg.buf),
STUN_USE_CANDIDATE);
if (val)
goto error;
}
val = stun_append32 (ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf),
STUN_PRIORITY, priority);
if (val)
goto error;
val = stun_append64 (ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf),
controlling ? STUN_ICE_CONTROLLING
: STUN_ICE_CONTROLLED, tie);
if (val)
goto error;
ctx->trans.msg.length = sizeof (ctx->trans.msg.buf);
val = stun_finish_short (ctx->trans.msg.buf, &ctx->trans.msg.length,
username, password, NULL);
if (val)
goto error;
return stun_bind_launch (ctx);
int val;
stun_bind_t *ctx;
assert (username != NULL);
assert (password != NULL);
val = stun_bind_alloc (&ctx, fd, srv, srvlen);
if (val)
return val;
ctx->trans.key.length = strlen (password);
ctx->trans.key.value = malloc (ctx->trans.key.length);
if (ctx->trans.key.value == NULL)
{
val = ENOMEM;
goto error;
}
*context = ctx;
memcpy (ctx->trans.key.value, password, ctx->trans.key.length);
if (cand_use)
{
val = stun_append_flag (ctx->trans.msg.buf,
sizeof (ctx->trans.msg.buf),
STUN_USE_CANDIDATE);
if (val)
goto error;
}
val = stun_append32 (ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf),
STUN_PRIORITY, priority);
if (val)
goto error;
val = stun_append64 (ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf),
controlling ? STUN_ICE_CONTROLLING
: STUN_ICE_CONTROLLED, tie);
if (val)
goto error;
ctx->trans.msg.length = sizeof (ctx->trans.msg.buf);
val = stun_finish_short (ctx->trans.msg.buf, &ctx->trans.msg.length,
username, password, NULL);
if (val)
goto error;
return stun_bind_launch (ctx);
error:
stun_bind_cancel (*context);
return val;
stun_bind_cancel (*context);
return val;
}
......@@ -52,20 +52,20 @@ static inline uint32_t crc32 (const struct iovec *iov, size_t size);
uint32_t stun_fingerprint (const uint8_t *msg, size_t len)
{
struct iovec iov[3];
uint16_t fakelen = htons (len - 20u);
struct iovec iov[3];
uint16_t fakelen = htons (len - 20u);
assert (len >= 28u);
assert (len >= 28u);
iov[0].iov_base = (void *)msg;
iov[0].iov_len = 2;
iov[1].iov_base = &fakelen;
iov[1].iov_len = 2;
iov[2].iov_base = (void *)(msg + 4);
/* first 4 bytes done, last 8 bytes not summed */
iov[2].iov_len = len - 12u;
iov[0].iov_base = (void *)msg;
iov[0].iov_len = 2;
iov[1].iov_base = &fakelen;
iov[1].iov_len = 2;
iov[2].iov_base = (void *)(msg + 4);
/* first 4 bytes done, last 8 bytes not summed */
iov[2].iov_len = len - 12u;
return crc32 (iov, sizeof (iov) / sizeof (iov[0])) ^ 0x5354554e;
return crc32 (iov, sizeof (iov) / sizeof (iov[0])) ^ 0x5354554e;
}
/*-
......@@ -165,17 +165,17 @@ static const uint32_t crc32_tab[] = {
static inline
uint32_t crc32 (const struct iovec *iov, size_t n)
{
size_t i;
uint32_t crc = 0xffffffff;
size_t i;
uint32_t crc = 0xffffffff;
for (i = 0; i < n; i++)
{
const uint8_t *p = iov[i].iov_base;
size_t size = iov[i].iov_len;
for (i = 0; i < n; i++)
{
const uint8_t *p = iov[i].iov_base;
size_t size = iov[i].iov_len;
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
}
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
}
return crc ^ 0xffffffff;
return crc ^ 0xffffffff;
}
......@@ -53,71 +53,71 @@
void stun_sha1 (const uint8_t *msg, size_t len, uint8_t *sha,
const void *restrict key, size_t keylen)
{
HMAC_CTX ctx;
uint16_t fakelen = htons (len - 20u);
assert (len >= 44u);
HMAC_CTX_init (&ctx);
HMAC_Init_ex (&ctx, key, keylen, EVP_sha1 (), NULL);
HMAC_Update (&ctx, msg, 2);
HMAC_Update (&ctx, (const uint8_t *)&fakelen, 2);
/* first 4 bytes done, last 24 bytes not summed */
HMAC_Update (&ctx, msg + 4, len - 28u);
HMAC_Final (&ctx, sha, NULL);
HMAC_CTX_cleanup (&ctx);
HMAC_CTX ctx;
uint16_t fakelen = htons (len - 20u);
assert (len >= 44u);
HMAC_CTX_init (&ctx);
HMAC_Init_ex (&ctx, key, keylen, EVP_sha1 (), NULL);
HMAC_Update (&ctx, msg, 2);
HMAC_Update (&ctx, (const uint8_t *)&fakelen, 2);
/* first 4 bytes done, last 24 bytes not summed */
HMAC_Update (&ctx, msg + 4, len - 28u);
HMAC_Final (&ctx, sha, NULL);
HMAC_CTX_cleanup (&ctx);
}
void stun_hash_creds (const char *realm, const char *login, const char *pw,
unsigned char md5[16])
{
EVP_MD_CTX ctx;
assert (realm && login && pw && md5);
EVP_MD_CTX_init (&ctx);
EVP_DigestInit_ex (&ctx, EVP_md5 (), NULL);
EVP_DigestUpdate (&ctx, realm, strlen (realm));
EVP_DigestUpdate (&ctx, ":", 1);
EVP_DigestUpdate (&ctx, login, strlen (login));
EVP_DigestUpdate (&ctx, ":", 1);
EVP_DigestUpdate (&ctx, pw, strlen (pw));
EVP_DigestFinal (&ctx, md5, NULL);
EVP_MD_CTX ctx;
assert (realm && login && pw && md5);
EVP_MD_CTX_init (&ctx);
EVP_DigestInit_ex (&ctx, EVP_md5 (), NULL);
EVP_DigestUpdate (&ctx, realm, strlen (realm));
EVP_DigestUpdate (&ctx, ":", 1);
EVP_DigestUpdate (&ctx, login, strlen (login));
EVP_DigestUpdate (&ctx, ":", 1);
EVP_DigestUpdate (&ctx, pw, strlen (pw));
EVP_DigestFinal (&ctx, md5, NULL);
}
void stun_make_transid (stun_transid_t id)
{
/*
* transid = (HMAC_SHA1 (secret, counter) >> 64)
* This consumes sizeof (secret) bytes of entropy every 2^64 messages.
*/
static struct
{
pthread_mutex_t lock;
uint64_t counter;
uint8_t secret[16];
} store = { PTHREAD_MUTEX_INITIALIZER, 0, "" };
union
{
uint64_t value;
uint8_t bytes[1];
} counter;
uint8_t key[16], sha[20];
pthread_mutex_lock (&store.lock);
counter.value = store.counter++;
if (counter.value == 0)
RAND_pseudo_bytes (store.secret, sizeof (store.secret));
memcpy (key, store.secret, sizeof (key));
pthread_mutex_unlock (&store.lock);
/* Computes hash out of contentious area */
HMAC (EVP_sha1 (), key, sizeof (key), counter.bytes, sizeof (counter),
sha, NULL);
memcpy (id, sha, 12);
/*
* transid = (HMAC_SHA1 (secret, counter) >> 64)
* This consumes sizeof (secret) bytes of entropy every 2^64 messages.
*/
static struct
{
pthread_mutex_t lock;
uint64_t counter;
uint8_t secret[16];
} store = { PTHREAD_MUTEX_INITIALIZER, 0, "" };
union
{
uint64_t value;
uint8_t bytes[1];
} counter;
uint8_t key[16], sha[20];
pthread_mutex_lock (&store.lock);
counter.value = store.counter++;
if (counter.value == 0)
RAND_pseudo_bytes (store.secret, sizeof (store.secret));
memcpy (key, store.secret, sizeof (key));
pthread_mutex_unlock (&store.lock);
/* Computes hash out of contentious area */
HMAC (EVP_sha1 (), key, sizeof (key), counter.bytes, sizeof (counter),
sha, NULL);
memcpy (id, sha, 12);
}
......@@ -48,7 +48,7 @@ static uint8_t unique_id[UNIQUE_SIZE];
static void generate_unique_id (void)
{
RAND_pseudo_bytes (unique_id, sizeof (unique_id));
RAND_pseudo_bytes (unique_id, sizeof (unique_id));
}
......@@ -56,45 +56,45 @@ static void
stun_generate_nonce (uint8_t *nonce, time_t now,
const struct sockaddr_storage *restrict addr)
{
static pthread_once_t once = PTHREAD_ONCE_INIT;
HMAC_CTX ctx;
uint32_t stamp = now;
static pthread_once_t once = PTHREAD_ONCE_INIT;
HMAC_CTX ctx;
uint32_t stamp = now;
pthread_once (&once, generate_unique_id);
pthread_once (&once, generate_unique_id);
/*
* Nonce are generated from the current time and the client address and
* port number, keyed with a pseudo-random secret.
*/
HMAC_CTX_init (&ctx);
HMAC_Init_ex (&ctx, unique_id, sizeof (unique_id), EVP_sha1 (), NULL);
HMAC_Update (&ctx, &stamp, 4);
HMAC_Update (&ctx, &ss->family, sizeof (ss->family));
switch (addr->ss_family)
{
case AF_INET:
{
const struct sockaddr_in *ip4 = (const struct sockaddr_in *)addr;
HMAC_Update (&ctx, &ip4->sin_addr, 4);
HMAC_Update (&ctx, &ip4->sin_port, 2);
break;
}
/*
* Nonce are generated from the current time and the client address and
* port number, keyed with a pseudo-random secret.
*/
HMAC_CTX_init (&ctx);
HMAC_Init_ex (&ctx, unique_id, sizeof (unique_id), EVP_sha1 (), NULL);
HMAC_Update (&ctx, &stamp, 4);
HMAC_Update (&ctx, &ss->family, sizeof (ss->family));
switch (addr->ss_family)
{
case AF_INET:
{
const struct sockaddr_in *ip4 = (const struct sockaddr_in *)addr;
HMAC_Update (&ctx, &ip4->sin_addr, 4);
HMAC_Update (&ctx, &ip4->sin_port, 2);
break;
}
case AF_INET6:
{
const struct sockaddr_in6*ip6 = (const struct sockaddr_in6*)addr;
HMAC_Update (&ctx, &ip6->sin6_addr, 16);
HMAC_Update (&ctx, &ip6->sin6_port, 2);
if (IN6_IS_ADDR_LINK_LOCAL (&ip6->sin6_addr))
HMAC_Update (&ctx, &ip6->sin6_scope_id
sizeof (ip6->sin6_scope_id));
break;
}
}
case AF_INET6:
{
const struct sockaddr_in6*ip6 = (const struct sockaddr_in6*)addr;
HMAC_Update (&ctx, &ip6->sin6_addr, 16);
HMAC_Update (&ctx, &ip6->sin6_port, 2);
if (IN6_IS_ADDR_LINK_LOCAL (&ip6->sin6_addr))
HMAC_Update (&ctx, &ip6->sin6_scope_id
sizeof (ip6->sin6_scope_id));
break;
}
}
HMAC_Final (&ctx, nonce, NULL);
HMAC_CTX_cleanup (&ctx);
memcpy (nonce + 20, &stamp, 4);
HMAC_Final (&ctx, nonce, NULL);
HMAC_CTX_cleanup (&ctx);
memcpy (nonce + 20, &stamp, 4);
}
......@@ -102,9 +102,9 @@ static int
stun_append_nonce (uint8_t *buf, size_t buflen,
const struct sockaddr_storage *restrict addr)
{
uint8_t nonce[NONCE_SIZE];
stun_generate_nonce (nonce, time (NULL), addr);
return stun_append_bytes (buf, buflen, STUN_NONCE, nonce, sizeof (nonce));
uint8_t nonce[NONCE_SIZE];
stun_generate_nonce (nonce, time (NULL), addr);
return stun_append_bytes (buf, buflen, STUN_NONCE, nonce, sizeof (nonce));
}
......@@ -112,7 +112,7 @@ static int
stun_verify_nonce (const uint8_t *buf, unsigned valid_time,
const struct sockaddr_storage *restrict addr)
{
const uint8_t *
stun_generate_nonce (nonce, time (NULL), addr);
return stun_append_bytes (buf, buflen, STUN_NONCE, nonce, sizeof (nonce));
const uint8_t *
stun_generate_nonce (nonce, time (NULL), addr);
return stun_append_bytes (buf, buflen, STUN_NONCE, nonce, sizeof (nonce));
}
......@@ -54,24 +54,24 @@ static int
stun_bind_error (uint8_t *buf, size_t *plen, const uint8_t *req,
stun_error_t code, const char *pass)
{
size_t len = *plen;
int val;
size_t len = *plen;
int val;
*plen = 0;
DBG ("STUN Error Reply (buffer size: %u)...\n", (unsigned)len);
*plen = 0;
DBG ("STUN Error Reply (buffer size: %u)...\n", (unsigned)len);
val = stun_init_error (buf, len, req, code);
if (val)
return val;
val = stun_init_error (buf, len, req, code);
if (val)
return val;
val = stun_finish_short (buf, &len, NULL, pass, NULL);
if (val)
return val;
val = stun_finish_short (buf, &len, NULL, pass, NULL);
if (val)
return val;
*plen = len;
DBG (" Error response (%u) of %u bytes\n", (unsigned)code,
(unsigned)*plen);
return 0;
*plen = len;
DBG (" Error response (%u) of %u bytes\n", (unsigned)code,
(unsigned)*plen);
return 0;
}
......@@ -80,125 +80,125 @@ stun_conncheck_reply (uint8_t *buf, size_t *restrict plen, const uint8_t *msg,
const struct sockaddr *restrict src, socklen_t srclen,
const char *pass, bool *restrict control, uint64_t tie)
{
size_t len = *plen;
uint64_t q;
int val, ret = 0;
size_t len = *plen;
uint64_t q;
int val, ret = 0;
#define err( code ) \
stun_bind_error (buf, &len, msg, code, pass); \
*plen = len
*plen = 0;
DBG ("STUN Reply (buffer size = %u)...\n", (unsigned)len);
if (stun_get_class (msg) != STUN_REQUEST)
{
DBG (" Unhandled non-request (class %u) message.\n",
stun_get_class (msg));
return EINVAL;
}
if (!stun_demux (msg))
{
DBG (" Incorrectly multiplexed STUN message ignored.\n");
return EINVAL;
}
if (stun_has_unknown (msg))
{
DBG (" Unknown mandatory attributes in message.\n");
val = stun_init_error_unknown (buf, len, msg);
if (!val)
val = stun_finish_short (buf, &len, NULL, pass, NULL);
if (val)
goto failure;
*plen = len;
return EPROTO;
}
/* Short term credentials checking */
val = 0;
if (!stun_present (msg, STUN_MESSAGE_INTEGRITY) // FIXME: wrong!
|| !stun_present (msg, STUN_USERNAME))
{
DBG (" Missing USERNAME or MESSAGE-INTEGRITY.\n");
val = STUN_BAD_REQUEST;
}
else
/* FIXME: verify USERNAME, return STUN_UNAUTHORIZED if wrong */
if (stun_verify_password (msg, pass))
{
DBG (" Integrity check failed.\n");
val = STUN_UNAUTHORIZED;
}
if (val)
{
stun_bind_error (buf, &len, msg, val, NULL);
*plen = len;
return EPERM;
}
if (stun_get_method (msg) != STUN_BINDING)
{
DBG (" Bad request (method %u) message.\n",
stun_get_method (msg));
err (STUN_BAD_REQUEST);
return EPROTO;
}
/* Role conflict handling */
assert (control != NULL);
if (!stun_find64 (msg, *control ? STUN_ICE_CONTROLLING
: STUN_ICE_CONTROLLED, &q))
{
DBG ("STUN Role Conflict detected:\n");
if (tie < q)
{
DBG (" switching role from \"controll%s\" to \"controll%s\"\n",
*control ? "ing" : "ed", *control ? "ed" : "ing");
*control = !*control;
ret = EACCES;
}
else
{
DBG (" staying \"controll%s\" (sending error)\n",
*control ? "ing" : "ed");
*plen = len;
err (STUN_ROLE_CONFLICT);
return 0;
}
}
stun_bind_error (buf, &len, msg, code, pass); \
*plen = len
*plen = 0;
DBG ("STUN Reply (buffer size = %u)...\n", (unsigned)len);
if (stun_get_class (msg) != STUN_REQUEST)
{
DBG (" Unhandled non-request (class %u) message.\n",
stun_get_class (msg));
return EINVAL;
}
if (!stun_demux (msg))
{
DBG (" Incorrectly multiplexed STUN message ignored.\n");
return EINVAL;
}
if (stun_has_unknown (msg))
{
DBG (" Unknown mandatory attributes in message.\n");
val = stun_init_error_unknown (buf, len, msg);
if (!val)
val = stun_finish_short (buf, &len, NULL, pass, NULL);
if (val)
goto failure;
*plen = len;
return EPROTO;
}
/* Short term credentials checking */
val = 0;
if (!stun_present (msg, STUN_MESSAGE_INTEGRITY) // FIXME: wrong!
|| !stun_present (msg, STUN_USERNAME))
{
DBG (" Missing USERNAME or MESSAGE-INTEGRITY.\n");
val = STUN_BAD_REQUEST;
}
else
/* FIXME: verify USERNAME, return STUN_UNAUTHORIZED if wrong */
if (stun_verify_password (msg, pass))
{
DBG (" Integrity check failed.\n");
val = STUN_UNAUTHORIZED;
}
if (val)
{
stun_bind_error (buf, &len, msg, val, NULL);
*plen = len;
return EPERM;
}
if (stun_get_method (msg) != STUN_BINDING)
{
DBG (" Bad request (method %u) message.\n",
stun_get_method (msg));
err (STUN_BAD_REQUEST);
return EPROTO;
}
/* Role conflict handling */
assert (control != NULL);
if (!stun_find64 (msg, *control ? STUN_ICE_CONTROLLING
: STUN_ICE_CONTROLLED, &q))
{
DBG ("STUN Role Conflict detected:\n");
if (tie < q)
{
DBG (" switching role from \"controll%s\" to \"controll%s\"\n",
*control ? "ing" : "ed", *control ? "ed" : "ing");
*control = !*control;
ret = EACCES;
}
else
{
DBG (" staying \"controll%s\" (sending error)\n",
*control ? "ing" : "ed");
*plen = len;
err (STUN_ROLE_CONFLICT);
return 0;
}
}
#ifndef NDEBUG
else
if (stun_find64 (msg, *control ? STUN_ICE_CONTROLLED
: STUN_ICE_CONTROLLING, &q))
DBG ("STUN Role not specified by peer!\n");
else
if (stun_find64 (msg, *control ? STUN_ICE_CONTROLLED
: STUN_ICE_CONTROLLING, &q))
DBG ("STUN Role not specified by peer!\n");
#endif
stun_init_response (buf, len, msg);
val = stun_append_xor_addr (buf, len, STUN_XOR_MAPPED_ADDRESS,
src, srclen);
if (val)
{
DBG (" Mapped address problem: %s\n", strerror (val));
goto failure;
}
stun_init_response (buf, len, msg);
val = stun_append_xor_addr (buf, len, STUN_XOR_MAPPED_ADDRESS,
src, srclen);
if (val)
{
DBG (" Mapped address problem: %s\n", strerror (val));
goto failure;
}
val = stun_finish_short (buf, &len, NULL, pass, NULL);
if (val)
goto failure;
val = stun_finish_short (buf, &len, NULL, pass, NULL);
if (val)
goto failure;
*plen = len;
DBG (" All done (response size: %u)\n", (unsigned)len);
return ret;
*plen = len;
DBG (" All done (response size: %u)\n", (unsigned)len);
return ret;
failure:
assert (*plen == 0);
DBG (" Fatal error formatting Response: %s\n", strerror (val));
return val;
assert (*plen == 0);
DBG (" Fatal error formatting Response: %s\n", strerror (val));
return val;
}
#undef err
......@@ -207,38 +207,38 @@ failure:
char *stun_conncheck_username (const uint8_t *restrict msg,
char *restrict buf, size_t buflen)
{
size_t i;
size_t i;
if ((buflen == 0)
|| stun_find_string (msg, STUN_USERNAME, buf, (buflen - 1) / 6))
return NULL;
if ((buflen == 0)
|| stun_find_string (msg, STUN_USERNAME, buf, (buflen - 1) / 6))
return NULL;
for (i = 0; buf[i]; i++)
{
char c = buf[i];
/* ref ICE sect 7.1.1.4. (ID-16) */
if (((c >= '/') && (c <= '9')) || ((c >= 'A') && (c <= 'Z'))
|| ((c >= 'a') && (c <= 'z')) || (c == '+') || (c == ':'))
continue;
for (i = 0; buf[i]; i++)
{
char c = buf[i];
/* ref ICE sect 7.1.1.4. (ID-16) */
if (((c >= '/') && (c <= '9')) || ((c >= 'A') && (c <= 'Z'))
|| ((c >= 'a') && (c <= 'z')) || (c == '+') || (c == ':'))
continue;
return NULL;
}
return NULL;
}
return buf;
return buf;
}
uint32_t stun_conncheck_priority (const uint8_t *msg)
{
uint32_t value;
uint32_t value;
if (stun_find32 (msg, STUN_PRIORITY, &value))
return 0;
return value;
if (stun_find32 (msg, STUN_PRIORITY, &value))
return 0;
return value;
}
bool stun_conncheck_use_candidate (const uint8_t *msg)
{
return !stun_find_flag (msg, STUN_USE_CANDIDATE);
return !stun_find_flag (msg, STUN_USE_CANDIDATE);
}
This diff is collapsed.
......@@ -53,120 +53,120 @@
static void
printaddr (const char *str, const struct sockaddr *addr, socklen_t addrlen)
{
char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
int val = getnameinfo (addr, addrlen, hostbuf, sizeof (hostbuf),
servbuf, sizeof (servbuf),
NI_NUMERICHOST | NI_NUMERICSERV);
if (val)
printf ("%s: %s\n", str, gai_strerror (val));
else
printf ("%s: %s port %s\n", str, hostbuf, servbuf);
char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
int val = getnameinfo (addr, addrlen, hostbuf, sizeof (hostbuf),
servbuf, sizeof (servbuf),
NI_NUMERICHOST | NI_NUMERICSERV);
if (val)
printf ("%s: %s\n", str, gai_strerror (val));
else
printf ("%s: %s port %s\n", str, hostbuf, servbuf);
}
static int run (int family, const char *hostname, const char *service)
{
struct addrinfo hints, *res;
const struct addrinfo *ptr;
int ret = -1;
memset (&hints, 0, sizeof (hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM;
if (service == NULL)
service = "3478";
ret = getaddrinfo (hostname, service, &hints, &res);
if (ret)
{
fprintf (stderr, "%s (port %s): %s\n", hostname, service,
gai_strerror (ret));
return -1;
}
for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
{
struct sockaddr_storage addr;
socklen_t addrlen = sizeof (addr);
int val;
printaddr ("Server address", ptr->ai_addr, ptr->ai_addrlen);
val = stun_bind_run (-1, ptr->ai_addr, ptr->ai_addrlen,
(struct sockaddr *)&addr, &addrlen);
if (val)
fprintf (stderr, "%s\n", strerror (val));
else
{
printaddr ("Mapped address", (struct sockaddr *)&addr, addrlen);
ret = 0;
}
}
freeaddrinfo (res);
return ret;
struct addrinfo hints, *res;
const struct addrinfo *ptr;
int ret = -1;
memset (&hints, 0, sizeof (hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM;
if (service == NULL)
service = "3478";
ret = getaddrinfo (hostname, service, &hints, &res);
if (ret)
{
fprintf (stderr, "%s (port %s): %s\n", hostname, service,
gai_strerror (ret));
return -1;
}
for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
{
struct sockaddr_storage addr;
socklen_t addrlen = sizeof (addr);
int val;
printaddr ("Server address", ptr->ai_addr, ptr->ai_addrlen);
val = stun_bind_run (-1, ptr->ai_addr, ptr->ai_addrlen,
(struct sockaddr *)&addr, &addrlen);
if (val)
fprintf (stderr, "%s\n", strerror (val));
else
{
printaddr ("Mapped address", (struct sockaddr *)&addr, addrlen);
ret = 0;
}
}
freeaddrinfo (res);
return ret;
}
int main (int argc, char *argv[])
{
static const struct option opts[] =
{
{ "ipv4", no_argument, NULL, '4' },
{ "ipv6", no_argument, NULL, '6' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
const char *server = NULL, *port = NULL;
int family = AF_UNSPEC;
for (;;)
{
int val = getopt_long (argc, argv, "46hV", opts, NULL);
if (val == EOF)
break;
switch (val)
{
case '4':
family = AF_INET;
break;
case '6':
family = AF_INET6;
break;
case 'h':
printf ("Usage: %s [-4|-6] <server> [port number]\n"
"Performs STUN Binding Discovery\n"
"\n"
" -4, --ipv4 Force IP version 4\n"
" -6, --ipv6 Force IP version 6\n"
"\n", argv[0]);
return 0;
case 'V':
printf ("stunbcd: STUN Binding Discovery client (%s v%s)\n",
PACKAGE, VERSION);
return 0;
default:
return 2;
}
}
if (optind < argc)
server = argv[optind++];
if (optind < argc)
port = argv[optind++];
if (optind < argc)
{
fprintf (stderr, "%s: extra parameter `%s'\n", argv[0], argv[optind]);
return 2;
}
return run (family, server, port) ? 1 : 0;
static const struct option opts[] =
{
{ "ipv4", no_argument, NULL, '4' },
{ "ipv6", no_argument, NULL, '6' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
const char *server = NULL, *port = NULL;
int family = AF_UNSPEC;
for (;;)
{
int val = getopt_long (argc, argv, "46hV", opts, NULL);
if (val == EOF)
break;
switch (val)
{
case '4':
family = AF_INET;
break;
case '6':
family = AF_INET6;
break;
case 'h':
printf ("Usage: %s [-4|-6] <server> [port number]\n"
"Performs STUN Binding Discovery\n"
"\n"
" -4, --ipv4 Force IP version 4\n"
" -6, --ipv6 Force IP version 6\n"
"\n", argv[0]);
return 0;
case 'V':
printf ("stunbcd: STUN Binding Discovery client (%s v%s)\n",
PACKAGE, VERSION);
return 0;
default:
return 2;
}
}
if (optind < argc)
server = argv[optind++];
if (optind < argc)
port = argv[optind++];
if (optind < argc)
{
fprintf (stderr, "%s: extra parameter `%s'\n", argv[0], argv[optind]);
return 2;
}
return run (family, server, port) ? 1 : 0;
}
......@@ -70,77 +70,77 @@
*/
int listen_socket (int fam, int type, int proto, uint16_t port)
{
int yes = 1;
int fd = socket (fam, type, proto);
if (fd == -1)
{
perror ("Error opening IP port");
return -1;
}
if (fd < 3)
goto error;
struct sockaddr_storage addr;
memset (&addr, 0, sizeof (addr));
addr.ss_family = fam;
int yes = 1;
int fd = socket (fam, type, proto);
if (fd == -1)
{
perror ("Error opening IP port");
return -1;
}
if (fd < 3)
goto error;
struct sockaddr_storage addr;
memset (&addr, 0, sizeof (addr));
addr.ss_family = fam;
#ifdef HAVE_SA_LEN
addr.ss_len = sizeof (addr);
addr.ss_len = sizeof (addr);
#endif
switch (fam)
{
case AF_INET:
((struct sockaddr_in *)&addr)->sin_port = port;
break;
switch (fam)
{
case AF_INET:
((struct sockaddr_in *)&addr)->sin_port = port;
break;
case AF_INET6:
case AF_INET6:
#ifdef IPV6_V6ONLY
setsockopt (fd, SOL_IPV6, IPV6_V6ONLY, &yes, sizeof (yes));
setsockopt (fd, SOL_IPV6, IPV6_V6ONLY, &yes, sizeof (yes));
#endif
((struct sockaddr_in6 *)&addr)->sin6_port = port;
break;
}
if (bind (fd, (struct sockaddr *)&addr, sizeof (addr)))
{
perror ("Error opening IP port");
goto error;
}
if ((type == SOCK_DGRAM) || (type == SOCK_RAW))
{
switch (fam)
{
case AF_INET:
setsockopt (fd, SOL_IP, IP_PKTINFO, &yes, sizeof (yes));
((struct sockaddr_in6 *)&addr)->sin6_port = port;
break;
}
if (bind (fd, (struct sockaddr *)&addr, sizeof (addr)))
{
perror ("Error opening IP port");
goto error;
}
if ((type == SOCK_DGRAM) || (type == SOCK_RAW))
{
switch (fam)
{
case AF_INET:
setsockopt (fd, SOL_IP, IP_PKTINFO, &yes, sizeof (yes));
#ifdef IP_RECVERR
setsockopt (fd, SOL_IP, IP_RECVERR, &yes, sizeof (yes));
setsockopt (fd, SOL_IP, IP_RECVERR, &yes, sizeof (yes));
#endif
break;
break;
case AF_INET6:
setsockopt (fd, SOL_IPV6, IPV6_RECVPKTINFO, &yes,
sizeof (yes));
case AF_INET6:
setsockopt (fd, SOL_IPV6, IPV6_RECVPKTINFO, &yes,
sizeof (yes));
#ifdef IPV6_RECVERR
setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &yes, sizeof (yes));
setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &yes, sizeof (yes));
#endif
break;
}
}
else
{
if (listen (fd, INT_MAX))
{
perror ("Error opening IP port");
goto error;
}
}
return fd;
break;
}
}
else
{
if (listen (fd, INT_MAX))
{
perror ("Error opening IP port");
goto error;
}
}
return fd;
error:
close (fd);
return -1;
close (fd);
return -1;
}
......@@ -148,9 +148,9 @@ error:
static int recv_err (int fd)
{
#ifdef MSG_ERRQUEUE
struct msghdr hdr;
memset (&hdr, 0, sizeof (hdr));
return recvmsg (fd, &hdr, MSG_ERRQUEUE) >= 0;
struct msghdr hdr;
memset (&hdr, 0, sizeof (hdr));
return recvmsg (fd, &hdr, MSG_ERRQUEUE) >= 0;
#endif
}
......@@ -158,104 +158,99 @@ static int recv_err (int fd)
/** Receives a message or dequeues an error from a socket */
ssize_t recv_safe (int fd, struct msghdr *msg)
{
ssize_t len = recvmsg (fd, msg, 0);
if (len == -1)
recv_err (fd);
else
if (msg->msg_flags & MSG_TRUNC)
{
errno = EMSGSIZE;
return -1;
}
return len;
ssize_t len = recvmsg (fd, msg, 0);
if (len == -1)
recv_err (fd);
else
if (msg->msg_flags & MSG_TRUNC)
{
errno = EMSGSIZE;
return -1;
}
return len;
}
/** Sends a message through a socket */
ssize_t send_safe (int fd, const struct msghdr *msg)
{
ssize_t len;
ssize_t len;
do
len = sendmsg (fd, msg, 0);
while ((len == -1) && (recv_err (fd) == 0));
do
len = sendmsg (fd, msg, 0);
while ((len == -1) && (recv_err (fd) == 0));
return len;
return len;
}
static int dgram_process (int sock)
{
struct sockaddr_storage addr;
uint8_t buf[STUN_MAXMSG];
char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))];
struct iovec iov = { buf, sizeof (buf) };
struct msghdr mh =
{
.msg_name = (struct sockaddr *)&addr,
.msg_namelen = sizeof (addr),
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = ctlbuf,
.msg_controllen = sizeof (ctlbuf)
};
size_t len = recv_safe (sock, &mh);
if (len == (size_t)-1)
return -1;
/* Mal-formatted packets */
if ((stun_validate (buf, len) <= 0)
|| (stun_get_class (buf) != STUN_REQUEST))
return -1;
/* Unknown attributes */
if (stun_has_unknown (buf))
{
stun_init_error_unknown (buf, sizeof (buf), buf);
goto finish;
}
switch (stun_get_method (buf))
{
case STUN_BINDING:
stun_init_response (buf, sizeof (buf), buf);
if (stun_has_cookie (buf))
stun_append_xor_addr (buf, sizeof (buf),
STUN_XOR_MAPPED_ADDRESS,
mh.msg_name, mh.msg_namelen);
else
stun_append_addr (buf, sizeof (buf), STUN_MAPPED_ADDRESS,
mh.msg_name, mh.msg_namelen);
break;
case STUN_ALLOCATE:
case STUN_CONNECT:
case STUN_SET_ACTIVE_DST:
goto send;
default:
stun_init_error (buf, sizeof (buf), buf, STUN_BAD_REQUEST);
}
struct sockaddr_storage addr;
uint8_t buf[STUN_MAXMSG];
char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))];
struct iovec iov = { buf, sizeof (buf) };
struct msghdr mh =
{
.msg_name = (struct sockaddr *)&addr,
.msg_namelen = sizeof (addr),
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = ctlbuf,
.msg_controllen = sizeof (ctlbuf)
};
size_t len = recv_safe (sock, &mh);
if (len == (size_t)-1)
return -1;
/* Mal-formatted packets */
if ((stun_validate (buf, len) <= 0)
|| (stun_get_class (buf) != STUN_REQUEST))
return -1;
/* Unknown attributes */
if (stun_has_unknown (buf))
{
stun_init_error_unknown (buf, sizeof (buf), buf);
goto finish;
}
switch (stun_get_method (buf))
{
case STUN_BINDING:
stun_init_response (buf, sizeof (buf), buf);
if (stun_has_cookie (buf))
stun_append_xor_addr (buf, sizeof (buf),
STUN_XOR_MAPPED_ADDRESS,
mh.msg_name, mh.msg_namelen);
else
stun_append_addr (buf, sizeof (buf), STUN_MAPPED_ADDRESS,
mh.msg_name, mh.msg_namelen);
break;
default:
stun_init_error (buf, sizeof (buf), buf, STUN_BAD_REQUEST);
}
finish:
stun_finish (buf, &iov.iov_len);
stun_finish (buf, &iov.iov_len);
send:
len = send_safe (sock, &mh);
return (len < iov.iov_len) ? -1 : 0;
len = send_safe (sock, &mh);
return (len < iov.iov_len) ? -1 : 0;
}
static int run (int family, int protocol, unsigned port)
{
int sock = listen_socket (family, SOCK_DGRAM, protocol, htons (port));
if (sock == -1)
return -1;
int sock = listen_socket (family, SOCK_DGRAM, protocol, htons (port));
if (sock == -1)
return -1;
for (;;)
dgram_process (sock);
for (;;)
dgram_process (sock);
}
......@@ -263,38 +258,38 @@ static int run (int family, int protocol, unsigned port)
* But calling exit() is needed for gcov to work properly. */
static void exit_handler (int signum)
{
(void)signum;
exit (0);
(void)signum;
exit (0);
}
int main (int argc, char *argv[])
{
int family = AF_INET;
unsigned port = IPPORT_STUN;
for (;;)
{
int c = getopt (argc, argv, "46");
if (c == EOF)
break;
switch (c)
{
case '4':
family = AF_INET;
break;
case '6':
family = AF_INET6;
break;
}
}
if (optind < argc)
port = atoi (argv[optind++]);
signal (SIGINT, exit_handler);
signal (SIGTERM, exit_handler);
return run (family, IPPROTO_UDP, port) ? EXIT_FAILURE : EXIT_SUCCESS;
int family = AF_INET;
unsigned port = IPPORT_STUN;
for (;;)
{
int c = getopt (argc, argv, "46");
if (c == EOF)
break;
switch (c)
{
case '4':
family = AF_INET;
break;
case '6':
family = AF_INET6;
break;
}
}
if (optind < argc)
port = atoi (argv[optind++]);
signal (SIGINT, exit_handler);
signal (SIGTERM, exit_handler);
return run (family, IPPROTO_UDP, port) ? EXIT_FAILURE : EXIT_SUCCESS;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -55,45 +55,45 @@
int main (void)
{
struct sockaddr_in ip4;
stun_msg_t buf;
ssize_t val;
size_t len;
static const uint8_t req[] =
"\x00\x01" "\x00\x00"
"\x00\x01\x02\x03\x04\x05\x06\x07"
"\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
struct sockaddr_in ip4;
stun_msg_t buf;
ssize_t val;
size_t len;
static const uint8_t req[] =
"\x00\x01" "\x00\x00"
"\x00\x01\x02\x03\x04\x05\x06\x07"
"\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
memset (&ip4, 0, sizeof (ip4));
ip4.sin_family = AF_INET;
memset (&ip4, 0, sizeof (ip4));
ip4.sin_family = AF_INET;
#ifdef HAVE_SA_LEN
ip4.sin_len = sizeof (addr);
ip4.sin_len = sizeof (addr);
#endif
ip4.sin_port = htons (12345);
ip4.sin_addr.s_addr = htonl (0x7f000001);
ip4.sin_port = htons (12345);
ip4.sin_addr.s_addr = htonl (0x7f000001);
/* Same with too small response buffer */
stun_init_request (buf, STUN_BINDING);
len = sizeof (buf);
stun_finish (buf, &len);
/* Same with too small response buffer */
stun_init_request (buf, STUN_BINDING);
len = sizeof (buf);
stun_finish (buf, &len);
len = 20 + 12 + 4 + stun_align (strlen (PACKAGE_STRING)) + 7;
val = stun_bind_reply (buf, &len, buf,
(struct sockaddr *)&ip4, sizeof (ip4), false);
assert (val == ENOBUFS);
assert (len == 0);
len = 20 + 12 + 4 + stun_align (strlen (PACKAGE_STRING)) + 7;
val = stun_bind_reply (buf, &len, buf,
(struct sockaddr *)&ip4, sizeof (ip4), false);
assert (val == ENOBUFS);
assert (len == 0);
/* Same with too small response buffer */
stun_init_request (buf, STUN_BINDING);
stun_append_string (buf, sizeof (buf), 0x666, "Unknown attribute!");
len = sizeof (buf);
stun_finish (buf, &len);
/* Same with too small response buffer */
stun_init_request (buf, STUN_BINDING);
stun_append_string (buf, sizeof (buf), 0x666, "Unknown attribute!");
len = sizeof (buf);
stun_finish (buf, &len);
len = 20 + 4 + stun_align (strlen (PACKAGE_STRING)) + 7;
val = stun_bind_reply (buf, &len, buf,
(struct sockaddr *)&ip4, sizeof (ip4), false);
assert (val == ENOBUFS);
assert (len == 0);
len = 20 + 4 + stun_align (strlen (PACKAGE_STRING)) + 7;
val = stun_bind_reply (buf, &len, buf,
(struct sockaddr *)&ip4, sizeof (ip4), false);
assert (val == ENOBUFS);
assert (len == 0);
return 0;
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -63,80 +63,80 @@
static void stun_gettime (struct timespec *restrict now)
{
#if (_POSIX_MONOTONIC_CLOCK - 0) >= 0
if (clock_gettime (CLOCK_MONOTONIC, now))
if (clock_gettime (CLOCK_MONOTONIC, now))
#endif
{ // fallback to wall clock
struct timeval tv;
gettimeofday (&tv, NULL);
now->tv_sec = tv.tv_sec;
now->tv_nsec = tv.tv_usec * 1000;
}
{ // fallback to wall clock
struct timeval tv;
gettimeofday (&tv, NULL);
now->tv_sec = tv.tv_sec;
now->tv_nsec = tv.tv_usec * 1000;
}
}
static inline void add_delay (struct timespec *ts, unsigned delay)
{
div_t d = div (delay, 1000);
ts->tv_sec += d.quot;
ts->tv_nsec += d.rem * 1000000;
while (ts->tv_nsec > 1000000000)
{
ts->tv_nsec -= 1000000000;
ts->tv_sec++;
}
div_t d = div (delay, 1000);
ts->tv_sec += d.quot;
ts->tv_nsec += d.rem * 1000000;
while (ts->tv_nsec > 1000000000)
{
ts->tv_nsec -= 1000000000;
ts->tv_sec++;
}
}
void stun_timer_start (stun_timer_t *timer)
{
stun_gettime (&timer->deadline);
add_delay (&timer->deadline, timer->delay = STUN_INIT_TIMEOUT);
stun_gettime (&timer->deadline);
add_delay (&timer->deadline, timer->delay = STUN_INIT_TIMEOUT);
}
void stun_timer_start_reliable (stun_timer_t *timer)
{
stun_gettime (&timer->deadline);
add_delay (&timer->deadline, timer->delay = STUN_RELIABLE_TIMEOUT);
stun_gettime (&timer->deadline);
add_delay (&timer->deadline, timer->delay = STUN_RELIABLE_TIMEOUT);
}
unsigned stun_timer_remainder (const stun_timer_t *timer)
{
unsigned delay;
struct timespec now;
unsigned delay;
struct timespec now;
stun_gettime (&now);
if (now.tv_sec > timer->deadline.tv_sec)
return 0;
stun_gettime (&now);
if (now.tv_sec > timer->deadline.tv_sec)
return 0;
delay = timer->deadline.tv_sec - now.tv_sec;
if ((delay == 0) && (now.tv_nsec >= timer->deadline.tv_nsec))
return 0;
delay = timer->deadline.tv_sec - now.tv_sec;
if ((delay == 0) && (now.tv_nsec >= timer->deadline.tv_nsec))
return 0;
delay *= 1000;
delay += ((signed)(timer->deadline.tv_nsec - now.tv_nsec)) / 1000000;
return delay;
delay *= 1000;
delay += ((signed)(timer->deadline.tv_nsec - now.tv_nsec)) / 1000000;
return delay;
}
int stun_timer_refresh (stun_timer_t *timer)
{
unsigned delay = stun_timer_remainder (timer);
if (delay == 0)
{
unsigned delay = stun_timer_remainder (timer);
if (delay == 0)
{
#if STUN_RELIABLE_TIMEOUT < STUN_END_TIMEOUT
/* Reliable timeout MUST be bigger (or equal) to end timeout, so that
* retransmissions never happen with reliable transports. */
# error Inconsistent STUN timeout values!
#endif
if (timer->delay >= STUN_END_TIMEOUT)
return -1;
if (timer->delay >= STUN_END_TIMEOUT)
return -1;
add_delay (&timer->deadline, timer->delay *= 2);
}
add_delay (&timer->deadline, timer->delay *= 2);
}
return delay;
return delay;
}
......@@ -46,8 +46,8 @@
typedef struct stun_timer_s
{
struct timespec deadline;
unsigned delay;
struct timespec deadline;
unsigned delay;
} stun_timer_t;
......
This diff is collapsed.
......@@ -48,27 +48,27 @@
typedef struct stun_trans_s
{
stun_timer_t timer;
unsigned flags;
struct
{
size_t length, offset;
uint8_t buf[STUN_MAXMSG];
} msg;
struct
{
int fd;
socklen_t dstlen;
struct sockaddr_storage dst;
} sock;
struct
{
size_t length;
uint8_t *value;
} key;
stun_timer_t timer;
unsigned flags;
struct
{
size_t length, offset;
uint8_t buf[STUN_MAXMSG];
} msg;
struct
{
int fd;
socklen_t dstlen;
struct sockaddr_storage dst;
} sock;
struct
{
size_t length;
uint8_t *value;
} key;
} stun_trans_t;
......@@ -171,12 +171,12 @@ ssize_t stun_recvfrom (int fd, uint8_t *buf, size_t maxlen,
static inline ssize_t stun_send (int fd, const uint8_t *buf, size_t len)
{
return stun_sendto (fd, buf, len, NULL, 0);
return stun_sendto (fd, buf, len, NULL, 0);
}
static inline ssize_t stun_recv (int fd, uint8_t *buf, size_t maxlen)
{
return stun_recvfrom (fd, buf, maxlen, NULL, NULL);
return stun_recvfrom (fd, buf, maxlen, NULL, NULL);
}
# ifdef __cplusplus
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment