diff options
-rw-r--r-- | backends/networking/sdl_net/localwebserver.cpp | 117 |
1 files changed, 71 insertions, 46 deletions
diff --git a/backends/networking/sdl_net/localwebserver.cpp b/backends/networking/sdl_net/localwebserver.cpp index fdc89b51e4..e5c5d58c0b 100644 --- a/backends/networking/sdl_net/localwebserver.cpp +++ b/backends/networking/sdl_net/localwebserver.cpp @@ -33,10 +33,20 @@ #include <common/config-manager.h> #ifdef POSIX -#include <sys/types.h> -#include <ifaddrs.h> -#include <netinet/in.h> +#include <errno.h> +#include <unistd.h> #include <arpa/inet.h> +#include <net/if.h> +#include <netinet/in.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/types.h> + +#ifndef _SIZEOF_ADDR_IFREQ +#define _SIZEOF_ADDR_IFREQ sizeof +#endif + +#define LSSDP_BUFFER_LEN 2048 #endif namespace Common { @@ -298,53 +308,68 @@ void LocalWebserver::resolveAddress(void *ipAddress) { struct ifaddrs *ifAddrStruct = NULL; void *tmpAddrPtr = NULL; - getifaddrs(&ifAddrStruct); - - for (struct ifaddrs *i = ifAddrStruct; i != NULL; i = i->ifa_next) { - if (!i->ifa_addr) { - continue; - } - - Common::String addr; - - // IPv4 - if (i->ifa_addr->sa_family == AF_INET) { - tmpAddrPtr = &((struct sockaddr_in *)i->ifa_addr)->sin_addr; - char addressBuffer[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN); - debug(9, "%s IP Address %s", i->ifa_name, addressBuffer); - addr = addressBuffer; + int fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + warning("LocalWebserver: failed to create socket: %s (%d)", strerror(errno), errno); + } else { + // get ifconfig + char buffer[LSSDP_BUFFER_LEN] = {}; + struct ifconf ifc; + ifc.ifc_len = sizeof(buffer); + ifc.ifc_buf = (caddr_t) buffer; + + if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { + warning("LocalWebserver: ioctl SIOCGIFCONF failed: %s (%d)", strerror(errno), errno); + } else { + struct ifreq *i; + for (size_t index = 0; index < ifc.ifc_len; index += _SIZEOF_ADDR_IFREQ(*i)) { + i = (struct ifreq *)(buffer + index); + + Common::String addr; + + // IPv4 + if (i->ifr_addr.sa_family == AF_INET) { + tmpAddrPtr = &((struct sockaddr_in *)&i->ifr_addr)->sin_addr; + char addressBuffer[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN); + debug(9, "%s IP Address %s", i->ifr_name, addressBuffer); + addr = addressBuffer; + } + + // IPv6 + /* + if (i->ifr_addr.sa_family == AF_INET6) { + tmpAddrPtr = &((struct sockaddr_in6 *)&i->ifr_addr)->sin6_addr; + char addressBuffer[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); + debug(9, "%s IP Address %s", i->ifr_name, addressBuffer); + addr = addressBuffer; + } + */ + + if (addr.empty()) + continue; + + // ignored IPv4 addresses + if (addr.equals("127.0.0.1") || addr.equals("0.0.0.0") || addr.equals("localhost")) + continue; + + // ignored IPv6 addresses + /* + if (addr.equals("::1")) + continue; + */ + + // use the address found + _address = "http://" + addr + Common::String::format(":%u/", _serverPort); + } } - // IPv6 - /* - if (i->ifa_addr->sa_family == AF_INET6) { - tmpAddrPtr = &((struct sockaddr_in6 *)i->ifa_addr)->sin6_addr; - char addressBuffer[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); - debug(9, "%s IP Address %s", i->ifa_name, addressBuffer); - addr = addressBuffer; + // close socket + if (close(fd) != 0) { + warning("LocalWebserver: failed to close socket [fd %d]: %s (%d)", fd, strerror(errno), errno); } - */ - - if (addr.empty()) - continue; - - // ignored IPv4 addresses - if (addr.equals("127.0.0.1") || addr.equals("0.0.0.0") || addr.equals("localhost")) - continue; - - // ignored IPv6 addresses - /* - if (addr.equals("::1")) - continue; - */ - - // use the address found - _address = "http://" + addr + Common::String::format(":%u/", _serverPort); } - - if (ifAddrStruct != NULL) freeifaddrs(ifAddrStruct); #endif } |