Exemple #1
0
wi_socket_t * wi_socket_init_with_address(wi_socket_t *_socket, wi_address_t *address, wi_socket_type_t type) {
	_socket->address	= wi_copy(address);
	_socket->close		= true;
	_socket->buffer		= wi_string_init_with_capacity(wi_string_alloc(), WI_SOCKET_BUFFER_SIZE);
	_socket->type		= type;

	_socket->sd			= socket(wi_address_family(_socket->address), _socket->type, 0);
	
	if(_socket->sd < 0) {
		wi_error_set_errno(errno);
		
		wi_release(_socket);
		
		return NULL;
	}
	
	if(!_wi_socket_set_option_int(_socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
		wi_release(_socket);
		
		return NULL;
	}
	
#ifdef SO_REUSEPORT
	if(!_wi_socket_set_option_int(_socket, SOL_SOCKET, SO_REUSEPORT, 1)) {
		wi_release(_socket);
		
		return NULL;
	}
#endif

	return _socket;
}
Exemple #2
0
wi_integer_t wi_address_compare_family(wi_runtime_instance_t *instance1, wi_runtime_instance_t *instance2) {
	wi_address_t			*address1 = instance1;
	wi_address_t			*address2 = instance2;
	wi_address_family_t		family1;
	wi_address_family_t		family2;
	
	family1 = wi_address_family(address1);
	family2 = wi_address_family(address2);
	
	if(family1 == WI_ADDRESS_IPV4 && family2 == WI_ADDRESS_IPV6)
		return 1;
	else if(family1 == WI_ADDRESS_IPV6 && family2 == WI_ADDRESS_IPV4)
		return -1;
	
	return 0;
}
Exemple #3
0
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));
}
Exemple #4
0
void wi_socket_set_interactive(wi_socket_t *socket, wi_boolean_t interactive) {
	if(socket->type == WI_SOCKET_TCP && interactive)
		_wi_socket_set_option(socket, IPPROTO_TCP, TCP_NODELAY, 1);
	
	if(wi_address_family(socket->address) == WI_ADDRESS_IPV4)
		_wi_socket_set_option(socket, IPPROTO_IP, IP_TOS, interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT);
	
	socket->interactive = interactive;
}
Exemple #5
0
void wi_socket_set_interactive(wi_socket_t *socket, wi_boolean_t interactive) {
	_wi_socket_set_option_int(socket, IPPROTO_TCP, TCP_NODELAY, interactive ? 1 : 0);
	
#if defined(IPTOS_LOWDELAY) && defined(IPTOS_THROUGHPUT)
	if(wi_address_family(socket->address) == WI_ADDRESS_IPV4)
		_wi_socket_set_option_int(socket, IPPROTO_IP, IP_TOS, interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT);
#endif
	
	socket->interactive = interactive;
}
Exemple #6
0
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;
}
Exemple #7
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
}