diff options
| -rw-r--r-- | Makefile | 22 | ||||
| -rw-r--r-- | Makefile.arc4random | 3 | ||||
| -rw-r--r-- | Makefile.gzip | 4 | ||||
| -rw-r--r-- | Makefile.zstd | 3 | ||||
| -rw-r--r-- | man1/opentracker.1 | 130 | ||||
| -rw-r--r-- | man4/opentracker.conf.4 | 86 | ||||
| -rw-r--r-- | opentracker.c | 11 | ||||
| -rw-r--r-- | opentracker.conf.sample | 5 | ||||
| -rw-r--r-- | ot_accesslist.c | 18 | ||||
| -rw-r--r-- | ot_accesslist.h | 2 | ||||
| -rw-r--r-- | ot_clean.c | 6 | ||||
| -rw-r--r-- | ot_fullscrape.c | 160 | ||||
| -rw-r--r-- | ot_fullscrape.h | 4 | ||||
| -rw-r--r-- | ot_http.c | 83 | ||||
| -rw-r--r-- | ot_http.h | 7 | ||||
| -rw-r--r-- | ot_iovec.c | 21 | ||||
| -rw-r--r-- | ot_iovec.h | 12 | ||||
| -rw-r--r-- | ot_livesync.c | 10 | ||||
| -rw-r--r-- | ot_mutex.c | 18 | ||||
| -rw-r--r-- | ot_mutex.h | 7 | ||||
| -rw-r--r-- | ot_stats.c | 97 | ||||
| -rw-r--r-- | ot_stats.h | 1 | ||||
| -rw-r--r-- | ot_sync.c | 8 | ||||
| -rw-r--r-- | ot_udp.c | 30 | ||||
| -rw-r--r-- | ot_vector.c | 17 | ||||
| -rw-r--r-- | ot_vector.h | 2 | ||||
| -rw-r--r-- | proxy.c | 6 | ||||
| -rw-r--r-- | trackerlogic.c | 20 | ||||
| -rw-r--r-- | trackerlogic.h | 2 |
29 files changed, 615 insertions, 180 deletions
| @@ -18,15 +18,24 @@ LIBOWFAT_LIBRARY=$(PREFIX)/libowfat | |||
| 18 | BINDIR?=$(PREFIX)/bin | 18 | BINDIR?=$(PREFIX)/bin |
| 19 | STRIP?=strip | 19 | STRIP?=strip |
| 20 | 20 | ||
| 21 | #FEATURES+=-DWAND_V4_ONLY | 21 | #FEATURES+=-DWANT_V4_ONLY |
| 22 | #FEATURES+=-DWANT_ACCESSLIST_BLACK | 22 | #FEATURES+=-DWANT_ACCESSLIST_BLACK |
| 23 | #FEATURES+=-DWANT_ACCESSLIST_WHITE | 23 | #FEATURES+=-DWANT_ACCESSLIST_WHITE |
| 24 | #FEATURES+=-DWANT_DYNAMIC_ACCESSLIST | 24 | #FEATURES+=-DWANT_DYNAMIC_ACCESSLIST |
| 25 | 25 | ||
| 26 | #FEATURES+=-DWANT_SYNC_LIVE | 26 | #FEATURES+=-DWANT_SYNC_LIVE |
| 27 | #FEATURES+=-DWANT_IP_FROM_QUERY_STRING | 27 | #FEATURES+=-DWANT_IP_FROM_QUERY_STRING |
| 28 | FEATURES+=-DWANT_COMPRESSION_GZIP | 28 | |
| 29 | FEATURES+=-DWANT_COMPRESSION_GZIP_ALWAYS | 29 | # If you want gzip support to be compiled in, uncomment the next include. |
| 30 | # You can further modify the behaviour by setting DWANT_COMPRESSION_GZIP_ALWAYS | ||
| 31 | # in Makefile.gzip | ||
| 32 | include Makefile.gzip | ||
| 33 | |||
| 34 | # If you want zstd support to be compiled in, uncomment the next include. | ||
| 35 | # You can further modify the behaviour by setting DWANT_COMPRESSION_ZSTD_ALWAYS | ||
| 36 | # in Makefile.zstd | ||
| 37 | #include Makefile.zstd | ||
| 38 | |||
| 30 | #FEATURES+=-DWANT_LOG_NETWORKS | 39 | #FEATURES+=-DWANT_LOG_NETWORKS |
| 31 | #FEATURES+=-DWANT_RESTRICT_STATS | 40 | #FEATURES+=-DWANT_RESTRICT_STATS |
| 32 | #FEATURES+=-DWANT_IP_FROM_PROXY | 41 | #FEATURES+=-DWANT_IP_FROM_PROXY |
| @@ -43,8 +52,8 @@ FEATURES+=-DWANT_FULLSCRAPE | |||
| 43 | #FEATURES+=-DWANT_NO_AUTO_FREE | 52 | #FEATURES+=-DWANT_NO_AUTO_FREE |
| 44 | 53 | ||
| 45 | # Is enabled on BSD systems by default in trackerlogic.h | 54 | # Is enabled on BSD systems by default in trackerlogic.h |
| 46 | # on Linux systems you will need -lbds | 55 | # on Linux systems the include Makefile adds -lbsd |
| 47 | #FEATURES+=-DWANT_ARC4RANDOM | 56 | #include Makefile.arc4random |
| 48 | 57 | ||
| 49 | #FEATURES+=-D_DEBUG_HTTPERROR | 58 | #FEATURES+=-D_DEBUG_HTTPERROR |
| 50 | #FEATURES+=-D_DEBUG_RANDOMTORRENTS | 59 | #FEATURES+=-D_DEBUG_RANDOMTORRENTS |
| @@ -55,8 +64,7 @@ OPTS_debug=-D_DEBUG -g -ggdb # -pg -fprofile-arcs -ftest-coverage | |||
| 55 | OPTS_production=-O3 | 64 | OPTS_production=-O3 |
| 56 | 65 | ||
| 57 | CFLAGS+=-I$(LIBOWFAT_HEADERS) -DGIT_VERSION=$(GIT_VERSION) -Wall -pipe -pthread -Wextra #-ansi -pedantic | 66 | CFLAGS+=-I$(LIBOWFAT_HEADERS) -DGIT_VERSION=$(GIT_VERSION) -Wall -pipe -pthread -Wextra #-ansi -pedantic |
| 58 | LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread -lz | 67 | LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread |
| 59 | #LDFLAGS+=-lbsd | ||
| 60 | 68 | ||
| 61 | BINARY =opentracker | 69 | BINARY =opentracker |
| 62 | HEADERS=trackerlogic.h scan_urlencoded_query.h ot_mutex.h ot_stats.h ot_vector.h ot_clean.h ot_udp.h ot_iovec.h ot_fullscrape.h ot_accesslist.h ot_http.h ot_livesync.h ot_rijndael.h | 70 | HEADERS=trackerlogic.h scan_urlencoded_query.h ot_mutex.h ot_stats.h ot_vector.h ot_clean.h ot_udp.h ot_iovec.h ot_fullscrape.h ot_accesslist.h ot_http.h ot_livesync.h ot_rijndael.h |
diff --git a/Makefile.arc4random b/Makefile.arc4random new file mode 100644 index 0000000..1488408 --- /dev/null +++ b/Makefile.arc4random | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | FEATURES+=-DWANT_ARC4RANDOM | ||
| 2 | LDFLAGS+=-lbsd | ||
| 3 | |||
diff --git a/Makefile.gzip b/Makefile.gzip new file mode 100644 index 0000000..70d6d62 --- /dev/null +++ b/Makefile.gzip | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | FEATURES+=-DWANT_COMPRESSION_GZIP | ||
| 2 | #FEATURES+=-DWANT_COMPRESSION_GZIP_ALWAYS | ||
| 3 | |||
| 4 | LDFLAGS+=-lz | ||
diff --git a/Makefile.zstd b/Makefile.zstd new file mode 100644 index 0000000..2bb56be --- /dev/null +++ b/Makefile.zstd | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | FEATURES+=-DWANT_COMPRESSION_ZSTD | ||
| 2 | #FEATURES+=-DWANT_COMPRESSION_ZSTD_ALWAYS | ||
| 3 | LDFLAGS+=-lzstd | ||
diff --git a/man1/opentracker.1 b/man1/opentracker.1 new file mode 100644 index 0000000..0103ebe --- /dev/null +++ b/man1/opentracker.1 | |||
| @@ -0,0 +1,130 @@ | |||
| 1 | .Dd 15/4/2024 | ||
| 2 | .Dt opentracker 1 | ||
| 3 | .Os Unix | ||
| 4 | .Sh opentracker | ||
| 5 | .Nm opentracker | ||
| 6 | .Nd a free and open bittorrent tracker | ||
| 7 | .Sh SYNOPSIS | ||
| 8 | .Nm | ||
| 9 | .Op Fl f Ar config | ||
| 10 | .Op Fl i Ar ip-select | ||
| 11 | .Op Fl p Ar port-bind-tcp | ||
| 12 | .Op Fl P Ar port-bind-udp | ||
| 13 | .Op Fl A Ar blessed-ip | ||
| 14 | .Op Fl r Ar redirect-url | ||
| 15 | .Op Fl d Ar chdir | ||
| 16 | .Op Fl u Ar user | ||
| 17 | .Op Fl w| Fl b accesslist | ||
| 18 | .Sh DESCRIPTION | ||
| 19 | .Nm | ||
| 20 | is a bittorrent tracker that implements announce and scrape actions over the | ||
| 21 | UDP and the plain http protocol, aiming for minimal resource usage. | ||
| 22 | .Pp | ||
| 23 | When invoked with parameters, it binds to TCP and UDP port 6969 on all | ||
| 24 | interfaces. The recommended way to configure opentracker is by providing a | ||
| 25 | config file using the | ||
| 26 | .Op Fl f Ar config | ||
| 27 | option. See | ||
| 28 | .Xr opentracker.conf 4 | ||
| 29 | for details. | ||
| 30 | .Pp | ||
| 31 | .Sh OPTIONS | ||
| 32 | The following options are available: | ||
| 33 | .Bl -tag -width -indent=8 | ||
| 34 | .It Fl f Ar config | ||
| 35 | Parse a config file with a list of options. Consecutive command options | ||
| 36 | will override options from the config file. See | ||
| 37 | .Xr opentracker.conf 4 | ||
| 38 | for details. | ||
| 39 | .It Fl i Ar ip-select | ||
| 40 | Select an ip address that will be used with the next | ||
| 41 | .Op Fl p | ||
| 42 | or | ||
| 43 | .Op Fl P | ||
| 44 | command to actually bind to this address. Setting this option without any bind | ||
| 45 | options in the config file or | ||
| 46 | .Op Fl p | ||
| 47 | or | ||
| 48 | .Op Fl P | ||
| 49 | commands will limit opentracker to only bind to this address. | ||
| 50 | .It Fl p Ar port-bind-tcp | ||
| 51 | Bind to the TCP port on the last preceding ip address set with the | ||
| 52 | .Op Fl i ip-select | ||
| 53 | option or to all available addresses if none has been set. Can be given multiple | ||
| 54 | times. | ||
| 55 | .It Fl P Ar port-bind-udp | ||
| 56 | Bind to the UDP port on the last preceding ip address set with the | ||
| 57 | .Op Fl i ip-select | ||
| 58 | option or to all available addresses if none has been set. Can be given multiple | ||
| 59 | times. | ||
| 60 | .It Fl A Ar blessed-ip | ||
| 61 | Set an ip address in IPv4 or IPv6 or a net in CIDR notation to bless the network | ||
| 62 | for access to restricted resources. | ||
| 63 | .It Fl r Ar redirect-url | ||
| 64 | Set the URL that | ||
| 65 | .Nm | ||
| 66 | will redirect users to when the / address is requested via HTTP. | ||
| 67 | .It Fl d Ar chdir | ||
| 68 | Sets the directory | ||
| 69 | .Nm | ||
| 70 | will | ||
| 71 | .Xr chroot 2 | ||
| 72 | to if ran as root or | ||
| 73 | .Xr chdir 2 | ||
| 74 | to if ran as unprivileged user. Note that any accesslist files need to be | ||
| 75 | relative to and within that directory. | ||
| 76 | .It Fl u Ar user | ||
| 77 | User to run | ||
| 78 | .Nm | ||
| 79 | under after all operations that need privileges have finished. | ||
| 80 | .It Fl w Ar accesslist | Fl b Ar accesslist | ||
| 81 | If | ||
| 82 | .Nm | ||
| 83 | has been compiled with the | ||
| 84 | .B WANT_ACCESSLIST_BLACK | ||
| 85 | or | ||
| 86 | .Br WANT_ACCESSLIST_WHITE | ||
| 87 | options, this option sets the location of the accesslist. | ||
| 88 | .El | ||
| 89 | .Sh EXAMPLES | ||
| 90 | Start | ||
| 91 | .Nm | ||
| 92 | bound on UDP and TCP ports 6969 on IPv6 localhost. | ||
| 93 | .Dl # ./opentracker -i ::1 -p 6969 -P 6969 | ||
| 94 | .Pp | ||
| 95 | Start | ||
| 96 | .Nm | ||
| 97 | bound on UDP port 6868 and TCP port 6868 on IPv4 localhost and allow | ||
| 98 | privileged access from the network 192.168/16 while redirecting | ||
| 99 | HTTP clients accessing the root directory, which is not covered by the | ||
| 100 | bittorrent tracker protocol, to https://my-trackersite.com/. | ||
| 101 | .Dl # ./opentracker -i 192.168.0.4 -p 6868 -P 6969 -A 192.168/16 -r https://my-trackersite.com/ | ||
| 102 | The announce URLs are http://192.168.0.4:6868/announce and | ||
| 103 | udp://192.168.0.4:6868/announce respectively. | ||
| 104 | .Sh FILES | ||
| 105 | .Bl -tag -width indent | ||
| 106 | .It Pa opentracker.conf | ||
| 107 | The | ||
| 108 | .Nm | ||
| 109 | config file. | ||
| 110 | .El | ||
| 111 | .Sh SEE ALSO | ||
| 112 | .Xr opentracker.conf 4 | ||
| 113 | .Pp | ||
| 114 | opentracker documentation | ||
| 115 | .Lk https://erdgeist.org/arts/software/opentracker | ||
| 116 | .Pp | ||
| 117 | Bittorrent tracker protocol | ||
| 118 | .Lk http://www.bittorrent.org/beps/bep_0015.html | ||
| 119 | .Sh AUTHOR | ||
| 120 | .An Dirk Engling | ||
| 121 | .Aq Mt erdgeist@erdgeist.org . | ||
| 122 | .Sh LICENSE | ||
| 123 | This software is released under the Beerware License: | ||
| 124 | .Pp | ||
| 125 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software | ||
| 126 | and associated documentation files (the "Software"), to deal in the Software with the following | ||
| 127 | terms and conditions: | ||
| 128 | .Pp | ||
| 129 | If you meet the author(s) someday, and you think this software is worth it, you can buy them | ||
| 130 | a beer in return. | ||
diff --git a/man4/opentracker.conf.4 b/man4/opentracker.conf.4 new file mode 100644 index 0000000..2bc1389 --- /dev/null +++ b/man4/opentracker.conf.4 | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | .Dd 2024-04-18 | ||
| 2 | .Dt opentracker.conf 5 | ||
| 3 | .Os Unix | ||
| 4 | .Sh NAME | ||
| 5 | .Nm opentracker.conf | ||
| 6 | .Nd configuration file for opentracker | ||
| 7 | .Sh SYNOPSIS | ||
| 8 | .Nm | ||
| 9 | .Sh DESCRIPTION | ||
| 10 | The | ||
| 11 | .Nm | ||
| 12 | configuration file specifies various options for configuring the behavior of the opentracker program. | ||
| 13 | .Pp | ||
| 14 | Lines starting with '#' are comments and are ignored. Options are specified as 'keyword value' pairs. | ||
| 15 | .Pp | ||
| 16 | The following options are available: | ||
| 17 | .Pp | ||
| 18 | .Bl -tag -width ".It access.proxy" -compact | ||
| 19 | .It listen.tcp_udp Ar address | ||
| 20 | Specifies an address opentracker will listen on for both TCP and UDP connections. If none are specified, opentracker listens on 0.0.0.0:6969 by default. Can be added more than once. | ||
| 21 | .Pp | ||
| 22 | .It listen.tcp Ar address | ||
| 23 | Specifies the address opentracker will listen on for TCP connections. Can be added more than once. | ||
| 24 | .Pp | ||
| 25 | .It listen.udp Ar address | ||
| 26 | Specifies the address opentracker will listen on for UDP connections. Can be added more than once. | ||
| 27 | .Pp | ||
| 28 | .It listen.udp.workers Ar threads | ||
| 29 | Specifies how many threads will be spawned to handle UDP connections. Defaults to 4. | ||
| 30 | .Pp | ||
| 31 | .It access.whitelist Ar path/to/whitelist | ||
| 32 | Specifies the path to the whitelist file containing all torrent hashes that opentracker will serve. Use this option if opentracker runs in a non-open mode. | ||
| 33 | .Pp | ||
| 34 | .It access.blacklist Ar path/to/blacklist | ||
| 35 | Specifies the path to the blacklist file containing all torrent hashes that opentracker will not serve. Use this option if opentracker was compiled to allow blacklisting. | ||
| 36 | .Pp | ||
| 37 | .It access.fifo_add Ar path/to/adder.fifo | ||
| 38 | Specifies the path to the FIFO (named pipe) used for dynamic changesets to accesslists. Info hashes written to this FIFO will be added to the main accesslist file. | ||
| 39 | .Pp | ||
| 40 | .It access.fifo_delete Ar path/to/deleter.fifo | ||
| 41 | Specifies the path to the FIFO (named pipe) used for dynamic changesets to accesslists. Info hashes written to this FIFO will be removed from the main accesslist file. | ||
| 42 | .Pp | ||
| 43 | .It access.stats Ar ip_address_or_network | ||
| 44 | Specifies the IP address or network in CIDR notation allowed to fetch stats from opentracker. | ||
| 45 | .Pp | ||
| 46 | .It access.stats_path Ar path | ||
| 47 | Specifies the path to the stats location. You can configure opentracker to appear anywhere on your tracker. Defaults to /stats. | ||
| 48 | .Pp | ||
| 49 | .It access.proxy Ar ip_address_or_network | ||
| 50 | Specifies the IP address or network of the reverse proxies. Opentracker will take the X-Forwarded-For address instead of the source IP address. Can be added more than once. | ||
| 51 | .Pp | ||
| 52 | .It livesync.cluster.listen Ar ip_address:port | ||
| 53 | Specifies the IP address and port opentracker will listen on for incoming live sync packets to keep a cluster of opentrackers synchronized. | ||
| 54 | .Pp | ||
| 55 | .It livesync.cluster.node_ip Ar ip_address | ||
| 56 | Specifies one trusted IP address for sync between trackers running in a cluster. Can be added more than once. | ||
| 57 | .Pp | ||
| 58 | .It batchsync.cluster.admin_ip Ar ip_address | ||
| 59 | Specifies the admin IP address for old-style (HTTP-based) asynchronous tracker syncing. | ||
| 60 | .Pp | ||
| 61 | .It tracker.rootdir Ar path | ||
| 62 | Specifies the directory opentracker will chroot/chdir to. All black/white list files must be located in this directory. | ||
| 63 | .Pp | ||
| 64 | .It tracker.user Ar username | ||
| 65 | Specifies the user opentracker will setuid to after binding to potentially privileged ports. | ||
| 66 | .Pp | ||
| 67 | .It tracker.redirect_url Ar URL | ||
| 68 | Specifies the URL opentracker will redirect to in response to a "GET / HTTP" request. | ||
| 69 | .El | ||
| 70 | .Sh EXAMPLES | ||
| 71 | To specify the address opentracker will listen on for both TCP and UDP connections: | ||
| 72 | .Dl listen.tcp_udp 0.0.0.0:6969 | ||
| 73 | .Pp | ||
| 74 | To specify the address opentracker will listen on for TCP connections: | ||
| 75 | .Dl listen.tcp 0.0.0.0 | ||
| 76 | .Pp | ||
| 77 | To specify the address opentracker will listen on for UDP connections: | ||
| 78 | .Dl listen.udp 0.0.0.0:6969 | ||
| 79 | .Pp | ||
| 80 | .Sh SEE ALSO | ||
| 81 | .Xr opentracker 1 | ||
| 82 | .Pp | ||
| 83 | .Sh AUTHOR | ||
| 84 | .An Dirk Engling | ||
| 85 | .Aq Mt erdgeist@erdgeist.org | ||
| 86 | .Pp | ||
diff --git a/opentracker.c b/opentracker.c index 14e9989..f63db72 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -281,7 +281,8 @@ static void *server_mainloop(void *args) { | |||
| 281 | struct ot_workstruct ws; | 281 | struct ot_workstruct ws; |
| 282 | time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; | 282 | time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; |
| 283 | struct iovec *iovector; | 283 | struct iovec *iovector; |
| 284 | int iovec_entries, is_partial; | 284 | size_t iovec_entries; |
| 285 | int is_partial; | ||
| 285 | 286 | ||
| 286 | (void)args; | 287 | (void)args; |
| 287 | 288 | ||
| @@ -444,7 +445,7 @@ int parse_configfile(char *config_filename) { | |||
| 444 | #if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE) | 445 | #if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE) |
| 445 | ot_net tmpnet; | 446 | ot_net tmpnet; |
| 446 | #endif | 447 | #endif |
| 447 | int bound = 0; | 448 | int bound = 0; |
| 448 | 449 | ||
| 449 | accesslist_filehandle = fopen(config_filename, "r"); | 450 | accesslist_filehandle = fopen(config_filename, "r"); |
| 450 | 451 | ||
| @@ -566,15 +567,15 @@ void load_state(const char *const state_filename) { | |||
| 566 | 567 | ||
| 567 | /* We do ignore anything that is not of the form "^[:xdigit:]:\d+:\d+" */ | 568 | /* We do ignore anything that is not of the form "^[:xdigit:]:\d+:\d+" */ |
| 568 | while (fgets(inbuf, sizeof(inbuf), state_filehandle)) { | 569 | while (fgets(inbuf, sizeof(inbuf), state_filehandle)) { |
| 569 | int i; | 570 | size_t i; |
| 570 | for (i = 0; i < (int)sizeof(ot_hash); ++i) { | 571 | for (i = 0; i < sizeof(ot_hash); ++i) { |
| 571 | int eger = 16 * scan_fromhex(inbuf[2 * i]) + scan_fromhex(inbuf[1 + 2 * i]); | 572 | int eger = 16 * scan_fromhex(inbuf[2 * i]) + scan_fromhex(inbuf[1 + 2 * i]); |
| 572 | if (eger < 0) | 573 | if (eger < 0) |
| 573 | continue; | 574 | continue; |
| 574 | infohash[i] = eger; | 575 | infohash[i] = eger; |
| 575 | } | 576 | } |
| 576 | 577 | ||
| 577 | if (i != (int)sizeof(ot_hash)) | 578 | if (i != sizeof(ot_hash)) |
| 578 | continue; | 579 | continue; |
| 579 | i *= 2; | 580 | i *= 2; |
| 580 | 581 | ||
diff --git a/opentracker.conf.sample b/opentracker.conf.sample index f8bef43..054e405 100644 --- a/opentracker.conf.sample +++ b/opentracker.conf.sample | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # | 2 | # |
| 3 | 3 | ||
| 4 | # I) Address opentracker will listen on, using both, tcp AND udp family | 4 | # I) Address opentracker will listen on, using both, tcp AND udp family |
| 5 | # (note, that port 6969 is implicite if ommitted). | 5 | # (note, that port 6969 is implicit if omitted). |
| 6 | # | 6 | # |
| 7 | # If no listen option is given (here or on the command line), opentracker | 7 | # If no listen option is given (here or on the command line), opentracker |
| 8 | # listens on 0.0.0.0:6969 tcp and udp. | 8 | # listens on 0.0.0.0:6969 tcp and udp. |
| @@ -83,9 +83,10 @@ | |||
| 83 | # IIb) | 83 | # IIb) |
| 84 | # If you do not want to grant anyone access to your stats, enable the | 84 | # If you do not want to grant anyone access to your stats, enable the |
| 85 | # WANT_RESTRICT_STATS option in Makefile and bless the ip addresses | 85 | # WANT_RESTRICT_STATS option in Makefile and bless the ip addresses |
| 86 | # allowed to fetch stats here. | 86 | # or network allowed to fetch stats here. |
| 87 | # | 87 | # |
| 88 | # access.stats 192.168.0.23 | 88 | # access.stats 192.168.0.23 |
| 89 | # access.stats 10.1.1.23 | ||
| 89 | # | 90 | # |
| 90 | # There is another way of hiding your stats. You can obfuscate the path | 91 | # There is another way of hiding your stats. You can obfuscate the path |
| 91 | # to them. Normally it is located at /stats but you can configure it to | 92 | # to them. Normally it is located at /stats but you can configure it to |
diff --git a/ot_accesslist.c b/ot_accesslist.c index 4b88c40..8e9afdc 100644 --- a/ot_accesslist.c +++ b/ot_accesslist.c | |||
| @@ -129,8 +129,8 @@ static void accesslist_readfile(void) { | |||
| 129 | 129 | ||
| 130 | /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" */ | 130 | /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" */ |
| 131 | while (read_offs <= map_end) { | 131 | while (read_offs <= map_end) { |
| 132 | int i; | 132 | size_t i; |
| 133 | for (i = 0; i < (int)sizeof(ot_hash); ++i) { | 133 | for (i = 0; i < sizeof(ot_hash); ++i) { |
| 134 | int eger1 = scan_fromhex((unsigned char)read_offs[2 * i]); | 134 | int eger1 = scan_fromhex((unsigned char)read_offs[2 * i]); |
| 135 | int eger2 = scan_fromhex((unsigned char)read_offs[1 + 2 * i]); | 135 | int eger2 = scan_fromhex((unsigned char)read_offs[1 + 2 * i]); |
| 136 | if (eger1 < 0 || eger2 < 0) | 136 | if (eger1 < 0 || eger2 < 0) |
| @@ -197,7 +197,7 @@ int accesslist_hashisvalid(ot_hash hash) { | |||
| 197 | 197 | ||
| 198 | /* If we found a matching hash on the main list, scan the list of dynamically deleted hashes */ | 198 | /* If we found a matching hash on the main list, scan the list of dynamically deleted hashes */ |
| 199 | accesslist_delete = g_accesslist_delete; | 199 | accesslist_delete = g_accesslist_delete; |
| 200 | if ((exactmatch != NULL) && accesslist_delete && bsearch(hash, accesslist_add->list, accesslist_add->size, OT_HASH_COMPARE_SIZE, vector_compare_hash)) | 200 | if ((exactmatch != NULL) && accesslist_delete && bsearch(hash, accesslist_delete->list, accesslist_delete->size, OT_HASH_COMPARE_SIZE, vector_compare_hash)) |
| 201 | exactmatch = NULL; | 201 | exactmatch = NULL; |
| 202 | #endif | 202 | #endif |
| 203 | 203 | ||
| @@ -262,7 +262,7 @@ static void *accesslist_adddel_worker(char *fifoname, ot_accesslist *_Atomic | |||
| 262 | 262 | ||
| 263 | while ((linelen = getline(&line, &linecap, fifo)) > 0) { | 263 | while ((linelen = getline(&line, &linecap, fifo)) > 0) { |
| 264 | ot_hash info_hash; | 264 | ot_hash info_hash; |
| 265 | int i; | 265 | size_t i; |
| 266 | 266 | ||
| 267 | printf("Got line %*s", (int)linelen, line); | 267 | printf("Got line %*s", (int)linelen, line); |
| 268 | /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" | 268 | /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" |
| @@ -270,7 +270,7 @@ static void *accesslist_adddel_worker(char *fifoname, ot_accesslist *_Atomic | |||
| 270 | if (linelen < 41) | 270 | if (linelen < 41) |
| 271 | continue; | 271 | continue; |
| 272 | 272 | ||
| 273 | for (i = 0; i < (int)sizeof(ot_hash); ++i) { | 273 | for (i = 0; i < sizeof(ot_hash); ++i) { |
| 274 | int eger1 = scan_fromhex((unsigned char)line[2 * i]); | 274 | int eger1 = scan_fromhex((unsigned char)line[2 * i]); |
| 275 | int eger2 = scan_fromhex((unsigned char)line[1 + 2 * i]); | 275 | int eger2 = scan_fromhex((unsigned char)line[1 + 2 * i]); |
| 276 | if (eger1 < 0 || eger2 < 0) | 276 | if (eger1 < 0 || eger2 < 0) |
| @@ -342,7 +342,7 @@ static void *accesslist_deleter_worker(void *args) { | |||
| 342 | #endif | 342 | #endif |
| 343 | 343 | ||
| 344 | static pthread_t thread_id; | 344 | static pthread_t thread_id; |
| 345 | void accesslist_init() { | 345 | void accesslist_init(void) { |
| 346 | pthread_mutex_init(&g_accesslist_mutex, NULL); | 346 | pthread_mutex_init(&g_accesslist_mutex, NULL); |
| 347 | pthread_create(&thread_id, NULL, accesslist_worker, NULL); | 347 | pthread_create(&thread_id, NULL, accesslist_worker, NULL); |
| 348 | #ifdef WANT_DYNAMIC_ACCESSLIST | 348 | #ifdef WANT_DYNAMIC_ACCESSLIST |
| @@ -444,7 +444,7 @@ void loglist_add_network(const ot_net *net) { | |||
| 444 | pthread_mutex_unlock(&g_lognets_list_mutex); | 444 | pthread_mutex_unlock(&g_lognets_list_mutex); |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | void loglist_reset() { | 447 | void loglist_reset(void) { |
| 448 | pthread_mutex_lock(&g_lognets_list_mutex); | 448 | pthread_mutex_lock(&g_lognets_list_mutex); |
| 449 | free(g_lognets_list.data); | 449 | free(g_lognets_list.data); |
| 450 | g_lognets_list.data = 0; | 450 | g_lognets_list.data = 0; |
| @@ -511,7 +511,7 @@ int proxylist_check_proxy(const ot_ip6 proxy, const ot_ip6 address) { | |||
| 511 | 511 | ||
| 512 | static ot_net g_admin_nets[OT_ADMINIP_MAX]; | 512 | static ot_net g_admin_nets[OT_ADMINIP_MAX]; |
| 513 | static ot_permissions g_admin_nets_permissions[OT_ADMINIP_MAX]; | 513 | static ot_permissions g_admin_nets_permissions[OT_ADMINIP_MAX]; |
| 514 | static unsigned int g_admin_nets_count = 0; | 514 | static size_t g_admin_nets_count = 0; |
| 515 | 515 | ||
| 516 | int accesslist_bless_net(ot_net *net, ot_permissions permissions) { | 516 | int accesslist_bless_net(ot_net *net, ot_permissions permissions) { |
| 517 | if (g_admin_nets_count >= OT_ADMINIP_MAX) | 517 | if (g_admin_nets_count >= OT_ADMINIP_MAX) |
| @@ -553,7 +553,7 @@ int accesslist_bless_net(ot_net *net, ot_permissions permissions) { | |||
| 553 | } | 553 | } |
| 554 | 554 | ||
| 555 | int accesslist_is_blessed(ot_ip6 ip, ot_permissions permissions) { | 555 | int accesslist_is_blessed(ot_ip6 ip, ot_permissions permissions) { |
| 556 | unsigned int i; | 556 | size_t i; |
| 557 | for (i = 0; i < g_admin_nets_count; ++i) | 557 | for (i = 0; i < g_admin_nets_count; ++i) |
| 558 | if (address_in_net(ip, g_admin_nets + i) && (g_admin_nets_permissions[i] & permissions)) | 558 | if (address_in_net(ip, g_admin_nets + i) && (g_admin_nets_permissions[i] & permissions)) |
| 559 | return 1; | 559 | return 1; |
diff --git a/ot_accesslist.h b/ot_accesslist.h index 0a7488e..d05e1f7 100644 --- a/ot_accesslist.h +++ b/ot_accesslist.h | |||
| @@ -72,7 +72,7 @@ struct ot_log { | |||
| 72 | extern ot_log *g_logchain_first, *g_logchain_last; | 72 | extern ot_log *g_logchain_first, *g_logchain_last; |
| 73 | 73 | ||
| 74 | void loglist_add_network(const ot_net *net); | 74 | void loglist_add_network(const ot_net *net); |
| 75 | void loglist_reset(); | 75 | void loglist_reset(void); |
| 76 | int loglist_check_address(const ot_ip6 address); | 76 | int loglist_check_address(const ot_ip6 address); |
| 77 | #endif | 77 | #endif |
| 78 | 78 | ||
| @@ -20,7 +20,7 @@ | |||
| 20 | #include "trackerlogic.h" | 20 | #include "trackerlogic.h" |
| 21 | 21 | ||
| 22 | /* Returns amount of removed peers */ | 22 | /* Returns amount of removed peers */ |
| 23 | static ssize_t clean_single_bucket(ot_peer *peers, size_t peer_count, size_t peer_size, time_t timedout, int *removed_seeders) { | 23 | static ssize_t clean_single_bucket(ot_peer *peers, size_t peer_count, size_t peer_size, time_t timedout, size_t *removed_seeders) { |
| 24 | ot_peer *last_peer = peers + peer_count * peer_size, *insert_point; | 24 | ot_peer *last_peer = peers + peer_count * peer_size, *insert_point; |
| 25 | 25 | ||
| 26 | /* Two scan modes: unless there is one peer removed, just increase ot_peertime */ | 26 | /* Two scan modes: unless there is one peer removed, just increase ot_peertime */ |
| @@ -50,7 +50,7 @@ static ssize_t clean_single_bucket(ot_peer *peers, size_t peer_count, size_t pee | |||
| 50 | int clean_single_peer_list(ot_peerlist *peer_list, size_t peer_size) { | 50 | int clean_single_peer_list(ot_peerlist *peer_list, size_t peer_size) { |
| 51 | ot_vector *peer_vector = &peer_list->peers; | 51 | ot_vector *peer_vector = &peer_list->peers; |
| 52 | time_t timedout = (time_t)(g_now_minutes - peer_list->base); | 52 | time_t timedout = (time_t)(g_now_minutes - peer_list->base); |
| 53 | int num_buckets = 1, removed_seeders = 0; | 53 | size_t num_buckets = 1, removed_seeders = 0; |
| 54 | 54 | ||
| 55 | /* No need to clean empty torrent */ | 55 | /* No need to clean empty torrent */ |
| 56 | if (!timedout) | 56 | if (!timedout) |
| @@ -111,7 +111,7 @@ int clean_single_torrent(ot_torrent *torrent) { | |||
| 111 | static void *clean_worker(void *args) { | 111 | static void *clean_worker(void *args) { |
| 112 | (void)args; | 112 | (void)args; |
| 113 | while (1) { | 113 | while (1) { |
| 114 | int bucket = OT_BUCKET_COUNT; | 114 | size_t bucket = OT_BUCKET_COUNT; |
| 115 | while (bucket--) { | 115 | while (bucket--) { |
| 116 | ot_vector *torrents_list = mutex_bucket_lock(bucket); | 116 | ot_vector *torrents_list = mutex_bucket_lock(bucket); |
| 117 | size_t toffs; | 117 | size_t toffs; |
diff --git a/ot_fullscrape.c b/ot_fullscrape.c index aed2ad9..b800431 100644 --- a/ot_fullscrape.c +++ b/ot_fullscrape.c | |||
| @@ -14,6 +14,10 @@ | |||
| 14 | #ifdef WANT_COMPRESSION_GZIP | 14 | #ifdef WANT_COMPRESSION_GZIP |
| 15 | #include <zlib.h> | 15 | #include <zlib.h> |
| 16 | #endif | 16 | #endif |
| 17 | #ifdef WANT_COMPRESSION_ZSTD | ||
| 18 | #include <zstd.h> | ||
| 19 | #endif | ||
| 20 | |||
| 17 | 21 | ||
| 18 | /* Libowfat */ | 22 | /* Libowfat */ |
| 19 | #include "byte.h" | 23 | #include "byte.h" |
| @@ -40,6 +44,9 @@ static void fullscrape_make(int taskid, ot_tasktype mode); | |||
| 40 | #ifdef WANT_COMPRESSION_GZIP | 44 | #ifdef WANT_COMPRESSION_GZIP |
| 41 | static void fullscrape_make_gzip(int taskid, ot_tasktype mode); | 45 | static void fullscrape_make_gzip(int taskid, ot_tasktype mode); |
| 42 | #endif | 46 | #endif |
| 47 | #ifdef WANT_COMPRESSION_ZSTD | ||
| 48 | static void fullscrape_make_zstd(int taskid, ot_tasktype mode); | ||
| 49 | #endif | ||
| 43 | 50 | ||
| 44 | /* Converter function from memory to human readable hex strings | 51 | /* Converter function from memory to human readable hex strings |
| 45 | XXX - Duplicated from ot_stats. Needs fix. */ | 52 | XXX - Duplicated from ot_stats. Needs fix. */ |
| @@ -64,6 +71,11 @@ static void *fullscrape_worker(void *args) { | |||
| 64 | while (g_opentracker_running) { | 71 | while (g_opentracker_running) { |
| 65 | ot_tasktype tasktype = TASK_FULLSCRAPE; | 72 | ot_tasktype tasktype = TASK_FULLSCRAPE; |
| 66 | ot_taskid taskid = mutex_workqueue_poptask(&tasktype); | 73 | ot_taskid taskid = mutex_workqueue_poptask(&tasktype); |
| 74 | #ifdef WANT_COMPRESSION_ZSTD | ||
| 75 | if (tasktype & TASK_FLAG_ZSTD) | ||
| 76 | fullscrape_make_zstd(taskid, tasktype); | ||
| 77 | else | ||
| 78 | #endif | ||
| 67 | #ifdef WANT_COMPRESSION_GZIP | 79 | #ifdef WANT_COMPRESSION_GZIP |
| 68 | if (tasktype & TASK_FLAG_GZIP) | 80 | if (tasktype & TASK_FLAG_GZIP) |
| 69 | fullscrape_make_gzip(taskid, tasktype); | 81 | fullscrape_make_gzip(taskid, tasktype); |
| @@ -76,11 +88,11 @@ static void *fullscrape_worker(void *args) { | |||
| 76 | } | 88 | } |
| 77 | 89 | ||
| 78 | static pthread_t thread_id; | 90 | static pthread_t thread_id; |
| 79 | void fullscrape_init( ) { | 91 | void fullscrape_init(void) { |
| 80 | pthread_create( &thread_id, NULL, fullscrape_worker, NULL ); | 92 | pthread_create( &thread_id, NULL, fullscrape_worker, NULL ); |
| 81 | } | 93 | } |
| 82 | 94 | ||
| 83 | void fullscrape_deinit( ) { | 95 | void fullscrape_deinit(void) { |
| 84 | pthread_cancel( thread_id ); | 96 | pthread_cancel( thread_id ); |
| 85 | } | 97 | } |
| 86 | 98 | ||
| @@ -137,8 +149,8 @@ static char * fullscrape_write_one( ot_tasktype mode, char *r, ot_torrent *torre | |||
| 137 | } | 149 | } |
| 138 | 150 | ||
| 139 | static void fullscrape_make(int taskid, ot_tasktype mode) { | 151 | static void fullscrape_make(int taskid, ot_tasktype mode) { |
| 140 | int bucket; | 152 | size_t bucket; |
| 141 | char *r, *re; | 153 | char *r, *re; |
| 142 | struct iovec iovector = {NULL, 0}; | 154 | struct iovec iovector = {NULL, 0}; |
| 143 | 155 | ||
| 144 | /* Setup return vector... */ | 156 | /* Setup return vector... */ |
| @@ -200,12 +212,11 @@ static void fullscrape_make(int taskid, ot_tasktype mode) { | |||
| 200 | #ifdef WANT_COMPRESSION_GZIP | 212 | #ifdef WANT_COMPRESSION_GZIP |
| 201 | 213 | ||
| 202 | static void fullscrape_make_gzip(int taskid, ot_tasktype mode) { | 214 | static void fullscrape_make_gzip(int taskid, ot_tasktype mode) { |
| 203 | int bucket; | 215 | size_t bucket; |
| 204 | char *r; | 216 | char *r; |
| 205 | struct iovec iovector = {NULL, 0}; | 217 | struct iovec iovector = {NULL, 0}; |
| 206 | int zres; | 218 | int zres; |
| 207 | z_stream strm; | 219 | z_stream strm; |
| 208 | fprintf(stderr, "GZIP path\n"); | ||
| 209 | /* Setup return vector... */ | 220 | /* Setup return vector... */ |
| 210 | iovector.iov_base = malloc(OT_SCRAPE_CHUNK_SIZE); | 221 | iovector.iov_base = malloc(OT_SCRAPE_CHUNK_SIZE); |
| 211 | if (!iovector.iov_base) | 222 | if (!iovector.iov_base) |
| @@ -267,8 +278,10 @@ static void fullscrape_make_gzip(int taskid, ot_tasktype mode) { | |||
| 267 | mutex_bucket_unlock(bucket, 0); | 278 | mutex_bucket_unlock(bucket, 0); |
| 268 | 279 | ||
| 269 | /* Parent thread died? */ | 280 | /* Parent thread died? */ |
| 270 | if (!g_opentracker_running) | 281 | if (!g_opentracker_running) { |
| 282 | deflateEnd(&strm); | ||
| 271 | return; | 283 | return; |
| 284 | } | ||
| 272 | } | 285 | } |
| 273 | 286 | ||
| 274 | if ((mode & TASK_TASK_MASK) == TASK_FULLSCRAPE) { | 287 | if ((mode & TASK_TASK_MASK) == TASK_FULLSCRAPE) { |
| @@ -282,7 +295,8 @@ static void fullscrape_make_gzip(int taskid, ot_tasktype mode) { | |||
| 282 | iovector.iov_len = (char *)strm.next_out - (char *)iovector.iov_base; | 295 | iovector.iov_len = (char *)strm.next_out - (char *)iovector.iov_base; |
| 283 | if (mutex_workqueue_pushchunked(taskid, &iovector)) { | 296 | if (mutex_workqueue_pushchunked(taskid, &iovector)) { |
| 284 | free(iovector.iov_base); | 297 | free(iovector.iov_base); |
| 285 | return mutex_bucket_unlock(bucket, 0); | 298 | deflateEnd(&strm); |
| 299 | return; | ||
| 286 | } | 300 | } |
| 287 | 301 | ||
| 288 | /* Check if there's a last batch of data in the zlib buffer */ | 302 | /* Check if there's a last batch of data in the zlib buffer */ |
| @@ -293,7 +307,7 @@ static void fullscrape_make_gzip(int taskid, ot_tasktype mode) { | |||
| 293 | if (!iovector.iov_base) { | 307 | if (!iovector.iov_base) { |
| 294 | fprintf(stderr, "Problem with iovec_fix_increase_or_free\n"); | 308 | fprintf(stderr, "Problem with iovec_fix_increase_or_free\n"); |
| 295 | deflateEnd(&strm); | 309 | deflateEnd(&strm); |
| 296 | return mutex_bucket_unlock(bucket, 0); | 310 | return; |
| 297 | } | 311 | } |
| 298 | strm.next_out = iovector.iov_base; | 312 | strm.next_out = iovector.iov_base; |
| 299 | strm.avail_out = OT_SCRAPE_CHUNK_SIZE; | 313 | strm.avail_out = OT_SCRAPE_CHUNK_SIZE; |
| @@ -311,5 +325,133 @@ static void fullscrape_make_gzip(int taskid, ot_tasktype mode) { | |||
| 311 | /* WANT_COMPRESSION_GZIP */ | 325 | /* WANT_COMPRESSION_GZIP */ |
| 312 | #endif | 326 | #endif |
| 313 | 327 | ||
| 328 | #ifdef WANT_COMPRESSION_ZSTD | ||
| 329 | |||
| 330 | static void fullscrape_make_zstd(int taskid, ot_tasktype mode) { | ||
| 331 | int bucket; | ||
| 332 | char *r; | ||
| 333 | struct iovec iovector = {NULL, 0}; | ||
| 334 | ZSTD_CCtx *zstream = ZSTD_createCCtx(); | ||
| 335 | ZSTD_inBuffer inbuf; | ||
| 336 | ZSTD_outBuffer outbuf; | ||
| 337 | size_t more_bytes; | ||
| 338 | |||
| 339 | if (!zstream) | ||
| 340 | return; | ||
| 341 | |||
| 342 | /* Setup return vector... */ | ||
| 343 | iovector.iov_base = malloc(OT_SCRAPE_CHUNK_SIZE); | ||
| 344 | if (!iovector.iov_base) { | ||
| 345 | ZSTD_freeCCtx(zstream); | ||
| 346 | return; | ||
| 347 | } | ||
| 348 | |||
| 349 | /* Working with a compression level 6 is half as fast as level 3, but | ||
| 350 | seems to be the last reasonable bump that's worth extra cpu */ | ||
| 351 | ZSTD_CCtx_setParameter(zstream, ZSTD_c_compressionLevel, 6); | ||
| 352 | |||
| 353 | outbuf.dst = iovector.iov_base; | ||
| 354 | outbuf.size = OT_SCRAPE_CHUNK_SIZE; | ||
| 355 | outbuf.pos = 0; | ||
| 356 | |||
| 357 | if ((mode & TASK_TASK_MASK) == TASK_FULLSCRAPE) { | ||
| 358 | inbuf.src = (const void *)"d5:filesd"; | ||
| 359 | inbuf.size = strlen("d5:filesd"); | ||
| 360 | inbuf.pos = 0; | ||
| 361 | ZSTD_compressStream2(zstream, &outbuf, &inbuf, ZSTD_e_continue); | ||
| 362 | } | ||
| 363 | |||
| 364 | /* For each bucket... */ | ||
| 365 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { | ||
| 366 | /* Get exclusive access to that bucket */ | ||
| 367 | ot_vector *torrents_list = mutex_bucket_lock(bucket); | ||
| 368 | ot_torrent *torrents = (ot_torrent *)(torrents_list->data); | ||
| 369 | size_t i; | ||
| 370 | |||
| 371 | /* For each torrent in this bucket.. */ | ||
| 372 | for (i = 0; i < torrents_list->size; ++i) { | ||
| 373 | char compress_buffer[OT_SCRAPE_MAXENTRYLEN]; | ||
| 374 | r = fullscrape_write_one(mode, compress_buffer, torrents + i, &torrents[i].hash); | ||
| 375 | inbuf.src = compress_buffer; | ||
| 376 | inbuf.size = r - compress_buffer; | ||
| 377 | inbuf.pos = 0; | ||
| 378 | ZSTD_compressStream2(zstream, &outbuf, &inbuf, ZSTD_e_continue); | ||
| 379 | |||
| 380 | /* Check if there still is enough buffer left */ | ||
| 381 | while (outbuf.pos + OT_SCRAPE_MAXENTRYLEN > outbuf.size) { | ||
| 382 | iovector.iov_len = outbuf.size; | ||
| 383 | |||
| 384 | if (mutex_workqueue_pushchunked(taskid, &iovector)) { | ||
| 385 | free(iovector.iov_base); | ||
| 386 | ZSTD_freeCCtx(zstream); | ||
| 387 | return mutex_bucket_unlock(bucket, 0); | ||
| 388 | } | ||
| 389 | /* Allocate a fresh output buffer */ | ||
| 390 | iovector.iov_base = malloc(OT_SCRAPE_CHUNK_SIZE); | ||
| 391 | if (!iovector.iov_base) { | ||
| 392 | fprintf(stderr, "Out of memory trying to claim ouput buffer\n"); | ||
| 393 | ZSTD_freeCCtx(zstream); | ||
| 394 | return mutex_bucket_unlock(bucket, 0); | ||
| 395 | } | ||
| 396 | |||
| 397 | outbuf.dst = iovector.iov_base; | ||
| 398 | outbuf.size = OT_SCRAPE_CHUNK_SIZE; | ||
| 399 | outbuf.pos = 0; | ||
| 400 | |||
| 401 | ZSTD_compressStream2(zstream, &outbuf, &inbuf, ZSTD_e_continue); | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | /* All torrents done: release lock on current bucket */ | ||
| 406 | mutex_bucket_unlock(bucket, 0); | ||
| 407 | |||
| 408 | /* Parent thread died? */ | ||
| 409 | if (!g_opentracker_running) | ||
| 410 | return; | ||
| 411 | } | ||
| 412 | |||
| 413 | if ((mode & TASK_TASK_MASK) == TASK_FULLSCRAPE) { | ||
| 414 | inbuf.src = (const void *)"ee"; | ||
| 415 | inbuf.size = strlen("ee"); | ||
| 416 | inbuf.pos = 0; | ||
| 417 | } | ||
| 418 | |||
| 419 | more_bytes = ZSTD_compressStream2(zstream, &outbuf, &inbuf, ZSTD_e_end); | ||
| 420 | |||
| 421 | iovector.iov_len = outbuf.pos; | ||
| 422 | if (mutex_workqueue_pushchunked(taskid, &iovector)) { | ||
| 423 | free(iovector.iov_base); | ||
| 424 | ZSTD_freeCCtx(zstream); | ||
| 425 | return; | ||
| 426 | } | ||
| 427 | |||
| 428 | /* Check if there's a last batch of data in the zlib buffer */ | ||
| 429 | if (more_bytes) { | ||
| 430 | /* Allocate a fresh output buffer */ | ||
| 431 | iovector.iov_base = malloc(OT_SCRAPE_CHUNK_SIZE); | ||
| 432 | |||
| 433 | if (!iovector.iov_base) { | ||
| 434 | fprintf(stderr, "Problem with iovec_fix_increase_or_free\n"); | ||
| 435 | ZSTD_freeCCtx(zstream); | ||
| 436 | return; | ||
| 437 | } | ||
| 438 | |||
| 439 | outbuf.dst = iovector.iov_base; | ||
| 440 | outbuf.size = OT_SCRAPE_CHUNK_SIZE; | ||
| 441 | outbuf.pos = 0; | ||
| 442 | |||
| 443 | ZSTD_compressStream2(zstream, &outbuf, &inbuf, ZSTD_e_end); | ||
| 444 | |||
| 445 | /* Only pass the new buffer if there actually was some data left in the buffer */ | ||
| 446 | iovector.iov_len = outbuf.pos; | ||
| 447 | if (!iovector.iov_len || mutex_workqueue_pushchunked(taskid, &iovector)) | ||
| 448 | free(iovector.iov_base); | ||
| 449 | } | ||
| 450 | |||
| 451 | ZSTD_freeCCtx(zstream); | ||
| 452 | } | ||
| 453 | /* WANT_COMPRESSION_ZSTD */ | ||
| 454 | #endif | ||
| 455 | |||
| 314 | /* WANT_FULLSCRAPE */ | 456 | /* WANT_FULLSCRAPE */ |
| 315 | #endif | 457 | #endif |
diff --git a/ot_fullscrape.h b/ot_fullscrape.h index bbb2a3f..843e039 100644 --- a/ot_fullscrape.h +++ b/ot_fullscrape.h | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | #include "ot_mutex.h" | 11 | #include "ot_mutex.h" |
| 12 | 12 | ||
| 13 | void fullscrape_init(); | 13 | void fullscrape_init(void); |
| 14 | void fullscrape_deinit(); | 14 | void fullscrape_deinit(void); |
| 15 | void fullscrape_deliver(int64 sock, ot_tasktype tasktype); | 15 | void fullscrape_deliver(int64 sock, ot_tasktype tasktype); |
| 16 | 16 | ||
| 17 | #else | 17 | #else |
| @@ -4,9 +4,9 @@ | |||
| 4 | $id$ */ | 4 | $id$ */ |
| 5 | 5 | ||
| 6 | /* System */ | 6 | /* System */ |
| 7 | #define _GNU_SOURCE | ||
| 7 | #include <arpa/inet.h> | 8 | #include <arpa/inet.h> |
| 8 | #include <pthread.h> | 9 | #include <pthread.h> |
| 9 | #define _GNU_SOURCE | ||
| 10 | #include <stdio.h> | 10 | #include <stdio.h> |
| 11 | #include <stdlib.h> | 11 | #include <stdlib.h> |
| 12 | #include <string.h> | 12 | #include <string.h> |
| @@ -32,7 +32,7 @@ | |||
| 32 | #include "trackerlogic.h" | 32 | #include "trackerlogic.h" |
| 33 | 33 | ||
| 34 | #ifdef WANT_NO_AUTO_FREE | 34 | #ifdef WANT_NO_AUTO_FREE |
| 35 | #define OT_IOB_INIT(B) bzero(B, sizeof(io_batch)) | 35 | #define OT_IOB_INIT(B) (bzero(B, sizeof(io_batch)), 0) |
| 36 | #else | 36 | #else |
| 37 | #define OT_IOB_INIT(B) iob_init_autofree(B, 0) | 37 | #define OT_IOB_INIT(B) iob_init_autofree(B, 0) |
| 38 | #endif | 38 | #endif |
| @@ -88,7 +88,15 @@ static void http_senddata(const int64 sock, struct ot_workstruct *ws) { | |||
| 88 | memcpy(outbuf, ws->reply + written_size, ws->reply_size - written_size); | 88 | memcpy(outbuf, ws->reply + written_size, ws->reply_size - written_size); |
| 89 | if (!cookie->batch) { | 89 | if (!cookie->batch) { |
| 90 | cookie->batch = malloc(sizeof(io_batch)); | 90 | cookie->batch = malloc(sizeof(io_batch)); |
| 91 | OT_IOB_INIT(cookie->batch); | 91 | if (!cookie->batch || OT_IOB_INIT(cookie->batch) == -1) { |
| 92 | free(cookie->batch); | ||
| 93 | free(outbuf); | ||
| 94 | array_reset(&cookie->request); | ||
| 95 | free(cookie); | ||
| 96 | io_close(sock); | ||
| 97 | return; | ||
| 98 | } | ||
| 99 | |||
| 92 | cookie->batches = 1; | 100 | cookie->batches = 1; |
| 93 | } | 101 | } |
| 94 | 102 | ||
| @@ -133,13 +141,12 @@ ssize_t http_issue_error(const int64 sock, struct ot_workstruct *ws, int code) { | |||
| 133 | return ws->reply_size = -2; | 141 | return ws->reply_size = -2; |
| 134 | } | 142 | } |
| 135 | 143 | ||
| 136 | ssize_t http_sendiovecdata(const int64 sock, struct ot_workstruct *ws, int iovec_entries, struct iovec *iovector, int is_partial) { | 144 | ssize_t http_sendiovecdata(const int64 sock, struct ot_workstruct *ws, size_t iovec_entries, struct iovec *iovector, int is_partial) { |
| 137 | struct http_data *cookie = io_getcookie(sock); | 145 | struct http_data *cookie = io_getcookie(sock); |
| 138 | io_batch *current; | 146 | io_batch *current; |
| 139 | char *header; | 147 | char *header; |
| 140 | const char *encoding = ""; | 148 | const char *encoding = ""; |
| 141 | int i; | 149 | size_t i, header_size, size = iovec_length(&iovec_entries, (const struct iovec **)&iovector); |
| 142 | size_t header_size, size = iovec_length(&iovec_entries, (const struct iovec **)&iovector); | ||
| 143 | tai6464 t; | 150 | tai6464 t; |
| 144 | 151 | ||
| 145 | /* No cookie? Bad socket. Leave. */ | 152 | /* No cookie? Bad socket. Leave. */ |
| @@ -159,7 +166,9 @@ ssize_t http_sendiovecdata(const int64 sock, struct ot_workstruct *ws, int iovec | |||
| 159 | 166 | ||
| 160 | if (iovec_entries) { | 167 | if (iovec_entries) { |
| 161 | 168 | ||
| 162 | if (cookie->flag & STRUCT_HTTP_FLAG_GZIP) | 169 | if (cookie->flag & STRUCT_HTTP_FLAG_ZSTD) |
| 170 | encoding = "Content-Encoding: zstd\r\n"; | ||
| 171 | else if (cookie->flag & STRUCT_HTTP_FLAG_GZIP) | ||
| 163 | encoding = "Content-Encoding: gzip\r\n"; | 172 | encoding = "Content-Encoding: gzip\r\n"; |
| 164 | else if (cookie->flag & STRUCT_HTTP_FLAG_BZIP2) | 173 | else if (cookie->flag & STRUCT_HTTP_FLAG_BZIP2) |
| 165 | encoding = "Content-Encoding: bzip2\r\n"; | 174 | encoding = "Content-Encoding: bzip2\r\n"; |
| @@ -181,26 +190,26 @@ ssize_t http_sendiovecdata(const int64 sock, struct ot_workstruct *ws, int iovec | |||
| 181 | 190 | ||
| 182 | if (!cookie->batch) { | 191 | if (!cookie->batch) { |
| 183 | cookie->batch = malloc(sizeof(io_batch)); | 192 | cookie->batch = malloc(sizeof(io_batch)); |
| 184 | if (!cookie->batch) { | 193 | if (!cookie->batch || OT_IOB_INIT(cookie->batch) == -1) { |
| 194 | free(cookie->batch); | ||
| 185 | free(header); | 195 | free(header); |
| 186 | iovec_free(&iovec_entries, &iovector); | 196 | iovec_free(&iovec_entries, &iovector); |
| 187 | HTTPERROR_500; | 197 | HTTPERROR_500; |
| 188 | } | 198 | } |
| 189 | OT_IOB_INIT(cookie->batch); | ||
| 190 | cookie->batches = 1; | 199 | cookie->batches = 1; |
| 191 | } | 200 | } |
| 192 | current = cookie->batch + cookie->batches - 1; | 201 | current = cookie->batch + cookie->batches - 1; |
| 193 | iob_addbuf_free(current, header, header_size); | 202 | iob_addbuf_free(current, header, header_size); |
| 194 | 203 | ||
| 195 | /* Split huge iovectors into separate io_batches */ | 204 | /* Split huge iovectors into separate io_batches */ |
| 196 | for (i = 0; i < iovec_entries; ++i) { | 205 | for (i = 0; i < (size_t)iovec_entries; ++i) { |
| 197 | /* If the current batch's limit is reached, try to reallocate a new batch to work on */ | 206 | /* If the current batch's limit is reached, try to reallocate a new batch to work on */ |
| 198 | if (current->bytesleft > OT_BATCH_LIMIT) { | 207 | if (current->bytesleft > OT_BATCH_LIMIT) { |
| 199 | io_batch *new_batch = realloc(cookie->batch, (cookie->batches + 1) * sizeof(io_batch)); | 208 | io_batch *new_batch = realloc(cookie->batch, (cookie->batches + 1) * sizeof(io_batch)); |
| 200 | if (new_batch) { | 209 | if (new_batch) { |
| 201 | cookie->batch = new_batch; | 210 | cookie->batch = new_batch; |
| 202 | current = cookie->batch + cookie->batches++; | 211 | if (OT_IOB_INIT(current) != -1) |
| 203 | OT_IOB_INIT(current); | 212 | current = cookie->batch + cookie->batches++; |
| 204 | } | 213 | } |
| 205 | } | 214 | } |
| 206 | iob_addbuf_free(current, iovector[i].iov_base, iovector[i].iov_len); | 215 | iob_addbuf_free(current, iovector[i].iov_base, iovector[i].iov_len); |
| @@ -369,19 +378,34 @@ static ssize_t http_handle_fullscrape(const int64 sock, struct ot_workstruct *ws | |||
| 369 | } | 378 | } |
| 370 | #endif | 379 | #endif |
| 371 | 380 | ||
| 372 | #ifdef WANT_COMPRESSION_GZIP | 381 | |
| 382 | #if defined(WANT_COMPRESSION_GZIP) || defined(WANT_COMPRESSION_ZSTD) | ||
| 373 | ws->request[ws->request_size - 1] = 0; | 383 | ws->request[ws->request_size - 1] = 0; |
| 374 | #ifndef WANT_COMPRESSION_GZIP_ALWAYS | 384 | #ifdef WANT_COMPRESSION_GZIP |
| 375 | if (strstr(ws->request, "gzip")) { | 385 | if (strstr(ws->request, "gzip")) { |
| 376 | #endif | ||
| 377 | cookie->flag |= STRUCT_HTTP_FLAG_GZIP; | 386 | cookie->flag |= STRUCT_HTTP_FLAG_GZIP; |
| 378 | format = TASK_FLAG_GZIP; | 387 | format |= TASK_FLAG_GZIP; |
| 379 | stats_issue_event(EVENT_FULLSCRAPE_REQUEST_GZIP, 0, (uintptr_t)cookie->ip); | 388 | } |
| 380 | #ifndef WANT_COMPRESSION_GZIP_ALWAYS | 389 | #endif |
| 381 | } else | 390 | #ifdef WANT_COMPRESSION_ZSTD |
| 391 | if (strstr(ws->request, "zstd")) { | ||
| 392 | cookie->flag |= STRUCT_HTTP_FLAG_ZSTD; | ||
| 393 | format |= TASK_FLAG_ZSTD; | ||
| 394 | } | ||
| 395 | #endif | ||
| 396 | |||
| 397 | #if defined(WANT_COMPRESSION_ZSTD) && defined(WANT_COMPRESSION_ZSTD_ALWAYS) | ||
| 398 | cookie->flag |= STRUCT_HTTP_FLAG_ZSTD; | ||
| 399 | format |= TASK_FLAG_ZSTD; | ||
| 400 | #endif | ||
| 401 | |||
| 402 | #if defined(WANT_COMPRESSION_GZIP) && defined(WANT_COMPRESSION_GZIP_ALWAYS) | ||
| 403 | cookie->flag |= STRUCT_HTTP_FLAG_GZIP; | ||
| 404 | format |= TASK_FLAG_GZIP; | ||
| 382 | #endif | 405 | #endif |
| 383 | #endif | 406 | #endif |
| 384 | stats_issue_event(EVENT_FULLSCRAPE_REQUEST, 0, (uintptr_t)cookie->ip); | 407 | |
| 408 | stats_issue_event(EVENT_FULLSCRAPE_REQUEST, 0, (uintptr_t)cookie->ip); | ||
| 385 | 409 | ||
| 386 | #ifdef _DEBUG_HTTPERROR | 410 | #ifdef _DEBUG_HTTPERROR |
| 387 | fprintf(stderr, "%s", ws->debugbuf); | 411 | fprintf(stderr, "%s", ws->debugbuf); |
| @@ -401,8 +425,9 @@ static ssize_t http_handle_fullscrape(const int64 sock, struct ot_workstruct *ws | |||
| 401 | static ssize_t http_handle_scrape(const int64 sock, struct ot_workstruct *ws, char *read_ptr) { | 425 | static ssize_t http_handle_scrape(const int64 sock, struct ot_workstruct *ws, char *read_ptr) { |
| 402 | static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}}; | 426 | static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}}; |
| 403 | 427 | ||
| 404 | ot_hash *multiscrape_buf = (ot_hash *)ws->request; | 428 | ot_hash *multiscrape_buf = (ot_hash *)ws->request; |
| 405 | int scanon = 1, numwant = 0; | 429 | int scanon = 1; |
| 430 | size_t numwant = 0; | ||
| 406 | 431 | ||
| 407 | /* This is to hack around stupid clients that send "scrape ?info_hash" */ | 432 | /* This is to hack around stupid clients that send "scrape ?info_hash" */ |
| 408 | if (read_ptr[-1] != '?') { | 433 | if (read_ptr[-1] != '?') { |
| @@ -477,7 +502,8 @@ static ot_keywords keywords_announce[] = {{"port", 1}, {"left", 2}, {"event", | |||
| 477 | {"peer_id", 9}, {NULL, -3}}; | 502 | {"peer_id", 9}, {NULL, -3}}; |
| 478 | static ot_keywords keywords_announce_event[] = {{"completed", 1}, {"stopped", 2}, {NULL, -3}}; | 503 | static ot_keywords keywords_announce_event[] = {{"completed", 1}, {"stopped", 2}, {NULL, -3}}; |
| 479 | static ssize_t http_handle_announce(const int64 sock, struct ot_workstruct *ws, char *read_ptr) { | 504 | static ssize_t http_handle_announce(const int64 sock, struct ot_workstruct *ws, char *read_ptr) { |
| 480 | int numwant, tmp, scanon; | 505 | size_t numwant; |
| 506 | int tmp, scanon; | ||
| 481 | unsigned short port = 0; | 507 | unsigned short port = 0; |
| 482 | char *write_ptr; | 508 | char *write_ptr; |
| 483 | ssize_t len; | 509 | ssize_t len; |
| @@ -553,12 +579,13 @@ static ssize_t http_handle_announce(const int64 sock, struct ot_workstruct * | |||
| 553 | break; | 579 | break; |
| 554 | case 4: /* matched "numwant" */ | 580 | case 4: /* matched "numwant" */ |
| 555 | len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); | 581 | len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); |
| 556 | if ((len <= 0) || scan_fixed_int(write_ptr, len, &numwant)) | 582 | if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp)) |
| 557 | HTTPERROR_400_PARAM; | 583 | HTTPERROR_400_PARAM; |
| 558 | if (numwant < 0) | 584 | if (tmp < 0) |
| 559 | numwant = 50; | 585 | tmp = 50; |
| 560 | if (numwant > 200) | 586 | if (tmp > 200) |
| 561 | numwant = 200; | 587 | tmp = 200; |
| 588 | numwant = tmp; | ||
| 562 | break; | 589 | break; |
| 563 | case 5: /* matched "compact" */ | 590 | case 5: /* matched "compact" */ |
| 564 | len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); | 591 | len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); |
| @@ -10,8 +10,9 @@ typedef enum { | |||
| 10 | STRUCT_HTTP_FLAG_WAITINGFORTASK = 1, | 10 | STRUCT_HTTP_FLAG_WAITINGFORTASK = 1, |
| 11 | STRUCT_HTTP_FLAG_GZIP = 2, | 11 | STRUCT_HTTP_FLAG_GZIP = 2, |
| 12 | STRUCT_HTTP_FLAG_BZIP2 = 4, | 12 | STRUCT_HTTP_FLAG_BZIP2 = 4, |
| 13 | STRUCT_HTTP_FLAG_CHUNKED = 8, | 13 | STRUCT_HTTP_FLAG_ZSTD = 8, |
| 14 | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER = 16 | 14 | STRUCT_HTTP_FLAG_CHUNKED = 16, |
| 15 | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER = 32 | ||
| 15 | } STRUCT_HTTP_FLAG; | 16 | } STRUCT_HTTP_FLAG; |
| 16 | 17 | ||
| 17 | struct http_data { | 18 | struct http_data { |
| @@ -23,7 +24,7 @@ struct http_data { | |||
| 23 | }; | 24 | }; |
| 24 | 25 | ||
| 25 | ssize_t http_handle_request(const int64 s, struct ot_workstruct *ws); | 26 | ssize_t http_handle_request(const int64 s, struct ot_workstruct *ws); |
| 26 | ssize_t http_sendiovecdata(const int64 s, struct ot_workstruct *ws, int iovec_entries, struct iovec *iovector, int is_partial); | 27 | ssize_t http_sendiovecdata(const int64 s, struct ot_workstruct *ws, size_t iovec_entries, struct iovec *iovector, int is_partial); |
| 27 | ssize_t http_issue_error(const int64 s, struct ot_workstruct *ws, int code); | 28 | ssize_t http_issue_error(const int64 s, struct ot_workstruct *ws, int code); |
| 28 | 29 | ||
| 29 | extern char *g_stats_path; | 30 | extern char *g_stats_path; |
| @@ -14,9 +14,9 @@ | |||
| 14 | /* Opentracker */ | 14 | /* Opentracker */ |
| 15 | #include "ot_iovec.h" | 15 | #include "ot_iovec.h" |
| 16 | 16 | ||
| 17 | void *iovec_increase(int *iovec_entries, struct iovec **iovector, size_t new_alloc) { | 17 | void *iovec_increase(size_t *iovec_entries, struct iovec **iovector, size_t new_alloc) { |
| 18 | void *new_data; | 18 | void *new_data; |
| 19 | int new_entries = 1 + *iovec_entries; | 19 | size_t new_entries = 1 + *iovec_entries; |
| 20 | struct iovec *new_vec = realloc(*iovector, new_entries * sizeof(struct iovec)); | 20 | struct iovec *new_vec = realloc(*iovector, new_entries * sizeof(struct iovec)); |
| 21 | 21 | ||
| 22 | if (!new_vec) | 22 | if (!new_vec) |
| @@ -35,8 +35,8 @@ void *iovec_increase(int *iovec_entries, struct iovec **iovector, size_t new_all | |||
| 35 | return new_data; | 35 | return new_data; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | void *iovec_append(int *iovec_entries, struct iovec **iovector, struct iovec *append_iovector) { | 38 | void *iovec_append(size_t *iovec_entries, struct iovec **iovector, struct iovec *append_iovector) { |
| 39 | int new_entries = *iovec_entries + 1; | 39 | size_t new_entries = *iovec_entries + 1; |
| 40 | struct iovec *new_vec = realloc(*iovector, new_entries * sizeof(struct iovec)); | 40 | struct iovec *new_vec = realloc(*iovector, new_entries * sizeof(struct iovec)); |
| 41 | if (!new_vec) | 41 | if (!new_vec) |
| 42 | return NULL; | 42 | return NULL; |
| @@ -54,15 +54,15 @@ void *iovec_append(int *iovec_entries, struct iovec **iovector, struct iovec *ap | |||
| 54 | return new_vec; | 54 | return new_vec; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | void iovec_free(int *iovec_entries, struct iovec **iovector) { | 57 | void iovec_free(size_t *iovec_entries, struct iovec **iovector) { |
| 58 | int i; | 58 | size_t i; |
| 59 | for (i = 0; i < *iovec_entries; ++i) | 59 | for (i = 0; i < *iovec_entries; ++i) |
| 60 | free(((*iovector)[i]).iov_base); | 60 | free(((*iovector)[i]).iov_base); |
| 61 | *iovector = NULL; | 61 | *iovector = NULL; |
| 62 | *iovec_entries = 0; | 62 | *iovec_entries = 0; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void iovec_fixlast(int *iovec_entries, struct iovec **iovector, void *last_ptr) { | 65 | void iovec_fixlast(size_t *iovec_entries, struct iovec **iovector, void *last_ptr) { |
| 66 | if (*iovec_entries) { | 66 | if (*iovec_entries) { |
| 67 | char *base = (char *)((*iovector)[*iovec_entries - 1]).iov_base; | 67 | char *base = (char *)((*iovector)[*iovec_entries - 1]).iov_base; |
| 68 | size_t new_alloc = ((char *)last_ptr) - base; | 68 | size_t new_alloc = ((char *)last_ptr) - base; |
| @@ -72,7 +72,7 @@ void iovec_fixlast(int *iovec_entries, struct iovec **iovector, void *last_ptr) | |||
| 72 | } | 72 | } |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | void *iovec_fix_increase_or_free(int *iovec_entries, struct iovec **iovector, void *last_ptr, size_t new_alloc) { | 75 | void *iovec_fix_increase_or_free(size_t *iovec_entries, struct iovec **iovector, void *last_ptr, size_t new_alloc) { |
| 76 | void *new_data; | 76 | void *new_data; |
| 77 | 77 | ||
| 78 | iovec_fixlast(iovec_entries, iovector, last_ptr); | 78 | iovec_fixlast(iovec_entries, iovector, last_ptr); |
| @@ -83,9 +83,8 @@ void *iovec_fix_increase_or_free(int *iovec_entries, struct iovec **iovector, vo | |||
| 83 | return new_data; | 83 | return new_data; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | size_t iovec_length(const int *iovec_entries, const struct iovec **iovector) { | 86 | size_t iovec_length(const size_t *iovec_entries, const struct iovec **iovector) { |
| 87 | size_t length = 0; | 87 | size_t i, length = 0; |
| 88 | int i; | ||
| 89 | for (i = 0; i < *iovec_entries; ++i) | 88 | for (i = 0; i < *iovec_entries; ++i) |
| 90 | length += ((*iovector)[i]).iov_len; | 89 | length += ((*iovector)[i]).iov_len; |
| 91 | return length; | 90 | return length; |
| @@ -8,13 +8,13 @@ | |||
| 8 | 8 | ||
| 9 | #include <sys/uio.h> | 9 | #include <sys/uio.h> |
| 10 | 10 | ||
| 11 | void *iovec_increase(int *iovec_entries, struct iovec **iovector, size_t new_alloc); | 11 | void *iovec_increase(size_t *iovec_entries, struct iovec **iovector, size_t new_alloc); |
| 12 | void *iovec_append(int *iovec_entries, struct iovec **iovector, struct iovec *append_iovector); | 12 | void *iovec_append(size_t *iovec_entries, struct iovec **iovector, struct iovec *append_iovector); |
| 13 | void iovec_fixlast(int *iovec_entries, struct iovec **iovector, void *last_ptr); | 13 | void iovec_fixlast(size_t *iovec_entries, struct iovec **iovector, void *last_ptr); |
| 14 | void iovec_free(int *iovec_entries, struct iovec **iovector); | 14 | void iovec_free(size_t *iovec_entries, struct iovec **iovector); |
| 15 | 15 | ||
| 16 | size_t iovec_length(const int *iovec_entries, const struct iovec **iovector); | 16 | size_t iovec_length(const size_t *iovec_entries, const struct iovec **iovector); |
| 17 | 17 | ||
| 18 | void *iovec_fix_increase_or_free(int *iovec_entries, struct iovec **iovector, void *last_ptr, size_t new_alloc); | 18 | void *iovec_fix_increase_or_free(size_t *iovec_entries, struct iovec **iovector, void *last_ptr, size_t new_alloc); |
| 19 | 19 | ||
| 20 | #endif | 20 | #endif |
diff --git a/ot_livesync.c b/ot_livesync.c index 269b8d8..f620592 100644 --- a/ot_livesync.c +++ b/ot_livesync.c | |||
| @@ -136,10 +136,18 @@ static void livesync_issue_peersync(sync_buffer *buf) { | |||
| 136 | static void livesync_handle_peersync(struct ot_workstruct *ws, size_t peer_size) { | 136 | static void livesync_handle_peersync(struct ot_workstruct *ws, size_t peer_size) { |
| 137 | size_t off = sizeof(g_tracker_id) + sizeof(uint32_t); | 137 | size_t off = sizeof(g_tracker_id) + sizeof(uint32_t); |
| 138 | 138 | ||
| 139 | /* Prepare peer record for v4mapped expansion */ | ||
| 140 | if (peer_size == OT_PEER_SIZE4) | ||
| 141 | memcpy(&ws->peer, V4mappedprefix, sizeof(V4mappedprefix)); | ||
| 142 | |||
| 139 | /* Now basic sanity checks have been done on the live sync packet | 143 | /* Now basic sanity checks have been done on the live sync packet |
| 140 | We might add more testing and logging. */ | 144 | We might add more testing and logging. */ |
| 141 | while ((ssize_t)(off + sizeof(ot_hash) + peer_size) <= ws->request_size) { | 145 | while ((ssize_t)(off + sizeof(ot_hash) + peer_size) <= ws->request_size) { |
| 142 | memcpy(&ws->peer, ws->request + off + sizeof(ot_hash), peer_size); | 146 | char *peer_ip = ws->request + off + sizeof(ot_hash); |
| 147 | if (peer_size == OT_PEER_SIZE4) | ||
| 148 | memcpy(&ws->peer[0] + sizeof(V4mappedprefix), peer_ip, peer_size); | ||
| 149 | else | ||
| 150 | memcpy(&ws->peer, peer_ip, peer_size); | ||
| 143 | ws->hash = (ot_hash *)(ws->request + off); | 151 | ws->hash = (ot_hash *)(ws->request + off); |
| 144 | 152 | ||
| 145 | if (!g_opentracker_running) | 153 | if (!g_opentracker_running) |
| @@ -48,7 +48,7 @@ void mutex_bucket_unlock_by_hash(ot_hash const hash, int delta_torrentcount) { | |||
| 48 | mutex_bucket_unlock(uint32_read_big((char *)hash) >> OT_BUCKET_COUNT_SHIFT, delta_torrentcount); | 48 | mutex_bucket_unlock(uint32_read_big((char *)hash) >> OT_BUCKET_COUNT_SHIFT, delta_torrentcount); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | size_t mutex_get_torrent_count() { return g_torrent_count; } | 51 | size_t mutex_get_torrent_count(void) { return g_torrent_count; } |
| 52 | 52 | ||
| 53 | /* TaskQueue Magic */ | 53 | /* TaskQueue Magic */ |
| 54 | 54 | ||
| @@ -56,7 +56,7 @@ struct ot_task { | |||
| 56 | ot_taskid taskid; | 56 | ot_taskid taskid; |
| 57 | ot_tasktype tasktype; | 57 | ot_tasktype tasktype; |
| 58 | int64 sock; | 58 | int64 sock; |
| 59 | int iovec_entries; | 59 | size_t iovec_entries; |
| 60 | struct iovec *iovec; | 60 | struct iovec *iovec; |
| 61 | struct ot_task *next; | 61 | struct ot_task *next; |
| 62 | }; | 62 | }; |
| @@ -105,7 +105,7 @@ void mutex_workqueue_canceltask(int64 sock) { | |||
| 105 | if ((*task)->sock == sock) { | 105 | if ((*task)->sock == sock) { |
| 106 | struct iovec *iovec = (*task)->iovec; | 106 | struct iovec *iovec = (*task)->iovec; |
| 107 | struct ot_task *ptask = *task; | 107 | struct ot_task *ptask = *task; |
| 108 | int i; | 108 | size_t i; |
| 109 | 109 | ||
| 110 | /* Free task's iovec */ | 110 | /* Free task's iovec */ |
| 111 | for (i = 0; i < (*task)->iovec_entries; ++i) | 111 | for (i = 0; i < (*task)->iovec_entries; ++i) |
| @@ -167,7 +167,7 @@ void mutex_workqueue_pushsuccess(ot_taskid taskid) { | |||
| 167 | pthread_mutex_unlock(&tasklist_mutex); | 167 | pthread_mutex_unlock(&tasklist_mutex); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | int mutex_workqueue_pushresult(ot_taskid taskid, int iovec_entries, struct iovec *iovec) { | 170 | int mutex_workqueue_pushresult(ot_taskid taskid, size_t iovec_entries, struct iovec *iovec) { |
| 171 | struct ot_task *task; | 171 | struct ot_task *task; |
| 172 | const char byte = 'o'; | 172 | const char byte = 'o'; |
| 173 | 173 | ||
| @@ -219,7 +219,7 @@ int mutex_workqueue_pushchunked(ot_taskid taskid, struct iovec *iovec) { | |||
| 219 | return task ? 0 : -1; | 219 | return task ? 0 : -1; |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | int64 mutex_workqueue_popresult(int *iovec_entries, struct iovec **iovec, int *is_partial) { | 222 | int64 mutex_workqueue_popresult(size_t *iovec_entries, struct iovec **iovec, int *is_partial) { |
| 223 | struct ot_task **task; | 223 | struct ot_task **task; |
| 224 | int64 sock = -1; | 224 | int64 sock = -1; |
| 225 | 225 | ||
| @@ -253,8 +253,8 @@ int64 mutex_workqueue_popresult(int *iovec_entries, struct iovec **iovec, int *i | |||
| 253 | return sock; | 253 | return sock; |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | void mutex_init() { | 256 | void mutex_init(void) { |
| 257 | int i; | 257 | size_t i; |
| 258 | pthread_mutex_init(&tasklist_mutex, NULL); | 258 | pthread_mutex_init(&tasklist_mutex, NULL); |
| 259 | pthread_cond_init(&tasklist_being_filled, NULL); | 259 | pthread_cond_init(&tasklist_being_filled, NULL); |
| 260 | for (i = 0; i < OT_BUCKET_COUNT; ++i) | 260 | for (i = 0; i < OT_BUCKET_COUNT; ++i) |
| @@ -262,8 +262,8 @@ void mutex_init() { | |||
| 262 | byte_zero(all_torrents, sizeof(all_torrents)); | 262 | byte_zero(all_torrents, sizeof(all_torrents)); |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | void mutex_deinit() { | 265 | void mutex_deinit(void) { |
| 266 | int i; | 266 | size_t i; |
| 267 | for (i = 0; i < OT_BUCKET_COUNT; ++i) | 267 | for (i = 0; i < OT_BUCKET_COUNT; ++i) |
| 268 | pthread_mutex_destroy(bucket_mutex + i); | 268 | pthread_mutex_destroy(bucket_mutex + i); |
| 269 | pthread_mutex_destroy(&tasklist_mutex); | 269 | pthread_mutex_destroy(&tasklist_mutex); |
| @@ -59,7 +59,8 @@ typedef enum { | |||
| 59 | 59 | ||
| 60 | TASK_FLAG_GZIP = 0x1000, | 60 | TASK_FLAG_GZIP = 0x1000, |
| 61 | TASK_FLAG_BZIP2 = 0x2000, | 61 | TASK_FLAG_BZIP2 = 0x2000, |
| 62 | TASK_FLAG_CHUNKED = 0x4000, | 62 | TASK_FLAG_ZSTD = 0x4000, |
| 63 | TASK_FLAG_CHUNKED = 0x8000, | ||
| 63 | 64 | ||
| 64 | TASK_TASK_MASK = 0x0fff, | 65 | TASK_TASK_MASK = 0x0fff, |
| 65 | TASK_CLASS_MASK = 0x0f00, | 66 | TASK_CLASS_MASK = 0x0f00, |
| @@ -72,8 +73,8 @@ int mutex_workqueue_pushtask(int64 sock, ot_tasktype tasktype) | |||
| 72 | void mutex_workqueue_canceltask(int64 sock); | 73 | void mutex_workqueue_canceltask(int64 sock); |
| 73 | void mutex_workqueue_pushsuccess(ot_taskid taskid); | 74 | void mutex_workqueue_pushsuccess(ot_taskid taskid); |
| 74 | ot_taskid mutex_workqueue_poptask(ot_tasktype *tasktype); | 75 | ot_taskid mutex_workqueue_poptask(ot_tasktype *tasktype); |
| 75 | int mutex_workqueue_pushresult(ot_taskid taskid, int iovec_entries, struct iovec *iovector); | 76 | int mutex_workqueue_pushresult(ot_taskid taskid, size_t iovec_entries, struct iovec *iovector); |
| 76 | int mutex_workqueue_pushchunked(ot_taskid taskid, struct iovec *iovec); | 77 | int mutex_workqueue_pushchunked(ot_taskid taskid, struct iovec *iovec); |
| 77 | int64 mutex_workqueue_popresult(int *iovec_entries, struct iovec **iovector, int *is_partial); | 78 | int64 mutex_workqueue_popresult(size_t *iovec_entries, struct iovec **iovector, int *is_partial); |
| 78 | 79 | ||
| 79 | #endif | 80 | #endif |
| @@ -38,7 +38,7 @@ | |||
| 38 | #endif | 38 | #endif |
| 39 | 39 | ||
| 40 | /* Forward declaration */ | 40 | /* Forward declaration */ |
| 41 | static void stats_make(int *iovec_entries, struct iovec **iovector, ot_tasktype mode); | 41 | static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_tasktype mode); |
| 42 | #define OT_STATS_TMPSIZE 8192 | 42 | #define OT_STATS_TMPSIZE 8192 |
| 43 | 43 | ||
| 44 | /* Clumsy counters... to be rethought */ | 44 | /* Clumsy counters... to be rethought */ |
| @@ -113,7 +113,7 @@ static int stat_increase_network_count(stats_network_node **pnode, int depth, ui | |||
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | static int stats_shift_down_network_count(stats_network_node **node, int depth, int shift) { | 115 | static int stats_shift_down_network_count(stats_network_node **node, int depth, int shift) { |
| 116 | int i, rest = 0; | 116 | size_t i, rest = 0; |
| 117 | 117 | ||
| 118 | if (!*node) | 118 | if (!*node) |
| 119 | return 0; | 119 | return 0; |
| @@ -134,8 +134,7 @@ static int stats_shift_down_network_count(stats_network_node **node, int depth, | |||
| 134 | 134 | ||
| 135 | static size_t stats_get_highscore_networks(stats_network_node *node, int depth, ot_ip6 node_value, size_t *scores, ot_ip6 *networks, int network_count, | 135 | static size_t stats_get_highscore_networks(stats_network_node *node, int depth, ot_ip6 node_value, size_t *scores, ot_ip6 *networks, int network_count, |
| 136 | int limit) { | 136 | int limit) { |
| 137 | size_t score = 0; | 137 | size_t i, score = 0; |
| 138 | int i; | ||
| 139 | 138 | ||
| 140 | if (!node) | 139 | if (!node) |
| 141 | return 0; | 140 | return 0; |
| @@ -191,11 +190,11 @@ static size_t stats_get_highscore_networks(stats_network_node *node, int depth, | |||
| 191 | return score; | 190 | return score; |
| 192 | } | 191 | } |
| 193 | 192 | ||
| 194 | static size_t stats_return_busy_networks(char *reply, stats_network_node *tree, int amount, int limit) { | 193 | static size_t stats_return_busy_networks(char *reply, stats_network_node *tree, size_t amount, int limit) { |
| 195 | ot_ip6 networks[amount]; | 194 | ot_ip6 networks[amount]; |
| 196 | ot_ip6 node_value; | 195 | ot_ip6 node_value; |
| 197 | size_t scores[amount]; | 196 | size_t scores[amount]; |
| 198 | int i; | 197 | size_t i; |
| 199 | char *r = reply; | 198 | char *r = reply; |
| 200 | 199 | ||
| 201 | memset(scores, 0, sizeof(scores)); | 200 | memset(scores, 0, sizeof(scores)); |
| @@ -205,14 +204,14 @@ static size_t stats_return_busy_networks(char *reply, stats_network_node *tree, | |||
| 205 | stats_get_highscore_networks(tree, 0, node_value, scores, networks, amount, limit); | 204 | stats_get_highscore_networks(tree, 0, node_value, scores, networks, amount, limit); |
| 206 | 205 | ||
| 207 | r += sprintf(r, "Networks, limit /%d:\n", limit + STATS_NETWORK_NODE_BITWIDTH); | 206 | r += sprintf(r, "Networks, limit /%d:\n", limit + STATS_NETWORK_NODE_BITWIDTH); |
| 208 | for (i = amount - 1; i >= 0; --i) { | 207 | for (i = amount; i > 0; --i) { |
| 209 | if (scores[i]) { | 208 | if (scores[i - 1]) { |
| 210 | r += sprintf(r, "%08zd: ", scores[i]); | 209 | r += sprintf(r, "%08zd: ", scores[i - 1]); |
| 211 | // #ifdef WANT_V6 | 210 | // #ifdef WANT_V6 |
| 212 | r += fmt_ip6c(r, networks[i]); | 211 | r += fmt_ip6c(r, networks[i - 1]); |
| 213 | #if 0 | 212 | #if 0 |
| 214 | // XXX | 213 | // XXX |
| 215 | r += fmt_ip4( r, networks[i]); | 214 | r += fmt_ip4( r, networks[i - 1]); |
| 216 | #endif | 215 | #endif |
| 217 | *r++ = '\n'; | 216 | *r++ = '\n'; |
| 218 | } | 217 | } |
| @@ -225,8 +224,7 @@ static size_t stats_return_busy_networks(char *reply, stats_network_node *tree, | |||
| 225 | static size_t stats_slash24s_txt(char *reply, size_t amount) { | 224 | static size_t stats_slash24s_txt(char *reply, size_t amount) { |
| 226 | stats_network_node *slash24s_network_counters_root = NULL; | 225 | stats_network_node *slash24s_network_counters_root = NULL; |
| 227 | char *r = reply; | 226 | char *r = reply; |
| 228 | int bucket; | 227 | size_t i, bucket, peer_size = OT_PEER_SIZE4; |
| 229 | size_t i, peer_size = OT_PEER_SIZE4; | ||
| 230 | 228 | ||
| 231 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { | 229 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { |
| 232 | ot_vector *torrents_list = mutex_bucket_lock(bucket); | 230 | ot_vector *torrents_list = mutex_bucket_lock(bucket); |
| @@ -317,55 +315,64 @@ typedef struct { | |||
| 317 | ot_hash hash; | 315 | ot_hash hash; |
| 318 | } ot_record; | 316 | } ot_record; |
| 319 | 317 | ||
| 318 | static inline void stats_insert_into_highscore(size_t val, ot_record* list, size_t amount, ot_hash* hash) { | ||
| 319 | size_t i; | ||
| 320 | for (i = 0; (i < amount) && (list[i].val > val); ++i) | ||
| 321 | {} | ||
| 322 | /* if we score better than a record in the list, we need to make room in the high | ||
| 323 | score array by moving lower scoring entries up */ | ||
| 324 | if (i < amount) { | ||
| 325 | memmove(list + i + 1, list + i, (amount - i - 1) * sizeof(ot_record)); | ||
| 326 | |||
| 327 | memcpy(&list[i].hash, hash, sizeof(ot_hash)); | ||
| 328 | list[i].val = val; | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | |||
| 320 | /* Fetches stats from tracker */ | 333 | /* Fetches stats from tracker */ |
| 321 | size_t stats_top_txt(char *reply, int amount) { | 334 | size_t stats_top_txt(char *reply, size_t amount) { |
| 322 | size_t j; | 335 | size_t j, idx, bucket; |
| 323 | ot_record top100s[100], top100c[100]; | 336 | ot_record top100s[100], top100c[100], top100l[100]; |
| 324 | char *r = reply, hex_out[42]; | 337 | char *r = reply, hex_out[42]; |
| 325 | int idx, bucket; | ||
| 326 | 338 | ||
| 327 | if (amount > 100) | 339 | if (amount > 100) |
| 328 | amount = 100; | 340 | amount = 100; |
| 329 | 341 | ||
| 330 | byte_zero(top100s, sizeof(top100s)); | 342 | byte_zero(top100s, sizeof(top100s)); |
| 331 | byte_zero(top100c, sizeof(top100c)); | 343 | byte_zero(top100c, sizeof(top100c)); |
| 344 | byte_zero(top100l, sizeof(top100l)); | ||
| 332 | 345 | ||
| 346 | /* Iterate over complete torrent list */ | ||
| 333 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { | 347 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { |
| 334 | ot_vector *torrents_list = mutex_bucket_lock(bucket); | 348 | ot_vector *torrents_list = mutex_bucket_lock(bucket); |
| 335 | for (j = 0; j < torrents_list->size; ++j) { | 349 | for (j = 0; j < torrents_list->size; ++j) { |
| 336 | ot_torrent *torrent = (ot_torrent *)(torrents_list->data) + j; | 350 | ot_torrent *torrent = (ot_torrent *)(torrents_list->data) + j; |
| 337 | size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; | 351 | size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; |
| 338 | size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; | 352 | size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; |
| 339 | idx = amount - 1; | 353 | size_t leech_count = peer_count - seed_count; |
| 340 | while ((idx >= 0) && (peer_count > top100c[idx].val)) | 354 | |
| 341 | --idx; | 355 | stats_insert_into_highscore(peer_count, top100c, amount, &torrent->hash); |
| 342 | if (idx++ != amount - 1) { | 356 | stats_insert_into_highscore(seed_count, top100s, amount, &torrent->hash); |
| 343 | memmove(top100c + idx + 1, top100c + idx, (amount - 1 - idx) * sizeof(ot_record)); | 357 | stats_insert_into_highscore(leech_count, top100l, amount, &torrent->hash); |
| 344 | memcpy(&top100c[idx].hash, &torrent->hash, sizeof(ot_hash)); | ||
| 345 | top100c[idx].val = peer_count; | ||
| 346 | } | ||
| 347 | idx = amount - 1; | ||
| 348 | while ((idx >= 0) && (seed_count > top100s[idx].val)) | ||
| 349 | --idx; | ||
| 350 | if (idx++ != amount - 1) { | ||
| 351 | memmove(top100s + idx + 1, top100s + idx, (amount - 1 - idx) * sizeof(ot_record)); | ||
| 352 | memcpy(&top100s[idx].hash, &torrent->hash, sizeof(ot_hash)); | ||
| 353 | top100s[idx].val = seed_count; | ||
| 354 | } | ||
| 355 | } | 358 | } |
| 356 | mutex_bucket_unlock(bucket, 0); | 359 | mutex_bucket_unlock(bucket, 0); |
| 357 | if (!g_opentracker_running) | 360 | if (!g_opentracker_running) |
| 358 | return 0; | 361 | return 0; |
| 359 | } | 362 | } |
| 360 | 363 | ||
| 361 | r += sprintf(r, "Top %d torrents by peers:\n", amount); | 364 | r += sprintf(r, "Top %zd torrents by peers:\n", amount); |
| 362 | for (idx = 0; idx < amount; ++idx) | 365 | for (idx = 0; idx < amount; ++idx) |
| 363 | if (top100c[idx].val) | 366 | if (top100c[idx].val) |
| 364 | r += sprintf(r, "\t%zd\t%s\n", top100c[idx].val, to_hex(hex_out, top100c[idx].hash)); | 367 | r += sprintf(r, "\t%zd\t%s\n", top100c[idx].val, to_hex(hex_out, top100c[idx].hash)); |
| 365 | r += sprintf(r, "Top %d torrents by seeds:\n", amount); | 368 | r += sprintf(r, "Top %zd torrents by seeds:\n", amount); |
| 366 | for (idx = 0; idx < amount; ++idx) | 369 | for (idx = 0; idx < amount; ++idx) |
| 367 | if (top100s[idx].val) | 370 | if (top100s[idx].val) |
| 368 | r += sprintf(r, "\t%zd\t%s\n", top100s[idx].val, to_hex(hex_out, top100s[idx].hash)); | 371 | r += sprintf(r, "\t%zd\t%s\n", top100s[idx].val, to_hex(hex_out, top100s[idx].hash)); |
| 372 | r += sprintf(r, "Top %zd torrents by leechers:\n", amount); | ||
| 373 | for (idx = 0; idx < amount; ++idx) | ||
| 374 | if (top100l[idx].val) | ||
| 375 | r += sprintf(r, "\t%zd\t%s\n", top100l[idx].val, to_hex(hex_out, top100l[idx].hash)); | ||
| 369 | 376 | ||
| 370 | return r - reply; | 377 | return r - reply; |
| 371 | } | 378 | } |
| @@ -463,7 +470,7 @@ static size_t stats_return_numwants(char *reply) { | |||
| 463 | #endif | 470 | #endif |
| 464 | 471 | ||
| 465 | #ifdef WANT_FULLLOG_NETWORKS | 472 | #ifdef WANT_FULLLOG_NETWORKS |
| 466 | static void stats_return_fulllog(int *iovec_entries, struct iovec **iovector, char *r) { | 473 | static void stats_return_fulllog(size_t *iovec_entries, struct iovec **iovector, char *r) { |
| 467 | ot_log *loglist = g_logchain_first, *llnext; | 474 | ot_log *loglist = g_logchain_first, *llnext; |
| 468 | char *re = r + OT_STATS_TMPSIZE; | 475 | char *re = r + OT_STATS_TMPSIZE; |
| 469 | 476 | ||
| @@ -577,7 +584,7 @@ size_t return_stats_for_tracker(char *reply, int mode, int format) { | |||
| 577 | } | 584 | } |
| 578 | } | 585 | } |
| 579 | 586 | ||
| 580 | static void stats_make(int *iovec_entries, struct iovec **iovector, ot_tasktype mode) { | 587 | static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_tasktype mode) { |
| 581 | char *r; | 588 | char *r; |
| 582 | 589 | ||
| 583 | *iovec_entries = 0; | 590 | *iovec_entries = 0; |
| @@ -734,7 +741,7 @@ void stats_issue_event(ot_status_event event, PROTO_FLAG proto, uintptr_t event_ | |||
| 734 | } | 741 | } |
| 735 | } | 742 | } |
| 736 | 743 | ||
| 737 | void stats_cleanup() { | 744 | void stats_cleanup(void) { |
| 738 | #ifdef WANT_SPOT_WOODPECKER | 745 | #ifdef WANT_SPOT_WOODPECKER |
| 739 | pthread_mutex_lock(&g_woodpeckers_mutex); | 746 | pthread_mutex_lock(&g_woodpeckers_mutex); |
| 740 | stats_shift_down_network_count(&stats_woodpeckers_tree, 0, 1); | 747 | stats_shift_down_network_count(&stats_woodpeckers_tree, 0, 1); |
| @@ -743,7 +750,7 @@ void stats_cleanup() { | |||
| 743 | } | 750 | } |
| 744 | 751 | ||
| 745 | static void *stats_worker(void *args) { | 752 | static void *stats_worker(void *args) { |
| 746 | int iovec_entries; | 753 | size_t iovec_entries; |
| 747 | struct iovec *iovector; | 754 | struct iovec *iovector; |
| 748 | 755 | ||
| 749 | (void)args; | 756 | (void)args; |
| @@ -761,11 +768,11 @@ static void *stats_worker(void *args) { | |||
| 761 | void stats_deliver(int64 sock, int tasktype) { mutex_workqueue_pushtask(sock, tasktype); } | 768 | void stats_deliver(int64 sock, int tasktype) { mutex_workqueue_pushtask(sock, tasktype); } |
| 762 | 769 | ||
| 763 | static pthread_t thread_id; | 770 | static pthread_t thread_id; |
| 764 | void stats_init() { | 771 | void stats_init(void) { |
| 765 | ot_start_time = g_now_seconds; | 772 | ot_start_time = g_now_seconds; |
| 766 | pthread_create(&thread_id, NULL, stats_worker, NULL); | 773 | pthread_create(&thread_id, NULL, stats_worker, NULL); |
| 767 | } | 774 | } |
| 768 | 775 | ||
| 769 | void stats_deinit() { | 776 | void stats_deinit(void) { |
| 770 | pthread_cancel(thread_id); | 777 | pthread_cancel(thread_id); |
| 771 | } | 778 | } |
| @@ -19,6 +19,7 @@ typedef enum { | |||
| 19 | EVENT_SCRAPE, | 19 | EVENT_SCRAPE, |
| 20 | EVENT_FULLSCRAPE_REQUEST, | 20 | EVENT_FULLSCRAPE_REQUEST, |
| 21 | EVENT_FULLSCRAPE_REQUEST_GZIP, | 21 | EVENT_FULLSCRAPE_REQUEST_GZIP, |
| 22 | EVENT_FULLSCRAPE_REQUEST_ZSTD, | ||
| 22 | EVENT_FULLSCRAPE, /* TCP only */ | 23 | EVENT_FULLSCRAPE, /* TCP only */ |
| 23 | EVENT_FAILED, | 24 | EVENT_FAILED, |
| 24 | EVENT_BUCKET_LOCKED, | 25 | EVENT_BUCKET_LOCKED, |
| @@ -72,9 +72,9 @@ int add_changeset_to_tracker(uint8_t *data, size_t len) { | |||
| 72 | /* Proposed output format | 72 | /* Proposed output format |
| 73 | d4:syncd20:<info_hash>8*N:(xxxxyyyy)*Nee | 73 | d4:syncd20:<info_hash>8*N:(xxxxyyyy)*Nee |
| 74 | */ | 74 | */ |
| 75 | static void sync_make(int *iovec_entries, struct iovec **iovector) { | 75 | static void sync_make(size_t *iovec_entries, struct iovec **iovector) { |
| 76 | int bucket; | 76 | size_t bucket; |
| 77 | char *r, *re; | 77 | char *r, *re; |
| 78 | 78 | ||
| 79 | /* Setup return vector... */ | 79 | /* Setup return vector... */ |
| 80 | *iovec_entries = 0; | 80 | *iovec_entries = 0; |
| @@ -140,7 +140,7 @@ static void sync_make(int *iovec_entries, struct iovec **iovector) { | |||
| 140 | It grabs tasks from mutex_tasklist and delivers results back | 140 | It grabs tasks from mutex_tasklist and delivers results back |
| 141 | */ | 141 | */ |
| 142 | static void *sync_worker(void *args) { | 142 | static void *sync_worker(void *args) { |
| 143 | int iovec_entries; | 143 | size_t iovec_entries; |
| 144 | struct iovec *iovector; | 144 | struct iovec *iovector; |
| 145 | 145 | ||
| 146 | args = args; | 146 | args = args; |
| @@ -25,10 +25,10 @@ | |||
| 25 | static const uint8_t g_static_connid[8] = { 0x23, 0x42, 0x05, 0x17, 0xde, 0x41, 0x50, 0xff }; | 25 | static const uint8_t g_static_connid[8] = { 0x23, 0x42, 0x05, 0x17, 0xde, 0x41, 0x50, 0xff }; |
| 26 | #endif | 26 | #endif |
| 27 | static uint32_t g_rijndael_round_key[44] = {0}; | 27 | static uint32_t g_rijndael_round_key[44] = {0}; |
| 28 | static uint32_t g_key_of_the_hour[2] = {0}; | 28 | static volatile uint32_t g_key_of_the_hour[2] = {0}; |
| 29 | static ot_time g_hour_of_the_key; | 29 | static volatile ot_time g_hour_of_the_key; |
| 30 | 30 | ||
| 31 | static void udp_generate_rijndael_round_key() { | 31 | static void udp_generate_rijndael_round_key(void) { |
| 32 | uint32_t key[16]; | 32 | uint32_t key[16]; |
| 33 | #ifdef WANT_ARC4RANDOM | 33 | #ifdef WANT_ARC4RANDOM |
| 34 | arc4random_buf(&key[0], sizeof(key)); | 34 | arc4random_buf(&key[0], sizeof(key)); |
| @@ -52,20 +52,30 @@ static void udp_generate_rijndael_round_key() { | |||
| 52 | static void udp_make_connectionid(uint32_t connid[2], const ot_ip6 remoteip, int age) { | 52 | static void udp_make_connectionid(uint32_t connid[2], const ot_ip6 remoteip, int age) { |
| 53 | uint32_t plain[4], crypt[4]; | 53 | uint32_t plain[4], crypt[4]; |
| 54 | int i; | 54 | int i; |
| 55 | if (g_now_minutes + 60 > g_hour_of_the_key) { | 55 | uint32_t current_key_of_the_hour; |
| 56 | g_hour_of_the_key = g_now_minutes; | 56 | |
| 57 | g_key_of_the_hour[1] = g_key_of_the_hour[0]; | 57 | if (g_now_minutes - g_hour_of_the_key >= 60) { |
| 58 | uint32_t old_key_of_the_hour = g_key_of_the_hour[0]; | ||
| 58 | #ifdef WANT_ARC4RANDOM | 59 | #ifdef WANT_ARC4RANDOM |
| 59 | g_key_of_the_hour[0] = arc4random(); | 60 | uint32_t new_key_of_the_hour = arc4random(); |
| 60 | #else | 61 | #else |
| 61 | g_key_of_the_hour[0] = random(); | 62 | uint32_t new_key_of_the_hour = random(); |
| 62 | #endif | 63 | #endif |
| 64 | /* If in the meantime another thread has performed | ||
| 65 | key rotation, do not overwrite their results */ | ||
| 66 | if (g_now_minutes - g_hour_of_the_key >= 60) { | ||
| 67 | /* Upgrade en bloc */ | ||
| 68 | g_hour_of_the_key = g_now_minutes; | ||
| 69 | g_key_of_the_hour[0] = new_key_of_the_hour; | ||
| 70 | g_key_of_the_hour[1] = old_key_of_the_hour; | ||
| 71 | } | ||
| 63 | } | 72 | } |
| 64 | 73 | ||
| 65 | memcpy(plain, remoteip, sizeof(plain)); | 74 | memcpy(plain, remoteip, sizeof(plain)); |
| 75 | current_key_of_the_hour = g_key_of_the_hour[age]; | ||
| 66 | for (i = 0; i < 4; ++i) | 76 | for (i = 0; i < 4; ++i) |
| 67 | plain[i] ^= g_key_of_the_hour[age]; | 77 | plain[i] ^= current_key_of_the_hour; |
| 68 | rijndaelEncrypt128(g_rijndael_round_key, (uint8_t *)remoteip, (uint8_t *)crypt); | 78 | rijndaelEncrypt128(g_rijndael_round_key, (uint8_t *)plain, (uint8_t *)crypt); |
| 69 | connid[0] = crypt[0] ^ crypt[1]; | 79 | connid[0] = crypt[0] ^ crypt[1]; |
| 70 | connid[1] = crypt[2] ^ crypt[3]; | 80 | connid[1] = crypt[2] ^ crypt[3]; |
| 71 | } | 81 | } |
diff --git a/ot_vector.c b/ot_vector.c index 2bc07b5..d068999 100644 --- a/ot_vector.c +++ b/ot_vector.c | |||
| @@ -45,7 +45,7 @@ void *binary_search(const void *const key, const void *base, const size_t member | |||
| 45 | return (void *)base; | 45 | return (void *)base; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static uint8_t vector_hash_peer(ot_peer const *peer, size_t compare_size, int bucket_count) { | 48 | static uint8_t vector_hash_peer(ot_peer const *peer, size_t compare_size, size_t bucket_count) { |
| 49 | unsigned int hash = 5381; | 49 | unsigned int hash = 5381; |
| 50 | uint8_t *p = (uint8_t *)peer; | 50 | uint8_t *p = (uint8_t *)peer; |
| 51 | while (compare_size--) | 51 | while (compare_size--) |
| @@ -67,12 +67,15 @@ void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, si | |||
| 67 | return match; | 67 | return match; |
| 68 | 68 | ||
| 69 | if (vector->size + 1 > vector->space) { | 69 | if (vector->size + 1 > vector->space) { |
| 70 | size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS; | 70 | size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS; |
| 71 | uint8_t *new_data = realloc(vector->data, new_space * member_size); | 71 | ptrdiff_t match_off = match - (uint8_t *)vector->data; |
| 72 | uint8_t *new_data = realloc(vector->data, new_space * member_size); | ||
| 73 | |||
| 72 | if (!new_data) | 74 | if (!new_data) |
| 73 | return NULL; | 75 | return NULL; |
| 76 | |||
| 74 | /* Adjust pointer if it moved by realloc */ | 77 | /* Adjust pointer if it moved by realloc */ |
| 75 | match = new_data + (match - (uint8_t *)vector->data); | 78 | match = new_data + match_off; |
| 76 | 79 | ||
| 77 | vector->data = new_data; | 80 | vector->data = new_data; |
| 78 | vector->space = new_space; | 81 | vector->space = new_space; |
| @@ -169,7 +172,7 @@ void vector_remove_torrent(ot_vector *vector, ot_torrent *match) { | |||
| 169 | } | 172 | } |
| 170 | } | 173 | } |
| 171 | 174 | ||
| 172 | void vector_clean_list(ot_vector *vector, int num_buckets) { | 175 | void vector_clean_list(ot_vector *vector, size_t num_buckets) { |
| 173 | while (num_buckets--) | 176 | while (num_buckets--) |
| 174 | free(vector[num_buckets].data); | 177 | free(vector[num_buckets].data); |
| 175 | free(vector); | 178 | free(vector); |
| @@ -177,7 +180,7 @@ void vector_clean_list(ot_vector *vector, int num_buckets) { | |||
| 177 | } | 180 | } |
| 178 | 181 | ||
| 179 | void vector_redistribute_buckets(ot_peerlist *peer_list, size_t peer_size) { | 182 | void vector_redistribute_buckets(ot_peerlist *peer_list, size_t peer_size) { |
| 180 | int tmp, bucket, bucket_size_new, num_buckets_new, num_buckets_old = 1; | 183 | size_t tmp, bucket, bucket_size_new, num_buckets_new, num_buckets_old = 1; |
| 181 | ot_vector *bucket_list_new, *bucket_list_old = &peer_list->peers; | 184 | ot_vector *bucket_list_new, *bucket_list_old = &peer_list->peers; |
| 182 | int (*sort_func)(const void *, const void *) = peer_size == OT_PEER_SIZE6 ? &vector_compare_peer6 : &vector_compare_peer4; | 185 | int (*sort_func)(const void *, const void *) = peer_size == OT_PEER_SIZE6 ? &vector_compare_peer6 : &vector_compare_peer4; |
| 183 | 186 | ||
| @@ -226,7 +229,7 @@ void vector_redistribute_buckets(ot_peerlist *peer_list, size_t peer_size) { | |||
| 226 | /* Now sort them into the correct bucket */ | 229 | /* Now sort them into the correct bucket */ |
| 227 | for (bucket = 0; bucket < num_buckets_old; ++bucket) { | 230 | for (bucket = 0; bucket < num_buckets_old; ++bucket) { |
| 228 | ot_peer *peers_old = bucket_list_old[bucket].data; | 231 | ot_peer *peers_old = bucket_list_old[bucket].data; |
| 229 | int peer_count_old = bucket_list_old[bucket].size; | 232 | size_t peer_count_old = bucket_list_old[bucket].size; |
| 230 | while (peer_count_old--) { | 233 | while (peer_count_old--) { |
| 231 | ot_vector *bucket_dest = bucket_list_new; | 234 | ot_vector *bucket_dest = bucket_list_new; |
| 232 | if (num_buckets_new > 1) | 235 | if (num_buckets_new > 1) |
diff --git a/ot_vector.h b/ot_vector.h index 8d41452..2618363 100644 --- a/ot_vector.h +++ b/ot_vector.h | |||
| @@ -31,6 +31,6 @@ void vector_remove_torrent(ot_vector *vector, ot_torrent *match); | |||
| 31 | /* For ot_clean.c */ | 31 | /* For ot_clean.c */ |
| 32 | void vector_redistribute_buckets(ot_peerlist *peer_list, size_t peer_size); | 32 | void vector_redistribute_buckets(ot_peerlist *peer_list, size_t peer_size); |
| 33 | void vector_fixup_peers(ot_vector *vector, size_t peer_size); | 33 | void vector_fixup_peers(ot_vector *vector, size_t peer_size); |
| 34 | void vector_clean_list(ot_vector *vector, int num_buckets); | 34 | void vector_clean_list(ot_vector *vector, size_t num_buckets); |
| 35 | 35 | ||
| 36 | #endif | 36 | #endif |
| @@ -276,12 +276,12 @@ void reset_info_block(proxy_peer *peer) { | |||
| 276 | * Multiple connections to/from the same ip are okay, if tracker_id doesn't match | 276 | * Multiple connections to/from the same ip are okay, if tracker_id doesn't match |
| 277 | * Reconnect attempts occur only twice a minute | 277 | * Reconnect attempts occur only twice a minute |
| 278 | */ | 278 | */ |
| 279 | static int g_connection_count; | 279 | static size_t g_connection_count; |
| 280 | static ot_time g_connection_reconn; | 280 | static ot_time g_connection_reconn; |
| 281 | static proxy_peer g_connections[MAX_PEERS]; | 281 | static proxy_peer g_connections[MAX_PEERS]; |
| 282 | 282 | ||
| 283 | static void handle_reconnects(void) { | 283 | static void handle_reconnects(void) { |
| 284 | int i; | 284 | size_t i; |
| 285 | for (i = 0; i < g_connection_count; ++i) | 285 | for (i = 0; i < g_connection_count; ++i) |
| 286 | if (PROXYPEER_NEEDSCONNECT(g_connections[i].state)) { | 286 | if (PROXYPEER_NEEDSCONNECT(g_connections[i].state)) { |
| 287 | int64 newfd = socket_tcp6(); | 287 | int64 newfd = socket_tcp6(); |
| @@ -625,7 +625,7 @@ int main(int argc, char **argv) { | |||
| 625 | static void *streamsync_worker(void *args) { | 625 | static void *streamsync_worker(void *args) { |
| 626 | (void)args; | 626 | (void)args; |
| 627 | while (1) { | 627 | while (1) { |
| 628 | int bucket; | 628 | size_t bucket; |
| 629 | /* For each bucket... */ | 629 | /* For each bucket... */ |
| 630 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { | 630 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { |
| 631 | /* Get exclusive access to that bucket */ | 631 | /* Get exclusive access to that bucket */ |
diff --git a/trackerlogic.c b/trackerlogic.c index 04df544..cacb12b 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
| @@ -195,7 +195,7 @@ size_t add_peer_to_torrent_and_return_peers(PROTO_FLAG proto, struct ot_workstru | |||
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | static size_t return_peers_all(ot_peerlist *peer_list, size_t peer_size, char *reply) { | 197 | static size_t return_peers_all(ot_peerlist *peer_list, size_t peer_size, char *reply) { |
| 198 | unsigned int bucket, num_buckets = 1; | 198 | size_t bucket, num_buckets = 1; |
| 199 | ot_vector *bucket_list = &peer_list->peers; | 199 | ot_vector *bucket_list = &peer_list->peers; |
| 200 | size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); | 200 | size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); |
| 201 | size_t result = compare_size * peer_list->peer_count; | 201 | size_t result = compare_size * peer_list->peer_count; |
| @@ -224,7 +224,7 @@ static size_t return_peers_all(ot_peerlist *peer_list, size_t peer_size, char *r | |||
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | static size_t return_peers_selection(struct ot_workstruct *ws, ot_peerlist *peer_list, size_t peer_size, size_t amount, char *reply) { | 226 | static size_t return_peers_selection(struct ot_workstruct *ws, ot_peerlist *peer_list, size_t peer_size, size_t amount, char *reply) { |
| 227 | unsigned int bucket_offset, bucket_index = 0, num_buckets = 1; | 227 | size_t bucket_offset, bucket_index = 0, num_buckets = 1; |
| 228 | ot_vector *bucket_list = &peer_list->peers; | 228 | ot_vector *bucket_list = &peer_list->peers; |
| 229 | unsigned int shifted_pc = peer_list->peer_count; | 229 | unsigned int shifted_pc = peer_list->peer_count; |
| 230 | unsigned int shifted_step = 0; | 230 | unsigned int shifted_step = 0; |
| @@ -262,7 +262,7 @@ static size_t return_peers_selection(struct ot_workstruct *ws, ot_peerlist *peer | |||
| 262 | bucket_offset -= bucket_list[bucket_index].size; | 262 | bucket_offset -= bucket_list[bucket_index].size; |
| 263 | bucket_index = (bucket_index + 1) % num_buckets; | 263 | bucket_index = (bucket_index + 1) % num_buckets; |
| 264 | } | 264 | } |
| 265 | peer = bucket_list[bucket_index].data + peer_size * bucket_offset; | 265 | peer = (ot_peer*)bucket_list[bucket_index].data + peer_size * bucket_offset; |
| 266 | if (OT_PEERFLAG_D(peer, peer_size) & PEER_FLAG_SEEDING) { | 266 | if (OT_PEERFLAG_D(peer, peer_size) & PEER_FLAG_SEEDING) { |
| 267 | r_end -= compare_size; | 267 | r_end -= compare_size; |
| 268 | memcpy(r_end, peer, compare_size); | 268 | memcpy(r_end, peer, compare_size); |
| @@ -403,9 +403,10 @@ size_t return_udp_scrape_for_torrent(ot_hash const hash, char *reply) { | |||
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | /* Fetches scrape info for a specific torrent */ | 405 | /* Fetches scrape info for a specific torrent */ |
| 406 | size_t return_tcp_scrape_for_torrent(ot_hash const *hash_list, int amount, char *reply) { | 406 | size_t return_tcp_scrape_for_torrent(ot_hash const *hash_list, size_t amount, char *reply) { |
| 407 | char *r = reply; | 407 | char *r = reply; |
| 408 | int exactmatch, i; | 408 | int exactmatch; |
| 409 | size_t i; | ||
| 409 | 410 | ||
| 410 | r += sprintf(r, "d5:filesd"); | 411 | r += sprintf(r, "d5:filesd"); |
| 411 | 412 | ||
| @@ -489,8 +490,7 @@ size_t remove_peer_from_torrent(PROTO_FLAG proto, struct ot_workstruct *ws) { | |||
| 489 | } | 490 | } |
| 490 | 491 | ||
| 491 | void iterate_all_torrents(int (*for_each)(ot_torrent *torrent, uintptr_t data), uintptr_t data) { | 492 | void iterate_all_torrents(int (*for_each)(ot_torrent *torrent, uintptr_t data), uintptr_t data) { |
| 492 | int bucket; | 493 | size_t bucket, j; |
| 493 | size_t j; | ||
| 494 | 494 | ||
| 495 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { | 495 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { |
| 496 | ot_vector *torrents_list = mutex_bucket_lock(bucket); | 496 | ot_vector *torrents_list = mutex_bucket_lock(bucket); |
| @@ -552,7 +552,7 @@ void exerr(char *message) { | |||
| 552 | exit(111); | 552 | exit(111); |
| 553 | } | 553 | } |
| 554 | 554 | ||
| 555 | void trackerlogic_init() { | 555 | void trackerlogic_init(void) { |
| 556 | g_tracker_id = random(); | 556 | g_tracker_id = random(); |
| 557 | 557 | ||
| 558 | if (!g_stats_path) | 558 | if (!g_stats_path) |
| @@ -569,8 +569,8 @@ void trackerlogic_init() { | |||
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | void trackerlogic_deinit(void) { | 571 | void trackerlogic_deinit(void) { |
| 572 | int bucket, delta_torrentcount = 0; | 572 | int delta_torrentcount = 0; |
| 573 | size_t j; | 573 | size_t bucket, j; |
| 574 | 574 | ||
| 575 | /* Free all torrents... */ | 575 | /* Free all torrents... */ |
| 576 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { | 576 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { |
diff --git a/trackerlogic.h b/trackerlogic.h index 022184d..88d9a11 100644 --- a/trackerlogic.h +++ b/trackerlogic.h | |||
| @@ -194,7 +194,7 @@ void exerr(char *message); | |||
| 194 | otherwise it is released in return_peers_for_torrent */ | 194 | otherwise it is released in return_peers_for_torrent */ |
| 195 | size_t add_peer_to_torrent_and_return_peers(PROTO_FLAG proto, struct ot_workstruct *ws, size_t amount); | 195 | size_t add_peer_to_torrent_and_return_peers(PROTO_FLAG proto, struct ot_workstruct *ws, size_t amount); |
| 196 | size_t remove_peer_from_torrent(PROTO_FLAG proto, struct ot_workstruct *ws); | 196 | size_t remove_peer_from_torrent(PROTO_FLAG proto, struct ot_workstruct *ws); |
| 197 | size_t return_tcp_scrape_for_torrent(ot_hash const *hash_list, int amount, char *reply); | 197 | size_t return_tcp_scrape_for_torrent(ot_hash const *hash_list, size_t amount, char *reply); |
| 198 | size_t return_udp_scrape_for_torrent(ot_hash const hash, char *reply); | 198 | size_t return_udp_scrape_for_torrent(ot_hash const hash, char *reply); |
| 199 | void add_torrent_from_saved_state(ot_hash const hash, ot_time base, size_t down_count); | 199 | void add_torrent_from_saved_state(ot_hash const hash, ot_time base, size_t down_count); |
| 200 | #ifdef _DEBUG_RANDOMTORRENTS | 200 | #ifdef _DEBUG_RANDOMTORRENTS |
