]> Sergey Matveev's repositories - dht-bootstrap.git/blobdiff - dht-bootstrap.c
Stats in process title
[dht-bootstrap.git] / dht-bootstrap.c
index 33ef79808d12d75080a1562bac7a344493f83caa..07ac332d8d5befe169585494109d81dfb7ff221d 100644 (file)
@@ -20,6 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */
 
+#include <err.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <netdb.h>
@@ -29,12 +30,19 @@ THE SOFTWARE.
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/resource.h>
 #include <sys/socket.h>
 #include <time.h>
 #include <unistd.h>
 
 #define MIN(x, y) ((x) <= (y) ? (x) : (y))
 
+#ifdef __linux__
+// clang-format off
+void setproctitle_fast(const char *_fmt, ...) {}
+// clang-format on
+#endif
+
 static int
 send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len);
 static int
@@ -131,24 +139,22 @@ struct circular_list {
     struct node nodes[CIRCULAR_LIST_SIZE];
 };
 
-struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
+static struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
 
 #define MAX_TOKEN_BUCKET_TOKENS 40
 static time_t token_bucket_time;
 static int token_bucket_tokens;
 
-FILE *dht_debug = NULL;
+static FILE *dht_debug = NULL;
 
-#ifdef __GNUC__
-__attribute__((format(printf, 1, 2)))
-#endif
 static void
 debugf(const char *format, ...)
 {
+    if (dht_debug == NULL)
+        return;
     va_list args;
     va_start(args, format);
-    if (dht_debug)
-        vfprintf(dht_debug, format, args);
+    vfprintf(dht_debug, format, args);
     va_end(args);
     fflush(dht_debug);
 }
@@ -354,9 +360,7 @@ send_request(struct circular_list *list, int dopop, int doping, int want)
         return send_ping((struct sockaddr *)&ss, sslen, ttid, 4);
     } else {
         unsigned char id[20];
-        int i;
-        for (i = 0; i < 20; i++)
-            id[i] = random() & 0xFF;
+        arc4random_buf(id, sizeof id);
         make_tid(ttid, "fn", 0);
         debugf("Sending find_node.\n");
         return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want);
@@ -371,34 +375,35 @@ newSock(const char *host, const char *port)
     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 rc = getaddrinfo(host, port, &hints, &res);
+    if (rc != 0)
+        err(EXIT_FAILURE, "getaddrinfo: %s\n", gai_strerror(rc));
     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);
-    }
+    if (sock == -1)
+        err(EXIT_FAILURE, "socket()");
+    if (bind(sock, res->ai_addr, res->ai_addrlen) != 0)
+        err(EXIT_FAILURE, "bind()");
+    rc = fcntl(sock, F_GETFL, 0);
+    if (rc < 0)
+        err(EXIT_FAILURE, "F_GETFL");
     rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
-    if (rc < 0) {
-        perror("F_SETFL");
-        exit(1);
-    }
+    if (rc < 0)
+        err(EXIT_FAILURE, "F_SETFL");
     freeaddrinfo(res);
     return sock;
 }
 
+static void
+rlimited(int res)
+{
+    struct rlimit r;
+    r.rlim_cur = 0;
+    r.rlim_max = 0;
+    if (setrlimit(res, &r) == -1) {
+        err(EXIT_FAILURE, "can not setrlimit()");
+    }
+}
+
 int
 main(int argc, char **argv)
 {
@@ -433,35 +438,15 @@ main(int argc, char **argv)
     if (argc < i + 1)
         goto usage;
 
-    const char *port = strdup(argv[i++]);
-
+    const char *ourPort = strdup(argv[i++]);
     if (ipv4addr != NULL) {
-        dht_socket = newSock(ipv4addr, port);
+        dht_socket = newSock(ipv4addr, ourPort);
     }
     if (ipv6addr != NULL) {
-        dht_socket6 = newSock(ipv6addr, port);
+        dht_socket6 = newSock(ipv6addr, ourPort);
     }
 
-    int rc = 0;
-    {
-        int fd = open("/dev/urandom", O_RDONLY);
-        if (fd < 0) {
-            perror("open(random)");
-            exit(1);
-        }
-
-        rc = read(fd, myid, 20);
-        if (rc < 20) {
-            perror("open(random)");
-            exit(1);
-        }
-
-        unsigned int seed;
-        rc = read(fd, &seed, sizeof(seed));
-        srandom(seed);
-
-        close(fd);
-    }
+    arc4random_buf(myid, sizeof myid);
 
     memcpy(my_v, "1:v4:JB\0\0", 9);
     have_v = 1;
@@ -469,6 +454,7 @@ main(int argc, char **argv)
     if (!quiet)
         dht_debug = stdout;
 
+    int rc = 0;
     unsigned char ttid[4];
 
     while (i < argc) {
@@ -481,10 +467,8 @@ main(int argc, char **argv)
         else if (dht_socket6 < 0)
             hints.ai_family |= AF_INET;
         rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
-        if (rc != 0) {
-            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
-            exit(1);
-        }
+        if (rc != 0)
+            err(EXIT_FAILURE, "getaddrinfo: %s\n", gai_strerror(rc));
 
         i++;
         if (i >= argc)
@@ -506,18 +490,19 @@ main(int argc, char **argv)
     token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
     int send4 = 0;
     struct pollfd fds[2];
-    if (dht_socket >= 0) {
-        fds[0].fd = dht_socket;
-        fds[0].events = POLLIN;
-    } else {
-        fds[0].fd = -1;
-    }
-    if (dht_socket6 >= 0) {
-        fds[1].fd = dht_socket6;
-        fds[1].events = POLLIN;
-    } else {
-        fds[1].fd = -1;
-    }
+    fds[0].fd = dht_socket;
+    fds[0].events = POLLIN;
+    fds[1].fd = dht_socket6;
+    fds[1].events = POLLIN;
+
+    close(STDIN_FILENO);
+    if (quiet)
+        close(STDOUT_FILENO);
+    rlimited(RLIMIT_NPROC);
+    rlimited(RLIMIT_FSIZE);
+#if __FreeBSD__
+    rlimited(RLIMIT_NOFILE);
+#endif // __FreeBSD__
 
     while (1) {
         int tv_sec = 0;
@@ -528,23 +513,20 @@ main(int argc, char **argv)
             tv_sec = random() % 30;
         int tv_msec = random() % 1000;
 
-        if (dht_debug)
-            debugf(
-                "%d+%d %d+%d\n",
-                list_elements(&v4_confirmed),
-                list_elements(&v6_confirmed),
-                list_elements(&v4_new),
-                list_elements(&v6_new));
-
-        int rc = poll(fds, 2, tv_sec * 1000 + tv_msec);
+        setproctitle_fast(
+            "%d+%d %d+%d",
+            list_elements(&v4_confirmed),
+            list_elements(&v6_confirmed),
+            list_elements(&v4_new),
+            list_elements(&v6_new));
 
+        rc = poll(fds, 2, tv_sec * 1000 + tv_msec);
         if (rc < 0) {
             perror("poll");
             sleep(1);
         }
 
         if (rc > 0) {
-            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];
@@ -570,7 +552,7 @@ main(int argc, char **argv)
                     rc = -1;
                 } else {
                     rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
-                };
+                }
             }
 
             if (rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
@@ -725,11 +707,9 @@ main(int argc, char **argv)
         }
     }
 
-    return 0;
-
 usage:
     fprintf(stderr, "dht-bootstrap [-q] [-4 ADDR4] [-6 ADDR6] port [node port...]\n");
-    exit(1);
+    exit(EXIT_FAILURE);
 }
 
 /* We could use a proper bencoding printer and parser, but the format of