예제 #1
0
Error PacketPeerUDPWinsock::listen(int p_port, const IP_Address &p_bind_address, int p_recv_buffer_size) {

	ERR_FAIL_COND_V(sockfd != -1, ERR_ALREADY_IN_USE);
	ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);

	sock_type = IP::TYPE_ANY;

	if (p_bind_address.is_valid())
		sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;

	int sock = _get_socket();
	if (sock == -1)
		return ERR_CANT_CREATE;

	struct sockaddr_storage addr = { 0 };
	size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, IP_Address());

	if (bind(sock, (struct sockaddr *)&addr, addr_size) == -1) {
		close();
		return ERR_UNAVAILABLE;
	}

	printf("UDP Connection listening on port %i\n", p_port);
	rb.resize(nearest_shift(p_recv_buffer_size));
	return OK;
}
예제 #2
0
Error TCPServerPosix::listen(uint16_t p_port, const IP_Address p_bind_address) {

	ERR_FAIL_COND_V(listen_sockfd != -1, ERR_ALREADY_IN_USE);
	ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);

	int sockfd;
#ifdef __OpenBSD__
	sock_type = IP::TYPE_IPV4; // OpenBSD does not support dual stacking, fallback to IPv4 only.
#else
	sock_type = IP::TYPE_ANY;
#endif

	// If the bind address is valid use its type as the socket type
	if (p_bind_address.is_valid())
		sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;

	sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP);

	ERR_FAIL_COND_V(sockfd == -1, FAILED);

#ifndef NO_FCNTL
	fcntl(sockfd, F_SETFL, O_NONBLOCK);
#else
	int bval = 1;
	ioctl(sockfd, FIONBIO, &bval);
#endif

	int reuse = 1;
	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) {
		WARN_PRINT("REUSEADDR failed!")
	}

	struct sockaddr_storage addr;
	size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, p_bind_address);

	if (bind(sockfd, (struct sockaddr *)&addr, addr_size) != -1) {

		if (::listen(sockfd, 1) == -1) {

			close(sockfd);
			ERR_FAIL_V(FAILED);
		};
	} else {
		return ERR_ALREADY_IN_USE;
	};

	if (listen_sockfd != -1) {
		stop();
	};

	listen_sockfd = sockfd;

	return OK;
};
예제 #3
0
bool NetSocketPosix::_can_use_ip(const IP_Address p_ip, const bool p_for_bind) const {

	if (p_for_bind && !(p_ip.is_valid() || p_ip.is_wildcard())) {
		return false;
	} else if (!p_for_bind && !p_ip.is_valid()) {
		return false;
	}
	// Check if socket support this IP type.
	IP::Type type = p_ip.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
	if (_ip_type != IP::TYPE_ANY && !p_ip.is_wildcard() && _ip_type != type) {
		return false;
	}
	return true;
}
예제 #4
0
static size_t _set_addr_storage(struct sockaddr_storage *p_addr, const IP_Address &p_ip, uint16_t p_port, IP::Type p_ip_type) {

	memset(p_addr, 0, sizeof(struct sockaddr_storage));
	if (p_ip_type == IP::TYPE_IPV6 || p_ip_type == IP::TYPE_ANY) { // IPv6 socket

		// IPv6 only socket with IPv4 address
		ERR_FAIL_COND_V(!p_ip.is_wildcard() && p_ip_type == IP::TYPE_IPV6 && p_ip.is_ipv4(), 0);

		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr;
		addr6->sin6_family = AF_INET6;
		addr6->sin6_port = htons(p_port);
		if (p_ip.is_valid()) {
			copymem(&addr6->sin6_addr.s6_addr, p_ip.get_ipv6(), 16);
		} else {
			addr6->sin6_addr = in6addr_any;
		}
		return sizeof(sockaddr_in6);
	} else { // IPv4 socket

		// IPv4 socket with IPv6 address
		ERR_FAIL_COND_V(!p_ip.is_ipv4(), 0);

		struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr;
		addr4->sin_family = AF_INET;
		addr4->sin_port = htons(p_port); // short, network byte order

		if (p_ip.is_valid()) {
			copymem(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 4);
		} else {
			addr4->sin_addr.s_addr = INADDR_ANY;
		}

		copymem(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 16);
		return sizeof(sockaddr_in);
	}
}
예제 #5
0
Error StreamPeerWinsock::connect_to_host(const IP_Address &p_host, uint16_t p_port) {

	ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER);

	sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
	sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP);
	if (sockfd == INVALID_SOCKET) {
		ERR_PRINT("Socket creation failed!");
		disconnect_from_host();
		//perror("socket");
		return FAILED;
	};

	unsigned long par = 1;
	if (ioctlsocket(sockfd, FIONBIO, &par)) {
		perror("setting non-block mode");
		disconnect_from_host();
		return FAILED;
	};

	struct sockaddr_storage their_addr;
	size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, sock_type);

	if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == SOCKET_ERROR) {

		if (WSAGetLastError() != WSAEWOULDBLOCK) {
			ERR_PRINT("Connection to remote host failed!");
			disconnect_from_host();
			return FAILED;
		};
		status = STATUS_CONNECTING;
	} else {
		status = STATUS_CONNECTED;
	};

	peer_host = p_host;
	peer_port = p_port;

	return OK;
};
예제 #6
0
파일: tcp_server.cpp 프로젝트: 93i/godot
Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) {

	ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
	ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
	ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);

	Error err;
	IP::Type ip_type = IP::TYPE_ANY;

	// If the bind address is valid use its type as the socket type
	if (p_bind_address.is_valid())
		ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;

	err = _sock->open(NetSocket::TYPE_TCP, ip_type);

	ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);

	_sock->set_blocking_enabled(false);
	_sock->set_reuse_address_enabled(true);

	err = _sock->bind(p_bind_address, p_port);

	if (err != OK) {

		_sock->close();
		return ERR_ALREADY_IN_USE;
	}

	err = _sock->listen(MAX_PENDING_CONNECTIONS);

	if (err != OK) {
		_sock->close();
		return FAILED;
	}
	return OK;
}