]> Sergey Matveev's repositories - dht-bootstrap.git/blobdiff - dht-bootstrap.c
Simplify code: sockets are already equal to -1
[dht-bootstrap.git] / dht-bootstrap.c
index 2e6e77dc25fe1aac8a5c858886a64e4b1b84554e..e98cd6ea6bd5f2e4c9be46d714e6bf54bf56d851 100644 (file)
@@ -20,26 +20,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */
 
-#include <arpa/inet.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <netdb.h>
 #include <netinet/in.h>
+#include <poll.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 
-#ifndef MSG_CONFIRM
-#define MSG_CONFIRM 0
-#endif
-
-#define MAX(x, y) ((x) >= (y) ? (x) : (y))
 #define MIN(x, y) ((x) <= (y) ? (x) : (y))
 
 static int
@@ -53,8 +46,7 @@ send_find_node(
     const unsigned char *tid,
     int tid_len,
     const unsigned char *target,
-    int want,
-    int confirm);
+    int want);
 static int
 send_nodes(
     struct sockaddr *sa,
@@ -367,19 +359,57 @@ send_request(struct circular_list *list, int dopop, int doping, int want)
             id[i] = random() & 0xFF;
         make_tid(ttid, "fn", 0);
         debugf("Sending find_node.\n");
-        return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want, 0);
+        return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want);
+    }
+}
+
+static int
+newSock(const char *host, const char *port)
+{
+    struct addrinfo hints;
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_DGRAM;
+    struct addrinfo *res = NULL;
+    int err = getaddrinfo(host, port, &hints, &res);
+    if (err != 0) {
+        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
+        exit(1);
     }
+    int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+    if (sock == -1) {
+        perror("socket");
+        exit(1);
+    }
+    if (bind(sock, res->ai_addr, res->ai_addrlen) != 0) {
+        perror("bind");
+        exit(1);
+    }
+    int rc = fcntl(sock, F_GETFL, 0);
+    if (rc < 0) {
+        perror("F_GETFL");
+        exit(1);
+    }
+    rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
+    if (rc < 0) {
+        perror("F_SETFL");
+        exit(1);
+    }
+    freeaddrinfo(res);
+    return sock;
 }
 
 int
 main(int argc, char **argv)
 {
-    int port = 6881, quiet = 0, ipv4 = 1, ipv6 = 1;
-    int opt, rc, i, send4;
-    unsigned char ttid[4];
+    errno = 0;
+    int quiet = 0;
+    char *ipv4addr = NULL;
+    char *ipv6addr = NULL;
+    int opt = 0;
 
     while (1) {
-        opt = getopt(argc, argv, "q46");
+        opt = getopt(argc, argv, "q4:6:");
         if (opt < 0)
             break;
 
@@ -388,110 +418,33 @@ main(int argc, char **argv)
             quiet = 1;
             break;
         case '4':
-            ipv6 = 0;
+            ipv4addr = strdup(optarg);
             break;
         case '6':
-            ipv4 = 0;
+            ipv6addr = strdup(optarg);
             break;
         default:
             goto usage;
         }
     }
 
-    i = optind;
+    int i = optind;
 
     if (argc < i + 1)
         goto usage;
 
-    port = atoi(argv[i++]);
-    if (port <= 0 || port >= 0x10000)
-        goto usage;
-
-    if (ipv4) {
-        dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
-        if (dht_socket < 0)
-            perror("socket(IPv4)");
-    }
-
-    if (ipv6) {
-        dht_socket6 = socket(PF_INET6, SOCK_DGRAM, 0);
-        if (dht_socket6 < 0)
-            perror("socket(IPv6)");
-    }
-
-    if (dht_socket < 0 && dht_socket6 < 0) {
-        fprintf(stderr, "Eek!\n");
-        exit(1);
-    }
-
-    if (dht_socket >= 0) {
-        struct sockaddr_in sin;
-        int rc;
-        memset(&sin, 0, sizeof(sin));
-        sin.sin_family = AF_INET;
-        sin.sin_port = htons(port);
-        rc = bind(dht_socket, (struct sockaddr *)&sin, sizeof(sin));
-        if (rc < 0) {
-            perror("bind(IPv4)");
-            exit(1);
-        }
-
-        rc = fcntl(dht_socket, F_GETFL, 0);
-        if (rc < 0) {
-            perror("F_GETFL");
-            exit(1);
-        }
+    const char *port = strdup(argv[i++]);
 
-        rc = fcntl(dht_socket, F_SETFL, (rc | O_NONBLOCK));
-        if (rc < 0) {
-            perror("F_SETFL");
-            exit(1);
-        }
+    if (ipv4addr != NULL) {
+        dht_socket = newSock(ipv4addr, port);
     }
-
-    if (dht_socket6 >= 0) {
-        struct sockaddr_in6 sin6;
-        int rc;
-        int val = 1;
-
-        rc = setsockopt(
-            dht_socket6, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val));
-        if (rc < 0) {
-            perror("setsockopt(IPV6_V6ONLY)");
-            exit(1);
-        }
-
-        /* BEP-32 mandates that we should bind this socket to one of our
-           global IPv6 addresses.  In this program, this only happens if
-           the user used the -b flag. */
-
-        memset(&sin6, 0, sizeof(sin6));
-        sin6.sin6_family = AF_INET6;
-        sin6.sin6_port = htons(port);
-        rc = bind(dht_socket6, (struct sockaddr *)&sin6, sizeof(sin6));
-        if (rc < 0) {
-            perror("bind(IPv6)");
-            exit(1);
-        }
-
-        rc = fcntl(dht_socket6, F_GETFL, 0);
-        if (rc < 0) {
-            perror("F_GETFL");
-            exit(1);
-        }
-
-        rc = fcntl(dht_socket6, F_SETFL, (rc | O_NONBLOCK));
-        if (rc < 0) {
-            perror("F_SETFL");
-            exit(1);
-        }
+    if (ipv6addr != NULL) {
+        dht_socket6 = newSock(ipv6addr, port);
     }
 
+    int rc = 0;
     {
-        int fd;
-        unsigned int seed;
-
-        fd = open("/dev/urandom", O_RDONLY);
+        int fd = open("/dev/urandom", O_RDONLY);
         if (fd < 0) {
             perror("open(random)");
             exit(1);
@@ -503,6 +456,7 @@ main(int argc, char **argv)
             exit(1);
         }
 
+        unsigned int seed;
         rc = read(fd, &seed, sizeof(seed));
         srandom(seed);
 
@@ -515,6 +469,8 @@ main(int argc, char **argv)
     if (!quiet)
         dht_debug = stdout;
 
+    unsigned char ttid[4];
+
     while (i < argc) {
         struct addrinfo hints, *info, *infop;
         memset(&hints, 0, sizeof(hints));
@@ -548,24 +504,21 @@ main(int argc, char **argv)
 
     token_bucket_time = time(NULL);
     token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
+    int send4 = 0;
+    struct pollfd fds[2];
+    fds[0].fd = dht_socket;
+    fds[0].events = POLLIN;
+    fds[1].fd = dht_socket6;
+    fds[1].events = POLLIN;
 
     while (1) {
-        struct timeval tv;
-        fd_set readfds;
-        int rc;
-
+        int tv_sec = 0;
         if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
             (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
-            tv.tv_sec = 0;
+            tv_sec = 0;
         else
-            tv.tv_sec = random() % 30;
-        tv.tv_usec = random() % 1000000;
-
-        FD_ZERO(&readfds);
-        if (dht_socket >= 0)
-            FD_SET(dht_socket, &readfds);
-        if (dht_socket6 >= 0)
-            FD_SET(dht_socket6, &readfds);
+            tv_sec = random() % 30;
+        int tv_msec = random() % 1000;
 
         if (dht_debug)
             debugf(
@@ -575,17 +528,16 @@ main(int argc, char **argv)
                 list_elements(&v4_new),
                 list_elements(&v6_new));
 
-        rc = select(MAX(dht_socket, dht_socket6) + 1, &readfds, NULL, NULL, &tv);
+        int rc = poll(fds, 2, tv_sec * 1000 + tv_msec);
 
         if (rc < 0) {
-            if (errno != EINTR) {
-                perror("select");
-                sleep(1);
-            }
+            perror("poll");
+            sleep(1);
         }
 
         if (rc > 0) {
-            int rc, message;
+            int 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;
@@ -597,10 +549,20 @@ main(int argc, char **argv)
             struct sockaddr_storage source_storage;
             struct sockaddr *source = (struct sockaddr *)&source_storage;
             socklen_t sourcelen = sizeof(source_storage);
-            if (dht_socket >= 0 && FD_ISSET(dht_socket, &readfds)) {
-                rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
-            } else if (dht_socket6 >= 0 && FD_ISSET(dht_socket6, &readfds)) {
-                rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
+            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))
@@ -758,7 +720,7 @@ main(int argc, char **argv)
     return 0;
 
 usage:
-    fprintf(stderr, "dht-bootstrap [-q] [-4] [-6] port [node port...]\n");
+    fprintf(stderr, "dht-bootstrap [-q] [-4 ADDR4] [-6 ADDR6] port [node port...]\n");
     exit(1);
 }
 
@@ -855,8 +817,7 @@ send_find_node(
     const unsigned char *tid,
     int tid_len,
     const unsigned char *target,
-    int want,
-    int confirm)
+    int want)
 {
     char buf[512];
     int i = 0, rc;
@@ -881,7 +842,7 @@ send_find_node(
     ADD_V(buf, i, 512);
     rc = snprintf(buf + i, 512 - i, "1:y1:qe");
     INC(i, rc, 512);
-    return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
+    return dht_send(buf, i, 0, sa, salen);
 
 fail:
     errno = ENOSPC;