From dd351a350184d84a5866dabc498b4c8be4d51abd Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 13 Sep 2017 03:05:28 +0200 Subject: [PATCH] (Xbox) Provide implementation function for inet_ntop_compat --- libretro-common/net/net_compat.c | 159 ++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 4 deletions(-) diff --git a/libretro-common/net/net_compat.c b/libretro-common/net/net_compat.c index 91d6a99d6e..d9de1d8ceb 100644 --- a/libretro-common/net/net_compat.c +++ b/libretro-common/net/net_compat.c @@ -348,10 +348,10 @@ uint16_t inet_htons(uint16_t hostshort) } #ifdef _XBOX -static int inet_aton(const char *cp, struct in_addr *addr) -{ - addr->s_addr = inet_addr(cp); - return (addr->s_addr == INADDR_NONE) ? 0 : 1; +static int inet_aton(const char *cp, struct in_addr *addr) +{ + addr->s_addr = inet_addr(cp); + return (addr->s_addr == INADDR_NONE) ? 0 : 1; } #endif @@ -372,12 +372,163 @@ struct in_addr6_compat unsigned char ip_addr[16]; }; +#ifdef _XBOX + +#ifndef IM_IN6ADDRSZ +#define IM_IN6ADDRSZ 16 +#endif + +#ifndef IM_INT16SZ +#define IM_INT16SZ 2 +#endif + +#ifndef IM_INADDRSZ +#define IM_INADDRSZ 4 +#endif +/* Taken from https://github.com/skywind3000/easenet/blob/master/inetbase.c + */ + +/* convert presentation format to network format */ +static const char * +inet_ntop4x(const unsigned char *src, char *dst, size_t size) +{ + char tmp[64]; + size_t len = snprintf(tmp, + sizeof(tmp), + "%u.%u.%u.%u", src[0], src[1], src[2], src[3]); + + if (len >= size) + goto error; + + memcpy(dst, tmp, len + 1); + return dst; + +error: + errno = ENOSPC; + return NULL; +} + + +/* convert presentation format to network format */ +static const char * +inet_ntop6x(const unsigned char *src, char *dst, size_t size) +{ + char tmp[64], *tp; + int i, inc; + struct { int base, len; } best, cur; + unsigned int words[IM_IN6ADDRSZ / IM_INT16SZ]; + + memset(words, '\0', sizeof(words)); + best.base = best.len = 0; + cur.base = cur.len = 0; + + for (i = 0; i < IM_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + + best.base = -1; + cur.base = -1; + + for (i = 0; i < (IM_IN6ADDRSZ / IM_INT16SZ); i++) + { + if (words[i] == 0) + { + if (cur.base == -1) + { + cur.base = i; + cur.len = 1; + } + else cur.len++; + } + else + { + if (cur.base != -1) + { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) + { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + tp = tmp; + for (i = 0; i < (IM_IN6ADDRSZ / IM_INT16SZ); i++) + { + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) + { + if (i == best.base) + *tp++ = ':'; + continue; + } + + if (i != 0) + *tp++ = ':'; + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) + { + if (!inet_ntop4x(src+12, tp, sizeof(tmp) - (tp - tmp))) + return NULL; + tp += strlen(tp); + break; + } + inc = sprintf(tp, "%x", words[i]); + tp += inc; + } + + if (best.base != -1 && (best.base + best.len) == + (IM_IN6ADDRSZ / IM_INT16SZ)) + *tp++ = ':'; + + *tp++ = '\0'; + + if ((size_t)(tp - tmp) > size) + goto error; + + memcpy(dst, tmp, tp - tmp); + return dst; + +error: + errno = ENOSPC; + return NULL; +} + +/* convert network format to presentation format */ +/* another inet_ntop, supports AF_INET/AF_INET6 */ +static const char *isockaddr_ntop(int af, + const void *src, char *dst, size_t size) +{ + switch (af) + { + case AF_INET: + return inet_ntop4x((const unsigned char*)src, dst, size); +#ifdef AF_INET6 + case AF_INET6: + return inet_ntop6x((const unsigned char*)src, dst, size); +#endif + default: + if (af == -6) + return inet_ntop6x((const unsigned char*)src, dst, size); + errno = EAFNOSUPPORT; + return NULL; + } +} +#endif + const char *inet_ntop_compat(int af, const void *src, char *dst, socklen_t cnt) { #if defined(VITA) || defined(__ORBIS__) return sceNetInetNtop(af,src,dst,cnt); #elif defined(WIIU) return inet_ntop(af, src, dst, cnt); +#elif defined(_XBOX) + return isockaddr_ntop(af, src, dst, cnt); #elif defined(_WIN32) if (af == AF_INET) {