From eac0d603f43df28f74e16d78cdf071c2c11ff02b Mon Sep 17 00:00:00 2001
From: natinusala <natinusala@gmail.com>
Date: Fri, 12 Oct 2018 17:29:24 +0200
Subject: [PATCH] libnx: add network interfaces info

---
 Makefile.libnx                     |  2 +-
 frontend/drivers/platform_switch.c |  2 +
 libretro-common/net/net_ifinfo.c   | 73 +++++++++++++++++++++++++++++-
 libretro-common/net/net_natt.c     |  2 +-
 menu/menu_displaylist.c            |  4 +-
 5 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/Makefile.libnx b/Makefile.libnx
index 00343d6b1c..d84f191f88 100644
--- a/Makefile.libnx
+++ b/Makefile.libnx
@@ -70,7 +70,7 @@ else
 endif
 
 include Makefile.common
-BLACKLIST := $(LIBRETRO_COMM_DIR)/net/net_ifinfo.o
+BLACKLIST :=
 
 OBJ := $(filter-out $(BLACKLIST),$(OBJ))
 
diff --git a/frontend/drivers/platform_switch.c b/frontend/drivers/platform_switch.c
index 39cb228a47..166640ee21 100644
--- a/frontend/drivers/platform_switch.c
+++ b/frontend/drivers/platform_switch.c
@@ -191,6 +191,7 @@ static void frontend_switch_deinit(void *data)
    (void)data;
 
 #ifdef HAVE_LIBNX
+   nifmExit();
 #if defined(SWITCH) && defined(NXLINK)
    socketExit();
 #endif
@@ -607,6 +608,7 @@ static void frontend_switch_init(void *data)
    (void)data;
 
 #ifdef HAVE_LIBNX
+   nifmInitialize();
 #ifndef HAVE_OPENGL
    /* Init Resolution before initDefault */
    gfxInitResolution(1280, 720);
diff --git a/libretro-common/net/net_ifinfo.c b/libretro-common/net/net_ifinfo.c
index 77c5971171..55be3c90e9 100644
--- a/libretro-common/net/net_ifinfo.c
+++ b/libretro-common/net/net_ifinfo.c
@@ -38,9 +38,11 @@
 #ifdef WANT_IFADDRS
 #include <compat/ifaddrs.h>
 #else
+#ifndef HAVE_LIBNX
 #include <ifaddrs.h>
 #endif
 #endif
+#endif
 
 #include <net/net_ifinfo.h>
 
@@ -71,10 +73,77 @@ void net_ifinfo_free(net_ifinfo_t *list)
    free(list->entries);
 }
 
+#ifdef HAVE_LIBNX
+static void convert_ip(char *dst, size_t size, uint32_t ip, bool inverted)
+{
+   unsigned char bytes[4];
+   bytes[0] = ip & 0xFF;
+   bytes[1] = (ip >> 8) & 0xFF;
+   bytes[2] = (ip >> 16) & 0xFF;
+   bytes[3] = (ip >> 24) & 0xFF;
+
+   if (inverted)
+      snprintf(dst, size, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
+   else
+      snprintf(dst, size, "%d.%d.%d.%d", bytes[3], bytes[2], bytes[1], bytes[0]);
+}
+#endif
+
 bool net_ifinfo_new(net_ifinfo_t *list)
 {
    unsigned k              = 0;
-#if defined(_WIN32) && !defined(_XBOX)
+#ifdef HAVE_LIBNX
+   uint32_t id;
+   Result rc;
+
+   char hostname[128];
+   struct net_ifinfo_entry *ptr = NULL;
+
+   memset(list, 0, sizeof(net_ifinfo_t));
+
+   /* loopback */
+   convert_ip(hostname, sizeof(hostname), INADDR_LOOPBACK, false);
+
+   ptr = (struct net_ifinfo_entry*)
+         realloc(list->entries, (k+1) * sizeof(struct net_ifinfo_entry));
+
+   if (!ptr)
+      goto error;
+
+   list->entries          = ptr;
+
+   list->entries[k].name  = strdup("lo");
+   list->entries[k].host  = strdup(hostname);
+   list->size             = k + 1;
+
+   k++;
+
+   /*
+      actual interface
+      can be wlan or eth (with a wiiu adapter)
+      so we just use "switch" as a name 
+   */
+   rc = nifmGetCurrentIpAddress(&id);
+
+   if (!R_SUCCEEDED(rc)) /* not connected to any network */
+      return true;
+
+   convert_ip(hostname, sizeof(hostname), id, true);
+
+   ptr = (struct net_ifinfo_entry*)
+         realloc(list->entries, (k+1) * sizeof(struct net_ifinfo_entry));
+
+   if (!ptr)
+      goto error;
+
+   list->entries          = ptr;
+
+   list->entries[k].name  = strdup("switch");
+   list->entries[k].host  = strdup(hostname);
+   list->size             = k + 1;
+
+   return true;
+#elif defined(_WIN32) && !defined(_XBOX)
    PIP_ADAPTER_ADDRESSES adapter_addresses = NULL, aa = NULL;
    PIP_ADAPTER_UNICAST_ADDRESS ua = NULL;
 #ifdef _WIN32_WINNT_WINXP
@@ -173,7 +242,7 @@ error:
 #ifdef _WIN32
    if (adapter_addresses)
       free(adapter_addresses);
-#else
+#elif !defined(HAVE_LIBNX)
    freeifaddrs(ifaddr);
 #endif
    net_ifinfo_free(list);
diff --git a/libretro-common/net/net_natt.c b/libretro-common/net/net_natt.c
index b6dc5c91b4..eca2a65500 100644
--- a/libretro-common/net/net_natt.c
+++ b/libretro-common/net/net_natt.c
@@ -184,7 +184,7 @@ static bool natt_open_port(struct natt_status *status,
 bool natt_open_port_any(struct natt_status *status,
       uint16_t port, enum socket_protocol proto)
 {
-#if !defined(HAVE_SOCKET_LEGACY) && !defined(SWITCH)
+#if !defined(HAVE_SOCKET_LEGACY) && (!defined(SWITCH) || defined(SWITCH) && defined(HAVE_LIBNX))
    size_t i;
    char port_str[6];
    struct net_ifinfo list;
diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c
index d816d94af0..adb2d3d375 100644
--- a/menu/menu_displaylist.c
+++ b/menu/menu_displaylist.c
@@ -97,7 +97,7 @@ static enum msg_hash_enums new_type     = MSG_UNKNOWN;
  * function pointer callback functions that don't necessarily
  * call each other. */
 
-#if !defined(HAVE_SOCKET_LEGACY) && !defined(SWITCH)
+#if !defined(HAVE_SOCKET_LEGACY) && (!defined(SWITCH) || defined(SWITCH) && defined(HAVE_LIBNX))
 #include <net/net_ifinfo.h>
 
 static int menu_displaylist_parse_network_info(menu_displaylist_info_t *info)
@@ -4834,7 +4834,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data)
          break;
       case DISPLAYLIST_NETWORK_INFO:
          menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
-#if defined(HAVE_NETWORKING) && !defined(HAVE_SOCKET_LEGACY) && !defined(SWITCH)
+#if defined(HAVE_NETWORKING) && !defined(HAVE_SOCKET_LEGACY) && (!defined(SWITCH) || defined(SWITCH) && defined(HAVE_LIBNX))
          count = menu_displaylist_parse_network_info(info);
 #endif