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); }
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); }
static void wd_control_accept_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wi_socket_t *socket = argument; wi_string_t *ip; wd_user_t *user; pool = wi_pool_init(wi_pool_alloc()); ip = wi_address_string(wi_socket_address(socket)); if(!wi_socket_accept_tls(socket, wd_control_socket_tls, 30.0)) { wi_log_err(WI_STR("Could not accept a TLS connection for %@: %m"), ip); goto end; } if(!wi_socket_set_timeout(socket, 30.0)) wi_log_warn(WI_STR("Could not set timeout for %@: %m"), ip); wi_socket_set_direction(socket, WI_SOCKET_READ); wi_log_info(WI_STR("Connect from %@"), ip); user = wd_user_with_socket(socket); wd_users_add_user(user); wd_users_set_user_for_thread(user); wd_command_loop_for_user(user); end: wi_socket_close(socket); wi_release(pool); }
static void wd_trackers_register_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wi_enumerator_t *enumerator; wi_number_t *number = argument; wd_tracker_t *tracker; wi_boolean_t update; pool = wi_pool_init(wi_pool_alloc()); update = wi_number_bool(number); wi_array_rdlock(wd_trackers); enumerator = wi_array_data_enumerator(wd_trackers); while((tracker = wi_enumerator_next_data(enumerator))) { wd_tracker_register(tracker); if(update && tracker->active) wd_tracker_update(tracker); } wi_array_unlock(wd_trackers); if(update) wi_timer_reschedule(wd_trackers_update_timer, WD_TRACKERS_UPDATE_INTERVAL); wi_release(pool); }
static void wd_transfer_accept_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wi_socket_t *socket = argument; wi_array_t *arguments; wi_string_t *ip, *string, *command; wd_transfer_t *transfer; pool = wi_pool_init(wi_pool_alloc()); ip = wi_address_string(wi_socket_address(socket)); if(!wi_socket_accept_tls(socket, wd_transfer_socket_tls, 30.0)) { wi_log_err(WI_STR("Could not accept a connection for %@: %m"), ip); goto end; } if(!wi_socket_set_timeout(socket, 30.0)) wi_log_warn(WI_STR("Could not set timeout for %@: %m"), ip); 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); goto end; } wi_parse_wired_command(string, &command, &arguments); if(wi_is_equal(command, WI_STR("TRANSFER")) && wi_array_count(arguments) >= 1) { transfer = wd_transfers_transfer_with_hash(WI_ARRAY(arguments, 0)); if(!transfer) goto end; if(!wi_is_equal(ip, wd_user_ip(transfer->user))) goto end; wi_lock_lock(transfer->socket_lock); if(!transfer->socket) { transfer->socket = wi_retain(socket); wi_lock_unlock(transfer->socket_lock); wd_transfer_loop(transfer); } else { wi_lock_unlock(transfer->socket_lock); } } end: wi_socket_close(socket); wi_release(pool); }
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 wi_test_fsevents_thread(wi_runtime_instance_t *instance) { wi_pool_t *pool; pool = wi_pool_init(wi_pool_alloc()); if(!wi_fsevents_run_with_timeout(wi_test_fsevents_fsevents, 1.0)) wi_log_warn(WI_STR("wi_fsevents_run_with_timeout: %m")); wi_condition_lock_lock(wi_test_fsevents_lock); wi_condition_lock_unlock_with_condition(wi_test_fsevents_lock, 1); wi_release(pool); }
void wi_tests_run_test(const char *name, wi_run_test_func_t *function) { wi_pool_t *pool; wi_assert_handler_func_t *handler; wi_time_interval_t interval; if(_wi_tests_name) { if(wi_string_index_of_string(wi_string_with_utf8_string(name), _wi_tests_name, 0) == WI_NOT_FOUND) return; } if(wi_string_has_suffix(wi_string_with_utf8_string(name), WI_STR("initialize"))) { (*function)(); } else { _wi_tests_current_test = _wi_test_init_with_function(_wi_test_alloc(), wi_string_with_utf8_string(name), function); handler = wi_assert_handler; wi_assert_handler = _wi_tests_assert_handler; interval = wi_time_interval(); pool = wi_pool_init(wi_pool_alloc()); if(setjmp(_wi_tests_jmp_buf) == 0) (*_wi_tests_current_test->function)(); wi_release(pool); _wi_tests_current_test->interval = wi_time_interval() - interval; wi_assert_handler = handler; if(_wi_tests_current_test->passed) { wi_log_info(WI_STR("Test \"%@\" passed (%.3f seconds)"), _wi_tests_current_test->name, _wi_tests_current_test->interval); wi_tests_passed++; } else { wi_log_info(WI_STR("Test \"%@\" failed (%.3f seconds)"), _wi_tests_current_test->name, _wi_tests_current_test->interval); wi_tests_failed++; } wi_release(_wi_tests_current_test); } }
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_initialize(); wi_load(argc, argv); wi_log_plain = true; wi_log_level = WI_LOG_DEBUG; pool = wi_pool_init(wi_pool_alloc()); wi_tests_start(); wi_test_fixture_path = wi_string_by_appending_path_component(WI_STR(WI_TEST_ROOT), WI_STR("fixture")); #include "test/testlist.inc" wi_tests_stop_and_report(); wi_release(pool); return wi_tests_failed; }
int main(int argc, const char **argv) { wi_pool_t *pool; wi_string_t *string; int ch, facility; wi_boolean_t no_chroot, test_config; /* init libwired */ wi_initialize(); wi_load(argc, argv); pool = wi_pool_init(wi_pool_alloc()); wi_log_startup = true; wi_log_syslog = true; wi_log_syslog_facility = LOG_DAEMON; /* init core systems */ wt_init_version(); wt_status_lock = wi_lock_init(wi_lock_alloc()); wt_start_date = wi_date_init(wi_date_alloc()); /* set defaults */ wi_root_path = wi_string_init_with_cstring(wi_string_alloc(), WT_ROOT); wi_settings_config_path = wi_string_init_with_cstring(wi_string_alloc(), WT_CONFIG_PATH); no_chroot = false; test_config = false; /* parse command line switches */ while((ch = getopt(argc, (char * const *) argv, "46Dd:f:hi:L:ls:tuVv")) != -1) { switch(ch) { case '4': wt_address_family = WI_ADDRESS_IPV4; break; case '6': wt_address_family = WI_ADDRESS_IPV6; break; case 'D': wt_daemonize = false; wi_log_stderr = true; break; case 'd': wi_release(wi_root_path); wi_root_path = wi_string_init_with_cstring(wi_string_alloc(), 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_err(WI_STR("Could not find syslog facility \"%@\": %m"), string); } wi_log_syslog_facility = facility; break; case 't': test_config = true; break; case 'u': no_chroot = true; break; case 'V': case 'v': wt_version(); break; case '?': case 'h': default: wt_usage(); break; } } /* open log */ wi_log_open(); /* init subsystems */ wt_init_ssl(); wt_init_clients(); wt_init_servers(); /* read the config file */ wt_settings_chroot = !no_chroot; wt_init_settings(); if(!wt_read_config()) exit(1); /* change root directory */ if(!no_chroot) { if(!wi_change_root()) wi_log_err(WI_STR("Could not change root to %@: %m"), wi_root_path); } /* apply config */ wt_apply_config(); if(test_config) { printf("Config OK\n"); exit(0); } /* dump command line */ if(wi_log_level >= WI_LOG_DEBUG) { wi_log_debug(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_init_tracker(); /* detach (don't chdir, don't close i/o channels) */ if(wt_daemonize) { if(!wi_daemon()) wi_log_err(WI_STR("Could not become a daemon: %m")); } /* switch user/group */ wi_switch_user(wt_settings.user, wt_settings.group); /* create tracker threads after privilege drop */ wt_init_signals(); wt_block_signals(); wt_schedule_servers(); wt_fork_tracker(); wt_write_pid(); wt_write_status(true); wi_log_startup = false; wi_release(pool); pool = wi_pool_init(wi_pool_alloc()); /* 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; }
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_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); }
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); }
void wd_control_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wd_client_t *client = argument; wi_string_t *string; unsigned int i = 0; int state; pool = wi_pool_init(wi_pool_alloc()); wd_clients_add_client(client); wd_client_set(client); while(client->state <= WD_CLIENT_STATE_LOGGED_IN) { if(!pool) pool = wi_pool_init(wi_pool_alloc()); if(client->buffer_offset == 0) { do { state = wi_socket_wait(client->socket, 0.1); } while(state == 0 && client->state <= WD_CLIENT_STATE_LOGGED_IN); if(client->state > WD_CLIENT_STATE_LOGGED_IN) { /* invalid state */ break; } if(state < 0) { 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; } } } wd_client_lock_socket(client); string = wi_socket_read_to_string(client->socket, 0.0, WI_STR(WD_MESSAGE_SEPARATOR_STR)); wd_client_unlock_socket(client); if(!string || wi_string_length(string) == 0) { if(!string) wi_log_info(WI_STR("Could not read from %@: %m"), client->ip); break; } wd_parse_command(string); if(++i % 10 == 0) { wi_release(pool); pool = NULL; } } /* announce parting if client disconnected by itself */ if(client->state == WD_CLIENT_STATE_LOGGED_IN) { client->state = WD_CLIENT_STATE_DISCONNECTED; wd_broadcast_lock(); wd_client_broadcast_leave(client, WD_PUBLIC_CID); wd_broadcast_unlock(); } /* update status for clients logged in and above */ if(client->state >= WD_CLIENT_STATE_LOGGED_IN) { wi_lock_lock(wd_status_lock); wd_current_users--; wd_write_status(true); wi_lock_unlock(wd_status_lock); } wi_log_info(WI_STR("Disconnect from %@"), client->ip); wi_socket_close(client->socket); wd_clients_remove_client(client); wi_release(pool); }
int main(int argc, const char **argv) { wi_pool_t *pool; wi_string_t *user, *password; wi_url_t *url; int ch; wi_initialize(); wi_load(argc, argv); wi_log_tool = true; wi_log_level = WI_LOG_DEBUG; pool = wi_pool_init(wi_pool_alloc()); user = WI_STR("guest"); password = WI_STR(""); wc_spec = wi_p7_spec_init_with_file(wi_p7_spec_alloc(), WI_STR("wired.xml"), WI_P7_CLIENT); while((ch = getopt(argc, (char * const *) argv, "D:U:c:p:u:")) != -1) { switch(ch) { case 'p': password = wi_string_with_cstring(optarg); break; case 'u': user = wi_string_with_cstring(optarg); break; case '?': case 'h': default: wc_usage(); break; } } argc -= optind; argv += optind; if(argc != 1) wc_usage(); url = wi_url_init_with_string(wi_url_alloc(), wi_string_with_cstring(argv[0])); wi_url_set_scheme(url, WI_STR("wired")); if(!url) wc_usage(); wi_url_set_user(url, user); wi_url_set_password(url, password); if(wi_url_port(url) == 0) wi_url_set_port(url, 4871); if(!wi_url_is_valid(url)) wc_usage(); signal(SIGPIPE, SIG_IGN); wc_client(url); wi_release(pool); return 0; }
int main(int argc, const char **argv) { wi_pool_t *pool; wi_string_t *user, *password, *root_path; wi_mutable_url_t *url; int ch; wi_initialize(); wi_load(argc, argv); wi_log_tool = true; wi_log_level = WI_LOG_DEBUG; pool = wi_pool_init(wi_pool_alloc()); user = WI_STR("guest"); password = WI_STR(""); root_path = WI_STR(WD_ROOT); while((ch = getopt(argc, (char * const *) argv, "d:p:u:")) != -1) { switch(ch) { case 'd': root_path = wi_string_with_cstring(optarg); break; case 'p': password = wi_string_with_cstring(optarg); break; case 'u': user = wi_string_with_cstring(optarg); break; case '?': case 'h': default: wc_usage(); break; } } argc -= optind; argv += optind; if(argc != 1) wc_usage(); if(!wi_fs_change_directory(root_path)) wi_log_fatal(WI_STR("Could not change directory to %@: %m"), root_path); wc_spec = wi_p7_spec_init_with_file(wi_p7_spec_alloc(), WI_STR("wired.xml"), WI_P7_CLIENT); if(!wc_spec) wi_log_fatal(WI_STR("Could not open wired.xml: %m")); url = wi_url_init_with_string(wi_mutable_url_alloc(), wi_string_with_cstring(argv[0])); wi_mutable_url_set_scheme(url, WI_STR("wired")); if(!url) wc_usage(); wi_mutable_url_set_user(url, user); wi_mutable_url_set_password(url, password); if(wi_url_port(url) == 0) wi_mutable_url_set_port(url, 4871); if(!wi_url_is_valid(url)) wc_usage(); signal(SIGPIPE, SIG_IGN); wc_test(url, 10, WI_STR("/transfertest")); wi_release(pool); return 0; }
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; }