diff options
-rw-r--r-- | Makefile | 26 | ||||
-rw-r--r-- | Makefile.arc4random | 3 | ||||
-rw-r--r-- | Makefile.gzip | 4 | ||||
-rw-r--r-- | Makefile.zstd | 3 | ||||
-rw-r--r-- | man1/opentracker.1 | 142 | ||||
-rw-r--r-- | man4/opentracker.conf.4 | 86 | ||||
-rw-r--r-- | opentracker.c | 5 | ||||
-rw-r--r-- | opentracker.conf.sample | 5 | ||||
-rw-r--r-- | ot_accesslist.c | 2 | ||||
-rw-r--r-- | ot_clean.c | 2 | ||||
-rw-r--r-- | ot_fullscrape.c | 151 | ||||
-rw-r--r-- | ot_http.c | 43 | ||||
-rw-r--r-- | ot_http.h | 5 | ||||
-rw-r--r-- | ot_iovec.c | 2 | ||||
-rw-r--r-- | ot_livesync.c | 1 | ||||
-rw-r--r-- | ot_mutex.c | 2 | ||||
-rw-r--r-- | ot_mutex.h | 3 | ||||
-rw-r--r-- | ot_rijndael.c | 2 | ||||
-rw-r--r-- | ot_stats.c | 50 | ||||
-rw-r--r-- | ot_stats.h | 4 | ||||
-rw-r--r-- | ot_sync.c | 2 | ||||
-rw-r--r-- | ot_udp.c | 2 | ||||
-rw-r--r-- | ot_vector.c | 2 | ||||
-rw-r--r-- | scan_urlencoded_query.c | 2 | ||||
-rw-r--r-- | trackerlogic.c | 2 |
25 files changed, 470 insertions, 81 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,18 +52,19 @@ 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 |
51 | 60 | ||
61 | GIT_VERSION=$(shell sh -c 'command -v git >/dev/null && test -d .git && git rev-parse HEAD || echo _git_or_commit_not_found_') | ||
62 | |||
52 | OPTS_debug=-D_DEBUG -g -ggdb # -pg -fprofile-arcs -ftest-coverage | 63 | OPTS_debug=-D_DEBUG -g -ggdb # -pg -fprofile-arcs -ftest-coverage |
53 | OPTS_production=-O3 | 64 | OPTS_production=-O3 |
54 | 65 | ||
55 | CFLAGS+=-I$(LIBOWFAT_HEADERS) -Wall -pipe -pthread -Wextra #-ansi -pedantic | 66 | CFLAGS+=-I$(LIBOWFAT_HEADERS) -DGIT_VERSION=$(GIT_VERSION) -Wall -pipe -pthread -Wextra #-ansi -pedantic |
56 | LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread -lz | 67 | LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread |
57 | #LDFLAGS+=-lbsd | ||
58 | 68 | ||
59 | BINARY =opentracker | 69 | BINARY =opentracker |
60 | 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..85ded7b --- /dev/null +++ b/man1/opentracker.1 | |||
@@ -0,0 +1,142 @@ | |||
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 | |||
24 | When invoked with parameters, it binds to TCP and UDP port 6969 on all | ||
25 | interfaces. The recommended way to configure opentracker is by providing a | ||
26 | config file using the | ||
27 | .Op Fl f Ar config | ||
28 | option. See | ||
29 | .Xr opentracker.conf 4 | ||
30 | for details. | ||
31 | .Pp | ||
32 | |||
33 | .Sh OPTIONS | ||
34 | The following options are available: | ||
35 | |||
36 | .Bl -tag -width -indent=8 | ||
37 | .It Fl f Ar config | ||
38 | Parse a config file with a list of options. Consecutive command options | ||
39 | will override options from the config file. See | ||
40 | .Xr opentracker.conf 4 | ||
41 | for details. | ||
42 | |||
43 | .It Fl i Ar ip-select | ||
44 | Select an ip address that will be used with the next | ||
45 | .Op Fl p | ||
46 | or | ||
47 | .Op Fl P | ||
48 | command to actually bind to this address. Setting this option without any bind | ||
49 | options in the config file or | ||
50 | .Op Fl p | ||
51 | or | ||
52 | .Op Fl P | ||
53 | commands will limit opentracker to only bind to this address. | ||
54 | .It Fl p Ar port-bind-tcp | ||
55 | Bind to the TCP port on the last preceding ip address set with the | ||
56 | .Op Fl i ip-select | ||
57 | option or to all available addresses if none has been set. Can be given multiple | ||
58 | times. | ||
59 | .It Fl P Ar port-bind-udp | ||
60 | Bind to the UDP port on the last preceding ip address set with the | ||
61 | .Op Fl i ip-select | ||
62 | option or to all available addresses if none has been set. Can be given multiple | ||
63 | times. | ||
64 | .It Fl A Ar blessed-ip | ||
65 | Set an ip address in IPv4 or IPv6 or a net in CIDR notation to bless the network | ||
66 | for access to restricted resources. | ||
67 | .It Fl r Ar redirect-url | ||
68 | Set the URL that | ||
69 | .Nm | ||
70 | will redirect users to when the / address is requested via HTTP. | ||
71 | .It Fl d Ar chdir | ||
72 | Sets the directory | ||
73 | .Nm | ||
74 | will | ||
75 | .Xr chroot 2 | ||
76 | to if ran as root or | ||
77 | .Xr chdir 2 | ||
78 | to if ran as unprivileged user. Note that any accesslist files need to be | ||
79 | relative to and within that directory. | ||
80 | .It Fl u Ar user | ||
81 | User to run | ||
82 | .Nm | ||
83 | under after all operations that need privileges have finished. | ||
84 | .It Fl w Ar accesslist | Fl b Ar accesslist | ||
85 | If | ||
86 | .Nm | ||
87 | has been compiled with the | ||
88 | .B WANT_ACCESSLIST_BLACK | ||
89 | or | ||
90 | .Br WANT_ACCESSLIST_WHITE | ||
91 | options, this option sets the location of the accesslist. | ||
92 | .El | ||
93 | |||
94 | .Sh EXAMPLES | ||
95 | |||
96 | Start | ||
97 | .Nm | ||
98 | bound on UDP and TCP ports 6969 on IPv6 localhost. | ||
99 | |||
100 | .Dl # ./opentracker -i ::1 -p 6969 -P 6969 | ||
101 | |||
102 | .Pp | ||
103 | Start | ||
104 | .Nm | ||
105 | bound on UDP port 6868 and TCP port 6868 on IPv4 localhost and allow | ||
106 | privileged access from the network 192.168/16 while redirecting | ||
107 | HTTP clients accessing the root directory, which is not covered by the | ||
108 | bittorrent tracker protocol, to https://my-trackersite.com/. | ||
109 | |||
110 | .Dl # ./opentracker -i 192.168.0.4 -p 6868 -P 6969 -A 192.168/16 -r https://my-trackersite.com/ | ||
111 | |||
112 | The announce URLs are http://192.168.0.4:6868/announce and | ||
113 | udp://192.168.0.4:6868/announce respectively. | ||
114 | |||
115 | .Sh FILES | ||
116 | .Bl -tag -width indent | ||
117 | .It Pa opentracker.conf | ||
118 | The | ||
119 | .Nm | ||
120 | config file. | ||
121 | .El | ||
122 | .Sh SEE ALSO | ||
123 | .Xr opentracker.conf 4 | ||
124 | .Pp | ||
125 | opentracker documentation | ||
126 | .Lk https://erdgeist.org/arts/software/opentracker | ||
127 | .Pp | ||
128 | Bittorrent tracker protocol | ||
129 | .Lk http://www.bittorrent.org/beps/bep_0015.html | ||
130 | .Sh | ||
131 | .Sh AUTHOR | ||
132 | .An Dirk Engling | ||
133 | .Aq Mt erdgeist@erdgeist.org . | ||
134 | .Sh LICENSE | ||
135 | This software is released under the Beerware License: | ||
136 | |||
137 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software | ||
138 | and associated documentation files (the "Software"), to deal in the Software with the following | ||
139 | terms and conditions: | ||
140 | |||
141 | If you meet the author(s) someday, and you think this software is worth it, you can buy them | ||
142 | a beer in return. | ||
diff --git a/man4/opentracker.conf.4 b/man4/opentracker.conf.4 new file mode 100644 index 0000000..b4f5f51 --- /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 | |||
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 | |||
22 | .It listen.tcp Ar address | ||
23 | Specifies the address opentracker will listen on for TCP connections. Can be added more than once. | ||
24 | |||
25 | .It listen.udp Ar address | ||
26 | Specifies the address opentracker will listen on for UDP connections. Can be added more than once. | ||
27 | |||
28 | .It listen.udp.workers Ar threads | ||
29 | Specifies how many threads will be spawned to handle UDP connections. Defaults to 4. | ||
30 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
58 | .It batchsync.cluster.admin_ip Ar ip_address | ||
59 | Specifies the admin IP address for old-style (HTTP-based) asynchronous tracker syncing. | ||
60 | |||
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 | |||
64 | .It tracker.user Ar username | ||
65 | Specifies the user opentracker will setuid to after binding to potentially privileged ports. | ||
66 | |||
67 | .It tracker.redirect_url Ar URL | ||
68 | Specifies the URL opentracker will redirect to in response to a "GET / HTTP" request. | ||
69 | |||
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 | |||
80 | .Sh SEE ALSO | ||
81 | .Xr opentracker 1 | ||
82 | |||
83 | .Sh AUTHOR | ||
84 | .An Dirk Engling | ||
85 | .Aq Mt erdgeist@erdgeist.org | ||
86 | |||
diff --git a/opentracker.c b/opentracker.c index 01cb501..14e9989 100644 --- a/opentracker.c +++ b/opentracker.c | |||
@@ -761,6 +761,8 @@ int main(int argc, char **argv) { | |||
761 | ot_try_bind(serverip, 6969, FLAG_UDP); | 761 | ot_try_bind(serverip, 6969, FLAG_UDP); |
762 | } | 762 | } |
763 | 763 | ||
764 | defaul_signal_handlers(); | ||
765 | |||
764 | #ifdef WANT_SYSLOGS | 766 | #ifdef WANT_SYSLOGS |
765 | openlog("opentracker", 0, LOG_USER); | 767 | openlog("opentracker", 0, LOG_USER); |
766 | setlogmask(LOG_UPTO(LOG_INFO)); | 768 | setlogmask(LOG_UPTO(LOG_INFO)); |
@@ -783,7 +785,6 @@ int main(int argc, char **argv) { | |||
783 | io_setcookie(g_self_pipe[0], (void *)FLAG_SELFPIPE); | 785 | io_setcookie(g_self_pipe[0], (void *)FLAG_SELFPIPE); |
784 | io_wantread(g_self_pipe[0]); | 786 | io_wantread(g_self_pipe[0]); |
785 | 787 | ||
786 | defaul_signal_handlers(); | ||
787 | /* Init all sub systems. This call may fail with an exit() */ | 788 | /* Init all sub systems. This call may fail with an exit() */ |
788 | trackerlogic_init(); | 789 | trackerlogic_init(); |
789 | 790 | ||
@@ -805,5 +806,3 @@ int main(int argc, char **argv) { | |||
805 | 806 | ||
806 | return 0; | 807 | return 0; |
807 | } | 808 | } |
808 | |||
809 | const char *g_version_opentracker_c = "$Source$: $Revision$\n"; | ||
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 c26e14a..4b88c40 100644 --- a/ot_accesslist.c +++ b/ot_accesslist.c | |||
@@ -559,5 +559,3 @@ int accesslist_is_blessed(ot_ip6 ip, ot_permissions permissions) { | |||
559 | return 1; | 559 | return 1; |
560 | return 0; | 560 | return 0; |
561 | } | 561 | } |
562 | |||
563 | const char *g_version_accesslist_c = "$Source$: $Revision$\n"; | ||
@@ -142,5 +142,3 @@ static pthread_t thread_id; | |||
142 | void clean_init(void) { pthread_create(&thread_id, NULL, clean_worker, NULL); } | 142 | void clean_init(void) { pthread_create(&thread_id, NULL, clean_worker, NULL); } |
143 | 143 | ||
144 | void clean_deinit(void) { pthread_cancel(thread_id); } | 144 | void clean_deinit(void) { pthread_cancel(thread_id); } |
145 | |||
146 | const char *g_version_clean_c = "$Source$: $Revision$\n"; | ||
diff --git a/ot_fullscrape.c b/ot_fullscrape.c index d299ed9..6fd6d1c 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); |
@@ -205,7 +217,6 @@ static void fullscrape_make_gzip(int taskid, ot_tasktype mode) { | |||
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,6 +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 |
316 | const char *g_version_fullscrape_c = "$Source$: $Revision$\n"; | ||
@@ -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> |
@@ -159,17 +159,19 @@ ssize_t http_sendiovecdata(const int64 sock, struct ot_workstruct *ws, int iovec | |||
159 | 159 | ||
160 | if (iovec_entries) { | 160 | if (iovec_entries) { |
161 | 161 | ||
162 | if (cookie->flag & STRUCT_HTTP_FLAG_GZIP) | 162 | if (cookie->flag & STRUCT_HTTP_FLAG_ZSTD) |
163 | encoding = "Content-Encoding: zstd\r\n"; | ||
164 | else if (cookie->flag & STRUCT_HTTP_FLAG_GZIP) | ||
163 | encoding = "Content-Encoding: gzip\r\n"; | 165 | encoding = "Content-Encoding: gzip\r\n"; |
164 | else if (cookie->flag & STRUCT_HTTP_FLAG_BZIP2) | 166 | else if (cookie->flag & STRUCT_HTTP_FLAG_BZIP2) |
165 | encoding = "Content-Encoding: bzip2\r\n"; | 167 | encoding = "Content-Encoding: bzip2\r\n"; |
166 | 168 | ||
167 | if (!(cookie->flag & STRUCT_HTTP_FLAG_CHUNKED)) | 169 | if (!(cookie->flag & STRUCT_HTTP_FLAG_CHUNKED)) |
168 | header_size = asprintf(&header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n%sContent-Length: %zd\r\n\r\n", encoding, size); | 170 | header_size = asprintf(&header, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n%sContent-Length: %zd\r\n\r\n", encoding, size); |
169 | else { | 171 | else { |
170 | if (!(cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)) { | 172 | if (!(cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)) { |
171 | header_size = | 173 | header_size = |
172 | asprintf(&header, "HTTP/1.0 200 OK\r\nContent-Type: application/octet-stream\r\n%sTransfer-Encoding: chunked\r\n\r\n%zx\r\n", encoding, size); | 174 | asprintf(&header, "HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\n%sTransfer-Encoding: chunked\r\n\r\n%zx\r\n", encoding, size); |
173 | cookie->flag |= STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER; | 175 | cookie->flag |= STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER; |
174 | } else | 176 | } else |
175 | header_size = asprintf(&header, "%zx\r\n", size); | 177 | header_size = asprintf(&header, "%zx\r\n", size); |
@@ -369,19 +371,34 @@ static ssize_t http_handle_fullscrape(const int64 sock, struct ot_workstruct *ws | |||
369 | } | 371 | } |
370 | #endif | 372 | #endif |
371 | 373 | ||
372 | #ifdef WANT_COMPRESSION_GZIP | 374 | |
375 | #if defined(WANT_COMPRESSION_GZIP) || defined(WANT_COMPRESSION_ZSTD) | ||
373 | ws->request[ws->request_size - 1] = 0; | 376 | ws->request[ws->request_size - 1] = 0; |
374 | #ifndef WANT_COMPRESSION_GZIP_ALWAYS | 377 | #ifdef WANT_COMPRESSION_GZIP |
375 | if (strstr(ws->request, "gzip")) { | 378 | if (strstr(ws->request, "gzip")) { |
376 | #endif | ||
377 | cookie->flag |= STRUCT_HTTP_FLAG_GZIP; | 379 | cookie->flag |= STRUCT_HTTP_FLAG_GZIP; |
378 | format = TASK_FLAG_GZIP; | 380 | format |= TASK_FLAG_GZIP; |
379 | stats_issue_event(EVENT_FULLSCRAPE_REQUEST_GZIP, 0, (uintptr_t)cookie->ip); | 381 | } |
380 | #ifndef WANT_COMPRESSION_GZIP_ALWAYS | ||
381 | } else | ||
382 | #endif | 382 | #endif |
383 | #ifdef WANT_COMPRESSION_ZSTD | ||
384 | if (strstr(ws->request, "zstd")) { | ||
385 | cookie->flag |= STRUCT_HTTP_FLAG_ZSTD; | ||
386 | format |= TASK_FLAG_ZSTD; | ||
387 | } | ||
383 | #endif | 388 | #endif |
384 | stats_issue_event(EVENT_FULLSCRAPE_REQUEST, 0, (uintptr_t)cookie->ip); | 389 | |
390 | #if defined(WANT_COMPRESSION_ZSTD) && defined(WANT_COMPRESSION_ZSTD_ALWAYS) | ||
391 | cookie->flag |= STRUCT_HTTP_FLAG_ZSTD; | ||
392 | format |= TASK_FLAG_ZSTD; | ||
393 | #endif | ||
394 | |||
395 | #if defined(WANT_COMPRESSION_GZIP) && defined(WANT_COMPRESSION_GZIP_ALWAYS) | ||
396 | cookie->flag |= STRUCT_HTTP_FLAG_GZIP; | ||
397 | format |= TASK_FLAG_GZIP; | ||
398 | #endif | ||
399 | #endif | ||
400 | |||
401 | stats_issue_event(EVENT_FULLSCRAPE_REQUEST, 0, (uintptr_t)cookie->ip); | ||
385 | 402 | ||
386 | #ifdef _DEBUG_HTTPERROR | 403 | #ifdef _DEBUG_HTTPERROR |
387 | fprintf(stderr, "%s", ws->debugbuf); | 404 | fprintf(stderr, "%s", ws->debugbuf); |
@@ -760,5 +777,3 @@ ssize_t http_handle_request(const int64 sock, struct ot_workstruct *ws) { | |||
760 | http_senddata(sock, ws); | 777 | http_senddata(sock, ws); |
761 | return ws->reply_size; | 778 | return ws->reply_size; |
762 | } | 779 | } |
763 | |||
764 | const char *g_version_http_c = "$Source$: $Revision$\n"; | ||
@@ -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 { |
@@ -90,5 +90,3 @@ size_t iovec_length(const int *iovec_entries, const struct iovec **iovector) { | |||
90 | length += ((*iovector)[i]).iov_len; | 90 | length += ((*iovector)[i]).iov_len; |
91 | return length; | 91 | return length; |
92 | } | 92 | } |
93 | |||
94 | const char *g_version_iovec_c = "$Source$: $Revision$\n"; | ||
diff --git a/ot_livesync.c b/ot_livesync.c index 246317b..269b8d8 100644 --- a/ot_livesync.c +++ b/ot_livesync.c | |||
@@ -237,4 +237,3 @@ static void *livesync_worker(void *args) { | |||
237 | } | 237 | } |
238 | 238 | ||
239 | #endif | 239 | #endif |
240 | const char *g_version_livesync_c = "$Source$: $Revision$\n"; | ||
@@ -270,5 +270,3 @@ void mutex_deinit() { | |||
270 | pthread_cond_destroy(&tasklist_being_filled); | 270 | pthread_cond_destroy(&tasklist_being_filled); |
271 | byte_zero(all_torrents, sizeof(all_torrents)); | 271 | byte_zero(all_torrents, sizeof(all_torrents)); |
272 | } | 272 | } |
273 | |||
274 | const char *g_version_mutex_c = "$Source$: $Revision$\n"; | ||
@@ -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, |
diff --git a/ot_rijndael.c b/ot_rijndael.c index f468e2f..3f36bde 100644 --- a/ot_rijndael.c +++ b/ot_rijndael.c | |||
@@ -486,5 +486,3 @@ void rijndaelEncrypt128(const uint32_t rk[44], const uint8_t pt[16], uint8_t ct[ | |||
486 | rk[43]; | 486 | rk[43]; |
487 | PUTU32(ct + 12, s3); | 487 | PUTU32(ct + 12, s3); |
488 | } | 488 | } |
489 | |||
490 | const char *g_version_rijndael_c = "$Source$: $Revision$\n"; | ||
@@ -320,7 +320,7 @@ typedef struct { | |||
320 | /* Fetches stats from tracker */ | 320 | /* Fetches stats from tracker */ |
321 | size_t stats_top_txt(char *reply, int amount) { | 321 | size_t stats_top_txt(char *reply, int amount) { |
322 | size_t j; | 322 | size_t j; |
323 | ot_record top100s[100], top100c[100]; | 323 | ot_record top100s[100], top100c[100], top100l[100]; |
324 | char *r = reply, hex_out[42]; | 324 | char *r = reply, hex_out[42]; |
325 | int idx, bucket; | 325 | int idx, bucket; |
326 | 326 | ||
@@ -329,14 +329,16 @@ size_t stats_top_txt(char *reply, int amount) { | |||
329 | 329 | ||
330 | byte_zero(top100s, sizeof(top100s)); | 330 | byte_zero(top100s, sizeof(top100s)); |
331 | byte_zero(top100c, sizeof(top100c)); | 331 | byte_zero(top100c, sizeof(top100c)); |
332 | byte_zero(top100l, sizeof(top100l)); | ||
332 | 333 | ||
333 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { | 334 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { |
334 | ot_vector *torrents_list = mutex_bucket_lock(bucket); | 335 | ot_vector *torrents_list = mutex_bucket_lock(bucket); |
335 | for (j = 0; j < torrents_list->size; ++j) { | 336 | for (j = 0; j < torrents_list->size; ++j) { |
336 | ot_torrent *torrent = (ot_torrent *)(torrents_list->data) + j; | 337 | ot_torrent *torrent = (ot_torrent *)(torrents_list->data) + j; |
337 | size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; | 338 | 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; | 339 | size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; |
339 | idx = amount - 1; | 340 | size_t leech_count = peer_count - seed_count; |
341 | idx = amount - 1; | ||
340 | while ((idx >= 0) && (peer_count > top100c[idx].val)) | 342 | while ((idx >= 0) && (peer_count > top100c[idx].val)) |
341 | --idx; | 343 | --idx; |
342 | if (idx++ != amount - 1) { | 344 | if (idx++ != amount - 1) { |
@@ -352,6 +354,14 @@ size_t stats_top_txt(char *reply, int amount) { | |||
352 | memcpy(&top100s[idx].hash, &torrent->hash, sizeof(ot_hash)); | 354 | memcpy(&top100s[idx].hash, &torrent->hash, sizeof(ot_hash)); |
353 | top100s[idx].val = seed_count; | 355 | top100s[idx].val = seed_count; |
354 | } | 356 | } |
357 | idx = amount - 1; | ||
358 | while ((idx >= 0) && (leech_count > top100l[idx].val)) | ||
359 | --idx; | ||
360 | if (idx++ != amount - 1) { | ||
361 | memmove(top100l + idx + 1, top100l + idx, (amount - 1 - idx) * sizeof(ot_record)); | ||
362 | memcpy(&top100l[idx].hash, &torrent->hash, sizeof(ot_hash)); | ||
363 | top100l[idx].val = leech_count; | ||
364 | } | ||
355 | } | 365 | } |
356 | mutex_bucket_unlock(bucket, 0); | 366 | mutex_bucket_unlock(bucket, 0); |
357 | if (!g_opentracker_running) | 367 | if (!g_opentracker_running) |
@@ -366,6 +376,10 @@ size_t stats_top_txt(char *reply, int amount) { | |||
366 | for (idx = 0; idx < amount; ++idx) | 376 | for (idx = 0; idx < amount; ++idx) |
367 | if (top100s[idx].val) | 377 | if (top100s[idx].val) |
368 | r += sprintf(r, "\t%zd\t%s\n", top100s[idx].val, to_hex(hex_out, top100s[idx].hash)); | 378 | r += sprintf(r, "\t%zd\t%s\n", top100s[idx].val, to_hex(hex_out, top100s[idx].hash)); |
379 | r += sprintf(r, "Top %d torrents by leechers:\n", amount); | ||
380 | for (idx = 0; idx < amount; ++idx) | ||
381 | if (top100l[idx].val) | ||
382 | r += sprintf(r, "\t%zd\t%s\n", top100l[idx].val, to_hex(hex_out, top100l[idx].hash)); | ||
369 | 383 | ||
370 | return r - reply; | 384 | return r - reply; |
371 | } | 385 | } |
@@ -476,9 +490,9 @@ static void stats_return_fulllog(int *iovec_entries, struct iovec **iovector, ch | |||
476 | return; | 490 | return; |
477 | re = r + 32 * OT_STATS_TMPSIZE; | 491 | re = r + 32 * OT_STATS_TMPSIZE; |
478 | } | 492 | } |
479 | r += sprintf(r, "%08ld: ", loglist->time); | 493 | r += sprintf(r, "%08ld: ", loglist->time); |
480 | r += fmt_ip6c(r, loglist->ip); | 494 | r += fmt_ip6c(r, loglist->ip); |
481 | *r++ = '\n'; | 495 | *r++ = '\n'; |
482 | memcpy(r, loglist->data, loglist->size); | 496 | memcpy(r, loglist->data, loglist->size); |
483 | r += loglist->size; | 497 | r += loglist->size; |
484 | *r++ = '\n'; | 498 | *r++ = '\n'; |
@@ -518,10 +532,8 @@ static size_t stats_return_everything(char *reply) { | |||
518 | r += sprintf(r, " <completed>\n <count>%llu</count>\n </completed>\n", ot_overall_completed); | 532 | r += sprintf(r, " <completed>\n <count>%llu</count>\n </completed>\n", ot_overall_completed); |
519 | r += sprintf(r, " <connections>\n"); | 533 | r += sprintf(r, " <connections>\n"); |
520 | r += sprintf(r, " <tcp>\n <accept>%llu</accept>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n </tcp>\n", | 534 | r += sprintf(r, " <tcp>\n <accept>%llu</accept>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n </tcp>\n", |
521 | ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, ot_overall_tcp_successfulscrapes); | 535 | ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, ot_overall_tcp_successfulscrapes); |
522 | r += sprintf( | 536 | r += sprintf(r, " <udp>\n <overall>%llu</overall>\n <connect>%llu</connect>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n <missmatch>%llu</missmatch>\n </udp>\n", |
523 | r, | ||
524 | " <udp>\n <overall>%llu</overall>\n <connect>%llu</connect>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n <missmatch>%llu</missmatch>\n </udp>\n", | ||
525 | ot_overall_udp_connections, ot_overall_udp_connects, ot_overall_udp_successfulannounces, ot_overall_udp_successfulscrapes, | 537 | ot_overall_udp_connections, ot_overall_udp_connects, ot_overall_udp_successfulannounces, ot_overall_udp_successfulscrapes, |
526 | ot_overall_udp_connectionidmissmatches); | 538 | ot_overall_udp_connectionidmissmatches); |
527 | r += sprintf(r, " <livesync>\n <count>%llu</count>\n </livesync>\n", ot_overall_sync_count); | 539 | r += sprintf(r, " <livesync>\n <count>%llu</count>\n </livesync>\n", ot_overall_sync_count); |
@@ -541,14 +553,10 @@ static size_t stats_return_everything(char *reply) { | |||
541 | return r - reply; | 553 | return r - reply; |
542 | } | 554 | } |
543 | 555 | ||
544 | extern const char *g_version_opentracker_c, *g_version_accesslist_c, *g_version_clean_c, *g_version_fullscrape_c, *g_version_http_c, *g_version_iovec_c, | ||
545 | *g_version_mutex_c, *g_version_stats_c, *g_version_udp_c, *g_version_vector_c, *g_version_scan_urlencoded_query_c, *g_version_trackerlogic_c, | ||
546 | *g_version_livesync_c, *g_version_rijndael_c; | ||
547 | |||
548 | size_t stats_return_tracker_version(char *reply) { | 556 | size_t stats_return_tracker_version(char *reply) { |
549 | return sprintf(reply, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", g_version_opentracker_c, g_version_accesslist_c, g_version_clean_c, g_version_fullscrape_c, | 557 | #define QUOTE(name) #name |
550 | g_version_http_c, g_version_iovec_c, g_version_mutex_c, g_version_stats_c, g_version_udp_c, g_version_vector_c, | 558 | #define SQUOTE(name) QUOTE(name) |
551 | g_version_scan_urlencoded_query_c, g_version_trackerlogic_c, g_version_livesync_c, g_version_rijndael_c); | 559 | return sprintf(reply, "https://erdgeist.org/gitweb/opentracker/commit/?id=" SQUOTE(GIT_VERSION) "\n"); |
552 | } | 560 | } |
553 | 561 | ||
554 | size_t return_stats_for_tracker(char *reply, int mode, int format) { | 562 | size_t return_stats_for_tracker(char *reply, int mode, int format) { |
@@ -775,5 +783,3 @@ void stats_init() { | |||
775 | void stats_deinit() { | 783 | void stats_deinit() { |
776 | pthread_cancel(thread_id); | 784 | pthread_cancel(thread_id); |
777 | } | 785 | } |
778 | |||
779 | const char *g_version_stats_c = "$Source$: $Revision$\n"; | ||
@@ -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, |
@@ -48,7 +49,4 @@ size_t stats_return_tracker_version(char *reply); | |||
48 | void stats_init(void); | 49 | void stats_init(void); |
49 | void stats_deinit(void); | 50 | void stats_deinit(void); |
50 | 51 | ||
51 | extern const char *g_version_rijndael_c; | ||
52 | extern const char *g_version_livesync_c; | ||
53 | |||
54 | #endif | 52 | #endif |
@@ -170,5 +170,3 @@ void sync_deliver( int64 socket ) { | |||
170 | } | 170 | } |
171 | 171 | ||
172 | #endif | 172 | #endif |
173 | |||
174 | const char *g_version_sync_c = "$Source$: $Revision$\n"; | ||
@@ -234,5 +234,3 @@ void udp_init(int64 sock, unsigned int worker_count) { | |||
234 | while (worker_count--) | 234 | while (worker_count--) |
235 | pthread_create(&thread_id, NULL, udp_worker, (void *)sock); | 235 | pthread_create(&thread_id, NULL, udp_worker, (void *)sock); |
236 | } | 236 | } |
237 | |||
238 | const char *g_version_udp_c = "$Source$: $Revision$\n"; | ||
diff --git a/ot_vector.c b/ot_vector.c index 744306f..2bc07b5 100644 --- a/ot_vector.c +++ b/ot_vector.c | |||
@@ -282,5 +282,3 @@ void vector_fixup_peers(ot_vector *vector, size_t peer_size) { | |||
282 | if (need_fix) | 282 | if (need_fix) |
283 | vector->data = realloc(vector->data, vector->space * peer_size); | 283 | vector->data = realloc(vector->data, vector->space * peer_size); |
284 | } | 284 | } |
285 | |||
286 | const char *g_version_vector_c = "$Source$: $Revision$\n"; | ||
diff --git a/scan_urlencoded_query.c b/scan_urlencoded_query.c index 2d3599d..38d544a 100644 --- a/scan_urlencoded_query.c +++ b/scan_urlencoded_query.c | |||
@@ -162,5 +162,3 @@ ssize_t scan_fixed_int(char *data, size_t len, int *tmp) { | |||
162 | *tmp = -*tmp; | 162 | *tmp = -*tmp; |
163 | return len; | 163 | return len; |
164 | } | 164 | } |
165 | |||
166 | const char *g_version_scan_urlencoded_query_c = "$Source$: $Revision$\n"; | ||
diff --git a/trackerlogic.c b/trackerlogic.c index 6cc239e..04df544 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
@@ -596,5 +596,3 @@ void trackerlogic_deinit(void) { | |||
596 | /* Release mutexes */ | 596 | /* Release mutexes */ |
597 | mutex_deinit(); | 597 | mutex_deinit(); |
598 | } | 598 | } |
599 | |||
600 | const char *g_version_trackerlogic_c = "$Source$: $Revision$\n"; | ||