added SOC:u getaddrinfo
This commit is contained in:
parent
517b1c9503
commit
6eb23d3fbd
@ -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
|
||||
|
162
libctru/source/services/soc/soc_getaddrinfo.c
Normal file
162
libctru/source/services/soc/soc_getaddrinfo.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user