- if (values_len || values6_len) {
- p = memmem(buf, buflen, "6:valuesl", 9);
- if (p) {
- int i = p - buf + 9;
- int j = 0, j6 = 0;
- while (1) {
- long l;
- char *q;
- l = strtol((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;
- 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;
- memcpy((char *)values6_return + j6, q + 1, l);
- j6 += l;
+ while (1) {
+ int tv_sec = 0;
+ if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
+ (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
+ tv_sec = 0;
+ else
+ tv_sec = random() % 30;
+ int tv_msec = random() % 1000;
+
+#ifndef __linux__
+ setproctitle_fast(
+ "%d+%d %d+%d",
+ list_elements(&v4_confirmed),
+ list_elements(&v6_confirmed),
+ list_elements(&v4_new),
+ list_elements(&v6_new));
+#endif // __linux__
+
+ rc = poll(fds, 2, tv_sec * 1000 + tv_msec);
+ if (rc < 0) {
+ perror("poll");
+ sleep(1);
+ }
+
+ 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 short port;
+ unsigned char values[2048], values6[2048];
+ int values_len = 2048, values6_len = 2048;
+ int want;
+ struct sockaddr_storage source_storage;
+ struct sockaddr *source = (struct sockaddr *)&source_storage;
+ socklen_t sourcelen = sizeof(source_storage);
+ if (fds[0].revents != 0) {
+ if ((fds[0].revents & (POLLERR | POLLNVAL)) > 0) {
+ fprintf(stderr, "error in fds[0]");
+ rc = -1;
+ } else {
+ rc = 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;
+ } else {
+ rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
+ }
+ }
+
+ if (rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
+ goto dontread;
+
+ if (is_martian(source))
+ goto dontread;
+
+ /* There's a bug in parse_message -- it will happily overflow the
+ buffer if it's not NUL-terminated. For now, put a NUL at the
+ end of buffers. */
+
+ if (rc < 1536) {
+ buf[rc] = '\0';
+ } else {
+ if (verbose)
+ printf("%s : overlong message\n", getAddr(source, sourcelen));
+ goto dontread;
+ }
+
+ message = parse_message(
+ buf,
+ rc,
+ tid,
+ &tid_len,
+ id,
+ info_hash,
+ target,
+ &port,
+ token,
+ &token_len,
+ nodes,
+ &nodes_len,
+ nodes6,
+ &nodes6_len,
+ values,
+ &values_len,
+ values6,
+ &values6_len,
+ &want,
+ source,
+ sourcelen);
+
+ if (id_cmp(id, myid) == 0) {
+ if (verbose)
+ printf(
+ "%s : received message from self\n",
+ getAddr(source, sourcelen));
+ goto dontread;
+ }
+
+ if (message > REPLY) {
+ /* Rate limit requests. */
+ if (!token_bucket()) {
+ if (verbose)
+ printf(
+ "%s : dropping request due to rate limiting.\n",
+ getAddr(source, sourcelen));
+ goto dontread;
+ }
+ }
+
+ switch (message) {
+ case REPLY:
+ if (tid_len != 4) {
+ if (verbose)
+ printf(
+ "%s : broken node truncates transaction ids\n",
+ getAddr(source, sourcelen));
+ goto dontread;
+ }
+ if (tid_match(tid, "pn", NULL)) {
+ if (verbose)
+ printf("%s -> PONG\n", getAddr(source, sourcelen));
+ new_node(id, source, sourcelen, 2);
+ } else if (tid_match(tid, "fn", NULL)) {
+ if (verbose)
+ printf(
+ "%s -> NODES (%d+%d)\n",
+ getAddr(source, sourcelen),
+ nodes_len / 26,
+ nodes6_len / 38);
+ if (nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
+ if (verbose)
+ printf(
+ "%s : unexpected length for node info\n",
+ getAddr(source, sourcelen));