static void wr_command_save(wi_array_t *arguments) { wi_file_t *file; wi_string_t *path, *login, *password, *port; path = wi_user_home(); path = wi_string_by_appending_path_component(path, WI_STR(WB_WIREBOT_USER_PATH)); path = wi_string_by_appending_path_component(path, WI_ARRAY(arguments, 0)); file = wi_file_for_writing(path); if(!file) { wr_printf_prefix(WI_STR("save: %@: %m"), path); return; } wi_file_write_format(file, WI_STR("charset %@\n"), wi_string_encoding_charset(wr_client_string_encoding)); wi_file_write_format(file, WI_STR("timestamp %@\n"), wr_timestamp_format); wi_file_write_format(file, WI_STR("nick %@\n"), wr_nick); if(wi_string_length(wr_status) > 0) wi_file_write_format(file, WI_STR("status %@\n"), wr_status); if(wr_icon_path) wi_file_write_format(file, WI_STR("icon %@\n"), wr_icon_path); if(wr_connected) { if(wi_string_length(wi_p7_socket_user_name(wr_p7_socket)) > 0) login = wi_string_with_format(WI_STR("-l %@"), wi_p7_socket_user_name(wr_p7_socket)); else login = NULL; if(wi_string_length(wr_password) > 0) password = wi_string_with_format(WI_STR("-p %@"), wr_password); else password = NULL; if(wi_address_port(wi_socket_address(wr_socket)) != WR_PORT) port = wi_string_with_format(WI_STR("-P %u"), wi_address_port(wi_socket_address(wr_socket))); else port = NULL; wi_file_write_format(file, WI_STR("open %#@ %#@ %#@ %@\n"), login, password, port, wi_address_string(wi_socket_address(wr_socket))); } wr_printf_prefix(WI_STR("save: \"%@\" saved"), path); }
static wi_string_t * _wi_address_description(wi_runtime_instance_t *instance) { wi_address_t *address = instance; wi_string_t *family; switch(wi_address_family(address)) { case WI_ADDRESS_IPV4: family = WI_STR("ipv4"); break; case WI_ADDRESS_IPV6: family = WI_STR("ipv6"); break; case WI_ADDRESS_NULL: default: family = WI_STR("none"); break; } return wi_string_with_format(WI_STR("<%@ %p>{family = %@, address = %@, port = %lu}"), wi_runtime_class_name(address), address, family, wi_address_string(address), wi_address_port(address)); }
static void wr_msg_400(wi_array_t *arguments) { wi_address_t *address; wr_transfer_t *transfer; transfer = wr_transfers_transfer_with_path(WI_ARRAY(arguments, 0)); if(!transfer) return; address = wi_copy(wr_address); wi_address_set_port(address, wi_address_port(address) + 1); transfer->state = WR_TRANSFER_RUNNING; transfer->offset = wi_string_uint64(WI_ARRAY(arguments, 1)); transfer->transferred = transfer->offset; transfer->key = wi_retain(WI_ARRAY(arguments, 2)); transfer->start_time = wi_time_interval(); transfer->socket = wi_socket_init_with_address(wi_socket_alloc(), address, WI_SOCKET_TCP); wi_socket_set_interactive(transfer->socket, false); if(!wi_socket_connect(transfer->socket, wr_socket_context, 15.0)) { wr_printf_prefix(WI_STR("Could not connect to %@: %m"), wi_address_string(address)); wr_transfer_stop(transfer); goto end; } wi_file_seek(transfer->file, transfer->offset); if(transfer->type == WR_TRANSFER_DOWNLOAD) { wi_socket_set_direction(transfer->socket, WI_SOCKET_READ); wr_runloop_add_socket(transfer->socket, wr_runloop_download_callback); } else { wi_socket_set_direction(transfer->socket, WI_SOCKET_WRITE); wr_runloop_add_socket(transfer->socket, wr_runloop_upload_callback); } wr_send_command_on_socket(transfer->socket, WI_STR("TRANSFER %#@"), transfer->key); wr_printf_prefix(WI_STR("Starting transfer of \"%@\""), transfer->name); wr_draw_transfers(true); end: wi_release(address); }
wi_boolean_t wi_socket_listen(wi_socket_t *socket) { struct sockaddr *sa; struct sockaddr_storage ss; wi_uinteger_t port; socklen_t length; port = wi_address_port(socket->address); sa = wi_address_sa(socket->address); length = wi_address_sa_length(socket->address); if(socket->type == WI_SOCKET_TCP) { if(wi_address_family(socket->address) == WI_ADDRESS_IPV6) _wi_socket_set_option_int(socket, IPPROTO_IPV6, IPV6_V6ONLY, 1); } if(bind(socket->sd, sa, length) < 0) { wi_error_set_errno(errno); return false; } if(socket->type == WI_SOCKET_TCP) { if(listen(socket->sd, SOMAXCONN) < 0) { wi_error_set_errno(errno); return false; } } if(port == 0) { length = sizeof(ss); if(getsockname(socket->sd, (struct sockaddr *) &ss, &length) == 0) { wi_release(socket->address); socket->address = wi_address_init_with_sa(wi_address_alloc(), (struct sockaddr *) &ss); } } socket->direction = WI_SOCKET_READ; return true; }
wi_boolean_t wi_socket_listen(wi_socket_t *socket, wi_uinteger_t backlog) { struct sockaddr *sa; struct sockaddr_storage ss; wi_uinteger_t port; socklen_t length; port = wi_address_port(socket->address); sa = wi_address_sa(socket->address); length = wi_address_sa_length(socket->address); if(bind(socket->sd, sa, length) < 0) { wi_error_set_errno(errno); return false; } if(socket->type == WI_SOCKET_TCP) { if(listen(socket->sd, backlog) < 0) { wi_error_set_errno(errno); return false; } } if(port == 0) { length = sizeof(ss); if(getsockname(socket->sd, (struct sockaddr *) &ss, &length) == 0) { wi_release(socket->address); socket->address = wi_address_init_with_sa(wi_address_alloc(), (struct sockaddr *) &ss); } } socket->direction = WI_SOCKET_READ; return true; }
wi_uinteger_t wi_socket_port(wi_socket_t *socket) { return wi_address_port(socket->address); }
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 }