From c8d1ae0468357f325c2e26aa4e13b59090c0a73e Mon Sep 17 00:00:00 2001 From: erdgeist <> Date: Sat, 14 Aug 2010 10:56:14 +0000 Subject: [PATCH] Fix encoding of peer count in proxy sync packet --- proxy.c | 120 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 43 deletions(-) diff --git a/proxy.c b/proxy.c index a3cbad2..dd9e6b0 100644 --- a/proxy.c +++ b/proxy.c @@ -368,7 +368,7 @@ static void handle_read( int64 peersocket ) { /* See, if we already have a connection to that peer */ for( i=0; i MAX_PEERS / 2 ) exerr( "Connection limit exceeded.\n" ); + case 'c': + if( g_connection_count > MAX_PEERS / 2 ) exerr( "Connection limit exceeded.\n" ); tmpport = 0; if( !scan_ip6_port( optarg, g_connections[g_connection_count].ip, @@ -613,46 +613,42 @@ static void * streamsync_worker( void * args ) { } /* Maximal memory requirement: max 3 blocks, max torrents * 20 + max peers * 7 */ - mem = 3 * ( 4 + 1 + 1 + 2 ) + ( count_one + count_two ) * 19 + count_def * 20 + + mem = 3 * ( 4 + 1 + 1 + 2 ) + ( count_one + count_two ) * 19 + count_def * ( 19 + 6 ) + ( count_one + 2 * count_two + count_peers ) * 7; - fprintf( stderr, "Mem: %zd\n", mem ); + fprintf( stderr, "Mem: %zd\n", mem ); ptr = ptr_a = ptr_b = ptr_c = malloc( mem ); if( !ptr ) goto unlock_continue; - if( count_one > 8 ) { + if( count_one > 8 || !count_def ) { mem_a = 4 + 1 + 1 + 2 + count_one * ( 19 + 7 ); ptr_b += mem_a; ptr_c += mem_a; memcpy( ptr_a, &g_tracker_id, sizeof(g_tracker_id)); /* Offset 0: the tracker ID */ - ptr_a[4] = 1; /* Offset 4: packet type 1 */ - ptr_a[5] = (bucket << 8) >> OT_BUCKET_COUNT_BITS; /* Offset 5: the shared prefix */ + ptr_a[4] = 1; /* Offset 4: packet type 1 */ + ptr_a[5] = (bucket << 8) >> OT_BUCKET_COUNT_BITS; /* Offset 5: the shared prefix */ ptr_a[6] = count_one >> 8; ptr_a[7] = count_one & 255; ptr_a += 8; - } else { + } else count_def += count_one; - count_peers += count_one; - } - if( count_two > 8 ) { + if( count_two > 8 || !count_def ) { mem_b = 4 + 1 + 1 + 2 + count_two * ( 19 + 14 ); ptr_c += mem_b; memcpy( ptr_b, &g_tracker_id, sizeof(g_tracker_id)); /* Offset 0: the tracker ID */ - ptr_b[4] = 2; /* Offset 4: packet type 2 */ - ptr_b[5] = (bucket << 8) >> OT_BUCKET_COUNT_BITS; /* Offset 5: the shared prefix */ + ptr_b[4] = 2; /* Offset 4: packet type 2 */ + ptr_b[5] = (bucket << 8) >> OT_BUCKET_COUNT_BITS; /* Offset 5: the shared prefix */ ptr_b[6] = count_two >> 8; ptr_b[7] = count_two & 255; ptr_b += 8; - } else { + } else count_def += count_two; - count_peers += 2 * count_two; - } if( count_def ) { memcpy( ptr_c, &g_tracker_id, sizeof(g_tracker_id)); /* Offset 0: the tracker ID */ - ptr_c[4] = 0; /* Offset 4: packet type 0 */ - ptr_c[5] = (bucket << 8) >> OT_BUCKET_COUNT_BITS; /* Offset 5: the shared prefix */ + ptr_c[4] = 0; /* Offset 4: packet type 0 */ + ptr_c[5] = (bucket << 8) >> OT_BUCKET_COUNT_BITS; /* Offset 5: the shared prefix */ ptr_c[6] = count_def >> 8; ptr_c[7] = count_def & 255; ptr_c += 8; @@ -665,26 +661,36 @@ static void * streamsync_worker( void * args ) { ot_peerlist *peer_list = torrent->peer_list; ot_peer *peers = (ot_peer*)(peer_list->peers.data); uint8_t **dst; - int multi = 0; - switch( peer_list->peer_count ) { + + /* Determine destination slot */ + count_peers = peer_list->peer_count; + switch( count_peers ) { case 0: continue; case 1: dst = mem_a ? &ptr_a : &ptr_c; break; case 2: dst = mem_b ? &ptr_b : &ptr_c; break; - default: dst = &ptr_c; multi = 1; break; + default: dst = &ptr_c; break; } - do { - size_t i, pc = peer_list->peer_count; - if( pc > 255 ) pc = 255; - memcpy( *dst, torrent->hash + 1, sizeof( ot_hash ) - 1); - *dst += sizeof( ot_hash ) - 1; - if( multi ) *(*dst)++ = pc; - for( i=0; i < pc; ++i ) { - memcpy( *dst, peers++, OT_IP_SIZE + 3 ); - *dst += OT_IP_SIZE + 3; + /* Copy tail of info_hash, advance pointer */ + memcpy( *dst, torrent->hash + 1, sizeof( ot_hash ) - 1); + *dst += sizeof( ot_hash ) - 1; + + /* Encode peer count */ + if( dst == &ptr_c ) + while( count_peers ) { + if( count_peers <= 0x7f ) + *(*dst)++ = count_peers; + else + *(*dst)++ = 0x80 | ( count_peers & 0x7f ); + count_peers >>= 7; } - peer_list->peer_count -= pc; - } while( peer_list->peer_count ); + + /* Copy peers */ + count_peers = peer_list->peer_count; + while( count_peers-- ) { + memcpy( *dst, peers++, OT_IP_SIZE + 3 ); + *dst += OT_IP_SIZE + 3; + } free_peerlist(peer_list); } @@ -700,7 +706,7 @@ unlock_continue: if( ptr_a > ptr_c ) ptr_c = ptr_a; mem = ptr_c - ptr; - for( i=0; i= g_peerbuffer_highwater ) livesync_issue_peersync(); } static void process_indata( proxy_peer * peer ) { - int ensuremem, consumed, peers; + int consumed, peers; uint8_t *data = peer->indata, *hash; uint8_t *dataend = data + peer->indata_length; @@ -760,21 +778,37 @@ static void process_indata( proxy_peer * peer ) { peer->packet_tprefix = data[5]; peer->packet_tcount = data[6] * 256 + data[7]; data += 8; +printf( "type: %d, prefix: %02X, torrentcount: %d\n", peer->packet_type, peer->packet_tprefix, peer->packet_tcount ); } - /* ensure size for the complete torrent block */ - if( data + 26 > dataend ) break; - peers = peer->packet_type ? peer->packet_type : data[19]; - ensuremem = 19 + ( peer->packet_type == 0 ) + 7 * peers; - if( data + ensuremem > dataend ) break; +next_torrent: + /* Ensure size for the complete torrent block */ + if( data + sizeof(ot_hash) + OT_IP_SIZE + 3 > dataend ) break; + /* Advance pointer to peer count or peers */ hash = data; - data += 19 + ( peer->packet_type == 0 ); + data += sizeof(ot_hash) - 1; + + /* Type 0 has peer count encoded before each peers */ + if( peer->packet_type == 0 ) { + int shift = 0; + peers = 0; + do peers |= ( 0x7f & *data ) << ( 7 * shift ); + while ( *(data++) & 0x80 && shift++ < 6 ); + } else + peers = peer->packet_type; + + /* Ensure enough data being read to hold all peers */ + if( data + 7 * peers > dataend ) break; + +printf( "peers: %d\n", peers ); while( peers-- ) { livesync_proxytell( peer->packet_tprefix, hash, data ); - data += 7; + data += OT_IP_SIZE + 3; } + if( --peer->packet_tcount ) + goto next_torrent; } consumed = data - peer->indata;