From cd74221d33d7cafc23829d7262ae9eadd2d74719 Mon Sep 17 00:00:00 2001 From: Cthulhu-throwaway <96153783+Cthulhu-throwaway@users.noreply.github.com> Date: Thu, 27 Jan 2022 07:38:31 -0300 Subject: [PATCH] [Networking] GetBestRoute refactor (#13553) Refactor to support UWP. --- libretro-common/include/net/net_ifinfo.h | 4 +- libretro-common/net/net_ifinfo.c | 97 +++++++++++++++++++++++- libretro-common/net/net_natt.c | 60 +++------------ network/netplay/netplay_frontend.c | 66 ++-------------- 4 files changed, 116 insertions(+), 111 deletions(-) diff --git a/libretro-common/include/net/net_ifinfo.h b/libretro-common/include/net/net_ifinfo.h index 3bf5412ffb..ad8a5d789f 100644 --- a/libretro-common/include/net/net_ifinfo.h +++ b/libretro-common/include/net/net_ifinfo.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2020 The RetroArch team +/* Copyright (C) 2010-2022 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_ifinfo.h). @@ -50,6 +50,8 @@ void net_ifinfo_free(net_ifinfo_t *list); bool net_ifinfo_new(net_ifinfo_t *list); +bool net_ifinfo_best(const char *dst, void *src, bool ipv6); + RETRO_END_DECLS #endif diff --git a/libretro-common/net/net_ifinfo.c b/libretro-common/net/net_ifinfo.c index 8b475892a3..2e82880642 100644 --- a/libretro-common/net/net_ifinfo.c +++ b/libretro-common/net/net_ifinfo.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2020 The RetroArch team +/* Copyright (C) 2010-2022 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_ifinfo.c). @@ -27,6 +27,10 @@ #include #if defined(_WIN32) && !defined(_XBOX) +#ifdef _MSC_VER +#pragma comment(lib, "Iphlpapi") +#endif + #include #include #include @@ -256,3 +260,94 @@ error: return false; } + +bool net_ifinfo_best(const char *dst, void *src, bool ipv6) +{ + bool ret = false; + +/* TODO/FIXME: Implement for other platforms, if necessary. */ +#if defined(_WIN32) && !defined(_XBOX) + if (!ipv6) + { + /* Courtesy of MiniUPnP: https://github.com/miniupnp/miniupnp */ + DWORD index; + unsigned long udst = inet_addr(dst); +#ifdef __WINRT__ + struct sockaddr_in addr_dst = {0}; +#endif + + if (udst == INADDR_NONE || udst == INADDR_ANY) + return ret; + + if (!src) + return ret; + +#ifdef __WINRT__ + addr_dst.sin_family = AF_INET; + addr_dst.sin_addr.s_addr = udst; + if (GetBestInterfaceEx((struct sockaddr *) &addr_dst, &index) + == NO_ERROR) +#else + if (GetBestInterface(udst, &index) == NO_ERROR) +#endif + { + /* Microsoft docs recommend doing it this way. */ + ULONG len = 15 * 1024; + PIP_ADAPTER_ADDRESSES addresses = calloc(1, len); + + if (addresses) + { + ULONG flags = GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER | + GAA_FLAG_SKIP_FRIENDLY_NAME; + ULONG result = GetAdaptersAddresses(AF_INET, flags, NULL, + addresses, &len); + + if (result == ERROR_BUFFER_OVERFLOW) + { + PIP_ADAPTER_ADDRESSES new_addresses = realloc(addresses, len); + + if (new_addresses) + { + memset(new_addresses, 0, len); + + addresses = new_addresses; + result = GetAdaptersAddresses(AF_INET, flags, NULL, + addresses, &len); + } + } + + if (result == NO_ERROR) + { + PIP_ADAPTER_ADDRESSES addr = addresses; + + do + { + if (addr->IfIndex == index) + { + if (addr->FirstUnicastAddress) + { + struct sockaddr_in *addr_unicast = + (struct sockaddr_in *) + addr->FirstUnicastAddress->Address.lpSockaddr; + + memcpy(src, &addr_unicast->sin_addr, + sizeof(addr_unicast->sin_addr)); + + ret = true; + } + + break; + } + } while ((addr = addr->Next)); + } + + free(addresses); + } + } + } +#endif + + return ret; +} diff --git a/libretro-common/net/net_natt.c b/libretro-common/net/net_natt.c index b025942256..01b0e5302c 100644 --- a/libretro-common/net/net_natt.c +++ b/libretro-common/net/net_natt.c @@ -20,10 +20,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#if defined(_WIN32) && !defined(__WINRT__) && defined(_MSC_VER) -#pragma comment(lib, "Iphlpapi") -#endif - #include #include @@ -33,14 +29,14 @@ #include +#ifndef HAVE_SOCKET_LEGACY +#include +#endif + #include "../../tasks/tasks_internal.h" #include -#if defined(_WIN32) && !defined(__WINRT__) -#include -#endif - static bool translate_addr(struct sockaddr_in *addr, char *host, size_t hostlen, char *port, size_t portlen) { @@ -85,9 +81,6 @@ bool natt_init(struct natt_discovery *discovery) "ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n" "MX: 5\r\n" "\r\n"; -#if defined(_WIN32) && !defined(__WINRT__) - MIB_IPFORWARDROW ip_forward; -#endif bool ret; int fd = -1; struct addrinfo *msearch_addr = NULL; @@ -110,51 +103,16 @@ bool natt_init(struct natt_discovery *discovery) if (!bind_addr) goto failure; -#if defined(_WIN32) && !defined(__WINRT__) - if (GetBestRoute(inet_addr("223.255.255.255"), - 0, &ip_forward) == NO_ERROR) +#ifndef HAVE_SOCKET_LEGACY { - DWORD index = ip_forward.dwForwardIfIndex; - PMIB_IPADDRTABLE table = malloc(sizeof(*table)); + struct sockaddr_in *addr = (struct sockaddr_in *) bind_addr->ai_addr; - if (table) + if (net_ifinfo_best("223.255.255.255", &addr->sin_addr, false)) { - DWORD len = sizeof(*table); - DWORD result = GetIpAddrTable(table, &len, FALSE); - - if (result == ERROR_INSUFFICIENT_BUFFER) - { - PMIB_IPADDRTABLE new_table = realloc(table, len); - - if (new_table) - { - table = new_table; - result = GetIpAddrTable(table, &len, FALSE); - } - } - - if (result == NO_ERROR) - { - DWORD i; - - for (i = 0; i < table->dwNumEntries; i++) - { - PMIB_IPADDRROW ip_addr = &table->table[i]; - - if (ip_addr->dwIndex == index) - { #ifdef IP_MULTICAST_IF - setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char *) &ip_addr->dwAddr, sizeof(ip_addr->dwAddr)); + setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + (const char *) &addr->sin_addr, sizeof(addr->sin_addr)); #endif - ((struct sockaddr_in *) bind_addr->ai_addr)->sin_addr.s_addr = - ip_addr->dwAddr; - break; - } - } - } - - free(table); } } #endif diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index facdd79f89..8ce280d104 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -2,7 +2,7 @@ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen * Copyright (C) 2011-2021 - Daniel De Matteis * Copyright (C) 2016-2017 - Gregor Richards - * Copyright (C) 2021-2021 - Roberto V. Rampim + * Copyright (C) 2021-2022 - Roberto V. Rampim * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- @@ -20,10 +20,6 @@ #pragma comment(lib, "ws2_32") #endif -#if defined(_WIN32) && !defined(__WINRT__) && defined(_MSC_VER) -#pragma comment(lib, "Iphlpapi") -#endif - #include #include #include @@ -41,14 +37,14 @@ #include #include +#ifndef HAVE_SOCKET_LEGACY +#include +#endif + #include #include #include -#if defined(_WIN32) && !defined(__WINRT__) -#include -#endif - #ifdef HAVE_DISCORD #include "../discord.h" #endif @@ -247,55 +243,9 @@ bool init_netplay_discovery(void) if (ret) { -#if defined(_WIN32) && !defined(__WINRT__) - MIB_IPFORWARDROW ip_forward; - - if (GetBestRoute(inet_addr("223.255.255.255"), - 0, &ip_forward) == NO_ERROR) - { - DWORD index = ip_forward.dwForwardIfIndex; - PMIB_IPADDRTABLE table = malloc(sizeof(*table)); - - if (table) - { - DWORD len = sizeof(*table); - DWORD result = GetIpAddrTable(table, &len, FALSE); - - if (result == ERROR_INSUFFICIENT_BUFFER) - { - PMIB_IPADDRTABLE new_table = realloc(table, len); - - if (new_table) - { - table = new_table; - result = GetIpAddrTable(table, &len, FALSE); - } - } - - if (result == NO_ERROR) - { - DWORD i; - - for (i = 0; i < table->dwNumEntries; i++) - { - PMIB_IPADDRROW ip_addr = &table->table[i]; - - if (ip_addr->dwIndex == index) - { -#ifdef IP_MULTICAST_IF - setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char *) &ip_addr->dwAddr, sizeof(ip_addr->dwAddr)); -#endif - ((struct sockaddr_in *) addr->ai_addr)->sin_addr.s_addr = - ip_addr->dwAddr; - break; - } - } - } - - free(table); - } - } +#ifndef HAVE_SOCKET_LEGACY + net_ifinfo_best("223.255.255.255", + &((struct sockaddr_in *) addr->ai_addr)->sin_addr, false); #endif #ifdef SO_BROADCAST