WiiU: fix network information

== DETAILS

For local netplay, it's useful to have your IP address easily
available. This commit makes the Information > Network Information
menu display the Wii U's IP address.

Change summary:
- Fix the logging init to be reentrant to avoid socket consumption
- Add implementation of POSIX `getifaddrs()` and `freeifaddrs()`
  to `missing_libc_functions.c`
- Remove compiler directives protecting the code paths that call
  `getifaddrs()` from being used in Wii U builds

== TESTING

Have tested locally, successfully get IP address information in
the Information > Network Information.

I think this may also fix NAT traversal. Will need to be tested.
This commit is contained in:
Nathan Strong 2018-10-11 15:37:15 -07:00
parent e9752fb546
commit c5f9fc0a34
7 changed files with 154 additions and 5 deletions

View File

@ -137,8 +137,6 @@ endif
WANT_IOSUHAX = 1
include Makefile.common
BLACKLIST := $(LIBRETRO_COMM_DIR)/net/net_ifinfo.o
OBJ := $(filter-out $(BLACKLIST),$(OBJ))
OBJ += gfx/drivers/gx2_gfx.o
OBJ += gfx/drivers_font/wiiu_font.o

View File

@ -530,6 +530,9 @@ static void wiiu_log_init(int port)
{
wiiu_log_lock = 0;
if(wiiu_log_socket >= 0)
return;
if(broadcast_init(port) < 0)
return;

View File

@ -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(WIIU) && !defined(SWITCH)
#if !defined(HAVE_SOCKET_LEGACY) && !defined(SWITCH)
size_t i;
char port_str[6];
struct net_ifinfo list;

View File

@ -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(WIIU) && !defined(SWITCH)
#if !defined(HAVE_SOCKET_LEGACY) && !defined(SWITCH)
#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(WIIU) && !defined(SWITCH)
#if defined(HAVE_NETWORKING) && !defined(HAVE_SOCKET_LEGACY) && !defined(SWITCH)
count = menu_displaylist_parse_network_info(info);
#endif

View File

@ -6,6 +6,7 @@ extern "C" {
#endif
#include <netinet/in.h>
#include <sys/socket.h>
char *inet_ntoa(struct in_addr in);
const char *inet_ntop(int af, const void *cp, char *buf, socklen_t len);

18
wiiu/include/ifaddrs.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _IFADDRS_H_
#define _IFADDRS_H_
#include <sys/socket.h>
struct ifaddrs {
struct ifaddrs *ifa_next;
char *ifa_name;
unsigned int ifa_flags;
struct sockaddr *ifa_addr;
struct sockaddr *ifa_netmask;
struct sockaddr *ifa_dstaddr;
void *ifa_data;
};
int getifaddrs(struct ifaddrs **ifap);
void freeifaddrs(struct ifaddrs *ifp);
#endif // _IFADDRS_H_

View File

@ -5,10 +5,18 @@
#include <unistd.h>
#include <stdio.h>
#include <wiiu/os.h>
#include <wiiu/ac.h>
#include <wiiu/types.h>
#include <pwd.h>
#include <sys/reent.h>
#include <ifaddrs.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <verbosity.h>
/* This is usually in libogc; we can't use that on wiiu */
int usleep(useconds_t microseconds) {
@ -112,3 +120,124 @@ int clock_gettime(clockid_t clk_id, struct timespec* tp) {
}
return 0;
}
/**
* Implementation of getifaddrs() and freeifaddrs() for WiiU.
*/
// the Wii U doesn't define an interface name, so we'll use something generic.
static const char *wiiu_iface_name = "eth0";
/**
* Allocate and zeroize the hunk of memory for the ifaddrs struct and its contents; the struct will be filled
* out later.
*
* returns NULL if any of the memory allocations fail.
*/
static struct ifaddrs *buildEmptyIfa() {
struct ifaddrs *result = (struct ifaddrs *)malloc(sizeof(struct ifaddrs));
if(result != NULL) {
memset(result, 0, sizeof(struct ifaddrs));
result->ifa_name = strdup(wiiu_iface_name);
result->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
result->ifa_netmask = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
result->ifa_dstaddr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
if(!result->ifa_name || !result->ifa_addr || !result->ifa_netmask || !result->ifa_dstaddr)
goto error;
memset(result->ifa_addr, 0, sizeof(struct sockaddr_in));
result->ifa_addr->sa_family = AF_INET;
memset(result->ifa_netmask, 0, sizeof(struct sockaddr_in));
result->ifa_netmask->sa_family = AF_INET;
memset(result->ifa_dstaddr, 0, sizeof(struct sockaddr_in));
result->ifa_dstaddr->sa_family = AF_INET;
}
return result;
error:
freeifaddrs(result);
return NULL;
}
static int getAssignedAddress(struct sockaddr_in *sa) {
if(sa == NULL)
return -1;
ACIpAddress addr;
int result = ACGetAssignedAddress(&addr);
if(result == 0)
sa->sin_addr.s_addr = addr;
return result;
}
static int getAssignedSubnet(struct sockaddr_in *sa) {
if(sa == NULL)
return -1;
ACIpAddress mask;
int result = ACGetAssignedSubnet(&mask);
if(result == 0)
sa->sin_addr.s_addr = mask;
return result;
}
static int getBroadcastAddress(struct sockaddr_in *sa, struct sockaddr_in *addr, struct sockaddr_in *mask) {
if(!sa || !addr || !mask)
return -1;
sa->sin_addr.s_addr = addr->sin_addr.s_addr | (~mask->sin_addr.s_addr);
return 0;
}
static struct ifaddrs *getWiiUInterfaceAddressData(void) {
struct ifaddrs *result = buildEmptyIfa();
if(result != NULL) {
if(getAssignedAddress((struct sockaddr_in *)result->ifa_addr) < 0 ||
getAssignedSubnet((struct sockaddr_in *)result->ifa_netmask) < 0 ||
getBroadcastAddress((struct sockaddr_in *)result->ifa_dstaddr,
(struct sockaddr_in *)result->ifa_addr,
(struct sockaddr_in *)result->ifa_netmask) < 0) {
goto error;
}
}
return result;
error:
freeifaddrs(result);
return NULL;
}
int getifaddrs(struct ifaddrs **ifap) {
if(ifap == NULL) {
return -1;
}
*ifap = getWiiUInterfaceAddressData();
return (*ifap == NULL) ? -1 : 0;
}
void freeifaddrs(struct ifaddrs *ifp) {
if(ifp != NULL) {
if(ifp->ifa_name) {
free(ifp->ifa_name);
ifp->ifa_name = NULL;
}
if(ifp->ifa_addr) {
free(ifp->ifa_addr);
ifp->ifa_addr = NULL;
}
if(ifp->ifa_netmask) {
free(ifp->ifa_netmask);
ifp->ifa_netmask = NULL;
}
if(ifp->ifa_dstaddr) {
free(ifp->ifa_dstaddr);
ifp->ifa_dstaddr = NULL;
}
free(ifp);
}
}