added SOC:u getaddrinfo
This commit is contained in:
parent
517b1c9503
commit
6eb23d3fbd
@ -17,6 +17,16 @@ struct hostent {
|
|||||||
char *h_addr;
|
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_MAXHOST 1025
|
||||||
#define NI_MAXSERV 32
|
#define NI_MAXSERV 32
|
||||||
|
|
||||||
@ -31,6 +41,16 @@ struct hostent {
|
|||||||
#define EAI_NONAME (-305)
|
#define EAI_NONAME (-305)
|
||||||
#define EAI_SOCKTYPE (-307)
|
#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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -46,6 +66,12 @@ extern "C" {
|
|||||||
char *host, socklen_t hostlen,
|
char *host, socklen_t hostlen,
|
||||||
char *serv, socklen_t servlen, int flags);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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