Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); struct sockaddr_storage from; socklen_t len = sizeof(struct sockaddr_storage); memset(&from, 0, len); r_read = ::recvfrom(_sock, SOCK_BUF(p_buffer), p_len, 0, (struct sockaddr *)&from, &len); if (r_read < 0) { NetError err = _get_socket_error(); if (err == ERR_NET_WOULD_BLOCK) return ERR_BUSY; return FAILED; } if (from.ss_family == AF_INET) { struct sockaddr_in *sin_from = (struct sockaddr_in *)&from; r_ip.set_ipv4((uint8_t *)&sin_from->sin_addr); r_port = ntohs(sin_from->sin_port); } else if (from.ss_family == AF_INET6) { struct sockaddr_in6 *s6_from = (struct sockaddr_in6 *)&from; r_ip.set_ipv6((uint8_t *)&s6_from->sin6_addr); r_port = ntohs(s6_from->sin6_port); } else { // Unsupported socket family, should never happen. ERR_FAIL_V(FAILED); } return OK; }
void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { ULONG buf_size = 1024; IP_ADAPTER_ADDRESSES *addrs; while (true) { addrs = (IP_ADAPTER_ADDRESSES *)memalloc(buf_size); int err = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, addrs, &buf_size); if (err == NO_ERROR) { break; }; memfree(addrs); if (err == ERROR_BUFFER_OVERFLOW) { continue; // will go back and alloc the right size }; ERR_EXPLAIN("Call to GetAdaptersAddresses failed with error " + itos(err)); ERR_FAIL(); return; }; IP_ADAPTER_ADDRESSES *adapter = addrs; while (adapter != NULL) { IP_ADAPTER_UNICAST_ADDRESS *address = adapter->FirstUnicastAddress; while (address != NULL) { IP_Address ip; if (address->Address.lpSockaddr->sa_family == AF_INET) { SOCKADDR_IN *ipv4 = reinterpret_cast<SOCKADDR_IN *>(address->Address.lpSockaddr); ip.set_ipv4((uint8_t *)&(ipv4->sin_addr)); } else { // ipv6 SOCKADDR_IN6 *ipv6 = reinterpret_cast<SOCKADDR_IN6 *>(address->Address.lpSockaddr); ip.set_ipv6(ipv6->sin6_addr.s6_addr); }; r_addresses->push_back(ip); address = address->Next; }; adapter = adapter->Next; }; memfree(addrs); };
static IP_Address _sockaddr2ip(struct sockaddr *p_addr) { IP_Address ip; if (p_addr->sa_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *)p_addr; ip.set_ipv4((uint8_t *)&(addr->sin_addr)); } else { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr; ip.set_ipv6(addr6->sin6_addr.s6_addr); }; return ip; };
void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IP_Address &r_ip, uint16_t &r_port) { if (p_addr->ss_family == AF_INET) { struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr; r_ip.set_ipv4((uint8_t *)&(addr4->sin_addr.s_addr)); r_port = ntohs(addr4->sin_port); } else if (p_addr->ss_family == AF_INET6) { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr; r_ip.set_ipv6(addr6->sin6_addr.s6_addr); r_port = ntohs(addr6->sin6_port); }; }