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; }
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; };
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; }
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); } }
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; };
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; }