void wd_chat_reply_user_list(wd_chat_t *chat) { wi_enumerator_t *enumerator; wd_user_t *user; wi_array_rdlock(chat->users); enumerator = wi_array_data_enumerator(chat->users); while((user = wi_enumerator_next_data(enumerator))) { if(wd_user_state(user) == WD_USER_LOGGED_IN) { wd_reply(310, 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_unlock(chat->users); wd_reply(311, WI_STR("%u"), chat->cid); }
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); }
static wi_string_t * wd_transfers_transfer_key_for_user(wd_user_t *user) { wi_string_t *login, *ip; login = wd_user_login(user); ip = wd_user_ip(user); if(login && ip) return wi_string_by_appending_string(login, ip); return NULL; }
static wd_topic_t * wd_topic_init_with_string(wd_topic_t *topic, wi_string_t *string) { wd_user_t *user = wd_users_user_for_thread(); topic->topic = wi_retain(string); topic->date = wi_date_init(wi_date_alloc()); topic->nick = wi_copy(wd_user_nick(user)); topic->login = wi_copy(wd_user_login(user)); topic->ip = wi_copy(wd_user_ip(user)); return topic; }
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); }
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 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); }