/* Handle incoming packets and pass them to the DHT code */ void dht_handler( int rc, int sock ) { UCHAR buf[1500]; IP from; socklen_t fromlen; time_t time_wait = 0; if( rc > 0 ) { /* Check which socket received the data */ fromlen = sizeof(from); rc = recvfrom( sock, buf, sizeof(buf) - 1, 0, (struct sockaddr*) &from, &fromlen ); if( rc <= 0 || rc >= sizeof(buf) ) { return; } /* The DHT code expects the message to be null-terminated. */ buf[rc] = '\0'; /* Handle incoming data */ dht_lock(); rc = dht_periodic( buf, rc, (struct sockaddr*) &from, fromlen, &time_wait, dht_callback_func, NULL ); dht_unlock(); if( rc < 0 && errno != EINTR ) { if( rc == EINVAL || rc == EFAULT ) { log_err( "DHT: Error calling dht_periodic." ); } g_dht_maintenance = time_now_sec() + 1; } else { g_dht_maintenance = time_now_sec() + time_wait; } } else if( g_dht_maintenance <= time_now_sec() ) { /* Do a maintenance call */ dht_lock(); rc = dht_periodic( NULL, 0, NULL, 0, &time_wait, dht_callback_func, NULL ); dht_unlock(); /* Wait for the next maintenance call */ g_dht_maintenance = time_now_sec() + time_wait; log_debug( "DHT: Next maintenance call in %u seconds.", (unsigned int) time_wait ); } else { rc = 0; } if( rc < 0 ) { if( errno == EINTR ) { return; } else if( rc == EINVAL || rc == EFAULT ) { log_err( "DHT: Error using select: %s", strerror( errno ) ); return; } else { g_dht_maintenance = time_now_sec() + 1; } } }
/* handle 'GET /announce?foo.p2p' */ void handle_announce( char *reply_buf, char *params ) { if( kad_announce( params, 0, (time_now_sec() + 60) ) >= 0 ) { sprintf( reply_buf , "done\n" ); } else { sprintf( reply_buf , "failed\n" ); } }
/* * Lookup known nodes that are nearest to the given id. */ int kad_lookup_value( const char _query[], IP addr_array[], size_t *addr_num ) { char query[QUERY_MAX_SIZE]; struct results_t *results; int is_new; int rc; if( query_sanitize( query, sizeof(query), _query ) != 0 ) { return -2; } log_debug( "KAD: Lookup string: %s", query ); dht_lock(); /* Find existing or create new item */ results = results_add( query, &is_new ); if( results && is_new ) { /* Search own announced values */ kad_lookup_local_values( results ); } if( results == NULL ) { /* Failed to create a new search */ rc = -1; } else if( results->done ) { /* * The search exists already but has finished. Restart the search when * no results have been found or more than half of the searches lifetime * has expired. */ if( results_entries_count( results ) == 0 || (time_now_sec() - results->start_time) > (MAX_SEARCH_LIFETIME / 2) ) { /* Mark search as in progress */ results_done( results, 0 ); /* Start another search for this id */ dht_search( results->id, 0, gconf->af, dht_callback_func, NULL ); } rc = 2; } else if( is_new ) { /* Start a new DHT search */ dht_search( results->id, 0, gconf->af, dht_callback_func, NULL ); rc = 1; } else { /* Search is still running */ rc = 0; } /* Collect addresses to be returned */ *addr_num = results_collect( results, addr_array, *addr_num ); dht_unlock(); return rc; }
int cmd_exec( REPLY *r, int argc, char **argv ) { char addrbuf[FULL_ADDSTRLEN+1]; time_t lifetime; int minutes; IP addrs[16]; int port; int count; static struct value_t *value; char *p; int rc = 0; if( argc == 0 ) { /* Print usage */ r_printf( r, cmd_usage ); if( r->allow_debug ) { r_printf( r, cmd_usage_debug ); } rc = 1; } else if( match( argv[0], "import" ) && argc == 2 ) { rc = cmd_import( r, argv[1] ); #if 0 } else if( match( argv[0], "lookup_node" ) && argc == 2 ) { /* Check searches for node */ rc = kad_lookup_node( argv[1], &addrs[0] ); if( rc == 0 ) { r_printf( r, "%s\n", str_addr( &addrs[0], addrbuf ) ); } else if( rc == 1 ) { r_printf( r ,"No search found.\n" ); rc = 1; } else if( rc == 2 ) { r_printf( r ,"Invalid id format. 20 digit hex string expected.\n" ); rc = 1; } else { rc = 1; } #endif } else if( match( argv[0], "lookup" ) && argc == 2 ) { size_t num = N_ELEMS(addrs); size_t i; /* Check searches for node */ rc = kad_lookup_value( argv[1], addrs, &num ); if( rc >= 0 && num > 0 ) { for( i = 0; i < num; ++i ) { r_printf( r, "%s\n", str_addr( &addrs[i], addrbuf ) ); } } else if( rc < 0 ) { r_printf( r ,"Some error occured.\n" ); rc = 1; } else if( rc == 0 ) { r_printf( r ,"Search in progress.\n" ); rc = 1; } else { r_printf( r ,"Search started.\n" ); rc = 1; } } else if( match( argv[0], "status" ) && argc == 1 ) { /* Print node id and statistics */ cmd_print_status( r ); } else if( match( argv[0], "announce" ) && (argc == 1 || argc == 2 || argc == 3) ) { if( argc == 1 ) { /* Announce all values; does not update value.refreshed */ count = 0; value = values_get(); while( value ) { kad_announce_once( value->id, value->port ); count++; value = value->next; } r_printf( r ,"%d announcements started.\n", count ); rc = 0; goto end; } else if( argc == 2 ) { minutes = 0; lifetime = 0; } else if( argc == 3 ) { minutes = atoi( argv[2] ); if( minutes < 0 ) { minutes = 0; lifetime = LONG_MAX; } else { /* Round up to multiple of 30 minutes */ minutes = (30 * (minutes/30 + 1)); lifetime = (time_now_sec() + (minutes * 60)); } } else { /* Make compilers happy */ exit( 1 ); } int is_random_port = 0; /* Find <id>:<port> delimiter */ p = strchr( argv[1], ':' ); if( p ) { *p = '\0'; port = port_parse( p + 1, -1 ); } else { /* A valid port will be choosen inside kad_announce() */ port = 0; is_random_port = 1; } if( kad_announce( argv[1], port, lifetime ) >= 0 ) { #ifdef FWD if( !is_random_port ) { forwardings_add( port, lifetime); } #endif if( lifetime == 0 ) { r_printf( r ,"Start single announcement now.\n" ); } else if( lifetime == LONG_MAX ) { r_printf( r ,"Start regular announcements for the entire run time (%sport %d).\n", (is_random_port ? "random " : ""), port ); } else { r_printf( r ,"Start regular announcements for %d minutes (%sport %d).\n", minutes, (is_random_port ? "random " : ""), port ); } } else { r_printf( r ,"Invalid port or query too long.\n" ); rc = 1; } } else if( match( argv[0], "blacklist" ) && argc == 2 ) { rc = cmd_blacklist( r, argv[1] ); } else if( match( argv[0], "export" ) && argc == 1 ) { rc = cmd_export( r ); } else if( match( argv[0], "list" ) && argc == 2 && r->allow_debug ) { if( gconf->is_daemon == 1 ) { r_printf( r ,"The 'list' command is not available while KadNode runs as daemon.\n" ); rc = 1; goto end; } else if( match( argv[1], "blacklist" ) ) { kad_debug_blacklist( STDOUT_FILENO ); rc = 0; } else if( match( argv[1], "buckets" ) ) { kad_debug_buckets( STDOUT_FILENO ); rc = 0; } else if( match( argv[1], "constants" ) ) { kad_debug_constants( STDOUT_FILENO ); rc = 0; #ifdef FWD } else if( match( argv[1], "forwardings" ) ) { forwardings_debug( STDOUT_FILENO ); rc = 0; #endif #ifdef AUTH } else if( match( argv[1], "pkeys" ) ) { auth_debug_pkeys( STDOUT_FILENO ); rc = 0; } else if( match( argv[1], "skeys" ) ) { auth_debug_skeys( STDOUT_FILENO ); rc = 0; #endif } else if( match( argv[1], "results" ) ) { results_debug( STDOUT_FILENO ); rc = 0; } else if( match( argv[1], "searches" ) ) { kad_debug_searches( STDOUT_FILENO ); rc = 0; } else if( match( argv[1], "storage" ) ) { kad_debug_storage( STDOUT_FILENO ); rc = 0; } else if( match( argv[1], "values" ) ) { values_debug( STDOUT_FILENO ); rc = 0; } else { dprintf( STDERR_FILENO, "Unknown argument.\n" ); rc = 1; } r_printf( r ,"\nOutput send to console.\n" ); } else { /* print usage */ r_printf( r, cmd_usage ); if( r->allow_debug ) { r_printf( r, cmd_usage_debug ); } rc = 1; } end: ; return rc; }
void handle_mcast( int rc, int sock_recv ) { char addrbuf[FULL_ADDSTRLEN+1]; char buf[512]; IP c_addr; socklen_t addrlen; int rc_recv; if( g_mcast_time <= time_now_sec() ) { if( kad_count_nodes( 0 ) == 0 ) { /* Join multicast group if possible */ if( g_mcast_registered == 0 && multicast_set_groups( sock_recv, &g_lpd_addr, gconf->dht_ifname, 1 ) == 0 ) { log_info( "LPD: No peers known. Joined multicast group." ); g_mcast_registered = 1; } if( g_mcast_registered == 1 ) { log_info( "LPD: Send multicast message to find nodes." ); /* Create message */ snprintf( buf, sizeof(buf), msg_fmt, str_addr( &g_lpd_addr, addrbuf ), atoi( gconf->dht_port ), g_infohash ); mcast_send_packets( buf, gconf->dht_ifname ); } } /* Cap number of received packets to 10 per minute */ g_packet_limit = 5 * PACKET_LIMIT_MAX; /* Try again in ~5 minutes */ g_mcast_time = time_add_min( 5 ); } if( rc <= 0 ) { return; } /* Reveice multicast ping */ addrlen = sizeof(IP); rc_recv = recvfrom( sock_recv, buf, sizeof(buf), 0, (struct sockaddr*) &c_addr, (socklen_t*) &addrlen ); if( rc_recv < 0 ) { log_warn( "LPD: Cannot receive multicast message: %s", strerror( errno ) ); return; } if( g_packet_limit < 0 ) { /* Too much traffic - leave multicast group for now */ if( g_mcast_registered == 1 && multicast_set_groups( sock_recv, &g_lpd_addr, gconf->dht_ifname, 0 ) == 0 ) { log_warn( "LPD: Too much traffic. Left multicast group." ); g_mcast_registered = 0; } return; } else { g_packet_limit--; } if( rc_recv >= sizeof(buf) ) { return; } else { buf[rc_recv] = '\0'; } int port = parse_packet( buf ); if( port > 0 ) { port_set( &c_addr, port ); log_debug( "LPD: Ping lonely peer at %s", str_addr( &c_addr, addrbuf ) ); kad_ping( &c_addr ); } else { log_debug( "LPD: Received invalid packet on multicast group." ); } }
time_t time_add_hour( unsigned int hours ) { return time_now_sec() + (60 * 60 * hours); }
time_t time_add_min( unsigned int minutes ) { return time_now_sec() + (60 * minutes); }