void wr_transfer_download_add_file(wr_transfer_t *transfer, wr_file_t *file, wi_boolean_t recursive) { wi_string_t *remote_path, *local_path, *parent_path; remote_path = wr_file_path(file); if(recursive) { local_path = wi_string_by_appending_path_component(transfer->name, wi_string_substring_from_index(remote_path, wi_string_length(transfer->master_path))); } else { local_path = wi_string_last_path_component(remote_path); } local_path = wi_string_by_appending_path_component(wi_string_by_normalizing_path(wr_download_path), local_path); parent_path = wi_string_by_deleting_last_path_component(local_path); wi_fs_create_directory(parent_path, 0755); if(wr_file_type(file) == WR_FILE_FILE) { wi_mutable_array_add_data(transfer->remote_paths, remote_path); wi_mutable_array_add_data(transfer->local_paths, local_path); wi_mutable_array_add_data(transfer->files, file); transfer->total_size += wr_file_size(file); } else { if(!wi_fs_path_exists(local_path, NULL)) { if(!wi_fs_create_directory(local_path, 0755)) { wr_printf_prefix(WI_STR("get: Unable to create directory at %@: %m"), local_path); } } } }
wi_array_t * wd_user_subscribed_virtual_paths_for_path(wd_user_t *user, wi_string_t *path) { wi_mutable_array_t *array; wi_string_t *virtualpath; array = wi_mutable_array(); wi_recursive_lock_lock(user->user_lock); if(wi_is_equal(wi_string_last_path_component(path), WI_STR(WD_FILES_META_PATH))) { path = wi_string_by_deleting_last_path_component(path); virtualpath = wi_dictionary_data_for_key(user->subscribed_virtualpaths, path); if(virtualpath) wi_mutable_array_add_data(array, virtualpath); if(!wi_is_equal(path, WI_STR("/"))) { path = wi_string_by_deleting_last_path_component(path); virtualpath = wi_dictionary_data_for_key(user->subscribed_virtualpaths, path); if(virtualpath) wi_mutable_array_add_data(array, virtualpath); } } else { virtualpath = wi_dictionary_data_for_key(user->subscribed_virtualpaths, path); if(virtualpath) wi_mutable_array_add_data(array, virtualpath); } wi_recursive_lock_unlock(user->user_lock); return array; }
static wi_mutable_array_t * _wi_terminal_buffer_lines_for_string(wi_terminal_buffer_t *buffer, wi_string_t *string) { wi_enumerator_t *enumerator; wi_mutable_array_t *array; wi_mutable_string_t *newstring; wi_string_t *line, *subline; wi_size_t size; wi_uinteger_t index; array = wi_array_init(wi_mutable_array_alloc()); size = wi_terminal_size(buffer->terminal); enumerator = wi_array_data_enumerator(wi_string_components_separated_by_string(string, WI_STR("\n"))); while((line = wi_enumerator_next_data(enumerator))) { if(wi_terminal_width_of_string(buffer->terminal, line) < size.width) { wi_mutable_array_add_data(array, line); } else { newstring = wi_mutable_copy(line); do { index = wi_terminal_index_of_string_for_width(buffer->terminal, newstring, size.width); subline = wi_string_substring_to_index(newstring, index); wi_mutable_array_add_data(array, subline); wi_mutable_string_delete_characters_to_index(newstring, wi_string_length(subline)); } while(wi_terminal_width_of_string(buffer->terminal, newstring) >= size.width); wi_mutable_array_add_data(array, newstring); wi_release(newstring); } } return wi_autorelease(array); }
void wi_test_directory_enumerator(void) { wi_directory_enumerator_t *enumerator; wi_mutable_array_t *contents; wi_string_t *path, *subpath; wi_boolean_t result; wi_directory_enumerator_status_t status; path = wi_filesystem_temporary_path_with_template(WI_STR("/tmp/libwired-test-directory-enumerator.XXXXXXX")); path = wi_string_by_resolving_symbolic_links_in_path(path); result = wi_filesystem_create_directory_at_path(path); WI_TEST_ASSERT_TRUE(result, ""); enumerator = wi_filesystem_directory_enumerator_at_path(path); WI_TEST_ASSERT_NOT_NULL(enumerator, ""); contents = wi_mutable_array(); while((status = wi_directory_enumerator_get_next_path(enumerator, &subpath)) == WI_DIRECTORY_ENUMERATOR_PATH) wi_mutable_array_add_data(contents, subpath); WI_TEST_ASSERT_EQUALS(status, WI_DIRECTORY_ENUMERATOR_EOF, ""); WI_TEST_ASSERT_EQUALS(wi_array_count(contents), 0U, ""); result = wi_filesystem_change_current_directory_to_path(path); WI_TEST_ASSERT_TRUE(result, ""); result = wi_filesystem_create_directory_at_path(WI_STR("foo")); WI_TEST_ASSERT_TRUE(result, ""); result = wi_filesystem_create_directory_at_path(WI_STR("foo/bar")); WI_TEST_ASSERT_TRUE(result, ""); result = wi_filesystem_create_directory_at_path(WI_STR("foo/bar/baz")); WI_TEST_ASSERT_TRUE(result, ""); enumerator = wi_filesystem_directory_enumerator_at_path(path); WI_TEST_ASSERT_NOT_NULL(enumerator, ""); while((status = wi_directory_enumerator_get_next_path(enumerator, &subpath)) == WI_DIRECTORY_ENUMERATOR_PATH) wi_mutable_array_add_data(contents, subpath); WI_TEST_ASSERT_EQUALS(status, WI_DIRECTORY_ENUMERATOR_EOF, ""); WI_TEST_ASSERT_EQUALS(wi_array_count(contents), 3U, ""); WI_TEST_ASSERT_EQUAL_INSTANCES(wi_array_data_at_index(contents, 0), wi_string_by_appending_path_component(path, WI_STR("foo")), ""); WI_TEST_ASSERT_EQUAL_INSTANCES(wi_array_data_at_index(contents, 1), wi_string_by_appending_path_component(path, WI_STR("foo/bar")), ""); WI_TEST_ASSERT_EQUAL_INSTANCES(wi_array_data_at_index(contents, 2), wi_string_by_appending_path_component(path, WI_STR("foo/bar/baz")), ""); wi_filesystem_delete_path(path); }
wi_array_t * wi_dictionary_keys_sorted_by_value(wi_dictionary_t *dictionary, wi_compare_func_t *compare) { wi_mutable_array_t *array, *buckets; _wi_dictionary_bucket_t *bucket; wi_array_callbacks_t callbacks; void **data; wi_uinteger_t i; if(dictionary->key_count == 0) return wi_autorelease(wi_array_init(wi_array_alloc())); callbacks.retain = NULL; callbacks.release = NULL; callbacks.is_equal = NULL; callbacks.description = NULL; buckets = wi_array_init_with_capacity_and_callbacks(wi_mutable_array_alloc(), dictionary->key_count, callbacks); for(i = 0; i < dictionary->buckets_count; i++) { for(bucket = dictionary->buckets[i]; bucket; bucket = bucket->next) wi_mutable_array_add_data(buckets, bucket); } data = wi_malloc(sizeof(void *) * dictionary->key_count); wi_array_get_data(buckets, data); #ifdef _WI_DICTIONARY_USE_QSORT_R qsort_r(data, dictionary->key_count, sizeof(void *), compare, _wi_dictionary_compare_buckets); #else wi_lock_lock(_wi_dictionary_sort_lock); _wi_dictionary_sort_function = compare; qsort(data, dictionary->key_count, sizeof(void *), _wi_dictionary_compare_buckets); wi_lock_unlock(_wi_dictionary_sort_lock); #endif callbacks.retain = dictionary->key_callbacks.retain; callbacks.release = dictionary->key_callbacks.release; callbacks.is_equal = dictionary->key_callbacks.is_equal; callbacks.description = dictionary->key_callbacks.description; array = wi_array_init_with_capacity_and_callbacks(wi_mutable_array_alloc(), dictionary->key_count, callbacks); for(i = 0; i < dictionary->key_count; i++) wi_mutable_array_add_data(array, ((_wi_dictionary_bucket_t *) data[i])->key); wi_free(data); wi_release(buckets); wi_runtime_make_immutable(array); return wi_autorelease(array); }
void wd_transfers_queue_download(wi_string_t *path, wi_file_offset_t offset) { wd_user_t *user = wd_users_user_for_thread(); wi_string_t *realpath; wd_transfer_t *transfer; wi_fs_stat_t sb; realpath = wi_string_by_resolving_aliases_in_path(wd_files_real_path(path)); if(!wi_fs_stat_path(realpath, &sb)) { wi_log_err(WI_STR("Could not open %@: %m"), realpath); wd_reply_error(); return; } transfer = wi_autorelease(wd_transfer_init_download_with_user(wd_transfer_alloc(), user)); transfer->path = wi_retain(path); transfer->realpath = wi_retain(realpath); transfer->size = sb.size; transfer->offset = offset; transfer->transferred = offset; wi_lock_lock(wd_transfers_update_queue_lock); wi_array_wrlock(wd_transfers); wi_mutable_array_add_data(wd_transfers, transfer); wi_array_unlock(wd_transfers); wd_transfers_update_queue(); wi_lock_unlock(wd_transfers_update_queue_lock); }
static void wr_command_ignore(wi_array_t *arguments) { wi_enumerator_t *enumerator; wi_string_t *string; wr_ignore_t *ignore; if(wi_array_count(arguments) > 0) { string = WI_ARRAY(arguments, 0); ignore = wr_ignore_init_with_string(wr_ignore_alloc(), string); if(ignore) { wr_printf_prefix(WI_STR("Ignoring \"%@\""), wr_ignore_string(ignore)); wi_mutable_array_add_data(wr_ignores, ignore); wi_release(ignore); } else { wr_printf_prefix(WI_STR("ignore: Could not compile regular expression \"%@\": %m"), string); } } else { wr_printf_prefix(WI_STR("Ignores:")); if(wi_array_count(wr_ignores) == 0) { wr_printf_block(WI_STR("(none)")); } else { enumerator = wi_array_data_enumerator(wr_ignores); while((ignore = wi_enumerator_next_data(enumerator))) wr_printf_block(WI_STR("%u: %@"), wr_ignore_id(ignore), wr_ignore_string(ignore)); } } }
void wr_transfers_upload(wi_string_t *path) { wr_transfer_t *transfer; wr_file_t *file; transfer = wi_autorelease(wr_transfer_init_upload(wr_transfer_alloc())); transfer->name = wi_retain(wi_string_last_path_component(path)); transfer->master_path = wi_retain(wr_files_full_path(transfer->name)); transfer->source_path = wi_retain(wi_string_by_normalizing_path(path)); file = wi_autorelease(wr_file_init_with_local_path(wr_file_alloc(), transfer->source_path)); if(!file) { wr_printf_prefix(WI_STR("put: Could not open %@: %m"), transfer->source_path); return; } if(!wr_transfer_upload_add_file(transfer, file)) { wr_printf_prefix(WI_STR("put: Could not add files from %@: %m"), transfer->source_path); return; } wi_mutable_array_add_data(wr_transfers, transfer); if(transfer->tid == 1) wr_transfer_start(transfer); }
static void wr_msg_420(wi_array_t *arguments) { wr_file_t *file; file = wr_file_init_with_arguments(wr_file_alloc(), arguments); wi_mutable_array_add_data(wr_files, file); wi_release(file); }
wi_array_t * wi_p7_message_list_for_name(wi_p7_message_t *p7_message, wi_string_t *field_name) { wi_p7_spec_field_t *field; wi_p7_spec_type_t *listtype; wi_array_t *list; wi_runtime_instance_t *instance; unsigned char *binary; wi_p7_type_t listtype_id; uint32_t field_size, list_size, string_size; field = wi_p7_spec_field_with_name(p7_message->spec, field_name); if(!field) { wi_error_set_libwired_error_with_format(WI_ERROR_P7_UNKNOWNFIELD, WI_STR("No id found for field \"%@\""), field_name); if(wi_p7_message_debug) wi_log_debug(WI_STR("wi_p7_message_list_for_name: %m")); return NULL; } listtype = wi_p7_spec_field_listtype(field); listtype_id = wi_p7_spec_type_id(listtype); if(listtype_id != WI_P7_STRING) { wi_error_set_libwired_error_with_format(WI_ERROR_P7_UNKNOWNFIELD, WI_STR("Unhandled type %@ in list"), wi_p7_spec_type_name(listtype)); if(wi_p7_message_debug) wi_log_debug(WI_STR("wi_p7_message_list_for_name: %m")); return NULL; } list = wi_mutable_array(); if(!_wi_p7_message_get_binary_buffer_for_reading_for_name(p7_message, field_name, &binary, &field_size)) return NULL; list_size = 0; while(list_size < field_size) { if(listtype_id == WI_P7_STRING) { string_size = wi_read_swap_big_to_host_int32(binary, list_size); list_size += 4; instance = wi_string_with_bytes(binary + list_size, string_size - 1); list_size += string_size; } wi_mutable_array_add_data(list, instance); } wi_runtime_make_immutable(list); return list; }
static wi_boolean_t _wi_plist_read_node_to_instance(xmlNodePtr content_node, wi_runtime_instance_t *collection) { xmlNodePtr node; wi_string_t *key = NULL; wi_runtime_instance_t *instance = NULL; wi_boolean_t dictionary; dictionary = (wi_runtime_id(collection) == wi_dictionary_runtime_id()); for(node = content_node->children; node != NULL; node = node->next) { if(node->type == XML_ELEMENT_NODE) { if(strcmp((const char *) node->name, "key") == 0) key = wi_xml_node_content(node); else if(strcmp((const char *) node->name, "string") == 0) instance = wi_xml_node_content(node); else if(strcmp((const char *) node->name, "integer") == 0) instance = wi_number_with_integer(wi_string_integer(wi_xml_node_content(node))); else if(strcmp((const char *) node->name, "real") == 0) instance = wi_number_with_double(wi_string_double(wi_xml_node_content(node))); else if(strcmp((const char *) node->name, "true") == 0) instance = wi_number_with_bool(true); else if(strcmp((const char *) node->name, "false") == 0) instance = wi_number_with_bool(false); else if(strcmp((const char *) node->name, "date") == 0) instance = wi_date_with_rfc3339_string(wi_xml_node_content(node)); else if(strcmp((const char *) node->name, "data") == 0) instance = wi_data_with_base64(wi_xml_node_content(node)); else if(strcmp((const char *) node->name, "dict") == 0) { instance = wi_mutable_dictionary(); if(!_wi_plist_read_node_to_instance(node, instance)) return false; } else if(strcmp((const char *) node->name, "array") == 0) { instance = wi_mutable_array(); if(!_wi_plist_read_node_to_instance(node, instance)) return false; } else { wi_error_set_libwired_error_with_format(WI_ERROR_PLIST_READFAILED, WI_STR("Unhandled node \"%s\""), node->name); return false; } } if(instance) { if(dictionary) wi_mutable_dictionary_set_data_for_key(collection, instance, key); else wi_mutable_array_add_data(collection, instance); instance = NULL; key = NULL; } } return true; }
void wr_transfers_download(wi_string_t *path) { wr_transfer_t *transfer; transfer = wi_autorelease(wr_transfer_init_download(wr_transfer_alloc())); transfer->name = wi_retain(wi_string_last_path_component(path)); transfer->master_path = wi_retain(path); wi_mutable_array_add_data(wr_transfers, transfer); if(transfer->tid == 1) wr_transfer_start(transfer); }
void wr_windows_add_window(wr_window_t *window) { wi_mutable_array_add_data(wr_windows, window); wi_terminal_add_buffer(wr_terminal, window->buffer); if(wr_window_is_private_chat(window) || wr_window_is_user(window)) { if(wr_window_is_user(window)) wr_wprintf_prefix(window, WI_STR("Opened new window for private messages with %@"), wr_user_nick(window->user)); else wr_wprintf_prefix(window, WI_STR("Opened new window for private chat")); wr_wprintf_prefix(window, WI_STR("Use ctrl-N/ctrl-P to cycle windows, and /close to exit")); } }
void wd_transfers_queue_upload(wi_string_t *path, wi_file_offset_t size, wi_string_t *checksum) { wd_user_t *user = wd_users_user_for_thread(); wi_string_t *realpath, *filechecksum; wd_transfer_t *transfer; wi_file_offset_t offset; wi_fs_stat_t sb; realpath = wi_string_by_resolving_aliases_in_path(wd_files_real_path(path)); if(wi_fs_stat_path(realpath, &sb)) { wd_reply(521, WI_STR("File or Directory Exists")); return; } if(!wi_string_has_suffix(realpath, WI_STR(WD_TRANSFERS_PARTIAL_EXTENSION))) realpath = wi_string_by_appending_path_extension(realpath, WI_STR(WD_TRANSFERS_PARTIAL_EXTENSION)); if(!wi_fs_stat_path(realpath, &sb)) { offset = 0; } else { offset = sb.size; if(sb.size >= WD_FILES_CHECKSUM_SIZE) { filechecksum = wi_fs_sha1_for_path(realpath, WD_FILES_CHECKSUM_SIZE); if(!wi_is_equal(filechecksum, checksum)) { wd_reply(522, WI_STR("Checksum Mismatch")); return; } } } transfer = wi_autorelease(wd_transfer_init_upload_with_user(wd_transfer_alloc(), user)); transfer->path = wi_retain(path); transfer->realpath = wi_retain(realpath); transfer->size = size; transfer->offset = offset; transfer->transferred = offset; wi_lock_lock(wd_transfers_update_queue_lock); wi_array_wrlock(wd_transfers); wi_mutable_array_add_data(wd_transfers, transfer); wi_array_unlock(wd_transfers); wd_transfers_update_queue(); wi_lock_unlock(wd_transfers_update_queue_lock); }
void wd_chat_add_user_and_broadcast(wd_chat_t *chat, wd_user_t *user) { wd_broadcast(chat, 302, WI_STR("%u%c%u%c%u%c%u%c%u%c%#@%c%#@%c%#@%c%#@%c%#@%c%#@"), chat->cid, WD_FIELD_SEPARATOR, wd_user_uid(user), WD_FIELD_SEPARATOR, wd_user_is_idle(user), WD_FIELD_SEPARATOR, wd_user_is_admin(user), WD_FIELD_SEPARATOR, wd_user_icon(user), WD_FIELD_SEPARATOR, wd_user_nick(user), WD_FIELD_SEPARATOR, wd_user_login(user), WD_FIELD_SEPARATOR, wd_user_ip(user), WD_FIELD_SEPARATOR, wd_user_host(user), WD_FIELD_SEPARATOR, wd_user_status(user), WD_FIELD_SEPARATOR, wd_user_image(user)); wi_array_wrlock(chat->users); wi_mutable_array_add_data(chat->users, user); wi_array_unlock(chat->users); }
wi_boolean_t wd_transfers_run_transfer(wd_transfer_t *transfer, wd_user_t *user, wi_p7_message_t *message) { wi_boolean_t result = false; wi_array_wrlock(wd_transfers); wi_mutable_array_add_data(wd_transfers, transfer); wi_array_unlock(wd_transfers); wi_condition_lock_lock(wd_transfers_queue_lock); wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 1); if(wd_transfers_wait_until_ready(transfer, user, message)) { wi_condition_lock_lock(transfer->queue_lock); transfer->state = WD_TRANSFER_RUNNING; wi_condition_lock_unlock(transfer->queue_lock); if(transfer->type == WD_TRANSFER_DOWNLOAD) result = wd_transfers_run_download(transfer, user, message); else result = wd_transfers_run_upload(transfer, user, message); wi_condition_lock_lock(transfer->finished_lock); wi_condition_lock_unlock_with_condition(transfer->finished_lock, 1); } else { wi_log_error(WI_STR("Could not process %@ for %@: %m"), (transfer->type == WD_TRANSFER_DOWNLOAD) ? WI_STR("download") : WI_STR("upload"), wd_user_identifier(user)); } if(transfer->queue == 0) wd_transfers_add_or_remove_transfer(transfer, false); wi_array_wrlock(wd_transfers); wi_mutable_array_remove_data(wd_transfers, transfer); wi_array_unlock(wd_transfers); wi_condition_lock_lock(wd_transfers_queue_lock); wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 1); return result; }
wi_array_t * wd_users_users_with_login(wi_string_t *name) { wi_enumerator_t *enumerator; wi_mutable_array_t *users; wd_user_t *user; users = wi_mutable_array(); wi_dictionary_rdlock(wd_users); enumerator = wi_dictionary_data_enumerator(wd_users); while((user = wi_enumerator_next_data(enumerator))) { if(wi_is_equal(wd_user_login(user), name)) wi_mutable_array_add_data(users, user); } wi_dictionary_unlock(wd_users); return users; }
wi_array_t * wi_set_all_data(wi_set_t *set) { wi_array_t *array; _wi_set_bucket_t *bucket; wi_array_callbacks_t callbacks; wi_uinteger_t i; callbacks.retain = set->callbacks.retain; callbacks.release = set->callbacks.release; callbacks.is_equal = set->callbacks.is_equal; callbacks.description = set->callbacks.description; array = wi_array_init_with_capacity_and_callbacks(wi_mutable_array_alloc(), set->data_count, callbacks); for(i = 0; i < set->buckets_count; i++) { for(bucket = set->buckets[i]; bucket; bucket = bucket->next) wi_mutable_array_add_data(array, bucket->data); } wi_runtime_make_immutable(array); return wi_autorelease(array); }
wi_array_t * wi_dictionary_all_values(wi_dictionary_t *dictionary) { wi_array_t *array; _wi_dictionary_bucket_t *bucket; wi_array_callbacks_t callbacks; wi_uinteger_t i; callbacks.retain = dictionary->value_callbacks.retain; callbacks.release = dictionary->value_callbacks.release; callbacks.is_equal = dictionary->value_callbacks.is_equal; callbacks.description = dictionary->value_callbacks.description; array = wi_array_init_with_capacity_and_callbacks(wi_mutable_array_alloc(), dictionary->key_count, callbacks); for(i = 0; i < dictionary->buckets_count; i++) { for(bucket = dictionary->buckets[i]; bucket; bucket = bucket->next) wi_mutable_array_add_data(array, bucket->data); } wi_runtime_make_immutable(array); return wi_autorelease(array); }
static wb_command_t * _wb_command_load_with_node(wb_command_t *command, xmlNodePtr node) { wi_string_t *permissions, *activated, *name; wb_output_t *output; xmlNodePtr sub_node, next_node; // get command name name = wi_xml_node_attribute_with_name(node, WI_STR("name")); if(name) command->name = wi_retain(name); // get command permissions permissions = wi_xml_node_attribute_with_name(node, WI_STR("permissions")); if(permissions) command->permissions = wi_retain(permissions); // is an activated command ? activated = wi_xml_node_attribute_with_name(node, WI_STR("activated")); if(activated) command->activated = wi_is_equal(activated, WI_STR("true")) ? true : false; // get rule children: outputs for(sub_node = node->children; sub_node != NULL; sub_node = next_node) { next_node = sub_node->next; if(sub_node->type == XML_ELEMENT_NODE) { if(strcmp((const char *) sub_node->name, "output") == 0) { output = wb_output_init(wb_output_alloc(), sub_node); if(output) wi_mutable_array_add_data(command->outputs, output); wi_release(output); } } } return command; }
wi_array_t * wi_backtrace(void) { #ifdef HAVE_BACKTRACE wi_mutable_array_t *array; void *callstack[128]; char **symbols; int i, frames; frames = backtrace(callstack, sizeof(callstack)); symbols = backtrace_symbols(callstack, frames); array = wi_array_init_with_capacity(wi_mutable_array_alloc(), frames); for(i = 0; i < frames; i++) wi_mutable_array_add_data(array, wi_string_with_utf8_string(symbols[i])); free(symbols); wi_runtime_make_immutable(array); return wi_autorelease(array); #else return NULL; #endif }
void wi_socket_initialize(void) { #ifdef HAVE_OPENSSL_SSL_H #ifdef WI_PTHREADS wi_lock_t *lock; wi_uinteger_t i, count; #endif SSL_library_init(); #ifdef WI_PTHREADS count = CRYPTO_num_locks(); _wi_socket_ssl_locks = wi_array_init_with_capacity(wi_mutable_array_alloc(), count); for(i = 0; i < count; i++) { lock = wi_lock_init(wi_lock_alloc()); wi_mutable_array_add_data(_wi_socket_ssl_locks, lock); wi_release(lock); } CRYPTO_set_id_callback(_wi_socket_ssl_id_function); CRYPTO_set_locking_callback(_wi_socket_ssl_locking_function); #endif #endif }
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); }
wi_boolean_t wr_transfer_upload_add_file(wr_transfer_t *transfer, wr_file_t *file) { WI_FTS *fts = NULL; WI_FTSENT *p; wi_string_t *local_path, *remote_path; wr_file_t *fts_file; char *paths[2]; if(wr_file_type(file) == WR_FILE_FILE) { wi_mutable_array_add_data(transfer->local_paths, wr_file_path(file)); wi_mutable_array_add_data(transfer->remote_paths, wr_files_full_path(transfer->name)); wi_mutable_array_add_data(transfer->files, file); transfer->total_size += wr_file_size(file); } else { wr_transfers_recursive_upload = true; transfer->recursive = true; paths[0] = (char *) wi_string_cstring(wr_file_path(file)); paths[1] = NULL; errno = 0; fts = wi_fts_open(paths, WI_FTS_NOSTAT | WI_FTS_LOGICAL, NULL); if(!fts) return false; if(fts && errno != 0) { wi_fts_close(fts); return false; } while((p = wi_fts_read(fts))) { if(p->fts_level > 10) { wi_fts_set(fts, p, WI_FTS_SKIP); continue; } switch(p->fts_info) { case WI_FTS_DC: errno = ELOOP; wr_printf_prefix(WI_STR("put: Could not read %s: %s"), strerror(errno)); continue; break; case WI_FTS_DP: continue; break; case WI_FTS_DNR: case WI_FTS_ERR: wr_printf_prefix(WI_STR("put: Could not read %s: %s"), strerror(p->fts_errno)); continue; break; } if(p->fts_name[0] == '.') { wi_fts_set(fts, p, WI_FTS_SKIP); continue; } local_path = wi_string_with_cstring(p->fts_path); remote_path = wi_string_by_normalizing_path(wi_string_by_appending_path_component(transfer->master_path, wi_string_substring_from_index(local_path, wi_string_length(transfer->source_path)))); if(p->fts_info == WI_FTS_D) { // wr_send_command(WI_STR("FOLDER %#@"), remote_path); } else { wi_mutable_array_add_data(transfer->local_paths, local_path); wi_mutable_array_add_data(transfer->remote_paths, remote_path); fts_file = wr_file_init_with_local_path(wr_file_alloc(), local_path); transfer->total_size += wr_file_size(fts_file); wi_mutable_array_add_data(transfer->files, fts_file); wi_release(fts_file); } } wi_fts_close(fts); } return true; }
static void wd_transfers_update_queue(void) { wi_mutable_set_t *users; wi_mutable_array_t *sorted_users, *transfers_queue, *failed_transfers; wd_transfer_t *transfer; wd_user_t *user; wi_uinteger_t position; wi_uinteger_t i, count; wi_uinteger_t total_downloads, total_uploads, user_downloads, user_uploads, active_downloads, active_uploads; wi_boolean_t queue; wi_array_rdlock(wd_transfers); total_downloads = wd_settings.totaldownloads; user_downloads = wd_settings.clientdownloads; total_uploads = wd_settings.totaluploads; user_uploads = wd_settings.clientuploads; active_downloads = 0; active_uploads = 0; failed_transfers = wi_array_init(wi_mutable_array_alloc()); users = wi_set_init(wi_mutable_set_alloc()); count = wi_array_count(wd_transfers); for(i = 0; i < count; i++) { transfer = WI_ARRAY(wd_transfers, i); if(wd_transfer_state(transfer) == WD_TRANSFER_QUEUED) { wi_mutable_array_add_data(wd_user_transfers_queue(transfer->user), transfer); wi_mutable_set_add_data(users, transfer->user); } wd_user_clear_downloads(transfer->user); wd_user_clear_uploads(transfer->user); } for(i = 0; i < count; i++) { transfer = WI_ARRAY(wd_transfers, i); if(wd_transfer_state(transfer) == WD_TRANSFER_RUNNING) { if(transfer->type == WD_TRANSFER_DOWNLOAD) { active_downloads++; wd_user_increase_downloads(transfer->user); } else { active_uploads++; wd_user_increase_uploads(transfer->user); } } } count = wi_set_count(users); if(count > 0) { sorted_users = wi_autorelease(wi_mutable_copy(wi_set_all_data(users))); wi_mutable_array_sort(sorted_users, wd_transfers_compare_user); position = 1; while(count > 0) { for(i = 0; i < count; i++) { user = WI_ARRAY(sorted_users, i); transfers_queue = wd_user_transfers_queue(user); transfer = WI_ARRAY(transfers_queue, 0); if(transfer->type == WD_TRANSFER_DOWNLOAD) { queue = ((total_downloads > 0 && active_downloads >= total_downloads) || (user_downloads > 0 && wd_user_downloads(transfer->user) >= user_downloads)); } else { queue = ((total_uploads > 0 && active_uploads >= total_uploads) || (user_uploads > 0 && wd_user_uploads(transfer->user) >= user_uploads)); } if(queue) { if(transfer->queue != position) { transfer->queue = position; wd_user_lock_socket(transfer->user); wd_sreply(wd_user_socket(transfer->user), 401, WI_STR("%#@%c%u"), transfer->path, WD_FIELD_SEPARATOR, transfer->queue); wd_user_unlock_socket(transfer->user); } position++; } else { transfer->queue = 0; transfer->waiting_time = wi_time_interval(); wd_transfer_set_state(transfer, WD_TRANSFER_WAITING); if(wd_transfer_open(transfer)) { wd_transfer_create_timer(transfer); wd_user_lock_socket(transfer->user); wd_sreply(wd_user_socket(transfer->user), 400, WI_STR("%#@%c%llu%c%#@"), transfer->path, WD_FIELD_SEPARATOR, transfer->offset, WD_FIELD_SEPARATOR, transfer->hash); wd_user_unlock_socket(transfer->user); } else { wd_user_lock_socket(transfer->user); wd_sreply(wd_user_socket(transfer->user), 500, WI_STR("Command Failed")); wd_user_unlock_socket(transfer->user); wi_mutable_array_add_data(failed_transfers, transfer); } } wi_mutable_array_remove_data_at_index(transfers_queue, 0); if(wi_array_count(transfers_queue) == 0) { wi_mutable_array_remove_data_at_index(sorted_users, i); i--; count--; } } } } wi_mutable_array_remove_data_in_array(wd_transfers, failed_transfers); wi_array_unlock(wd_transfers); wi_release(users); wi_release(failed_transfers); }
void wi_terminal_add_buffer(wi_terminal_t *terminal, wi_terminal_buffer_t *buffer) { wi_mutable_array_add_data(terminal->buffers, buffer); }
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; }
void wd_server_init(void) { wi_enumerator_t *enumerator; wi_array_t *array, *addresses; wi_address_t *address; wi_socket_t *control_socket, *transfer_socket; wi_string_t *ip, *string; wi_address_family_t family; wd_control_sockets = wi_array_init(wi_mutable_array_alloc()); wd_transfer_sockets = wi_array_init(wi_mutable_array_alloc()); addresses = wi_array_init(wi_mutable_array_alloc()); if(wi_array_count(wd_settings.address) > 0) { /* listen on configured addresses */ wi_array_rdlock(wd_settings.address); enumerator = wi_array_data_enumerator(wd_settings.address); while((string = wi_enumerator_next_data(enumerator))) { array = wi_host_addresses(wi_host_with_string(string)); if(array) wi_mutable_array_add_data_from_array(addresses, array); else wi_log_err(WI_STR("Could not resolve \"%@\": %m"), string); } wi_array_unlock(wd_settings.address); } else { /* add wildcard addresses */ wi_mutable_array_add_data(addresses, wi_address_wildcard_for_family(WI_ADDRESS_IPV6)); wi_mutable_array_add_data(addresses, wi_address_wildcard_for_family(WI_ADDRESS_IPV4)); } enumerator = wi_array_data_enumerator(addresses); while((address = wi_enumerator_next_data(enumerator))) { ip = wi_address_string(address); family = wi_address_family(address); /* force address family? */ if(wd_address_family != WI_ADDRESS_NULL && family != wd_address_family) continue; /* create sockets */ wi_address_set_port(address, wd_settings.port); control_socket = wi_autorelease(wi_socket_init_with_address(wi_socket_alloc(), address, WI_SOCKET_TCP)); wi_address_set_port(address, wd_settings.port + 1); transfer_socket = wi_autorelease(wi_socket_init_with_address(wi_socket_alloc(), address, WI_SOCKET_TCP)); if(!control_socket || !transfer_socket) { wi_log_warn(WI_STR("Could not create socket for %@: %m"), ip); continue; } /* listen on sockets */ if(!wi_socket_listen(control_socket)) { wi_log_warn(WI_STR("Could not listen on %@ port %u: %m"), ip, wi_address_port(wi_socket_address(control_socket))); continue; } if(!wi_socket_listen(transfer_socket)) { wi_log_warn(WI_STR("Could not listen on %@ port %u: %m"), ip, wi_address_port(wi_socket_address(transfer_socket))); continue; } wi_socket_set_interactive(control_socket, true); wi_socket_set_interactive(transfer_socket, false); /* add to list of sockets */ wi_mutable_array_add_data(wd_control_sockets, control_socket); wi_mutable_array_add_data(wd_transfer_sockets, transfer_socket); wi_log_info(WI_STR("Listening on %@ ports %d-%d"), ip, wd_settings.port, wd_settings.port + 1); } if(wi_array_count(wd_control_sockets) == 0 || wi_array_count(wd_transfer_sockets) == 0) wi_log_fatal(WI_STR("No addresses available for listening")); wi_release(addresses); #ifdef HAVE_DNS_SD_H if(wd_settings.zeroconf) wd_server_register_dnssd(); #endif }
wi_boolean_t wi_config_read_file(wi_config_t *config) { wi_enumerator_t *enumerator; wi_runtime_instance_t *instance; wi_file_t *file; wi_mutable_array_t *array; wi_mutable_dictionary_t *previous_values; wi_string_t *string, *name, *value; wi_config_type_t type; file = wi_file_for_reading(config->path); if(!file) { wi_log_err(WI_STR("Could not open %@: %m"), config->path); return false; } wi_log_info(WI_STR("Reading %@"), config->path); config->line = 0; wi_lock_lock(config->lock); previous_values = config->values; config->values = wi_dictionary_init(wi_mutable_dictionary_alloc()); if(config->defaults) { enumerator = wi_dictionary_key_enumerator(config->defaults); while((name = wi_enumerator_next_data(enumerator))) { // instance = wi_mutable_copy(wi_dictionary_data_for_key(config->defaults, name)); instance = wi_dictionary_data_for_key(config->defaults, name); if(wi_runtime_id(instance) == wi_array_runtime_id()) instance = wi_autorelease(wi_mutable_copy(instance)); wi_mutable_dictionary_set_data_for_key(config->values, instance, name); // wi_release(instance); } } while((string = wi_file_read_line(file))) { config->line++; if(wi_string_length(string) > 0 && !wi_string_has_prefix(string, WI_STR("#"))) { if(_wi_config_parse_string(config, string, &name, &value)) { instance = _wi_config_instance_for_setting(config, name, value, &type); if(instance) { wi_log_debug(WI_STR(" %@ = %@"), name, value); if(type == WI_CONFIG_STRINGLIST) { array = wi_dictionary_data_for_key(config->values, name); if(!array) { array = wi_mutable_array(); wi_mutable_dictionary_set_data_for_key(config->values, array, name); } wi_mutable_array_add_data(array, instance); } else { wi_mutable_dictionary_set_data_for_key(config->values, instance, name); } } else { _wi_config_log_error(config, name); } } else { wi_error_set_libwired_error(WI_ERROR_SETTINGS_SYNTAXERROR); _wi_config_log_error(config, string); } } } enumerator = wi_dictionary_key_enumerator(config->values); while((name = wi_enumerator_next_data(enumerator))) { instance = wi_dictionary_data_for_key(config->values, name); if(!previous_values || !wi_is_equal(instance, wi_dictionary_data_for_key(previous_values, name))) wi_mutable_set_add_data(config->changes, name); } wi_release(previous_values); wi_lock_unlock(config->lock); return true; }
void wd_trackers_apply_settings(void) { wi_enumerator_t *enumerator, *address_enumerator; wi_string_t *string, *path; wi_url_t *url; wi_address_t *address; wd_tracker_t *tracker; wi_uinteger_t port; wi_array_wrlock(wd_trackers); wi_mutable_array_remove_all_data(wd_trackers); enumerator = wi_array_data_enumerator(wd_settings.tracker); while((string = wi_enumerator_next_data(enumerator))) { tracker = wi_autorelease(wd_tracker_init(wd_tracker_alloc())); url = wi_autorelease(wi_url_init_with_string(wi_url_alloc(), string)); if(!wi_url_is_valid(url)) { wi_log_warn(WI_STR("Could not parse tracker URL \"%@\""), string); continue; } tracker->tls = wi_socket_tls_init_with_type(wi_socket_tls_alloc(), WI_SOCKET_TLS_CLIENT); if(!tracker->tls) { wi_log_warn(WI_STR("Could not create TLS context: %m")); continue; } if(wd_settings.controlcipher) { if(!wi_socket_tls_set_ciphers(tracker->tls, wd_settings.controlcipher)) { wi_log_err(WI_STR("Could not set TLS cipher list \"%@\": %m"), wd_settings.controlcipher); continue; } } path = wi_url_path(url); if(!path || wi_string_length(path) == 0) path = WI_STR("/"); tracker->host = wi_retain(wi_url_host(url)); tracker->category = wi_retain(wi_string_substring_from_index(path, 1)); tracker->addresses = wi_retain(wi_host_addresses(wi_host_with_string(tracker->host))); if(!tracker->addresses) { wi_log_warn(WI_STR("Could not resolve \"%@\": %m"), tracker->host); continue; } port = wi_url_port(url); if(port == 0) port = WD_TRACKER_PORT; address_enumerator = wi_array_data_enumerator(tracker->addresses); while((address = wi_enumerator_next_data(address_enumerator))) wi_address_set_port(address, port); wi_mutable_array_add_data(wd_trackers, tracker); } wi_array_unlock(wd_trackers); }