static wi_p7_message_t * _wi_p7_socket_read_xml_message(wi_p7_socket_t *p7_socket, wi_time_interval_t timeout, wi_string_t *prefix) { wi_string_t *string; wi_p7_message_t *p7_message; p7_message = wi_autorelease(wi_p7_message_init(wi_p7_message_alloc(), p7_socket)); while(true) { string = wi_socket_read_to_string(p7_socket->socket, timeout, WI_STR(">")); if(!string || wi_string_length(string) == 0) return NULL; wi_string_delete_surrounding_whitespace(string); if(!p7_message->xml_string) p7_message->xml_string = wi_copy(string); else wi_string_append_string(p7_message->xml_string, string); if(wi_string_has_suffix(string, WI_STR("</p7:message>")) || (wi_string_has_suffix(string, WI_STR("/>")) && wi_string_has_prefix(string, WI_STR("<p7:message")))) { break; } } wi_retain(p7_message->xml_string); if(prefix) wi_string_insert_string_at_index(p7_message->xml_string, prefix, 0); wi_string_delete_surrounding_whitespace(p7_message->xml_string); return p7_message; }
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 wi_integer_t wr_runloop_server_callback(wi_socket_t *socket) { wi_string_t *string; uint32_t message = 0; string = wi_socket_read_to_string(wr_socket, 0.0, WI_STR(WR_MESSAGE_SEPARATOR_STR)); if(string && wi_string_length(string) > 0) { message = wr_parse_message(string); } else { if(!string) wr_printf_prefix(WI_STR("Could not read from server: %m")); wr_disconnect(); } return message; }
static wi_boolean_t wd_tracker_read(wd_tracker_t *tracker, uint32_t *message, wi_array_t **arguments) { wi_string_t *string; *message = 0; *arguments = NULL; string = wi_socket_read_to_string(tracker->socket, 30.0, WI_STR(WD_MESSAGE_SEPARATOR_STR)); if(string && wi_string_length(string) > 0) { wi_parse_wired_message(string, message, arguments); } else { if(!string) { wi_log_err(WI_STR("Could not read from tracker %@: %m"), tracker->host); } else { wi_log_err(WI_STR("Could not read from tracker %@: %s"), tracker->host, "Connection closed"); } } return (string != NULL); }
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); }
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); }