added SOC:u getaddrinfo

This commit is contained in:
Lectem 2016-01-13 12:20:33 -05:00
parent 517b1c9503
commit 6eb23d3fbd
2 changed files with 188 additions and 0 deletions

View File

@ -17,6 +17,16 @@ struct hostent {
char *h_addr;
};
#define AI_PASSIVE 0x01
#define AI_CANONNAME 0x02
#define AI_NUMERICHOST 0x04
#define AI_NUMERICSERV 0x00 /* probably 0x08 but services names are never resolved */
// doesn't apply to 3ds
#define AI_ADDRCONFIG 0x00
#define NI_MAXHOST 1025
#define NI_MAXSERV 32
@ -31,6 +41,16 @@ struct hostent {
#define EAI_NONAME (-305)
#define EAI_SOCKTYPE (-307)
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
char *ai_canonname;
struct sockaddr *ai_addr;
struct addrinfo *ai_next;
};
#ifdef __cplusplus
extern "C" {
@ -46,6 +66,12 @@ extern "C" {
char *host, socklen_t hostlen,
char *serv, socklen_t servlen, int flags);
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
void freeaddrinfo(struct addrinfo *ai);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,162 @@
#include "soc_common.h"
#include <netdb.h>
#include <3ds/ipc.h>
#include <3ds/result.h>
#include <stdlib.h>
#define DEFAULT_NUM_ADDRINFO 4
typedef struct addrinfo_3ds_t addrinfo_3ds_t;
struct addrinfo_3ds_t
{
s32 ai_flags;
s32 ai_family;
s32 ai_socktype;
s32 ai_protocol;
u32 ai_addrlen;
char ai_canonname[256];
struct sockaddr_storage ai_addr;
};
void freeaddrinfo(struct addrinfo *ai)
{
struct addrinfo *next_ai = ai;
while(ai != NULL)
{
next_ai = ai->ai_next;
free(ai);
ai = next_ai;
}
}
static struct addrinfo * buffer2addrinfo(addrinfo_3ds_t * entry)
{
int ai_canonname_len = strnlen(entry->ai_canonname, sizeof(entry->ai_canonname));
struct addrinfo *ai;
size_t len = sizeof(*ai)
+ sizeof(struct sockaddr_storage)
+ ai_canonname_len
+ 1;
ai = (struct addrinfo*)calloc(1,len);
if(ai != NULL)
{
ai->ai_canonname = (char*)ai + sizeof(*ai) + sizeof(struct sockaddr_storage);
ai->ai_addr = (struct sockaddr*)((char*)ai + sizeof(*ai));
ai->ai_flags = entry->ai_flags;
ai->ai_family = entry->ai_family;
ai->ai_socktype = entry->ai_socktype;
ai->ai_protocol = entry->ai_protocol;
ai->ai_addrlen = entry->ai_addrlen;
memcpy(ai->ai_canonname, entry->ai_canonname, ai_canonname_len);
memcpy(ai->ai_addr, &entry->ai_addr, ai->ai_addrlen);
}
return ai;
}
static int getaddrinfo_detail(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res, addrinfo_3ds_t *info, s32 info_count, s32 * count)
{
int i;
u32 *cmdbuf = getThreadCommandBuffer();
u32 saved_threadstorage[2];
if(node == NULL && service == NULL)
{
return EAI_NONAME;
}
cmdbuf[ 0] = IPC_MakeHeader(0xF,4,6); // 0x00F0106
cmdbuf[ 1] = node == NULL ? 0 : strlen(node)+1;
cmdbuf[ 2] = service == NULL ? 0 : strlen(service)+1;
cmdbuf[ 3] = hints == NULL ? 0 : sizeof(*hints);
cmdbuf[ 4] = sizeof(addrinfo_3ds_t) * info_count;
cmdbuf[ 5] = IPC_Desc_StaticBuffer(cmdbuf[1], 5);
cmdbuf[ 6] = (u32)node;
cmdbuf[ 7] = IPC_Desc_StaticBuffer(cmdbuf[2], 6);
cmdbuf[ 8] = (u32)service;
cmdbuf[ 9] = IPC_Desc_StaticBuffer(cmdbuf[3], 7);
cmdbuf[10] = (u32)hints;
u32 * staticbufs = getThreadStaticBuffers();
// Save the thread storage values
for(i = 0 ; i < 2 ; ++i)
saved_threadstorage[i] = staticbufs[i];
staticbufs[0] = IPC_Desc_StaticBuffer(sizeof(addrinfo_3ds_t) * info_count, 0);
staticbufs[1] = (u32)info;
int ret = svcSendSyncRequest(SOCU_handle);
// Restore the thread storage values
for(i = 0 ; i < 2 ; ++i)
staticbufs[i] = saved_threadstorage[i];
if(R_FAILED(ret)) {
errno = SYNC_ERROR;
return ret;
}
ret = cmdbuf[1];
if(R_FAILED(ret)) {
errno = SYNC_ERROR;
return ret;
}
if(cmdbuf[2] != 0)
{
return cmdbuf[2];
}
*count = cmdbuf[3];
if(*count <= 0)
*res = NULL;
else if(*count <= info_count)
{
struct addrinfo **ptr = res;
for(i = 0; i < *count; ++i)
{
*ptr = buffer2addrinfo(&info[i]);
if(*ptr == NULL)
{
freeaddrinfo(*res);
*res = NULL;
return EAI_MEMORY;
}
ptr = &(*ptr)->ai_next;
}
*ptr = NULL;
}
return 0;
}
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
{
Result ret;
addrinfo_3ds_t *info = NULL, *tmp;
s32 count = DEFAULT_NUM_ADDRINFO, info_count;
if(node == NULL && service == NULL)
{
return EAI_NONAME;
}
do
{
info_count = count;
tmp = (addrinfo_3ds_t*)realloc(info, sizeof(addrinfo_3ds_t) * info_count);
if(tmp == NULL)
{
free(info);
return EAI_MEMORY;
}
info = tmp;
ret = getaddrinfo_detail(node,service,hints,res,info,info_count,&count);
} while(count > info_count && R_SUCCEEDED(ret));
free(info);
return ret;
}