summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerdgeist <>2008-10-03 21:33:53 +0000
committererdgeist <>2008-10-03 21:33:53 +0000
commit00c8a89efe6757ee0cbe43f776f4f7985d988291 (patch)
treef5f41c12da30dc4127033ae34633e4926183a59b
parentcee13cbebb6cb47b0f4c09106e19e07d0c851d04 (diff)
Live syncing between multiple tracker instances via udp multicast.
-rw-r--r--ot_livesync.c122
-rw-r--r--ot_livesync.h85
2 files changed, 207 insertions, 0 deletions
diff --git a/ot_livesync.c b/ot_livesync.c
new file mode 100644
index 0000000..577bb5f
--- /dev/null
+++ b/ot_livesync.c
@@ -0,0 +1,122 @@
1/* This software was written by Dirk Engling <erdgeist@erdgeist.org>
2 It is considered beerware. Prost. Skol. Cheers or whatever.
3
4 $id$ */
5
6/* System */
7#include <sys/types.h>
8#include <sys/uio.h>
9#include <string.h>
10
11/* Libowfat */
12#include "socket.h"
13
14/* Opentracker */
15#include "trackerlogic.h"
16#include "ot_livesync.h"
17#include "ot_accesslist.h"
18
19#ifdef WANT_SYNC_LIVE
20char groupip_1[4] = { LIVESYNC_MCASTDOMAIN_1 };
21
22/* For outgoing packets */
23int64 g_livesync_socket = -1;
24
25static uint8_t livesync_inbuffer[LIVESYNC_BUFFINSIZE];
26static uint8_t livesync_outbuffer_start[ LIVESYNC_BUFFSIZE ];
27static uint8_t *livesync_outbuffer_pos;
28static uint8_t *livesync_outbuffer_highwater = livesync_outbuffer_start + LIVESYNC_BUFFSIZE - LIVESYNC_BUFFWATER;
29static ot_time livesync_lastpacket_time;
30
31void livesync_init( ) {
32 if( g_livesync_socket == -1 )
33 exerr( "No socket address for live sync specified." );
34 livesync_outbuffer_pos = livesync_outbuffer_start;
35 memmove( livesync_outbuffer_pos, &g_tracker_id, sizeof( g_tracker_id ) );
36 livesync_outbuffer_pos += sizeof( g_tracker_id );
37 livesync_lastpacket_time = g_now;
38}
39
40void livesync_deinit() {
41
42}
43
44void livesync_bind_mcast( char *ip, uint16_t port) {
45 char tmpip[4] = {0,0,0,0};
46 if( g_livesync_socket != -1 )
47 exerr("Livesync listen ip specified twice.");
48 if( socket_mcjoin4( ot_try_bind(tmpip, port, FLAG_MCA ), groupip_1, ip ) )
49 exerr("Cant join mcast group.");
50 g_livesync_socket = ot_try_bind( ip, port, FLAG_UDP );
51 io_dontwantread(g_livesync_socket);
52
53 socket_mcttl4(g_livesync_socket, 1);
54 socket_mcloop4(g_livesync_socket, 0);
55}
56
57static void livesync_issuepacket( ) {
58 socket_send4(g_livesync_socket, (char*)livesync_outbuffer_start, livesync_outbuffer_pos - livesync_outbuffer_start,
59 groupip_1, LIVESYNC_PORT);
60 livesync_outbuffer_pos = livesync_outbuffer_start + sizeof( g_tracker_id );
61 livesync_lastpacket_time = g_now;
62}
63
64/* Inform live sync about whats going on. */
65void livesync_tell( ot_hash * const info_hash, const ot_peer * const peer, const uint8_t peerflag ) {
66 memmove( livesync_outbuffer_pos , info_hash, sizeof(ot_hash));
67 memmove( livesync_outbuffer_pos + sizeof(ot_hash), peer, sizeof(ot_peer));
68 OT_FLAG( livesync_outbuffer_pos + sizeof(ot_hash) ) |= peerflag;
69
70 livesync_outbuffer_pos += sizeof(ot_hash) + sizeof(ot_peer);
71 if( livesync_outbuffer_pos >= livesync_outbuffer_highwater )
72 livesync_issuepacket();
73}
74
75/* Tickle the live sync module from time to time, so no events get
76 stuck when there's not enough traffic to fill udp packets fast
77 enough */
78void livesync_ticker( ) {
79 if( ( g_now - livesync_lastpacket_time > LIVESYNC_MAXDELAY) &&
80 ( livesync_outbuffer_pos > livesync_outbuffer_start + sizeof( g_tracker_id ) ) )
81 livesync_issuepacket();
82}
83
84/* Handle an incoming live sync packet */
85void handle_livesync( int64 serversocket ) {
86 uint8_t in_ip[4]; uint16_t in_port;
87 ssize_t datalen = socket_recv4(serversocket, (char*)livesync_inbuffer, LIVESYNC_BUFFINSIZE, (char*)in_ip, &in_port);
88 int off = 4;
89
90 if( datalen < (ssize_t)(sizeof( g_tracker_id ) + sizeof( ot_hash ) + sizeof( ot_peer ) ) ) {
91 // TODO: log invalid sync packet
92 return;
93 }
94
95 if( !accesslist_isblessed((char*)in_ip, OT_PERMISSION_MAY_LIVESYNC)) {
96 // TODO: log invalid sync packet
97 return;
98 }
99
100 if( !memcmp( livesync_inbuffer, &g_tracker_id, sizeof( g_tracker_id ) ) ) {
101 // TODO: log packet coming from ourselves
102 return;
103 }
104
105 // Now basic sanity checks have been done on the live sync packet
106 // We might add more testing and logging.
107 while( off + (ssize_t)sizeof( ot_hash ) + (ssize_t)sizeof( ot_peer ) <= datalen ) {
108 ot_peer *peer = (ot_peer*)(livesync_inbuffer + off + sizeof(ot_hash));
109 ot_hash *hash = (ot_hash*)(livesync_inbuffer + off);
110
111 if( OT_FLAG(peer) & PEER_FLAG_STOPPED )
112 remove_peer_from_torrent(hash, peer, NULL, FLAG_MCA);
113 else
114 add_peer_to_torrent( hash, peer WANT_SYNC_PARAM(1));
115
116 off += sizeof( ot_hash ) + sizeof( ot_peer );
117 }
118
119}
120
121#endif
122const char *g_version_livesync_c = "$Source$: $Revision$\n";
diff --git a/ot_livesync.h b/ot_livesync.h
new file mode 100644
index 0000000..4dc6b60
--- /dev/null
+++ b/ot_livesync.h
@@ -0,0 +1,85 @@
1/* This software was written by Dirk Engling <erdgeist@erdgeist.org>
2 It is considered beerware. Prost. Skol. Cheers or whatever.
3
4 $id$ */
5
6#ifndef __OT_LIVESYNC_H__
7#define __OT_LIVESYNC_H__
8
9#include "io.h"
10#include "trackerlogic.h"
11
12/*
13 Syncing is done as udp packets in the multicast domain 224.23.42.N port 9696
14
15 Each tracker should join the multicast group and send its live sync packets
16 to that group, using a ttl of 1
17
18 Format of a live sync packet is straight forward and depends on N:
19
20 For N == 1: (simple tracker2tracker sync)
21 0x0000 0x04 id of tracker instance
22 [ 0x0004 0x14 info_hash
23 0x0018 0x04 peer's ipv4 address
24 0x001c 0x02 peer's port
25 0x0020 0x02 peer flags v1 ( SEEDING = 0x80, COMPLETE = 0x40, STOPPED = 0x20 )
26 ]*
27
28 For N == 2: (aggregator syncs)
29 0x0000 0x04 id of tracker instance
30 [ 0x0004 0x14 info_hash
31 0x0018 0x01 number of peers
32 [ 0x0019 0x04 peer's ipv4 address
33 0x001a 0x02 peer's port
34 0x0021 0x02 peer flags v1 ( SEEDING = 0x80, COMPLETE = 0x40, STOPPED = 0x20 )
35 ]+
36 ]*
37
38
39 */
40
41#ifdef WANT_SYNC_LIVE
42
43#define LIVESYNC_PORT 9696
44#define LIVESYNC_MCASTDOMAIN_1 224,23,42,1
45#define LIVESYNC_MCASTDOMAIN_2 224,23,42,2
46extern char groupip_1[4];
47extern char groupip_2[4];
48
49extern int64 g_livesync_socket;
50
51#define LIVESYNC_BUFFINSIZE (256*256)
52#define LIVESYNC_BUFFSIZE 1504
53#define LIVESYNC_BUFFWATER (sizeof(ot_peer)+sizeof(ot_hash))
54
55#define LIVESYNC_MAXDELAY 15
56
57void livesync_init();
58void livesync_deinit();
59
60/* Join multicast group for listening and create sending socket */
61void livesync_bind_mcast( char *ip, uint16_t port );
62
63/* Inform live sync about whats going on. */
64void livesync_tell( ot_hash * const info_hash, const ot_peer * const peer, const uint8_t peerflag );
65
66/* Tickle the live sync module from time to time, so no events get
67 stuck when there's not enough traffic to fill udp packets fast
68 enough */
69void livesync_ticker( );
70
71/* Handle an incoming live sync packet */
72void handle_livesync( const int64 serversocket );
73
74#else
75
76/* If no syncing is required, save calling code from #ifdef
77 constructions */
78
79#define livesync_init()
80#define livesync_ticker()
81#define handle_livesync(a)
82
83#endif
84
85#endif