static void wd_transfer_listen_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wi_socket_t *socket; wi_address_t *address; pool = wi_pool_init(wi_pool_alloc()); while(wd_running) { wi_pool_drain(pool); socket = wi_socket_accept_multiple(wd_transfer_sockets, 30.0, &address); if(!address) { wi_log_err(WI_STR("Could not accept a connection: %m")); continue; } if(!socket) { wi_log_err(WI_STR("Could not accept a connection for %@: %m"), wi_address_string(address)); continue; } if(!wi_thread_create_thread(wd_transfer_accept_thread, socket)) { wi_log_err(WI_STR("Could not create a transfer thread for %@: %m"), wi_address_string(address)); continue; } } wi_release(pool); }
void wi_test_runtime_pool(void) { wi_pool_t *pool, *pool2; _wi_runtimetest_t *runtimetest, *runtimetest2; _wi_runtimetest_deallocs = 0; pool = wi_pool_init(wi_pool_alloc()); runtimetest = wi_retain(wi_autorelease(_wi_runtimetest_init_with_value(_wi_runtimetest_alloc(), 42))); wi_release(pool); WI_TEST_ASSERT_EQUALS(wi_retain_count(runtimetest), 1U, ""); wi_release(runtimetest); pool = wi_pool_init(wi_pool_alloc()); runtimetest = wi_retain(wi_autorelease(_wi_runtimetest_init_with_value(_wi_runtimetest_alloc(), 42))); wi_pool_drain(pool); WI_TEST_ASSERT_EQUALS(wi_retain_count(runtimetest), 1U, ""); wi_release(pool); wi_release(runtimetest); pool = wi_pool_init(wi_pool_alloc()); runtimetest = wi_retain(wi_autorelease(_wi_runtimetest_init_with_value(_wi_runtimetest_alloc(), 42))); pool2 = wi_pool_init(wi_pool_alloc()); runtimetest2 = wi_retain(wi_autorelease(_wi_runtimetest_init_with_value(_wi_runtimetest_alloc(), 42))); wi_release(pool2); WI_TEST_ASSERT_EQUALS(wi_retain_count(runtimetest2), 1U, ""); wi_release(pool); WI_TEST_ASSERT_EQUALS(wi_retain_count(runtimetest), 1U, ""); wi_release(runtimetest); wi_release(runtimetest2); }
void wt_control_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wt_client_t *client = argument; wi_string_t *string; wi_socket_state_t state; wi_uinteger_t i = 0; pool = wi_pool_init(wi_pool_alloc()); wt_client_set(client); while(client->state <= WT_CLIENT_STATE_SAID_HELLO) { do { state = wi_socket_wait(client->socket, 0.1); } while(state == WI_SOCKET_TIMEOUT && client->state <= WT_CLIENT_STATE_SAID_HELLO); if(client->state > WT_CLIENT_STATE_SAID_HELLO) { /* invalid state */ break; } if(state == WI_SOCKET_ERROR) { if(wi_error_code() == EINTR) { /* got a signal */ continue; } else { /* error in TCP communication */ wi_log_err(WI_STR("Could not read from %@: %m"), client->ip); break; } } string = wi_socket_read_to_string(client->socket, 0.0, WI_STR(WT_MESSAGE_SEPARATOR_STR)); if(!string || wi_string_length(string) == 0) { if(!string) wi_log_info(WI_STR("Could not read from %@: %m"), client->ip); break; } wt_parse_command(string); if(++i % 10 == 0) wi_pool_drain(pool); } wi_log_info(WI_STR("Disconnect from %@ after %.2fs"), client->ip, wi_time_interval() - client->connect_time); wi_release(pool); }
static void _wi_timer_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wi_timer_t *timer, *fire_timer; wi_time_interval_t interval, diff; wi_boolean_t locked; pool = wi_pool_init(wi_pool_alloc()); while(true) { fire_timer = NULL; locked = true; interval = wi_time_interval(); timer = _wi_timer_first_timer(); if(!timer) { locked = wi_condition_lock_lock_when_condition(_wi_timer_lock, 1, 0.0); timer = _wi_timer_first_timer(); interval = wi_time_interval(); if(timer && timer->fire - interval <= _WI_TIMER_MINIMUM_INTERVAL) fire_timer = timer; } else { diff = timer->fire - interval; if(diff <= _WI_TIMER_MINIMUM_INTERVAL) { fire_timer = timer; locked = false; } else { locked = wi_condition_lock_lock_when_condition(_wi_timer_lock, 1, diff); if(!locked) fire_timer = _wi_timer_first_timer(); } } if(locked) wi_condition_lock_unlock_with_condition(_wi_timer_lock, 0); if(fire_timer) { _wi_timer_invalidate(fire_timer); wi_timer_fire(fire_timer); if(timer->repeats) _wi_timer_schedule(fire_timer); } wi_pool_drain(pool); } wi_release(pool); }
static void wd_control_listen_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wi_socket_t *socket; wi_address_t *address; wi_string_t *ip; wd_user_t *user; pool = wi_pool_init(wi_pool_alloc()); while(wd_running) { wi_pool_drain(pool); /* accept new user */ socket = wi_socket_accept_multiple(wd_control_sockets, wd_control_socket_context, 30.0, &address); if(!address) { wi_log_err(WI_STR("Could not accept a connection: %m")); continue; } ip = wi_address_string(address); if(!socket) { wi_log_err(WI_STR("Could not accept a connection for %@: %m"), ip); continue; } wi_socket_set_direction(socket, WI_SOCKET_READ); wi_log_info(WI_STR("Connect from %@"), ip); /* spawn a user thread */ user = wd_user_with_socket(socket); if(!wi_thread_create_thread(wd_control_thread, user)) wi_log_err(WI_STR("Could not create a thread for %@: %m"), ip); } wi_release(pool); }
int main(int argc, const char **argv) { wi_pool_t *pool; wi_string_t *homepath, *wirepath, *path, *component; wi_file_t *file; int ch; /* init libwired */ wi_initialize(); wi_load(argc, argv); pool = wi_pool_init(wi_pool_alloc()); wi_log_callback = wr_wi_log_callback; /* init core systems */ wr_version_init(); wr_start_date = wi_date_init(wi_date_alloc()); /* set defaults */ wr_nick = wi_retain(wi_user_name()); homepath = wi_user_home(); wr_timestamp_format = wi_retain(WI_STR("%H:%M")); /* parse command line switches */ while((ch = getopt(argc, (char * const *) argv, "DhVv")) != -1) { switch(ch) { case 'D': wr_debug = true; wi_log_level = WI_LOG_DEBUG; wi_log_file = true; wi_log_path = WI_STR("wire.out"); wi_log_callback = NULL; break; case 'V': case 'v': wr_version(); break; case '?': case 'h': default: wr_usage(); break; } } argc -= optind; argv += optind; /* open log */ wi_log_open(); /* create ~/.wire */ wirepath = wi_string_by_appending_path_component(homepath, WI_STR(WR_WIRE_PATH)); wi_file_create_directory(wirepath, 0700); /* init subsystems */ wr_signals_init(); wr_terminal_init(); wr_readline_init(); wr_chats_init(); wr_windows_init(); wr_client_init(); wr_runloop_init(); wr_users_init(); wr_ignores_init(); wr_files_init(); wr_transfers_init(); wr_servers_init(); /* open default settings */ path = wi_string_by_appending_path_component(homepath, WI_STR(WR_WIRE_CONFIG_PATH)); file = wi_file_for_reading(path); if(file) wr_parse_file(file); else wr_printf_prefix(WI_STR("%@: %m"), path); /* read specified bookmark */ if(*argv) { component = wi_string_with_cstring(*argv); path = wi_string_by_appending_path_component(wirepath, component); file = wi_file_for_reading(path); if(file) wr_parse_file(file); else wr_printf_prefix(WI_STR("%@: %m"), path); } /* clean up pool after startup */ wi_pool_drain(pool); /* enter event loop */ wr_runloop_run(); /* clean up */ wr_cleanup(); wi_release(pool); return 0; }
static void wd_transfer_upload(wd_transfer_t *transfer) { wi_pool_t *pool; wi_string_t *path; wd_account_t *account; char buffer[WD_TRANSFER_BUFFER_SIZE]; wi_time_interval_t timeout, interval, speedinterval, statusinterval, accountinterval; wi_socket_state_t state; ssize_t result, speedbytes, statsbytes; int sd, bytes; pool = wi_pool_init(wi_pool_alloc()); /* start upload */ wi_log_info(WI_STR("Receiving \"%@\" from %@"), transfer->path, wd_user_identifier(transfer->user)); wi_socket_set_direction(transfer->socket, WI_SOCKET_READ); // if(!wi_socket_set_blocking(transfer->socket, false)) // wi_log_warn(WI_STR("Could not set non-blocking for %@: %m"), wd_user_ip(transfer->user)); sd = wi_socket_descriptor(transfer->socket); speedinterval = statusinterval = accountinterval = wi_time_interval(); speedbytes = statsbytes = 0; account = wd_user_account(transfer->user); /* update status */ wi_lock_lock(wd_status_lock); wd_current_uploads++; wd_total_uploads++; wd_write_status(true); wi_lock_unlock(wd_status_lock); while(wd_transfer_state(transfer) == WD_TRANSFER_RUNNING && transfer->transferred < transfer->size) { /* wait to read */ timeout = 0.0; do { state = wi_socket_wait_descriptor(sd, 0.1, true, false); if(state == WI_SOCKET_TIMEOUT) { timeout += 0.1; if(timeout >= 30.0) break; } } while(state == WI_SOCKET_TIMEOUT && wd_transfer_state(transfer) == WD_TRANSFER_RUNNING); if(state == WI_SOCKET_ERROR) { wi_log_err(WI_STR("Could not wait for upload from %@: %m"), wd_user_ip(transfer->user)); break; } if(timeout >= 30.0) { wi_log_err(WI_STR("Timed out waiting to read upload from %@"), wd_user_ip(transfer->user)); break; } /* read data */ bytes = wi_socket_read_buffer(transfer->socket, 30.0, buffer, sizeof(buffer)); if(bytes <= 0) { if(bytes < 0) { wi_log_err(WI_STR("Could not read upload from %@: %m"), wd_user_ip(transfer->user)); } break; } if((wi_file_offset_t) bytes > transfer->size - transfer->transferred) bytes = transfer->size - transfer->transferred; /* write data */ result = write(transfer->fd, buffer, bytes); if(result <= 0) { if(result < 0) { wi_log_err(WI_STR("Could not write upload to %@: %s"), transfer->realpath, strerror(errno)); } break; } /* update counters */ interval = wi_time_interval(); transfer->transferred += bytes; speedbytes += bytes; statsbytes += bytes; /* update speed */ transfer->speed = speedbytes / (interval - speedinterval); wd_transfer_limit_upload_speed(transfer, account, speedbytes, interval, speedinterval); if(interval - speedinterval > 30.0) { speedbytes = 0; speedinterval = interval; } /* update status */ if(interval - statusinterval > wd_current_uploads) { wi_lock_lock(wd_status_lock); wd_uploads_traffic += statsbytes; wd_write_status(false); wi_lock_unlock(wd_status_lock); statsbytes = 0; statusinterval = interval; } /* update account */ if(interval - accountinterval > 15.0) { account = wd_user_account(transfer->user); accountinterval = interval; } wi_pool_drain(pool); } wi_log_info(WI_STR("Received %@/%@ (%llu/%llu bytes) of \"%@\" from %@"), wd_files_string_for_bytes(transfer->transferred - transfer->offset), wd_files_string_for_bytes(transfer->size - transfer->offset), transfer->transferred - transfer->offset, transfer->size - transfer->offset, transfer->path, wd_user_identifier(transfer->user)); /* update status */ wd_transfer_set_state(transfer, WD_TRANSFER_STOPPED); wi_lock_lock(wd_status_lock); wd_current_uploads--; wd_uploads_traffic += statsbytes; wd_write_status(true); wi_lock_unlock(wd_status_lock); if(transfer->transferred == transfer->size) { path = wi_string_by_deleting_path_extension(transfer->realpath); if(wi_fs_rename_path(transfer->realpath, path)) { path = wi_string_by_appending_path_extension(transfer->path, WI_STR(WD_TRANSFERS_PARTIAL_EXTENSION)); wd_files_move_comment(path, transfer->path); } else { wi_log_warn(WI_STR("Could not move %@ to %@: %m"), transfer->realpath, path); } } wi_release(pool); }
static wi_boolean_t wd_transfer_download(wd_transfer_t *transfer) { wi_pool_t *pool; wi_socket_t *socket; wi_p7_socket_t *p7_socket; wd_account_t *account; char buffer[WD_TRANSFER_BUFFER_SIZE]; wi_socket_state_t state; wi_time_interval_t timeout, interval, speedinterval, statusinterval, accountinterval; wi_file_offset_t sendbytes, speedbytes, statsbytes; wi_uinteger_t i, transfers; ssize_t readbytes; int sd; wi_boolean_t data, result; wd_user_state_t user_state; interval = wi_time_interval(); speedinterval = interval; statusinterval = interval; accountinterval = interval; speedbytes = 0; statsbytes = 0; i = 0; socket = wd_user_socket(transfer->user); sd = wi_socket_descriptor(socket); p7_socket = wd_user_p7_socket(transfer->user); account = wd_user_account(transfer->user); data = true; result = true; wd_transfers_note_statistics(WD_TRANSFER_DOWNLOAD, WD_TRANSFER_STATISTICS_ADD, 0); wi_dictionary_rdlock(wd_transfers_user_downloads); transfers = (wi_integer_t) wi_dictionary_data_for_key(wd_transfers_user_downloads, transfer->key); wi_dictionary_unlock(wd_transfers_user_downloads); pool = wi_pool_init(wi_pool_alloc()); wd_user_lock_socket(transfer->user); while(wd_user_state(transfer->user) == WD_USER_LOGGED_IN) { if(data && transfer->remainingdatasize == 0) data = false; if(!data && transfer->remainingrsrcsize == 0) break; readbytes = read(data ? transfer->datafd : transfer->rsrcfd, buffer, sizeof(buffer)); if(readbytes <= 0) { if(readbytes < 0) { wi_log_error(WI_STR("Could not read download from \"%@\": %m"), data ? transfer->realdatapath : transfer->realrsrcpath, strerror(errno)); } result = false; break; } timeout = wi_time_interval(); do { user_state = wd_user_state(transfer->user); state = wi_socket_wait_descriptor(sd, 0.1, false, true); if(state == WI_SOCKET_TIMEOUT) { if(wi_time_interval() - timeout >= 30.0) break; } } while(state == WI_SOCKET_TIMEOUT && user_state == WD_USER_LOGGED_IN); if(state == WI_SOCKET_ERROR || wi_time_interval() - timeout >= 30.0) { wi_log_error(WI_STR("Could not wait for download to %@: %@"), wd_user_identifier(transfer->user), (state == WI_SOCKET_ERROR) ? wi_error_string() : WI_STR("Timed out")); result = false; break; } if(user_state != WD_USER_LOGGED_IN) { result = false; break; } if(data) { sendbytes = (transfer->remainingdatasize < (wi_file_offset_t) readbytes) ? transfer->remainingdatasize : (wi_file_offset_t) readbytes; } else { sendbytes = (transfer->remainingrsrcsize < (wi_file_offset_t) readbytes) ? transfer->remainingrsrcsize : (wi_file_offset_t) readbytes; } if(!wi_p7_socket_write_oobdata(p7_socket, 30.0, buffer, sendbytes)) { wi_log_error(WI_STR("Could not write download to %@: %m"), wd_user_identifier(transfer->user)); result = false; break; } if(data) transfer->remainingdatasize -= sendbytes; else transfer->remainingrsrcsize -= sendbytes; interval = wi_time_interval(); transfer->transferred += sendbytes; transfer->actualtransferred += sendbytes; speedbytes += sendbytes; statsbytes += sendbytes; transfer->speed = speedbytes / (interval - speedinterval); wd_transfer_limit_speed(transfer, wd_transfers_total_download_speed, wd_account_transfer_download_speed_limit(account), wd_current_downloads, transfers, speedbytes, interval, speedinterval); if(interval - speedinterval > 30.0) { speedbytes = 0; speedinterval = interval; } if(interval - statusinterval > wd_current_downloads) { wd_transfers_note_statistics(WD_TRANSFER_DOWNLOAD, WD_TRANSFER_STATISTICS_DATA, statsbytes); statsbytes = 0; statusinterval = interval; } if(interval - accountinterval > 15.0) { account = wd_user_account(transfer->user); accountinterval = interval; wi_dictionary_rdlock(wd_transfers_user_downloads); transfers = (wi_integer_t) wi_dictionary_data_for_key(wd_transfers_user_downloads, transfer->key); wi_dictionary_unlock(wd_transfers_user_downloads); } if(++i % 1000 == 0) wi_pool_drain(pool); } wd_user_unlock_socket(transfer->user); wi_release(pool); wd_transfers_note_statistics(WD_TRANSFER_DOWNLOAD, WD_TRANSFER_STATISTICS_REMOVE, statsbytes); return result; }
static void wd_transfers_queue_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wi_enumerator_t *enumerator; wi_mutable_dictionary_t *key_queues; wi_mutable_array_t *key_queue, *keys; wi_string_t *key; wd_transfer_t *transfer; wd_account_t *account; wi_uinteger_t user_downloads, user_uploads, user_transfers; wi_uinteger_t new_position, position, queue, i, count, longest_queue; pool = wi_pool_init(wi_pool_alloc()); key_queues = wi_dictionary_init(wi_mutable_dictionary_alloc()); while(true) { wi_mutable_dictionary_remove_all_data(key_queues); wi_condition_lock_lock_when_condition(wd_transfers_queue_lock, 1, 0.0); wi_array_rdlock(wd_transfers); longest_queue = 0; enumerator = wi_array_data_enumerator(wd_transfers); while((transfer = wi_enumerator_next_data(enumerator))) { wi_condition_lock_lock(transfer->queue_lock); if(transfer->state == WD_TRANSFER_QUEUED && transfer->queue != 0) { key_queue = wi_dictionary_data_for_key(key_queues, transfer->key); if(!key_queue) { key_queue = wi_mutable_array(); wi_mutable_dictionary_set_data_for_key(key_queues, key_queue, transfer->key); } wi_mutable_array_add_data(key_queue, transfer); if(wi_array_count(key_queue) > longest_queue) longest_queue = wi_array_count(key_queue); } wi_condition_lock_unlock(transfer->queue_lock); } keys = wi_autorelease(wi_mutable_copy(wi_dictionary_keys_sorted_by_value(key_queues, wd_transfers_queue_compare))); position = 1; count = wi_array_count(keys); while(longest_queue > 0) { for(i = 0; i < count; i++) { key = WI_ARRAY(keys, i); key_queue = wi_dictionary_data_for_key(key_queues, key); if(wi_array_count(key_queue) > 0) { transfer = WI_ARRAY(key_queue, 0); account = wd_user_account(transfer->user); wi_lock_lock(wd_transfers_status_lock); if(transfer->type == WD_TRANSFER_DOWNLOAD) { wi_dictionary_rdlock(wd_transfers_user_downloads); user_downloads = wd_account_transfer_download_limit(account); user_transfers = (wi_integer_t) wi_dictionary_data_for_key(wd_transfers_user_downloads, transfer->key); queue = ((wd_transfers_total_downloads > 0 && wd_transfers_active_downloads >= wd_transfers_total_downloads) || (user_downloads > 0 && user_transfers >= user_downloads)); wi_dictionary_unlock(wd_transfers_user_downloads); } else { wi_dictionary_rdlock(wd_transfers_user_uploads); user_uploads = wd_account_transfer_upload_limit(account); user_transfers = (wi_integer_t) wi_dictionary_data_for_key(wd_transfers_user_uploads, transfer->key); queue = ((wd_transfers_total_uploads > 0 && wd_transfers_active_uploads >= wd_transfers_total_uploads) || (user_uploads > 0 && user_transfers >= user_uploads)); wi_dictionary_unlock(wd_transfers_user_uploads); } wi_lock_unlock(wd_transfers_status_lock); if(queue) new_position = position++; else new_position = 0; if(new_position != (wi_uinteger_t) transfer->queue) { if(new_position == 0) wd_transfers_add_or_remove_transfer(transfer, true); wi_condition_lock_lock(transfer->queue_lock); transfer->queue = new_position; wi_condition_lock_unlock_with_condition(transfer->queue_lock, 1); } wi_mutable_array_remove_data_at_index(key_queue, 0); } } longest_queue--; } wi_array_unlock(wd_transfers); wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 0); wi_pool_drain(pool); } wi_release(key_queues); wi_release(pool); }
int main(int argc, const char **argv) { wi_mutable_array_t *arguments; wi_pool_t *pool; wi_string_t *string, *root_path; int ch, facility; wi_boolean_t test_config, daemonize, change_directory, switch_user; /* init libwired */ wi_initialize(); wi_load(argc, argv); pool = wi_pool_init(wi_pool_alloc()); wi_log_syslog = true; wi_log_syslog_facility = LOG_DAEMON; /* init core systems */ wt_version_init(); wt_status_lock = wi_lock_init(wi_lock_alloc()); wt_start_date = wi_date_init(wi_date_alloc()); /* set defaults */ root_path = WI_STR(WT_ROOT); wi_settings_config_path = wi_string_init_with_cstring(wi_string_alloc(), WT_CONFIG_PATH); test_config = false; daemonize = true; change_directory = true; switch_user = true; /* init reexec argument list */ arguments = wi_array_init(wi_mutable_array_alloc()); /* parse command line switches */ while((ch = getopt(argc, (char * const *) argv, "46Dd:f:hi:L:ls:tuVvXx")) != -1) { switch(ch) { case '4': wt_address_family = WI_ADDRESS_IPV4; break; case '6': wt_address_family = WI_ADDRESS_IPV6; break; case 'D': daemonize = false; wi_log_stderr = true; break; case 'd': root_path = wi_string_with_cstring(optarg); break; case 'f': wi_release(wi_settings_config_path); wi_settings_config_path = wi_string_init_with_cstring(wi_string_alloc(), optarg); break; case 'i': wi_log_limit = wi_string_uint32(wi_string_with_cstring(optarg)); break; case 'L': wi_log_syslog = false; wi_log_file = true; wi_release(wi_log_path); wi_log_path = wi_string_init_with_cstring(wi_string_alloc(), optarg); break; case 'l': wi_log_level++; break; case 's': string = wi_string_with_cstring(optarg); facility = wi_log_syslog_facility_with_name(string); if(facility < 0) wi_log_fatal(WI_STR("Could not find syslog facility \"%@\": %m"), string); wi_log_syslog_facility = facility; break; case 't': test_config = true; break; case 'u': break; case 'V': case 'v': wt_version(); break; case 'X': daemonize = false; break; case 'x': daemonize = false; change_directory = false; switch_user = false; break; case '?': case 'h': default: wt_usage(); break; } wi_mutable_array_add_data(arguments, wi_string_with_format(WI_STR("-%c"), ch)); if(optarg) wi_mutable_array_add_data(arguments, wi_string_with_cstring(optarg)); } /* detach */ if(daemonize) { wi_mutable_array_add_data(arguments, WI_STR("-X")); switch(wi_fork()) { case -1: wi_log_fatal(WI_STR("Could not fork: %m")); break; case 0: if(!wi_execv(wi_string_with_cstring(argv[0]), arguments)) wi_log_fatal(WI_STR("Could not execute %s: %m"), argv[0]); break; default: _exit(0); break; } } wi_release(arguments); /* change directory */ if(change_directory) { if(!wi_fs_change_directory(root_path)) wi_log_error(WI_STR("Could not change directory to %@: %m"), root_path); } /* open log */ wi_log_open(); /* init subsystems */ wt_ssl_init(); wt_clients_init(); wt_servers_init(); /* read the config file */ wt_settings_init(); if(!wt_settings_read_config()) exit(1); /* apply settings */ wt_settings_apply_settings(); if(test_config) { printf("Config OK\n"); exit(0); } /* dump command line */ wi_log_info(WI_STR("Started as %@ %@"), wi_process_path(wi_process()), wi_array_components_joined_by_string(wi_process_arguments(wi_process()), WI_STR(" "))); /* init tracker */ wi_log_info(WI_STR("Starting Wired Tracker version %@"), wt_version_string); wt_tracker_init(); /* switch user/group */ if(switch_user) wi_switch_user(wt_settings.user, wt_settings.group); /* create tracker threads after privilege drop */ wt_signals_init(); wt_block_signals(); wt_servers_schedule(); wt_tracker_create_threads(); wt_write_pid(); wt_write_status(true); /* clean up pool after startup */ wi_pool_drain(pool); /* enter the signal handling thread in the main thread */ wt_signal_thread(NULL); /* dropped out */ wt_cleanup(); wi_log_close(); wi_release(pool); return 0; }
static void wd_transfer_listen_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wi_socket_t *socket; wi_address_t *address; wi_array_t *arguments; wi_string_t *ip, *string, *command; wd_transfer_t *transfer; pool = wi_pool_init(wi_pool_alloc()); while(wd_running) { wi_pool_drain(pool); /* accept new connection */ socket = wi_socket_accept_multiple(wd_transfer_sockets, wd_transfer_socket_context, 30.0, &address); if(!address) { wi_log_err(WI_STR("Could not accept a connection: %m")); continue; } ip = wi_address_string(address); if(!socket) { wi_log_err(WI_STR("Could not accept a connection for %@: %m"), ip); continue; } string = wi_socket_read_to_string(socket, 5.0, WI_STR(WD_MESSAGE_SEPARATOR_STR)); if(!string || wi_string_length(string) == 0) { if(!string) wi_log_warn(WI_STR("Could not read from %@: %m"), ip); continue; } /* parse command */ wi_parse_wired_command(string, &command, &arguments); if(wi_is_equal(command, WI_STR("TRANSFER")) && wi_array_count(arguments) >= 1) { /* get transfer by identifier */ transfer = wd_transfers_transfer_with_hash(WI_ARRAY(arguments, 0)); if(!transfer) continue; if(!wi_is_equal(ip, wd_user_ip(transfer->user))) continue; transfer->socket = wi_retain(socket); /* spawn a transfer thread */ if(!wi_thread_create_thread(wd_transfer_thread, transfer)) wi_log_err(WI_STR("Could not create a thread for %@: %m"), ip); } } wi_release(pool); }