Exemplo n.º 1
0
void wi_test_host_runtime_functions(void) {
    wi_host_t   *host1, *host2, *host3, *host4, *host5, *host6;
    
    host1 = wi_host();
    host2 = wi_autorelease(wi_copy(host1));
    host3 = wi_host_with_string(WI_STR("localhost"));
    host4 = wi_autorelease(wi_copy(host3));
    host5 = wi_host_with_string(WI_STR("aab119a592b9e23779b66649677b436d24b35aaa5ad5beadf4c2a945b70577e5.com"));
    host6 = wi_autorelease(wi_copy(host5));
    
    WI_TEST_ASSERT_EQUAL_INSTANCES(host1, host2, "");
    WI_TEST_ASSERT_EQUAL_INSTANCES(host3, host4, "");
    WI_TEST_ASSERT_EQUAL_INSTANCES(host5, host6, "");
    WI_TEST_ASSERT_NOT_EQUAL_INSTANCES(host1, host3, "");
    WI_TEST_ASSERT_NOT_EQUAL_INSTANCES(host2, host3, "");
    WI_TEST_ASSERT_NOT_EQUAL_INSTANCES(host1, host4, "");
    WI_TEST_ASSERT_NOT_EQUAL_INSTANCES(host2, host4, "");
    WI_TEST_ASSERT_NOT_EQUAL_INSTANCES(host1, host5, "");
    WI_TEST_ASSERT_NOT_EQUAL_INSTANCES(host2, host5, "");
    WI_TEST_ASSERT_NOT_EQUAL_INSTANCES(host1, host6, "");
    WI_TEST_ASSERT_NOT_EQUAL_INSTANCES(host2, host6, "");
    WI_TEST_ASSERT_EQUALS(wi_hash(host1), wi_hash(host2), "");
    WI_TEST_ASSERT_EQUALS(wi_hash(host3), wi_hash(host4), "");
    WI_TEST_ASSERT_EQUALS(wi_hash(host5), wi_hash(host6), "");
    WI_TEST_ASSERT_EQUALS(wi_runtime_id(host1), wi_host_runtime_id(), "");
    WI_TEST_ASSERT_EQUALS(wi_runtime_id(host2), wi_host_runtime_id(), "");
    WI_TEST_ASSERT_EQUALS(wi_runtime_id(host3), wi_host_runtime_id(), "");
    WI_TEST_ASSERT_EQUALS(wi_runtime_id(host4), wi_host_runtime_id(), "");
    WI_TEST_ASSERT_EQUALS(wi_runtime_id(host5), wi_host_runtime_id(), "");
    WI_TEST_ASSERT_EQUALS(wi_runtime_id(host6), wi_host_runtime_id(), "");
    
#ifdef HAVE_GETIFADDRS
    WI_TEST_ASSERT_NOT_EQUALS(wi_string_index_of_string(wi_description(host1), WI_STR("127.0.0.1"), 0), WI_NOT_FOUND, "");
#else
    WI_TEST_ASSERT_NOT_EQUALS(wi_string_index_of_string(wi_description(host1), WI_STR("0.0.0.0"), 0), WI_NOT_FOUND, "");
#endif

    WI_TEST_ASSERT_NOT_EQUALS(wi_string_index_of_string(wi_description(host3), WI_STR("127.0.0.1"), 0), WI_NOT_FOUND, "");
}
Exemplo n.º 2
0
void wi_test_host_creation(void) {
    wi_host_t   *host;
    
    host = wi_host();
    
    WI_TEST_ASSERT_NOT_NULL(host, "");
    WI_TEST_ASSERT_NOT_NULL(wi_host_address(host), "");
    
    host = wi_host_with_string(WI_STR("localhost"));
    
    WI_TEST_ASSERT_NOT_NULL(host, "");
    WI_TEST_ASSERT_NOT_NULL(wi_host_address(host), "");
}
Exemplo n.º 3
0
void wi_test_host_addresses(void) {
    wi_host_t   *host;
    wi_array_t  *addresses;
    
    host = wi_host();
    addresses = wi_host_addresses(host);
    
    WI_TEST_ASSERT_TRUE(wi_array_count(addresses) > 0, "");
    WI_TEST_ASSERT_TRUE(wi_array_contains_data(addresses, wi_host_address(host)), "");
    
#ifndef HAVE_GETIFADDRS
    WI_TEST_ASSERT_TRUE(wi_array_contains_data(addresses, wi_address_wildcard_for_family(WI_ADDRESS_IPV4)), "");
    WI_TEST_ASSERT_TRUE(wi_array_contains_data(addresses, wi_address_wildcard_for_family(WI_ADDRESS_IPV6)), "");
#endif
    
    host = wi_host_with_string(WI_STR("aab119a592b9e23779b66649677b436d24b35aaa5ad5beadf4c2a945b70577e5.com"));

    WI_TEST_ASSERT_NULL(wi_host_addresses(host), "");
    WI_TEST_ASSERT_NULL(wi_host_address(host), "");
}
Exemplo n.º 4
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
}
Exemplo n.º 5
0
void wr_client_connect(wi_string_t *hostname, wi_uinteger_t port, wi_string_t *login, wi_string_t *password) {
	wi_enumerator_t		*enumerator;
	wi_array_t			*addresses;
	wi_address_t		*address;
	wi_p7_socket_t		*p7_socket;
	wi_p7_message_t		*message;
	wi_socket_t			*socket;
	wi_string_t			*ip;
	wr_server_t			*server;
	
	if(wr_connected)
		wr_client_disconnect();
	
	wr_printf_prefix(WI_STR("Connecting to %@..."), hostname);
	
	if(port == 0)
		port = WR_PORT;
	
	if(!login)
		login = WI_STR("guest");
	
	if(!password)
		password = WI_STR("");
	
	addresses = wi_host_addresses(wi_host_with_string(hostname));
	
	if(!addresses) {
		wr_printf_prefix(WI_STR("Could not resolve \"%@\": %m"),
			hostname);
		
		return;
	}
	
	enumerator = wi_array_data_enumerator(addresses);
	
	while((address = wi_enumerator_next_data(enumerator))) {
		ip = wi_address_string(address);

		wr_printf_prefix(WI_STR("Trying %@ at port %u..."), ip, port);
		
		wi_address_set_port(address, port);
		
		socket = wi_autorelease(wi_socket_init_with_address(wi_socket_alloc(), address, WI_SOCKET_TCP));
		
		if(!socket) {
			wr_printf_prefix(WI_STR("Could not open a socket to %@: %m"), ip);
			
			continue;
		}
		
		wi_socket_set_interactive(socket, true);
		
		if(!wi_socket_connect(socket, 10.0)) {
			wr_printf_prefix(WI_STR("Could not connect to %@: %m"), ip);

			continue;
		}
		
		p7_socket = wi_autorelease(wi_p7_socket_init_with_socket(wi_p7_socket_alloc(), socket, wr_p7_spec));
		
		if(!wi_p7_socket_connect(p7_socket,
								 10.0,
								 WI_P7_COMPRESSION_DEFLATE | WI_P7_ENCRYPTION_RSA_AES256_SHA1 | WI_P7_CHECKSUM_SHA1,
								 WI_P7_BINARY,
								 login,
								 wi_string_sha1(password))) {
			wr_printf_prefix(WI_STR("Could not connect to %@: %m"), ip);
			
			continue;
		}
		
		wr_printf_prefix(WI_STR("Connected using %@/%u bits, logging in..."),
			wi_cipher_name(wi_p7_socket_cipher(p7_socket)),
			wi_cipher_bits(wi_p7_socket_cipher(p7_socket)));
		
		server = wr_client_login(p7_socket, login, password);
		
		if(!server)
			break;

		wr_printf_prefix(WI_STR("Logged in, welcome to %@"), wr_server_name(server));
		
		message = wi_p7_message_with_name(WI_STR("wired.chat.join_chat"), wr_p7_spec);
		wi_p7_message_set_uint32_for_name(message, wr_chat_id(wr_public_chat), WI_STR("wired.chat.id"));
		wr_client_write_message(p7_socket, message);
		
		wr_connected	= true;
		wr_socket		= wi_retain(socket);
		wr_p7_socket	= wi_retain(p7_socket);
		wr_server		= wi_retain(server);
		wr_password		= wi_retain(password);
		
		wi_socket_set_direction(wr_socket, WI_SOCKET_READ);
		wr_runloop_add_socket(wr_socket, &wr_runloop_server_callback);

		break;
	}
		
	wr_draw_divider();
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
void wr_connect(wi_string_t *hostname, wi_uinteger_t port, wi_string_t *login, wi_string_t *password) {
	wi_enumerator_t		*enumerator;
	wi_array_t			*addresses;
	wi_address_t		*address;
	wi_socket_t			*socket;
	wi_string_t			*ip;
	
	if(wr_connected)
		wr_disconnect();
	
	wr_printf_prefix(WI_STR("Connecting to %@..."), hostname);
	
	if(port == 0)
		port = WR_CONTROL_PORT;
	
	addresses = wi_host_addresses(wi_host_with_string(hostname));
	
	if(!addresses) {
		wr_printf_prefix(WI_STR("Could not resolve \"%@\": %m"),
			hostname);
		
		return;
	}
	
	enumerator = wi_array_data_enumerator(addresses);
	
	while((address = wi_enumerator_next_data(enumerator))) {
		ip = wi_address_string(address);

		wr_printf_prefix(WI_STR("Trying %@ at port %u..."), ip, port);
		
		wi_address_set_port(address, port);
		
		socket = wi_autorelease(wi_socket_init_with_address(wi_socket_alloc(), address, WI_SOCKET_TCP));
		
		if(!socket) {
			wr_printf_prefix(WI_STR("Could not open a socket to %@: %m"), ip);
			
			continue;
		}
		
		wi_socket_set_interactive(socket, true);
		
		if(!wi_socket_connect(socket, 10.0)) {
			wr_printf_prefix(WI_STR("Could not connect to %@: %m"), ip);

			continue;
		}

		if(!wi_socket_connect_tls(socket, wr_socket_tls, 10.0)) {
			wr_printf_prefix(WI_STR("Could not connect to %@: %m"), ip);

			continue;
		}

		wr_printf_prefix(WI_STR("Connected using %@/%@/%u bits, logging in..."),
			wi_socket_cipher_version(socket),
			wi_socket_cipher_name(socket),
			wi_socket_cipher_bits(socket));

		wr_connected	= true;
		wr_host			= wi_retain(hostname);
		wr_port			= port;
		wr_login		= wi_retain(login);
		wr_password		= wi_retain(password);
		wr_socket		= wi_retain(socket);
		wr_address		= wi_retain(address);
		
		wr_runloop_add_socket(wr_socket, &wr_runloop_server_callback);
		wr_send_command(WI_STR("HELLO"));

		break;
	}

	if(wr_socket)
		wi_socket_set_direction(wr_socket, WI_SOCKET_READ);
}
Exemplo n.º 8
0
static void wt_cmd_register(wi_array_t *arguments) {
	wt_client_t					*client = wt_client();
	wi_enumerator_t				*enumerator;
	wi_array_t					*array;
	wi_address_t				*address, *hostaddress;
	wi_url_t					*url;
	wi_string_t					*hostname;
	wt_server_t					*server;
	wi_boolean_t				failed = false, passed;
	uint32_t					bandwidth;

	url			= wi_autorelease(wi_url_init_with_string(wi_url_alloc(), WI_ARRAY(arguments, 1)));
	hostname	= wi_url_host(url);
	address		= wi_socket_address(client->socket);
	
	if(!wi_url_is_valid(url)) {
		/* invalid URL */
		if(wt_settings.strictlookup) {
			wt_reply(503, WI_STR("Syntax Error"));
			wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ aborted: %s"),
				client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1),
				"Invalid URL");
			
			return;
		}
		
		failed = true;
		goto failed;
	}

	if(wi_ip_version(hostname) > 0) {
		/* hostname is numeric, compare with source address */
		if(!wi_is_equal(hostname, client->ip)) {
			/* IP mismatch */
			if(wt_settings.strictlookup) {
				wt_reply(530, WI_STR("Address Mismatch"));
				wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ denied: %s"),
					client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1),
					"IP mismatch");

				return;
			}

			failed = true;
			goto failed;
		}
	} else {
		/* hostname is symbolic */
		if(wt_settings.lookup) {
			/* look up and compare with source address */
			passed = false;
			array = wi_host_addresses(wi_host_with_string(hostname));
			
			if(array) {
				enumerator = wi_array_data_enumerator(array);
				
				while((hostaddress = wi_enumerator_next_data(enumerator))) {
					if(wi_is_equal(hostaddress, address)) {
						passed = true;
						
						break;
					}
				}
			}
			
			if(!passed) {
				/* lookup failed */
				if(wt_settings.strictlookup) {
					wt_reply(531, WI_STR("Address Mismatch"));
					wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ denied: %s"),
						client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1),
						"Lookup failed");
					
					return;
				}
				
				failed = true;
				goto failed;
			}
		}

		if(wt_settings.reverselookup) {
			/* reverse look up and compare to hostname */
			if(!wi_is_equal(wi_address_hostname(address), hostname)) {
				/* reverse lookup failed */
				if(wt_settings.strictlookup) {
					wt_reply(531, WI_STR("Address Mismatch"));
					wi_log_warn(WI_STR("Register from %@ as \"%@\" URL % denied: %@"),
						client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1),
						"Reverse lookup failed");

					return;
				}

				failed = true;
				goto failed;
			}
		}
	}

failed:
	/* get bandwidth */
	bandwidth = wi_string_uint32(WI_ARRAY(arguments, 3));

	/* bandwidth too low? */
	if(wt_settings.minbandwidth > 0 && bandwidth < wt_settings.minbandwidth) {
		wt_reply(516, WI_STR("Permission Denied"));
		wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ denied: Bandwidth %.0f Kbps considered too low"),
			client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1), bandwidth / 128.0);

		return;
	}

	/* bandwidth too high? */
	if(wt_settings.maxbandwidth > 0 && bandwidth > wt_settings.maxbandwidth) {
		wt_reply(516, WI_STR("Permission Denied"));
		wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ denied: Bandwidth %.0f Kbps considered too high"),
			client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1), bandwidth / 128.0);

		return;
	}

	/* is there an existing server from this host? */
	server = wt_servers_server_with_ip(client->ip);

	if(server) {
		if(server->port == wi_url_port(url)) {
			/* remove existing server in preparation for re-registration */
			wt_servers_remove_stats_for_server(server);
			wt_servers_remove_server(server);
		} else {
			/* multiple servers from the same IP allowed? */
			if(!wt_settings.allowmultiple) {
				wt_reply(530, WI_STR("Address Registered"));
				wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ denied: %s"),
					client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1),
					"A server from the same address is already registered");
				
				return;
			}
		}
	}
	
	/* rewrite URL if host verification failed */
	if(failed) {
		wi_url_set_scheme(url, WI_STR("wired"));
		wi_url_set_host(url, client->ip);

		if(wi_string_length(WI_ARRAY(arguments, 1)) == 0)
			wi_log_info(WI_STR("Rewriting URL to %@"), wi_url_string(url));
		else
			wi_log_info(WI_STR("Rewriting URL from %@ to %@"), WI_ARRAY(arguments, 1), wi_url_string(url));
	}

	/* create new server */
	server					= wt_server_init(wt_server_alloc());
	server->key				= wi_retain(wi_string_sha1(wi_autorelease(wi_string_init_random_string_with_length(wi_string_alloc(), 1024))));
	server->port			= wi_url_port(url);
	server->bandwidth		= bandwidth;
	server->register_time	= wi_time_interval();
	server->update_time		= 0.0;
	server->ip				= wi_retain(client->ip);
	server->category		= wt_servers_category_is_valid(WI_ARRAY(arguments, 0))
		? wi_retain(WI_ARRAY(arguments, 0))
		: wi_string_init(wi_string_alloc());
	server->name			= wi_retain(WI_ARRAY(arguments, 2));
	server->description		= wi_retain(WI_ARRAY(arguments, 4));
	server->url				= wi_copy(wi_url_string(url));

	wt_servers_add_server(server);
	wt_servers_add_stats_for_server(server);
	
	/* reply 700 */
	wt_reply(700, WI_STR("%@"), server->key);
	wi_log_info(WI_STR("Registered \"%@\" with URL %@"), server->name, server->url);
	wt_servers_write_file();
	wi_release(server);
}
Exemplo n.º 9
0
void wr_connect(wi_string_t *hostname, unsigned int port, wi_string_t *login, wi_string_t *password) {
	wi_list_t			*addresses;
	wi_list_node_t		*node;
	wi_address_t		*address;
	wi_socket_t			*socket;
	wi_string_t			*ip;
	
	if(wr_connected)
		wr_disconnect();
	
	wr_printf_prefix(WI_STR("Connecting to %@..."), hostname);
	
	if(port == 0)
		port = WR_CONTROL_PORT;
	
	addresses = wi_host_addresses(wi_host_with_string(hostname));
	
	if(!addresses) {
		wr_printf_prefix(WI_STR("Could not resolve \"%@\": %m"),
			hostname);
		
		return;
	}
	
	WI_LIST_FOREACH(addresses, node, address) {
		ip = wi_address_string(address);

		wr_printf_prefix(WI_STR("Trying %@..."), ip);
		
		wi_address_set_port(address, port);
		
		socket = wi_socket_init_with_address(wi_socket_alloc(), address, WI_SOCKET_TCP);
		wi_socket_set_interactive(socket, true);

		if(!wi_socket_connect(socket, wr_socket_context, 10.0)) {
			wr_printf_prefix(WI_STR("Could not connect to %@: %m"), ip);

			goto next;
		}

		wr_printf_prefix(WI_STR("Connected using %@/%@/%u bits, logging in..."),
			wi_socket_cipher_version(socket),
			wi_socket_cipher_name(socket),
			wi_socket_cipher_bits(socket));

		wr_connected	= true;
		wr_host			= wi_retain(hostname);
		wr_port			= port;
		wr_login		= wi_retain(login);
		wr_password		= wi_retain(password);
		wr_socket		= wi_retain(socket);
		wr_address		= wi_retain(address);
		
		wr_runloop_add_socket(wr_socket, &wr_runloop_server_callback);
		wr_send_command(WI_STR("HELLO"));

next:
		wi_release(socket);
		
		if(wr_connected)
			break;
	}