summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Mk/tests.mk7
-rw-r--r--man5/opentracker.conf.513
-rw-r--r--opentracker.conf.sample20
-rw-r--r--src/opentracker.c2
-rw-r--r--src/ot_config.c6
-rw-r--r--src/ot_livesync.c46
-rw-r--r--src/ot_livesync.h7
-rw-r--r--src/ot_worker.c2
-rw-r--r--src/trackerlogic.c6
-rw-r--r--src/trackerlogic.h2
-rw-r--r--tests/integration/harness.py4
-rw-r--r--tests/integration/test_livesync.py87
-rw-r--r--tests/t_trackerlogic.c2
13 files changed, 175 insertions, 29 deletions
diff --git a/Mk/tests.mk b/Mk/tests.mk
index a7d4fbc..2efdd72 100644
--- a/Mk/tests.mk
+++ b/Mk/tests.mk
@@ -70,11 +70,10 @@ check-integration: opentracker.integration
70check-tsan: opentracker.tsan 70check-tsan: opentracker.tsan
71 OPENTRACKER=./opentracker.tsan $(PYTHON) -m unittest discover -s tests/integration 71 OPENTRACKER=./opentracker.tsan $(PYTHON) -m unittest discover -s tests/integration
72 72
73# Only the live sync tests: a build with WANT_SYNC_LIVE refuses to start 73# The whole suite against a build that has live sync, which is also the only
74# without a live sync address, so it cannot stand in for the plain binary in 74# way the live sync tests stop skipping.
75# the rest of the suite.
76check-livesync: opentracker.livesync 75check-livesync: opentracker.livesync
77 OPENTRACKER=./opentracker.livesync $(PYTHON) -m unittest discover -s tests/integration -p 'test_livesync.py' 76 OPENTRACKER=./opentracker.livesync $(PYTHON) -m unittest discover -s tests/integration
78 77
79# Cheapest first, so a quick failure comes back quickly. 78# Cheapest first, so a quick failure comes back quickly.
80check-all: 79check-all:
diff --git a/man5/opentracker.conf.5 b/man5/opentracker.conf.5
index 67e624f..9a836ae 100644
--- a/man5/opentracker.conf.5
+++ b/man5/opentracker.conf.5
@@ -79,7 +79,18 @@ Specifies the path to the stats location. You can configure opentracker to appea
79Specifies 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. 79Specifies 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.
80.Pp 80.Pp
81.It livesync.cluster.listen Ar ip_address:port 81.It livesync.cluster.listen Ar ip_address:port
82Specifies the IP address and port opentracker will listen on for incoming live sync packets to keep a cluster of opentrackers synchronized. 82Specifies the IP address and port opentracker will listen on for incoming live
83sync packets to keep a cluster of opentrackers synchronized. Every member of a
84cluster has to agree on the port, which is also the one packets are sent to.
85.Pp
86.It livesync.cluster.group Ar ip_address
87Specifies the multicast group a cluster talks in. For reaosns of backwards
88comaptibility with legacy trackers, it defaults to 224.0.23.5, which,
89technically sits in a range IANA assigns on request.
90
91A cluster of its own is better served by an address out of 239.192.0.0/14,
92which RFC 2365 sets aside for private use. Packets carry a ttl of 1 either
93way and never leave the local link.
83.Pp 94.Pp
84.It livesync.cluster.node_ip Ar ip_address 95.It livesync.cluster.node_ip Ar ip_address
85Specifies one trusted IP address for sync between trackers running in a cluster. Can be added more than once. 96Specifies one trusted IP address for sync between trackers running in a cluster. Can be added more than once.
diff --git a/opentracker.conf.sample b/opentracker.conf.sample
index 491c88a..7b35369 100644
--- a/opentracker.conf.sample
+++ b/opentracker.conf.sample
@@ -138,12 +138,22 @@
138# livesync.cluster.listen 192.168.0.1:9696 138# livesync.cluster.listen 192.168.0.1:9696
139# 139#
140# Note that two udp sockets will be opened. One on ip address 0.0.0.0 140# Note that two udp sockets will be opened. One on ip address 0.0.0.0
141# port 9696, that will join the multicast group 224.0.42.23 for incoming 141# port 9696, that will join the multicast group for incoming udp packets
142# udp packets and one on ip address 192.168.0.1 port 9696 for outgoing 142# and one on ip address 192.168.0.1 port 9696 for outgoing ones. Every
143# udp packets. 143# member of a cluster has to agree on the port as well as the group.
144#
145# The group a cluster talks in.
146#
147# livesync.cluster.group 239.192.23.5
148#
149# For reaosns of backwards comaptibility with legacy trackers, it
150# defaults to 224.0.23.5, which, technically sits in a range IANA
151# assigns on request.
152#
153# A cluster of your own is better served by an address out of
154# 239.192.0.0/14, which RFC 2365 sets aside for private use. Packets
155# carry a ttl of 1 either way, so they never leave the local link.
144# 156#
145# As of now one and only one ip address must be given, if opentracker
146# was built with the WANT_SYNC_LIVE feature.
147# 157#
148 158
149# IV) Sync between trackers running in a cluster is restricted to packets 159# IV) Sync between trackers running in a cluster is restricted to packets
diff --git a/src/opentracker.c b/src/opentracker.c
index 14b817e..60a6d8c 100644
--- a/src/opentracker.c
+++ b/src/opentracker.c
@@ -109,7 +109,7 @@ static void *server_mainloop(void *args) {
109 109
110 (void)args; 110 (void)args;
111 111
112 if (workstruct_init(&ws) == -1) 112 if (workstruct_init(&ws, G_INBUF_SIZE) == -1)
113 panic("Initializing worker failed"); 113 panic("Initializing worker failed");
114 114
115 while (g_opentracker_running) { 115 while (g_opentracker_running) {
diff --git a/src/ot_config.c b/src/ot_config.c
index 95136b5..4064d1b 100644
--- a/src/ot_config.c
+++ b/src/ot_config.c
@@ -208,6 +208,7 @@ typedef enum {
208 CONFIG_TRACKER_REDIRECT_URL, 208 CONFIG_TRACKER_REDIRECT_URL,
209 CONFIG_LIVESYNC_CLUSTER_NODE_IP, 209 CONFIG_LIVESYNC_CLUSTER_NODE_IP,
210 CONFIG_LIVESYNC_CLUSTER_LISTEN, 210 CONFIG_LIVESYNC_CLUSTER_LISTEN,
211 CONFIG_LIVESYNC_CLUSTER_GROUP,
211} config_kind; 212} config_kind;
212 213
213typedef struct { 214typedef struct {
@@ -247,6 +248,7 @@ static const config_key config_keys[] = {
247#ifdef WANT_SYNC_LIVE 248#ifdef WANT_SYNC_LIVE
248 CONFIG_KEY("livesync.cluster.node_ip", CONFIG_LIVESYNC_CLUSTER_NODE_IP), 249 CONFIG_KEY("livesync.cluster.node_ip", CONFIG_LIVESYNC_CLUSTER_NODE_IP),
249 CONFIG_KEY("livesync.cluster.listen", CONFIG_LIVESYNC_CLUSTER_LISTEN), 250 CONFIG_KEY("livesync.cluster.listen", CONFIG_LIVESYNC_CLUSTER_LISTEN),
251 CONFIG_KEY("livesync.cluster.group", CONFIG_LIVESYNC_CLUSTER_GROUP),
250#endif 252#endif
251}; 253};
252static const size_t config_entry_count = sizeof(config_keys) / sizeof(config_keys[0]); 254static const size_t config_entry_count = sizeof(config_keys) / sizeof(config_keys[0]);
@@ -378,6 +380,10 @@ static int parse_configfile(char *config_filename) {
378 set_config_option(&g_redirecturl, p); 380 set_config_option(&g_redirecturl, p);
379 break; 381 break;
380#ifdef WANT_SYNC_LIVE 382#ifdef WANT_SYNC_LIVE
383 case CONFIG_LIVESYNC_CLUSTER_GROUP:
384 if (!ip_parse(p, tmpip) || livesync_set_group(tmpip) == -1)
385 goto parse_error;
386 break;
381 case CONFIG_LIVESYNC_CLUSTER_NODE_IP: 387 case CONFIG_LIVESYNC_CLUSTER_NODE_IP:
382 if (!scan_ip6_net(p, &tmpnet)) 388 if (!scan_ip6_net(p, &tmpnet))
383 goto parse_error; 389 goto parse_error;
diff --git a/src/ot_livesync.c b/src/ot_livesync.c
index 083fe1a..85577f7 100644
--- a/src/ot_livesync.c
+++ b/src/ot_livesync.c
@@ -4,6 +4,7 @@
4/* System */ 4/* System */
5#include <arpa/inet.h> 5#include <arpa/inet.h>
6#include <pthread.h> 6#include <pthread.h>
7#include <stdio.h>
7#include <stdlib.h> 8#include <stdlib.h>
8#include <string.h> 9#include <string.h>
9#include <sys/socket.h> 10#include <sys/socket.h>
@@ -21,7 +22,10 @@
21 22
22#ifdef WANT_SYNC_LIVE 23#ifdef WANT_SYNC_LIVE
23 24
24ot_ip6 groupip_1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 224, 0, 23, 5}; 25/* The multicast group, legacy opentrackers joined by default 224.0.23.5, so it
26 stays the default */
27static ot_ip6 g_group = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 224, 0, 23, 5};
28static uint16_t g_port = LIVESYNC_PORT;
25 29
26#define LIVESYNC_INCOMING_BUFFSIZE (256 * 256) 30#define LIVESYNC_INCOMING_BUFFSIZE (256 * 256)
27 31
@@ -59,7 +63,7 @@ void livesync_init(void) {
59 uint32_t packet_type4 = htonl(OT_SYNC_PEER4); 63 uint32_t packet_type4 = htonl(OT_SYNC_PEER4);
60 64
61 if (g_socket_in == -1) 65 if (g_socket_in == -1)
62 exerr("No socket address for live sync specified."); 66 return;
63 67
64 /* Prepare outgoing peers buffer */ 68 /* Prepare outgoing peers buffer */
65 memcpy(g_v6_buf.data, &g_tracker_id, sizeof(g_tracker_id)); 69 memcpy(g_v6_buf.data, &g_tracker_id, sizeof(g_tracker_id));
@@ -94,6 +98,14 @@ void livesync_deinit(void) {
94 close(g_socket_out); 98 close(g_socket_out);
95} 99}
96 100
101int livesync_set_group(const ot_ip6 group) {
102 /* v4 multicast is 224.0.0.0/4, and the socket layer has nothing else */
103 if (!ip_is_v4mapped(group) || (group[12] & 0xf0) != 0xe0)
104 return -1;
105 memcpy(g_group, group, sizeof(ot_ip6));
106 return 0;
107}
108
97void livesync_bind_mcast(ot_ip6 ip, uint16_t port) { 109void livesync_bind_mcast(ot_ip6 ip, uint16_t port) {
98 if (!ip_is_v4mapped(ip)) 110 if (!ip_is_v4mapped(ip))
99 exerr("v6 mcast support not yet available."); 111 exerr("v6 mcast support not yet available.");
@@ -101,7 +113,9 @@ void livesync_bind_mcast(ot_ip6 ip, uint16_t port) {
101 if (g_socket_in != -1) 113 if (g_socket_in != -1)
102 exerr("Error: Livesync listen ip specified twice."); 114 exerr("Error: Livesync listen ip specified twice.");
103 115
104 if ((g_socket_in = socket_mcast_join(groupip_1, ip, port)) == -1) 116 g_port = port;
117
118 if ((g_socket_in = socket_mcast_join(g_group, ip, port)) == -1)
105 exerr("Error: Cant bind live sync incoming socket."); 119 exerr("Error: Cant bind live sync incoming socket.");
106 120
107 if ((g_socket_out = socket_mcast_bind(ip, port, 0)) == -1) 121 if ((g_socket_out = socket_mcast_bind(ip, port, 0)) == -1)
@@ -121,7 +135,7 @@ static void livesync_issue_peersync(sync_buffer *buf) {
121 has modified the protected element */ 135 has modified the protected element */
122 pthread_mutex_unlock(&g_outbuf_mutex); 136 pthread_mutex_unlock(&g_outbuf_mutex);
123 137
124 socket_mcast_send(g_socket_out, mycopy, fill, groupip_1, LIVESYNC_PORT); 138 socket_mcast_send(g_socket_out, mycopy, fill, g_group, g_port);
125} 139}
126 140
127static void livesync_handle_peersync(struct ot_workstruct *ws, size_t peer_size) { 141static void livesync_handle_peersync(struct ot_workstruct *ws, size_t peer_size) {
@@ -159,6 +173,9 @@ static void livesync_handle_peersync(struct ot_workstruct *ws, size_t peer_size)
159 stuck when there's not enough traffic to fill udp packets fast 173 stuck when there's not enough traffic to fill udp packets fast
160 enough */ 174 enough */
161void livesync_ticker(void) { 175void livesync_ticker(void) {
176 if (g_socket_out == -1)
177 return;
178
162 /* livesync_issue_peersync sets g_next_packet_time */ 179 /* livesync_issue_peersync sets g_next_packet_time */
163 pthread_mutex_lock(&g_outbuf_mutex); 180 pthread_mutex_lock(&g_outbuf_mutex);
164 if (time_now_seconds() > g_v6_buf.next_packet_time && g_v6_buf.fill > sizeof(g_tracker_id) + sizeof(uint32_t)) 181 if (time_now_seconds() > g_v6_buf.next_packet_time && g_v6_buf.fill > sizeof(g_tracker_id) + sizeof(uint32_t))
@@ -176,8 +193,14 @@ void livesync_ticker(void) {
176/* Inform live sync about whats going on. */ 193/* Inform live sync about whats going on. */
177void livesync_tell(struct ot_workstruct *ws) { 194void livesync_tell(struct ot_workstruct *ws) {
178 size_t peer_size; /* initialized in next line */ 195 size_t peer_size; /* initialized in next line */
179 ot_peer *peer_src = peer_from_peer6(&ws->peer, &peer_size); 196 ot_peer *peer_src;
180 sync_buffer *dest_buf = peer_size == OT_PEER_SIZE6 ? &g_v6_buf : &g_v4_buf; 197 sync_buffer *dest_buf;
198
199 if (g_socket_out == -1)
200 return;
201
202 peer_src = peer_from_peer6(&ws->peer, &peer_size);
203 dest_buf = peer_size == OT_PEER_SIZE6 ? &g_v6_buf : &g_v4_buf;
181 204
182 pthread_mutex_lock(&g_outbuf_mutex); 205 pthread_mutex_lock(&g_outbuf_mutex);
183 206
@@ -200,9 +223,12 @@ static void *livesync_worker(void *args) {
200 223
201 (void)args; 224 (void)args;
202 225
203 /* Initialize our "thread local storage" */ 226 if (workstruct_init(&ws, LIVESYNC_INCOMING_BUFFSIZE) == -1) {
204 ws.inbuf = ws.request = malloc(LIVESYNC_INCOMING_BUFFSIZE); 227 fprintf(stderr, "Warning: live sync could not get its buffers and will not run.\n");
205 ws.outbuf = ws.reply = 0; 228 atomic_store(&thread_left, 1);
229 return NULL;
230 }
231 ws.request = ws.inbuf;
206 232
207 while (g_opentracker_running) { 233 while (g_opentracker_running) {
208 uint32_t packet_type; 234 uint32_t packet_type;
@@ -233,7 +259,7 @@ static void *livesync_worker(void *args) {
233 } 259 }
234 } 260 }
235 261
236 free(ws.inbuf); 262 workstruct_deinit(&ws);
237 atomic_store(&thread_left, 1); 263 atomic_store(&thread_left, 1);
238 return NULL; 264 return NULL;
239} 265}
diff --git a/src/ot_livesync.h b/src/ot_livesync.h
index 4bd3af0..cf3c64c 100644
--- a/src/ot_livesync.h
+++ b/src/ot_livesync.h
@@ -7,7 +7,8 @@
7#include "trackerlogic.h" 7#include "trackerlogic.h"
8 8
9/* 9/*
10 Syncing is done as udp packets in the multicast domain 224.0.42.5 port 9696 10 Syncing is done as udp packets in the multicast group 224.0.23.5, on the
11 port livesync.cluster.listen names, 9696 by default
11 12
12 Each tracker should join the multicast group and send its live sync packets 13 Each tracker should join the multicast group and send its live sync packets
13 to that group, using a ttl of 1 14 to that group, using a ttl of 1
@@ -47,6 +48,10 @@
47void livesync_init(void); 48void livesync_init(void);
48void livesync_deinit(void); 49void livesync_deinit(void);
49 50
51/* The group to join and to send to, (defaults to 224.0.23.5).
52 Returns -1 if group is not a v4 multicast address. */
53int livesync_set_group(const ot_ip6 group);
54
50/* Join multicast group for listening and create sending socket */ 55/* Join multicast group for listening and create sending socket */
51void livesync_bind_mcast(ot_ip6 ip, uint16_t port); 56void livesync_bind_mcast(ot_ip6 ip, uint16_t port);
52 57
diff --git a/src/ot_worker.c b/src/ot_worker.c
index 432d272..ef50945 100644
--- a/src/ot_worker.c
+++ b/src/ot_worker.c
@@ -20,7 +20,7 @@ static size_t g_worker_count;
20static void *worker_trampoline(void *args) { 20static void *worker_trampoline(void *args) {
21 struct ot_worker *me = args; 21 struct ot_worker *me = args;
22 22
23 if (workstruct_init(&me->ws) == -1) 23 if (workstruct_init(&me->ws, G_INBUF_SIZE) == -1)
24 fprintf(stderr, "Warning: a worker could not get its buffers and will not run.\n"); 24 fprintf(stderr, "Warning: a worker could not get its buffers and will not run.\n");
25 else { 25 else {
26 me->run(me); 26 me->run(me);
diff --git a/src/trackerlogic.c b/src/trackerlogic.c
index 9565090..8e30a48 100644
--- a/src/trackerlogic.c
+++ b/src/trackerlogic.c
@@ -567,9 +567,11 @@ void trackerlogic_init(void) {
567 stats_init(); 567 stats_init();
568} 568}
569 569
570int workstruct_init(struct ot_workstruct *ws) { 570/* Live sync reads whole packets rather than requests and wants a larger
571 inbuf than the request path does, hence the size. */
572int workstruct_init(struct ot_workstruct *ws, size_t inbuf_size) {
571 memset(ws, 0, sizeof(*ws)); 573 memset(ws, 0, sizeof(*ws));
572 ws->inbuf = malloc(G_INBUF_SIZE); 574 ws->inbuf = malloc(inbuf_size);
573 ws->outbuf = malloc(G_OUTBUF_SIZE); 575 ws->outbuf = malloc(G_OUTBUF_SIZE);
574#ifdef _DEBUG_HTTPERROR 576#ifdef _DEBUG_HTTPERROR
575 ws->debugbuf = malloc(G_DEBUGBUF_SIZE); 577 ws->debugbuf = malloc(G_DEBUGBUF_SIZE);
diff --git a/src/trackerlogic.h b/src/trackerlogic.h
index 7292d36..692b6af 100644
--- a/src/trackerlogic.h
+++ b/src/trackerlogic.h
@@ -242,7 +242,7 @@ struct ot_workstruct {
242/* Everything a thread that serves requests needs for itself. Set up and torn 242/* Everything a thread that serves requests needs for itself. Set up and torn
243 down in one place so that a new kind of worker cannot miss a piece. 243 down in one place so that a new kind of worker cannot miss a piece.
244 Returns -1 if the buffers could not be had. */ 244 Returns -1 if the buffers could not be had. */
245int workstruct_init(struct ot_workstruct *ws); 245int workstruct_init(struct ot_workstruct *ws, size_t inbuf_size);
246void workstruct_deinit(struct ot_workstruct *ws); 246void workstruct_deinit(struct ot_workstruct *ws);
247 247
248/* 248/*
diff --git a/tests/integration/harness.py b/tests/integration/harness.py
index a9d38ca..10aa6de 100644
--- a/tests/integration/harness.py
+++ b/tests/integration/harness.py
@@ -192,7 +192,7 @@ class Tracker:
192 def torrent_count(self): 192 def torrent_count(self):
193 return int(self.stats("torr").split()[0]) 193 return int(self.stats("torr").split()[0])
194 194
195 def livesync_send(self, payload): 195 def livesync_send(self, payload, group=LIVESYNC_GROUP):
196 """Put a packet on the live sync group. 196 """Put a packet on the live sync group.
197 197
198 It has to go to the group rather than straight at the port: the 198 It has to go to the group rather than straight at the port: the
@@ -204,7 +204,7 @@ class Tracker:
204 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton("127.0.0.1")) 204 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton("127.0.0.1"))
205 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1) 205 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
206 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1) 206 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1)
207 sock.sendto(payload, (LIVESYNC_GROUP, self.livesync_port)) 207 sock.sendto(payload, (group, self.livesync_port))
208 finally: 208 finally:
209 sock.close() 209 sock.close()
210 210
diff --git a/tests/integration/test_livesync.py b/tests/integration/test_livesync.py
index 8dd754b..52e871f 100644
--- a/tests/integration/test_livesync.py
+++ b/tests/integration/test_livesync.py
@@ -102,6 +102,17 @@ class LiveSyncIn(TrackerTestCase):
102 self.tracker.livesync_send(packet(99, [(info_hash, peer4("10.1.2.11", 6881, FLAG_SEEDING))])) 102 self.tracker.livesync_send(packet(99, [(info_hash, peer4("10.1.2.11", 6881, FLAG_SEEDING))]))
103 self.assertFalse(self.tracker.wait_until(lambda: self.counts(info_hash) is not None, timeout=1)) 103 self.assertFalse(self.tracker.wait_until(lambda: self.counts(info_hash) is not None, timeout=1))
104 104
105 def test_synced_peers_are_counted(self):
106 """The live sync worker keeps its own tally like every other worker,
107 and ?mode=syncs is the sum of them."""
108 before = int(self.tracker.stats("syncs").split()[0])
109 hashes = [self.hash_for("sync-count-%d" % i) for i in range(3)]
110 self.tracker.livesync_send(packet(SYNC_PEER4, [(h, peer4("10.1.2.%d" % (20 + i), 6881, FLAG_SEEDING))
111 for i, h in enumerate(hashes)]))
112 self.assertTrue(self.tracker.wait_until(
113 lambda: int(self.tracker.stats("syncs").split()[0]) == before + 3),
114 "syncs says %s" % self.tracker.stats("syncs").split()[0])
115
105 def test_a_packet_with_nothing_but_a_header_is_ignored(self): 116 def test_a_packet_with_nothing_but_a_header_is_ignored(self):
106 before = self.tracker.torrent_count() 117 before = self.tracker.torrent_count()
107 self.tracker.livesync_send(struct.pack("!I", 0xDEADBEEF) + struct.pack("!I", SYNC_PEER4)) 118 self.tracker.livesync_send(struct.pack("!I", 0xDEADBEEF) + struct.pack("!I", SYNC_PEER4))
@@ -119,3 +130,79 @@ class LiveSyncAccess(TrackerTestCase):
119 info_hash = self.hash_for("sync-unblessed") 130 info_hash = self.hash_for("sync-unblessed")
120 self.tracker.livesync_send(packet(SYNC_PEER4, [(info_hash, peer4("10.1.2.12", 6881, FLAG_SEEDING))])) 131 self.tracker.livesync_send(packet(SYNC_PEER4, [(info_hash, peer4("10.1.2.12", 6881, FLAG_SEEDING))]))
121 self.assertFalse(self.tracker.wait_until(lambda: self.tracker.torrent_count() != 0, timeout=1)) 132 self.assertFalse(self.tracker.wait_until(lambda: self.tracker.torrent_count() != 0, timeout=1))
133
134
135@unittest.skipUnless(has_livesync(), "this build has no WANT_SYNC_LIVE")
136class LiveSyncUnconfigured(TrackerTestCase):
137 """A binary that has the feature but no cluster to join. Somebody whose
138 packager turned WANT_SYNC_LIVE on did not ask for live sync and should
139 not be able to tell that it is there."""
140
141 config = ""
142
143 def test_the_tracker_runs_anyway(self):
144 info_hash = self.hash_for("no-cluster")
145 self.tracker.announce(info_hash, port=6881, left=0)
146 self.assertEqual(self.tracker.torrent_count(), 1)
147
148 def test_nothing_is_said_about_the_missing_cluster(self):
149 self.assertNotIn("sync", self.tracker.output().lower())
150
151 def test_no_socket_is_bound_for_it(self):
152 """A configured tracker holds the wildcard address on that port, so
153 taking it here proves nothing was started."""
154 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
155 try:
156 sock.bind(("0.0.0.0", self.tracker.livesync_port))
157 finally:
158 sock.close()
159
160 def test_announcing_stays_clean(self):
161 """Enough announces to pass the watermark that would flush an
162 outgoing buffer, if there were one to flush. The sanitizers in this
163 build turn anything the attempt touched into a failure."""
164 for i in range(200):
165 self.tracker.announce(self.hash_for("no-cluster-%d" % i), port=6881 + i, left=0)
166 self.assertEqual(self.tracker.torrent_count(), 200)
167
168
169# RFC 2365 sets 239.192.0.0/14 aside for exactly this kind of use
170OWN_GROUP = "239.192.0.7"
171
172
173@unittest.skipUnless(has_livesync(), "this build has no WANT_SYNC_LIVE")
174class LiveSyncGroup(TrackerTestCase):
175 config = ("livesync.cluster.group %s\n"
176 "livesync.cluster.listen 127.0.0.1:{livesync_port}\n"
177 "livesync.cluster.node_ip 127.0.0.1\n" % OWN_GROUP)
178
179 def test_the_configured_group_is_joined(self):
180 info_hash = self.hash_for("own-group")
181 self.tracker.livesync_send(packet(SYNC_PEER4, [(info_hash, peer4("10.1.3.1", 6881, FLAG_SEEDING))]),
182 group=OWN_GROUP)
183 self.assertTrue(self.tracker.wait_until(lambda: self.tracker.torrent_count() == 1))
184
185 def test_the_default_group_is_left_alone(self):
186 """A cluster that picked its own group should not hear the one every
187 other opentracker is on."""
188 info_hash = self.hash_for("not-our-group")
189 self.tracker.livesync_send(packet(SYNC_PEER4, [(info_hash, peer4("10.1.3.2", 6881, FLAG_SEEDING))]))
190 self.assertFalse(self.tracker.wait_until(lambda: self.tracker.torrent_count() != 0, timeout=1))
191
192
193@unittest.skipUnless(has_livesync(), "this build has no WANT_SYNC_LIVE")
194class LiveSyncGroupRefused(TrackerTestCase):
195 """A unicast address is not a group. The line is refused like any other
196 bad config line, which leaves the default standing."""
197
198 config = ("livesync.cluster.group 10.0.0.1\n"
199 "livesync.cluster.listen 127.0.0.1:{livesync_port}\n"
200 "livesync.cluster.node_ip 127.0.0.1\n")
201
202 def test_the_line_is_refused(self):
203 self.assertIn("Parse error", self.tracker.output())
204
205 def test_and_the_default_group_still_works(self):
206 info_hash = self.hash_for("fallback-group")
207 self.tracker.livesync_send(packet(SYNC_PEER4, [(info_hash, peer4("10.1.3.3", 6881, FLAG_SEEDING))]))
208 self.assertTrue(self.tracker.wait_until(lambda: self.tracker.torrent_count() == 1))
diff --git a/tests/t_trackerlogic.c b/tests/t_trackerlogic.c
index f64977f..1cf9141 100644
--- a/tests/t_trackerlogic.c
+++ b/tests/t_trackerlogic.c
@@ -224,7 +224,7 @@ void test_trackerlogic(void) {
224 pthread_sigmask(SIG_BLOCK, &signal_mask, NULL); 224 pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
225 225
226 trackerlogic_init(); 226 trackerlogic_init();
227 CHECK_INT(workstruct_init(&ws), 0); 227 CHECK_INT(workstruct_init(&ws, G_INBUF_SIZE), 0);
228 228
229 case_an_announce_makes_a_torrent(); 229 case_an_announce_makes_a_torrent();
230 case_the_same_peer_twice_is_one_peer(); 230 case_the_same_peer_twice_is_one_peer();