#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static time_t token_bucket_time;
static int token_bucket_tokens;
-static int verbose = 1;
+static bool verbose = true;
// ------------------------ >8 ------------------------
static const char *
-getAddr(const struct sockaddr *sa, const size_t saLen)
+getAddr(const struct sockaddr *sa, const socklen_t saLen)
{
static char host[NI_MAXHOST];
static char port[NI_MAXSERV];
static int
parse_message(
const unsigned char *buf,
- int buflen,
+ const size_t buflen,
unsigned char *tid_return,
- int *tid_len,
+ size_t *tid_len,
unsigned char *id_return,
unsigned char *info_hash_return,
unsigned char *target_return,
unsigned short *port_return,
unsigned char *token_return,
- int *token_len,
+ size_t *token_len,
unsigned char *nodes_return,
- int *nodes_len,
+ size_t *nodes_len,
unsigned char *nodes6_return,
- int *nodes6_len,
+ size_t *nodes6_len,
unsigned char *values_return,
- int *values_len,
+ size_t *values_len,
unsigned char *values6_return,
- int *values6_len,
+ size_t *values6_len,
int *want_return,
const struct sockaddr *sa,
- const size_t saLen)
+ const socklen_t saLen)
{
- const unsigned char *p;
-
/* This code will happily crash if the buffer is not NUL-terminated. */
if (buf[buflen] != '\0') {
if (verbose)
}
#define CHECK(ptr, len) \
- if (((unsigned char *)ptr) + (len) > (buf) + (buflen)) \
+ if (((const unsigned char *)ptr) + (len) > (buf) + (buflen)) \
goto overflow;
+ unsigned char *p;
+ unsigned long l = 0;
+ char *q;
if (tid_return) {
p = memmem(buf, buflen, "1:t", 3);
if (p) {
- long l;
- char *q;
- l = strtol((char *)p + 3, &q, 10);
+ l = strtoul((const char *)p + 3, &q, 10);
if (q && *q == ':' && l > 0 && l < *tid_len) {
CHECK(q + 1, l);
memcpy(tid_return, q + 1, l);
if (port_return) {
p = memmem(buf, buflen, "porti", 5);
if (p) {
- long l;
- char *q;
- l = strtol((char *)p + 5, &q, 10);
+ l = strtoul((const char *)p + 5, &q, 10);
if (q && *q == 'e' && l > 0 && l < 0x10000)
- *port_return = l;
+ *port_return = (unsigned short)l;
else
*port_return = 0;
} else
if (token_return) {
p = memmem(buf, buflen, "5:token", 7);
if (p) {
- long l;
- char *q;
- l = strtol((char *)p + 7, &q, 10);
+ l = strtoul((const char *)p + 7, &q, 10);
if (q && *q == ':' && l > 0 && l < *token_len) {
CHECK(q + 1, l);
memcpy(token_return, q + 1, l);
if (nodes_len) {
p = memmem(buf, buflen, "5:nodes", 7);
if (p) {
- long l;
- char *q;
- l = strtol((char *)p + 7, &q, 10);
+ l = strtoul((const char *)p + 7, &q, 10);
if (q && *q == ':' && l > 0 && l < *nodes_len) {
CHECK(q + 1, l);
memcpy(nodes_return, q + 1, l);
if (nodes6_len) {
p = memmem(buf, buflen, "6:nodes6", 8);
if (p) {
- long l;
- char *q;
- l = strtol((char *)p + 8, &q, 10);
+ l = strtoul((const char *)p + 8, &q, 10);
if (q && *q == ':' && l > 0 && l < *nodes6_len) {
CHECK(q + 1, l);
memcpy(nodes6_return, q + 1, l);
if (values_len || values6_len) {
p = memmem(buf, buflen, "6:valuesl", 9);
if (p) {
- int i = p - buf + 9;
- int j = 0, j6 = 0;
+ size_t i = p - buf + 9;
+ unsigned long j = 0, j6 = 0;
while (1) {
- long l;
- char *q;
- l = strtol((char *)buf + i, &q, 10);
+ l = strtoul((const char *)buf + i, &q, 10);
if (q && *q == ':' && l > 0) {
CHECK(q + 1, l);
if (l == 6) {
if (j + l > *values_len)
continue;
- i = q + 1 + l - (char *)buf;
+ i = q + 1 + l - (const char *)buf;
memcpy((char *)values_return + j, q + 1, l);
j += l;
} else if (l == 18) {
if (j6 + l > *values6_len)
continue;
- i = q + 1 + l - (char *)buf;
+ i = q + 1 + l - (const char *)buf;
memcpy((char *)values6_return + j6, q + 1, l);
j6 += l;
} else {
"%s : received weird value: %d bytes\n",
getAddr(sa, saLen),
(int)l);
- i = q + 1 + l - (char *)buf;
+ i = q + 1 + l - (const char *)buf;
}
} else {
break;
if (want_return) {
p = memmem(buf, buflen, "4:wantl", 7);
if (p) {
- int i = p - buf + 7;
+ size_t i = p - buf + 7;
*want_return = 0;
while (buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
i + 2 + buf[i] - '0' < buflen) {
#define INC(offset, delta, size) \
CHECK(offset, delta, size); \
- offset += delta
+ offset += delta;
#define COPY(buf, offset, src, delta, size) \
CHECK(offset, delta, size); \
#define ADD_V(buf, offset, size) COPY(buf, offset, my_v, (sizeof my_v), size)
-static int
-is_martian(struct sockaddr *sa)
+static bool
+is_martian(const struct sockaddr *sa)
{
switch (sa->sa_family) {
case AF_INET: {
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
const unsigned char *address = (const unsigned char *)&sin->sin_addr;
return sin->sin_port == 0 || (address[0] == 0) || (address[0] == 127) ||
((address[0] & 0xE0) == 0xE0);
}
case AF_INET6: {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
const unsigned char *address = (const unsigned char *)&sin6->sin6_addr;
return sin6->sin6_port == 0 || (address[0] == 0xFF) ||
(address[0] == 0xFE && (address[1] & 0xC0) == 0x80) ||
(address[15] == 0 || address[15] == 1)) ||
(memcmp(address, v4prefix, 12) == 0);
}
-
- default:
- return 0;
}
+ return false;
}
/* Forget about the ``XOR-metric''. An id is just a path from the
host order. */
static void
-make_tid(unsigned char *tid_return, const char *prefix, unsigned short seqno)
+make_tid(unsigned char *tid_return, const char *prefix, const unsigned short seqno)
{
tid_return[0] = prefix[0] & 0xFF;
tid_return[1] = prefix[1] & 0xFF;
return circular(list->head, list->tail);
}
-static int
+static bool
list_empty(struct circular_list *list)
{
return list_elements(list) == 0;
/* We just learnt about a node, not necessarily a new one. Confirm is 1 if
the node sent a message, 2 if it sent us a reply. */
-static int
-new_node(unsigned char *id, struct sockaddr *sa, socklen_t salen, int confirm)
+static bool
+new_node(
+ const unsigned char *id,
+ const struct sockaddr *sa,
+ const socklen_t salen,
+ const int confirm)
{
struct circular_list *list;
if (sa->sa_family == AF_INET)
include such a node if we have plenty of space. */
if (confirm == 1 && list_free(list) < 32)
- return 0;
+ return false;
for (int i = list->head; i != list->tail; i = (i + 1) % CIRCULAR_LIST_SIZE) {
struct node *n = &list->nodes[i];
if (n->sslen == salen && memcmp(&n->ss, sa, salen) == 0)
- return 0;
+ return false;
}
memcpy(&list->nodes[list->tail].id, id, 160);
if (verbose)
printf("%s : new node\n", getAddr(sa, salen));
- return 1;
+ return true;
}
-static int
+static bool
token_bucket(void)
{
time_t now = time(NULL);
token_bucket_time = now;
}
if (token_bucket_tokens == 0)
- return 0;
+ return false;
token_bucket_tokens--;
- return 1;
+ return true;
}
-static int
-dht_send(const void *buf, size_t len, int flags, const struct sockaddr *sa, int salen)
+static ssize_t
+dht_send(
+ const void *buf,
+ const size_t len,
+ const struct sockaddr *sa,
+ const socklen_t salen)
{
if (salen == 0)
abort();
errno = EAFNOSUPPORT;
return -1;
}
- return sendto(s, buf, len, flags, sa, salen);
+ return sendto(s, buf, len, 0, sa, salen);
}
-static int
-send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
+static ssize_t
+send_ping(
+ const struct sockaddr *sa,
+ const socklen_t salen,
+ const unsigned char *tid,
+ const size_t tid_len)
{
char buf[512];
- int i = 0, rc;
- rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
+ int i = 0;
+ int rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
INC(i, rc, 512);
COPY(buf, i, myid, 20, 512);
- rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%d:", tid_len);
+ rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%zu:", tid_len);
INC(i, rc, 512);
COPY(buf, i, tid, tid_len, 512);
ADD_V(buf, i, 512);
INC(i, rc, 512);
if (verbose)
printf("%s <- PING\n", getAddr(sa, salen));
- return dht_send(buf, i, 0, sa, salen);
+ return dht_send(buf, (size_t)i, sa, salen);
fail:
errno = ENOSPC;
return -1;
}
-static int
-send_pong(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
+static ssize_t
+send_pong(
+ const struct sockaddr *sa,
+ const socklen_t salen,
+ const unsigned char *tid,
+ const size_t tid_len)
{
char buf[512];
int i = 0;
int rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:");
INC(i, rc, 512);
COPY(buf, i, myid, 20, 512);
- rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
+ rc = snprintf(buf + i, 512 - i, "e1:t%zu:", tid_len);
INC(i, rc, 512);
COPY(buf, i, tid, tid_len, 512);
ADD_V(buf, i, 512);
INC(i, rc, 512);
if (verbose)
printf("%s <- PONG\n", getAddr(sa, salen));
- return dht_send(buf, i, 0, sa, salen);
+ return dht_send(buf, (size_t)i, sa, salen);
fail:
errno = ENOSPC;
return -1;
}
-static int
+static ssize_t
send_find_node(
- struct sockaddr *sa,
- int salen,
+ const struct sockaddr *sa,
+ const socklen_t salen,
const unsigned char *tid,
- int tid_len,
+ const size_t tid_len,
const unsigned char *target,
- int want)
+ const int want)
{
char buf[512];
int i = 0;
(want & WANT6) ? "2:n6" : "");
INC(i, rc, 512);
}
- rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
+ rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%zu:", tid_len);
INC(i, rc, 512);
COPY(buf, i, tid, tid_len, 512);
ADD_V(buf, i, 512);
INC(i, rc, 512);
if (verbose)
printf("%s <- FIND_NODE\n", getAddr(sa, salen));
- return dht_send(buf, i, 0, sa, salen);
+ return dht_send(buf, (size_t)i, sa, salen);
fail:
errno = ENOSPC;
return -1;
}
-static int
-send_request(struct circular_list *list, int dopop, int doping, int want)
+static ssize_t
+send_request(
+ struct circular_list *list,
+ const bool dopop,
+ const bool doping,
+ const int want)
{
if (list_empty(list))
return 0;
r.rlim_cur = 0;
r.rlim_max = 0;
if (setrlimit(res, &r) == -1) {
- err(EXIT_FAILURE, "can not setrlimit()");
+ err(EXIT_FAILURE, "setrlimit()");
}
}
-static int
+static ssize_t
send_nodes(
- struct sockaddr *sa,
- int salen,
+ const struct sockaddr *sa,
+ const socklen_t salen,
const unsigned char *tid,
- int tid_len,
+ const size_t tid_len,
const unsigned char *nodes,
- int nodes_len,
+ const size_t nodes_len,
const unsigned char *nodes6,
- int nodes6_len)
+ const size_t nodes6_len)
{
char buf[2048];
int i = 0;
INC(i, rc, 2048);
COPY(buf, i, myid, 20, 2048);
if (nodes_len > 0) {
- rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
+ rc = snprintf(buf + i, 2048 - i, "5:nodes%zu:", nodes_len);
INC(i, rc, 2048);
COPY(buf, i, nodes, nodes_len, 2048);
}
if (nodes6_len > 0) {
- rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
+ rc = snprintf(buf + i, 2048 - i, "6:nodes6%zu:", nodes6_len);
INC(i, rc, 2048);
COPY(buf, i, nodes6, nodes6_len, 2048);
}
- rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len);
+ rc = snprintf(buf + i, 2048 - i, "e1:t%zu:", tid_len);
INC(i, rc, 2048);
COPY(buf, i, tid, tid_len, 2048);
ADD_V(buf, i, 2048);
rc = snprintf(buf + i, 2048 - i, "1:y1:re");
INC(i, rc, 2048);
- return dht_send(buf, i, 0, sa, salen);
+ return dht_send(buf, (size_t)i, sa, salen);
fail:
errno = ENOSPC;
return n;
}
-static int
+static ssize_t
send_random_nodes(
- struct sockaddr *sa,
- int salen,
+ const struct sockaddr *sa,
+ const socklen_t salen,
const unsigned char *tid,
- int tid_len,
+ const size_t tid_len,
int want)
{
unsigned char nodes[8 * 26];
sa, salen, tid, tid_len, nodes, numnodes * 26, nodes6, numnodes6 * 38);
}
-static int
+static ssize_t
send_error(
- struct sockaddr *sa,
- int salen,
- unsigned char *tid,
- int tid_len,
- int code,
+ const struct sockaddr *sa,
+ const socklen_t salen,
+ const unsigned char *tid,
+ const size_t tid_len,
+ const int code,
const char *message)
{
char buf[512];
int rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:", code, (int)strlen(message));
INC(i, rc, 512);
COPY(buf, i, message, (int)strlen(message), 512);
- rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
+ rc = snprintf(buf + i, 512 - i, "e1:t%zu:", tid_len);
INC(i, rc, 512);
COPY(buf, i, tid, tid_len, 512);
ADD_V(buf, i, 512);
rc = snprintf(buf + i, 512 - i, "1:y1:ee");
INC(i, rc, 512);
- return dht_send(buf, i, 0, sa, salen);
+ return dht_send(buf, (size_t)i, sa, salen);
fail:
errno = ENOSPC;
token_bucket_time = time(NULL);
token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
- int send4 = 0;
+ bool send4 = false;
struct pollfd fds[2];
fds[0].fd = dht_socket;
fds[0].events = POLLIN;
if (rc > 0) {
int message;
- unsigned char tid[16], id[20], info_hash[20], target[20];
- unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
- int tid_len = 16, token_len = 128;
- int nodes_len = 256, nodes6_len = 1024;
+ unsigned char tid[16];
+ unsigned char id[20];
+ unsigned char info_hash[20];
+ unsigned char target[20];
+ unsigned char buf[1536];
+ unsigned char nodes[256];
+ unsigned char nodes6[1024];
+ unsigned char token[128];
+ size_t tid_len = sizeof tid;
+ size_t token_len = sizeof token;
+ size_t nodes_len = sizeof nodes;
+ size_t nodes6_len = sizeof nodes6;
unsigned short port;
- unsigned char values[2048], values6[2048];
- int values_len = 2048, values6_len = 2048;
+ unsigned char values[2048];
+ unsigned char values6[2048];
+ size_t values_len = sizeof values;
+ size_t values6_len = sizeof values6;
int want;
struct sockaddr_storage source_storage;
struct sockaddr *source = (struct sockaddr *)&source_storage;
socklen_t sourcelen = sizeof(source_storage);
+ ssize_t got = 0;
if (fds[0].revents != 0) {
if ((fds[0].revents & (POLLERR | POLLNVAL)) > 0) {
fprintf(stderr, "error in fds[0]");
- rc = -1;
+ got = -1;
} else {
- rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
+ got = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
}
} else if (fds[1].revents != 0) {
if ((fds[1].revents & (POLLERR | POLLNVAL)) > 0) {
fprintf(stderr, "error in fds[1]");
- rc = -1;
+ got = -1;
} else {
- rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
+ got = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
}
}
- if (rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
+ if (got < 0 || sourcelen > sizeof(struct sockaddr_storage))
goto dontread;
if (is_martian(source))
buffer if it's not NUL-terminated. For now, put a NUL at the
end of buffers. */
- if (rc < 1536) {
- buf[rc] = '\0';
+ if (got < 1536) {
+ buf[got] = '\0';
} else {
if (verbose)
printf("%s : overlong message\n", getAddr(source, sourcelen));
message = parse_message(
buf,
- rc,
+ (size_t)got,
tid,
&tid_len,
id,
} else if (tid_match(tid, "fn", NULL)) {
if (verbose)
printf(
- "%s -> NODES (%d+%d)\n",
+ "%s -> NODES (%zu+%zu)\n",
getAddr(source, sourcelen),
nodes_len / 26,
nodes6_len / 38);
getAddr(source, sourcelen));
} else {
new_node(id, source, sourcelen, 2);
- for (i = 0; i < nodes_len / 26; i++) {
- unsigned char *ni = nodes + i * 26;
+ size_t n;
+ for (n = 0; n < nodes_len / 26; n++) {
+ unsigned char *ni = nodes + n * 26;
struct sockaddr_in sin;
if (id_cmp(ni, myid) == 0)
continue;
memcpy(&sin.sin_port, ni + 24, 2);
new_node(ni, (struct sockaddr *)&sin, sizeof(sin), 0);
}
- for (i = 0; i < nodes6_len / 38; i++) {
- unsigned char *ni = nodes6 + i * 38;
+ for (n = 0; n < nodes6_len / 38; n++) {
+ unsigned char *ni = nodes6 + n * 38;
struct sockaddr_in6 sin6;
if (id_cmp(ni, myid) == 0)
continue;
break;
case PING:
if (verbose)
- printf("%s -> PING (%d)\n", getAddr(source, sourcelen), tid_len);
+ printf("%s -> PING (%zu)\n", getAddr(source, sourcelen), tid_len);
new_node(id, source, sourcelen, 1);
send_pong(source, sourcelen, tid, tid_len);
break;
loop. */
if (dht_socket6 < 0)
- send4 = 1;
+ send4 = true;
else if (dht_socket < 0)
- send4 = 0;
+ send4 = false;
else
- send4 = random() % 2;
+ send4 = (random() % 2) == 1;
if (send4) {
int want = dht_socket6 >= 0 && list_free(&v6_new) > 8 ? (WANT4 | WANT6) : 0;
if (!list_empty(&v4_new))
- send_request(&v4_new, 1, list_free(&v4_new) < 8, want);
+ send_request(&v4_new, true, list_free(&v4_new) < 8, want);
else if (!list_empty(&v4_confirmed))
- send_request(&v4_confirmed, 0, 0, want);
+ send_request(&v4_confirmed, false, false, want);
} else {
int want = dht_socket >= 0 && list_free(&v4_new) > 8 ? (WANT4 | WANT6) : 0;
if (!list_empty(&v6_new))
- send_request(&v6_new, 1, list_free(&v6_new) < 8, want);
+ send_request(&v6_new, true, list_free(&v6_new) < 8, want);
else if (!list_empty(&v6_confirmed))
- send_request(&v6_confirmed, 0, 0, want);
+ send_request(&v6_confirmed, false, false, want);
}
}