size_t NetSocketPosix::_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_wildcard() && !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; } return sizeof(sockaddr_in); } }
Error PacketPeerUDPWinsock::listen(int p_port, 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; } blocking = true; 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; }
Error PacketPeerUDP::_set_dest_address(const String &p_address, int p_port) { IP_Address ip; if (p_address.is_valid_ip_address()) { ip = p_address; } else { ip = IP::get_singleton()->resolve_hostname(p_address); if (!ip.is_valid()) return ERR_CANT_RESOLVE; } set_dest_address(ip, p_port); return OK; }
Error StreamPeerTCP::_connect(const String &p_address, int p_port) { IP_Address ip; if (p_address.is_valid_ip_address()) { ip = p_address; } else { ip = IP::get_singleton()->resolve_hostname(p_address); if (!ip.is_valid()) return ERR_CANT_RESOLVE; } connect_to_host(ip, 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; }
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 LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocols) { ERR_FAIL_COND_V(context != NULL, FAILED); IP_Address addr; if (!p_host.is_valid_ip_address()) { addr = IP::get_singleton()->resolve_hostname(p_host); } else { addr = p_host; } ERR_FAIL_COND_V(!addr.is_valid(), ERR_INVALID_PARAMETER); // Prepare protocols _lws_make_protocols(this, &LWSClient::_lws_gd_callback, p_protocols, &_lws_ref); // Init lws client struct lws_context_creation_info info; struct lws_client_connect_info i; memset(&i, 0, sizeof i); memset(&info, 0, sizeof info); info.port = CONTEXT_PORT_NO_LISTEN; info.protocols = _lws_ref->lws_structs; info.gid = -1; info.uid = -1; //info.ws_ping_pong_interval = 5; info.user = _lws_ref; #if defined(LWS_OPENSSL_SUPPORT) info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; #endif context = lws_create_context(&info); if (context == NULL) { _lws_free_ref(_lws_ref); _lws_ref = NULL; ERR_EXPLAIN("Unable to create lws context"); ERR_FAIL_V(FAILED); } i.context = context; if (p_protocols.size() > 0) i.protocol = _lws_ref->lws_names; else i.protocol = NULL; if (p_ssl) { i.ssl_connection = LCCSCF_USE_SSL; if (!verify_ssl) i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED; } else { i.ssl_connection = 0; } // These CharStrings needs to survive till we call lws_client_connect_via_info CharString addr_ch = ((String)addr).ascii(); CharString host_ch = p_host.utf8(); CharString path_ch = p_path.utf8(); i.address = addr_ch.get_data(); i.host = host_ch.get_data(); i.path = path_ch.get_data(); i.port = p_port; lws_client_connect_via_info(&i); return OK; };
Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocols) { ERR_FAIL_COND_V(context != NULL, FAILED); IP_Address addr; if (!p_host.is_valid_ip_address()) { addr = IP::get_singleton()->resolve_hostname(p_host); } else { addr = p_host; } ERR_FAIL_COND_V(!addr.is_valid(), ERR_INVALID_PARAMETER); // prepare protocols if (p_protocols.size() == 0) // default to binary protocol p_protocols.append("binary"); _lws_make_protocols(this, &LWSClient::_lws_gd_callback, p_protocols, &_lws_ref); // init lws client struct lws_context_creation_info info; struct lws_client_connect_info i; memset(&i, 0, sizeof i); memset(&info, 0, sizeof info); info.port = CONTEXT_PORT_NO_LISTEN; info.protocols = _lws_ref->lws_structs; info.gid = -1; info.uid = -1; //info.ws_ping_pong_interval = 5; info.user = _lws_ref; #if defined(LWS_OPENSSL_SUPPORT) info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; #endif context = lws_create_context(&info); if (context == NULL) { _lws_free_ref(_lws_ref); _lws_ref = NULL; ERR_EXPLAIN("Unable to create lws context"); ERR_FAIL_V(FAILED); } char abuf[1024]; char hbuf[1024]; char pbuf[2048]; String addr_str = (String)addr; strncpy(abuf, addr_str.ascii().get_data(), 1024); strncpy(hbuf, p_host.utf8().get_data(), 1024); strncpy(pbuf, p_path.utf8().get_data(), 2048); i.context = context; i.protocol = _lws_ref->lws_names; i.address = abuf; i.host = hbuf; i.path = pbuf; i.port = p_port; if (p_ssl) { i.ssl_connection = LCCSCF_USE_SSL; if (!verify_ssl) i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED; } else { i.ssl_connection = 0; } lws_client_connect_via_info(&i); return OK; };