2 Copyright (c) 2009-2011 by Juliusz Chroboczek
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #include <netinet/in.h>
32 #include <sys/socket.h>
36 #define MIN(x, y) ((x) <= (y) ? (x) : (y))
39 send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len);
41 send_pong(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len);
46 const unsigned char *tid,
48 const unsigned char *target,
54 const unsigned char *tid,
56 const unsigned char *nodes,
58 const unsigned char *nodes6,
64 const unsigned char *tid,
66 const unsigned char *id,
82 #define ANNOUNCE_PEER 5
89 const unsigned char *buf,
91 unsigned char *tid_return,
93 unsigned char *id_return,
94 unsigned char *info_hash_return,
95 unsigned char *target_return,
96 unsigned short *port_return,
97 unsigned char *token_return,
99 unsigned char *nodes_return,
101 unsigned char *nodes6_return,
103 unsigned char *values_return,
105 unsigned char *values6_return,
109 static const unsigned char zeroes[20] = {0};
110 static const unsigned char v4prefix[16] =
111 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0};
113 static unsigned char myid[20];
114 static int have_v = 0;
115 static unsigned char my_v[9];
117 static int dht_socket = -1;
118 static int dht_socket6 = -1;
121 unsigned char id[160];
122 struct sockaddr_storage ss;
126 #define CIRCULAR_LIST_SIZE 256
128 struct circular_list {
131 struct node nodes[CIRCULAR_LIST_SIZE];
134 struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
136 #define MAX_TOKEN_BUCKET_TOKENS 40
137 static time_t token_bucket_time;
138 static int token_bucket_tokens;
140 FILE *dht_debug = NULL;
143 __attribute__((format(printf, 1, 2)))
146 debugf(const char *format, ...)
149 va_start(args, format);
151 vfprintf(dht_debug, format, args);
157 is_martian(struct sockaddr *sa)
159 switch (sa->sa_family) {
161 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
162 const unsigned char *address = (const unsigned char *)&sin->sin_addr;
163 return sin->sin_port == 0 || (address[0] == 0) || (address[0] == 127) ||
164 ((address[0] & 0xE0) == 0xE0);
167 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
168 const unsigned char *address = (const unsigned char *)&sin6->sin6_addr;
169 return sin6->sin6_port == 0 || (address[0] == 0xFF) ||
170 (address[0] == 0xFE && (address[1] & 0xC0) == 0x80) ||
171 (memcmp(address, zeroes, 15) == 0 &&
172 (address[15] == 0 || address[15] == 1)) ||
173 (memcmp(address, v4prefix, 12) == 0);
181 /* Forget about the ``XOR-metric''. An id is just a path from the
182 root of the tree, so bits are numbered from the start. */
185 id_cmp(const unsigned char *restrict id1, const unsigned char *restrict id2)
187 /* Memcmp is guaranteed to perform an unsigned comparison. */
188 return memcmp(id1, id2, 20);
191 /* Our transaction-ids are 4-bytes long, with the first two bytes identi-
192 fying the kind of request, and the remaining two a sequence number in
196 make_tid(unsigned char *tid_return, const char *prefix, unsigned short seqno)
198 tid_return[0] = prefix[0] & 0xFF;
199 tid_return[1] = prefix[1] & 0xFF;
200 memcpy(tid_return + 2, &seqno, 2);
204 tid_match(const unsigned char *tid, const char *prefix, unsigned short *seqno_return)
206 if (tid[0] == (prefix[0] & 0xFF) && tid[1] == (prefix[1] & 0xFF)) {
208 memcpy(seqno_return, tid + 2, 2);
215 circular(int from, int to)
219 return x + CIRCULAR_LIST_SIZE;
224 list_elements(struct circular_list *list)
226 return circular(list->head, list->tail);
230 list_empty(struct circular_list *list)
232 return list_elements(list) == 0;
236 list_free(struct circular_list *list)
238 return circular(list->tail + 1, list->head);
242 list_pop(struct circular_list *list, struct sockaddr_storage *ss, socklen_t *sslen)
244 if (list->head == list->tail)
247 memcpy(ss, &list->nodes[list->head].ss, list->nodes[list->head].sslen);
248 *sslen = list->nodes[list->head].sslen;
249 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
255 struct circular_list *list,
257 struct sockaddr_storage *ss,
261 if (list->head == list->tail)
264 n = random() % (list->tail - list->head);
265 n = (list->head + n) % CIRCULAR_LIST_SIZE;
268 memcpy(id, &list->nodes[n].id, 20);
269 memcpy(ss, &list->nodes[n].ss, list->nodes[n].sslen);
270 *sslen = list->nodes[n].sslen;
274 /* We just learnt about a node, not necessarily a new one. Confirm is 1 if
275 the node sent a message, 2 if it sent us a reply. */
278 new_node(unsigned char *id, struct sockaddr *sa, socklen_t salen, int confirm)
280 struct circular_list *list;
283 if (sa->sa_family == AF_INET)
284 list = confirm >= 2 ? &v4_confirmed : &v4_new;
285 else if (sa->sa_family == AF_INET6)
286 list = confirm >= 2 ? &v6_confirmed : &v6_new;
290 /* A node that sends us a request is most probably bootstrapping.
291 We want to avoid getting our tables full of very young nodes -- only
292 include such a node if we have plenty of space. */
294 if (confirm == 1 && list_free(list) < 32)
297 for (i = list->head; i != list->tail; i = (i + 1) % CIRCULAR_LIST_SIZE) {
298 struct node *n = &list->nodes[i];
299 if (n->sslen == salen && memcmp(&n->ss, sa, salen) == 0)
303 memcpy(&list->nodes[list->tail].id, id, 160);
304 memcpy(&list->nodes[list->tail].ss, sa, salen);
305 list->nodes[list->tail].sslen = salen;
306 list->tail = (list->tail + 1) % CIRCULAR_LIST_SIZE;
307 if (list->head == list->tail)
308 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
316 time_t now = time(NULL);
317 if (token_bucket_tokens == 0) {
318 token_bucket_tokens =
319 MIN(MAX_TOKEN_BUCKET_TOKENS, 4 * (now - token_bucket_time));
320 token_bucket_time = now;
323 if (token_bucket_tokens == 0)
326 token_bucket_tokens--;
331 send_request(struct circular_list *list, int dopop, int doping, int want)
333 unsigned char ttid[4];
334 struct sockaddr_storage ss;
338 if (list_empty(list))
342 rc = list_pop(list, &ss, &sslen);
346 rc = list_random(list, NULL, &ss, &sslen);
352 make_tid(ttid, "pn", 0);
353 debugf("Sending ping.\n");
354 return send_ping((struct sockaddr *)&ss, sslen, ttid, 4);
356 unsigned char id[20];
358 for (i = 0; i < 20; i++)
359 id[i] = random() & 0xFF;
360 make_tid(ttid, "fn", 0);
361 debugf("Sending find_node.\n");
362 return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want);
367 newSock(const char *host, const char *port)
369 struct addrinfo hints;
370 memset(&hints, 0, sizeof(hints));
371 hints.ai_family = AF_UNSPEC;
372 hints.ai_socktype = SOCK_DGRAM;
373 struct addrinfo *res = NULL;
374 int err = getaddrinfo(host, port, &hints, &res);
376 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
379 int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
384 if (bind(sock, res->ai_addr, res->ai_addrlen) != 0) {
388 int rc = fcntl(sock, F_GETFL, 0);
393 rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
403 main(int argc, char **argv)
407 char *ipv4addr = NULL;
408 char *ipv6addr = NULL;
412 opt = getopt(argc, argv, "q4:6:");
421 ipv4addr = strdup(optarg);
424 ipv6addr = strdup(optarg);
436 const char *port = strdup(argv[i++]);
438 if (ipv4addr != NULL) {
439 dht_socket = newSock(ipv4addr, port);
441 if (ipv6addr != NULL) {
442 dht_socket6 = newSock(ipv6addr, port);
447 int fd = open("/dev/urandom", O_RDONLY);
449 perror("open(random)");
453 rc = read(fd, myid, 20);
455 perror("open(random)");
460 rc = read(fd, &seed, sizeof(seed));
466 memcpy(my_v, "1:v4:JB\0\0", 9);
472 unsigned char ttid[4];
475 struct addrinfo hints, *info, *infop;
476 memset(&hints, 0, sizeof(hints));
477 hints.ai_socktype = SOCK_DGRAM;
480 hints.ai_family = AF_INET6;
481 else if (dht_socket6 < 0)
482 hints.ai_family |= AF_INET;
483 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
485 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
495 make_tid(ttid, "pn", 0);
496 debugf("Sending ping.\n");
497 send_ping(infop->ai_addr, infop->ai_addrlen, ttid, 4);
498 infop = infop->ai_next;
505 token_bucket_time = time(NULL);
506 token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
508 struct pollfd fds[2];
509 if (dht_socket >= 0) {
510 fds[0].fd = dht_socket;
511 fds[0].events = POLLIN;
515 if (dht_socket6 >= 0) {
516 fds[1].fd = dht_socket6;
517 fds[1].events = POLLIN;
524 if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
525 (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
528 tv_sec = random() % 30;
529 int tv_msec = random() % 1000;
534 list_elements(&v4_confirmed),
535 list_elements(&v6_confirmed),
536 list_elements(&v4_new),
537 list_elements(&v6_new));
539 int rc = poll(fds, 2, tv_sec * 1000 + tv_msec);
549 unsigned char tid[16], id[20], info_hash[20], target[20];
550 unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
551 int tid_len = 16, token_len = 128;
552 int nodes_len = 256, nodes6_len = 1024;
554 unsigned char values[2048], values6[2048];
555 int values_len = 2048, values6_len = 2048;
557 struct sockaddr_storage source_storage;
558 struct sockaddr *source = (struct sockaddr *)&source_storage;
559 socklen_t sourcelen = sizeof(source_storage);
560 if (fds[0].revents != 0) {
561 if ((fds[0].revents & (POLLERR | POLLNVAL)) > 0) {
562 fprintf(stderr, "error in fds[0]");
565 rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
567 } else if (fds[1].revents != 0) {
568 if ((fds[1].revents & (POLLERR | POLLNVAL)) > 0) {
569 fprintf(stderr, "error in fds[1]");
572 rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
576 if (rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
579 if (is_martian(source))
582 /* There's a bug in parse_message -- it will happily overflow the
583 buffer if it's not NUL-terminated. For now, put a NUL at the
589 debugf("Overlong message.\n");
593 message = parse_message(
614 if (id_cmp(id, myid) == 0) {
615 debugf("Received message from self.\n");
619 if (message > REPLY) {
620 /* Rate limit requests. */
621 if (!token_bucket()) {
622 debugf("Dropping request due to rate limiting.\n");
630 debugf("Broken node truncates transaction ids.\n");
633 if (tid_match(tid, "pn", NULL)) {
635 new_node(id, source, sourcelen, 2);
636 } else if (tid_match(tid, "fn", NULL)) {
637 debugf("Nodes found!\n");
638 if (nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
639 debugf("Unexpected length for node info!\n");
641 new_node(id, source, sourcelen, 2);
642 for (i = 0; i < nodes_len / 26; i++) {
643 unsigned char *ni = nodes + i * 26;
644 struct sockaddr_in sin;
645 if (id_cmp(ni, myid) == 0)
647 memset(&sin, 0, sizeof(sin));
648 sin.sin_family = AF_INET;
649 memcpy(&sin.sin_addr, ni + 20, 4);
650 memcpy(&sin.sin_port, ni + 24, 2);
651 new_node(ni, (struct sockaddr *)&sin, sizeof(sin), 0);
653 for (i = 0; i < nodes6_len / 38; i++) {
654 unsigned char *ni = nodes6 + i * 38;
655 struct sockaddr_in6 sin6;
656 if (id_cmp(ni, myid) == 0)
658 memset(&sin6, 0, sizeof(sin6));
659 sin6.sin6_family = AF_INET6;
660 memcpy(&sin6.sin6_addr, ni + 20, 16);
661 memcpy(&sin6.sin6_port, ni + 36, 2);
662 new_node(ni, (struct sockaddr *)&sin6, sizeof(sin6), 0);
666 debugf("Unexpected reply!\n");
671 debugf("Ping (%d)!\n", tid_len);
672 new_node(id, source, sourcelen, 1);
673 debugf("Sending pong.\n");
674 send_pong(source, sourcelen, tid, tid_len);
679 if (message == FIND_NODE)
680 debugf("Find node!\n");
682 debugf("Get peers!\n");
683 new_node(id, source, sourcelen, 1);
684 debugf("Sending nodes (%d).\n", want);
685 send_random_nodes(source, sourcelen, tid, tid_len, target, want);
688 debugf("Announce peer!\n");
695 "This node doesn't accept announces");
702 /* We need to be careful to avoid a positive feedback loop. Make
703 sure we send at most one packet each time through the select
708 else if (dht_socket < 0)
711 send4 = random() % 2;
714 int want = dht_socket6 >= 0 && list_free(&v6_new) > 8 ? (WANT4 | WANT6) : 0;
715 if (!list_empty(&v4_new))
716 send_request(&v4_new, 1, list_free(&v4_new) < 8, want);
717 else if (!list_empty(&v4_confirmed))
718 send_request(&v4_confirmed, 0, 0, want);
720 int want = dht_socket >= 0 && list_free(&v4_new) > 8 ? (WANT4 | WANT6) : 0;
721 if (!list_empty(&v6_new))
722 send_request(&v6_new, 1, list_free(&v6_new) < 8, want);
723 else if (!list_empty(&v6_confirmed))
724 send_request(&v6_confirmed, 0, 0, want);
731 fprintf(stderr, "dht-bootstrap [-q] [-4 ADDR4] [-6 ADDR6] port [node port...]\n");
735 /* We could use a proper bencoding printer and parser, but the format of
736 DHT messages is fairly stylised, so this seemed simpler. */
738 #define CHECK(offset, delta, size) \
739 if (delta < 0 || offset + delta > size) \
742 #define INC(offset, delta, size) \
743 CHECK(offset, delta, size); \
746 #define COPY(buf, offset, src, delta, size) \
747 CHECK(offset, delta, size); \
748 memcpy(buf + offset, src, delta); \
751 #define ADD_V(buf, offset, size) \
753 COPY(buf, offset, my_v, sizeof(my_v), size); \
757 dht_send(const void *buf, size_t len, int flags, const struct sockaddr *sa, int salen)
764 if (sa->sa_family == AF_INET)
766 else if (sa->sa_family == AF_INET6)
772 errno = EAFNOSUPPORT;
776 return sendto(s, buf, len, flags, sa, salen);
780 send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
784 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
786 COPY(buf, i, myid, 20, 512);
787 rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%d:", tid_len);
789 COPY(buf, i, tid, tid_len, 512);
791 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
793 return dht_send(buf, i, 0, sa, salen);
801 send_pong(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
805 rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:");
807 COPY(buf, i, myid, 20, 512);
808 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
810 COPY(buf, i, tid, tid_len, 512);
812 rc = snprintf(buf + i, 512 - i, "1:y1:re");
814 return dht_send(buf, i, 0, sa, salen);
825 const unsigned char *tid,
827 const unsigned char *target,
832 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
834 COPY(buf, i, myid, 20, 512);
835 rc = snprintf(buf + i, 512 - i, "6:target20:");
837 COPY(buf, i, target, 20, 512);
843 (want & WANT4) ? "2:n4" : "",
844 (want & WANT6) ? "2:n6" : "");
847 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
849 COPY(buf, i, tid, tid_len, 512);
851 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
853 return dht_send(buf, i, 0, sa, salen);
864 const unsigned char *tid,
866 const unsigned char *nodes,
868 const unsigned char *nodes6,
874 rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:");
876 COPY(buf, i, myid, 20, 2048);
878 rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
880 COPY(buf, i, nodes, nodes_len, 2048);
882 if (nodes6_len > 0) {
883 rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
885 COPY(buf, i, nodes6, nodes6_len, 2048);
888 rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len);
890 COPY(buf, i, tid, tid_len, 2048);
892 rc = snprintf(buf + i, 2048 - i, "1:y1:re");
895 return dht_send(buf, i, 0, sa, salen);
903 buffer_random_nodes(int af, unsigned char *nodes)
905 struct circular_list *list;
906 struct sockaddr_storage ss;
908 unsigned char id[20];
914 list = &v4_confirmed;
917 list = &v6_confirmed;
925 rc = list_random(list, id, &ss, &sslen);
930 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
931 memcpy(nodes + n * 26, id, 20);
932 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
933 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
938 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
939 memcpy(nodes + n * 38, id, 20);
940 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
941 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
956 const unsigned char *tid,
958 const unsigned char *id,
961 unsigned char nodes[8 * 26];
962 unsigned char nodes6[8 * 38];
963 int numnodes = 0, numnodes6 = 0;
966 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
969 numnodes = buffer_random_nodes(AF_INET, nodes);
972 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
975 sa, salen, tid, tid_len, nodes, numnodes * 26, nodes6, numnodes6 * 38);
990 rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:", code, (int)strlen(message));
992 COPY(buf, i, message, (int)strlen(message), 512);
993 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
995 COPY(buf, i, tid, tid_len, 512);
997 rc = snprintf(buf + i, 512 - i, "1:y1:ee");
999 return dht_send(buf, i, 0, sa, salen);
1013 const unsigned char *buf,
1015 unsigned char *tid_return,
1017 unsigned char *id_return,
1018 unsigned char *info_hash_return,
1019 unsigned char *target_return,
1020 unsigned short *port_return,
1021 unsigned char *token_return,
1023 unsigned char *nodes_return,
1025 unsigned char *nodes6_return,
1027 unsigned char *values_return,
1029 unsigned char *values6_return,
1033 const unsigned char *p;
1035 /* This code will happily crash if the buffer is not NUL-terminated. */
1036 if (buf[buflen] != '\0') {
1037 debugf("Eek! parse_message with unterminated buffer.\n");
1041 #define CHECK(ptr, len) \
1042 if (((unsigned char *)ptr) + (len) > (buf) + (buflen)) \
1046 p = memmem(buf, buflen, "1:t", 3);
1050 l = strtol((char *)p + 3, &q, 10);
1051 if (q && *q == ':' && l > 0 && l < *tid_len) {
1053 memcpy(tid_return, q + 1, l);
1060 p = memmem(buf, buflen, "2:id20:", 7);
1063 memcpy(id_return, p + 7, 20);
1065 memset(id_return, 0, 20);
1068 if (info_hash_return) {
1069 p = memmem(buf, buflen, "9:info_hash20:", 14);
1072 memcpy(info_hash_return, p + 14, 20);
1074 memset(info_hash_return, 0, 20);
1078 p = memmem(buf, buflen, "porti", 5);
1082 l = strtol((char *)p + 5, &q, 10);
1083 if (q && *q == 'e' && l > 0 && l < 0x10000)
1090 if (target_return) {
1091 p = memmem(buf, buflen, "6:target20:", 11);
1094 memcpy(target_return, p + 11, 20);
1096 memset(target_return, 0, 20);
1100 p = memmem(buf, buflen, "5:token", 7);
1104 l = strtol((char *)p + 7, &q, 10);
1105 if (q && *q == ':' && l > 0 && l < *token_len) {
1107 memcpy(token_return, q + 1, l);
1116 p = memmem(buf, buflen, "5:nodes", 7);
1120 l = strtol((char *)p + 7, &q, 10);
1121 if (q && *q == ':' && l > 0 && l < *nodes_len) {
1123 memcpy(nodes_return, q + 1, l);
1132 p = memmem(buf, buflen, "6:nodes6", 8);
1136 l = strtol((char *)p + 8, &q, 10);
1137 if (q && *q == ':' && l > 0 && l < *nodes6_len) {
1139 memcpy(nodes6_return, q + 1, l);
1147 if (values_len || values6_len) {
1148 p = memmem(buf, buflen, "6:valuesl", 9);
1150 int i = p - buf + 9;
1155 l = strtol((char *)buf + i, &q, 10);
1156 if (q && *q == ':' && l > 0) {
1159 if (j + l > *values_len)
1161 i = q + 1 + l - (char *)buf;
1162 memcpy((char *)values_return + j, q + 1, l);
1164 } else if (l == 18) {
1165 if (j6 + l > *values6_len)
1167 i = q + 1 + l - (char *)buf;
1168 memcpy((char *)values6_return + j6, q + 1, l);
1171 debugf("Received weird value -- %d bytes.\n", (int)l);
1172 i = q + 1 + l - (char *)buf;
1178 if (i >= buflen || buf[i] != 'e')
1179 debugf("eek... unexpected end for values.\n");
1191 p = memmem(buf, buflen, "4:wantl", 7);
1193 int i = p - buf + 7;
1195 while (buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
1196 i + 2 + buf[i] - '0' < buflen) {
1197 CHECK(buf + i + 2, buf[i] - '0');
1198 if (buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
1199 *want_return |= WANT4;
1200 else if (buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
1201 *want_return |= WANT6;
1203 debugf("eek... unexpected want flag (%c)\n", buf[i]);
1204 i += 2 + buf[i] - '0';
1206 if (i >= buflen || buf[i] != 'e')
1207 debugf("eek... unexpected end for want.\n");
1215 if (memmem(buf, buflen, "1:y1:r", 6))
1217 if (memmem(buf, buflen, "1:y1:e", 6))
1219 if (!memmem(buf, buflen, "1:y1:q", 6))
1221 if (memmem(buf, buflen, "1:q4:ping", 9))
1223 if (memmem(buf, buflen, "1:q9:find_node", 14))
1225 if (memmem(buf, buflen, "1:q9:get_peers", 14))
1227 if (memmem(buf, buflen, "1:q13:announce_peer", 19))
1228 return ANNOUNCE_PEER;
1232 debugf("Truncated message.\n");