From 4f5c8bba3ced40955edeb42d31c748029efffe4e Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 28 Jan 2014 19:35:40 -0500 Subject: [PATCH] Added code for using the socket service. --- libctru/include/ctr/SOC.h | 9 + libctru/source/SOC.c | 404 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 413 insertions(+) create mode 100644 libctru/include/ctr/SOC.h create mode 100644 libctru/source/SOC.c diff --git a/libctru/include/ctr/SOC.h b/libctru/include/ctr/SOC.h new file mode 100644 index 0000000..4008230 --- /dev/null +++ b/libctru/include/ctr/SOC.h @@ -0,0 +1,9 @@ +#ifndef SOC_H +#define SOC_H + +Result SOC_Initialize(u32 *context_addr, u32 context_size); +Result SOC_Shutdown(); +int SOC_GetErrno(); + +#endif + diff --git a/libctru/source/SOC.c b/libctru/source/SOC.c new file mode 100644 index 0000000..ab36051 --- /dev/null +++ b/libctru/source/SOC.c @@ -0,0 +1,404 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static Handle socu_handle = 0; +static int soc_errno = 0; + +Result socu_cmd1(Handle memhandle, u32 memsize) +{ + Result ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = 0x00010044; + cmdbuf[1] = memsize; + cmdbuf[2] = 0x20; + cmdbuf[4] = 0; + cmdbuf[5] = memhandle; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + return cmdbuf[1]; +} + +Result SOC_Shutdown() +{ + Result ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = 0x00190000; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + svc_closeHandle(socu_handle); + + return cmdbuf[1]; +} + +Result SOC_Initialize(u32 *context_addr, u32 context_size)//Example context_size: 0x48000. The specified context buffer can no longer be accessed by the process which called this function, since the userland permissions for this block are set to no-access. +{ + Result ret=0; + Handle memhandle = 0; + + ret = svc_createMemoryBlock(&memhandle, (u32)context_addr, context_size, 0, 3); + if(ret!=0)return ret; + + if((ret = srv_getServiceHandle(NULL, &socu_handle, "soc:U"))!=0)return ret; + + return socu_cmd1(memhandle, context_size); +} + +int SOC_GetErrno() +{ + return soc_errno; +} + +int socket(int domain, int type, int protocol) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = 0x000200C2; + cmdbuf[1] = domain; + cmdbuf[2] = type; + cmdbuf[3] = protocol; + cmdbuf[4] = 0x20; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + ret = (int)cmdbuf[1]; + soc_errno = ret; + + if(ret!=0)return -1; + return (int)cmdbuf[2]; +} + +int closesocket(int sockfd) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = 0x000B0042; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = 0x20; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + ret = (int)cmdbuf[1]; + if(ret==0)ret = (int)cmdbuf[2]; + soc_errno = ret; + + if(ret!=0)return -1; + return 0; +} + +int shutdown(int sockfd, int shutdown_type) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = 0x000C0082; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)shutdown_type; + cmdbuf[3] = 0x20; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + ret = (int)cmdbuf[1]; + if(ret==0)ret = (int)cmdbuf[2]; + soc_errno = ret; + + if(ret!=0)return -1; + return 0; +} + +int listen(int sockfd, int max_connections) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = 0x00030082; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)max_connections; + cmdbuf[3] = 0x20; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + ret = (int)cmdbuf[1]; + if(ret==0)ret = (int)cmdbuf[2]; + soc_errno = ret; + + if(ret!=0)return -1; + return 0; +} + +int accept(int sockfd, struct sockaddr *addr, int *addrlen) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u8 tmpaddr[8]; + int tmp_addrlen=8; + u32 saved_threadstorage[2]; + + memset(tmpaddr, 0, 8); + + cmdbuf[0] = 0x00040082; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)tmp_addrlen; + cmdbuf[3] = 0x20; + + saved_threadstorage[0] = cmdbuf[0x100>>2]; + saved_threadstorage[1] = cmdbuf[0x104>>2]; + + cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2; + cmdbuf[0x104>>2] = (u32)tmpaddr; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + cmdbuf[0x100>>2] = saved_threadstorage[0]; + cmdbuf[0x104>>2] = saved_threadstorage[1]; + + ret = (int)cmdbuf[1]; + if(ret==0)ret = (int)cmdbuf[2]; + if(ret<0)soc_errno = ret; + + if(ret>=0 && addr!=NULL) + { + *addrlen = tmpaddr[0]; + memset(addr, 0, sizeof(struct sockaddr)); + addr->sa_family = tmpaddr[1]; + memcpy(&addr->sa_data, &tmpaddr[2], tmp_addrlen-2); + } + + if(ret<0)return -1; + return ret; +} + +int bind(int sockfd, const struct sockaddr *addr, int addrlen) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u8 tmpaddr[8]; + struct sockaddr_in *inaddr = (struct sockaddr_in*)addr; + + addrlen = 8; + tmpaddr[0] = 8; + tmpaddr[1] = addr->sa_family; + memcpy(&tmpaddr[2], &addr->sa_data, addrlen-2); + + cmdbuf[0] = 0x00050084; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)addrlen; + cmdbuf[3] = 0x20; + cmdbuf[5] = (((u32)addrlen)<<14) | 2; + cmdbuf[6] = (u32)tmpaddr; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + ret = (int)cmdbuf[1]; + if(ret==0)ret = (int)cmdbuf[2]; + soc_errno = ret; + + if(ret<0)return -1; + return 0; +} + +int connect(int sockfd, const struct sockaddr *addr, int addrlen) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u8 tmpaddr[8]; + struct sockaddr_in *inaddr = (struct sockaddr_in*)addr; + + addrlen = 8; + tmpaddr[0] = 8; + tmpaddr[1] = addr->sa_family; + memcpy(&tmpaddr[2], &addr->sa_data, addrlen-2); + + cmdbuf[0] = 0x00060084; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)addrlen; + cmdbuf[3] = 0x20; + cmdbuf[5] = (((u32)addrlen)<<14) | 2; + cmdbuf[6] = (u32)tmpaddr; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + ret = (int)cmdbuf[1]; + if(ret==0)ret = (int)cmdbuf[2]; + soc_errno = ret; + + if(ret<0)return -1; + return 0; +} + +int socuipc_cmd7(int sockfd, void *buf, int len, int flags, struct sockaddr *src_addr, int *addrlen) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u8 tmpaddr[8]; + u32 tmp_addrlen=0; + u32 saved_threadstorage[2]; + + memset(tmpaddr, 0, 8); + + cmdbuf[0] = 0x00070104; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)len; + cmdbuf[3] = (u32)flags; + cmdbuf[4] = (u32)tmp_addrlen; + cmdbuf[5] = 0x20; + cmdbuf[7] = (((u32)len)<<4) | 12; + cmdbuf[8] = (u32)buf; + + saved_threadstorage[0] = cmdbuf[0x100>>2]; + saved_threadstorage[1] = cmdbuf[0x104>>2]; + + cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2; + cmdbuf[0x104>>2] = (u32)tmpaddr; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + cmdbuf[0x100>>2] = saved_threadstorage[0]; + cmdbuf[0x104>>2] = saved_threadstorage[1]; + + ret = (int)cmdbuf[1]; + if(ret==0)ret = (int)cmdbuf[2]; + if(ret<0)soc_errno = ret; + + if(ret<0)return -1; + return ret; +} + +int socuipc_cmd8(int sockfd, void *buf, int len, int flags, struct sockaddr *src_addr, int *addrlen) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u8 tmpaddr[8]; + u32 tmp_addrlen=0; + u32 saved_threadstorage[4]; + + memset(tmpaddr, 0, 8); + + cmdbuf[0] = 0x00070104; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)len; + cmdbuf[3] = (u32)flags; + cmdbuf[4] = (u32)tmp_addrlen; + cmdbuf[5] = 0x20; + + saved_threadstorage[0] = cmdbuf[0x100>>2]; + saved_threadstorage[1] = cmdbuf[0x104>>2]; + saved_threadstorage[2] = cmdbuf[0x108>>2]; + saved_threadstorage[3] = cmdbuf[0x10c>>2]; + + cmdbuf[0x100>>2] = (((u32)len)<<14) | 2; + cmdbuf[0x104>>2] = (u32)buf; + cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2; + cmdbuf[0x10c>>2] = (u32)tmpaddr; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + cmdbuf[0x100>>2] = saved_threadstorage[0]; + cmdbuf[0x104>>2] = saved_threadstorage[1]; + cmdbuf[0x108>>2] = saved_threadstorage[2]; + cmdbuf[0x10c>>2] = saved_threadstorage[3]; + + ret = (int)cmdbuf[1]; + if(ret==0)ret = (int)cmdbuf[2]; + if(ret<0)soc_errno = ret; + + if(ret<0)return -1; + return ret; +} + +int socuipc_cmd9(int sockfd, const void *buf, int len, int flags, struct sockaddr *dest_addr, int addrlen) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u8 tmpaddr[8]; + u32 tmp_addrlen=0; + + memset(tmpaddr, 0, 8); + + cmdbuf[0] = 0x00090106; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)len; + cmdbuf[3] = (u32)flags; + cmdbuf[4] = (u32)tmp_addrlen; + cmdbuf[5] = 0x20; + cmdbuf[7] = (tmp_addrlen<<14) | 0x402; + cmdbuf[8] = (u32)tmpaddr; + cmdbuf[9] = (((u32)len)<<4) | 10; + cmdbuf[10] = (u32)buf; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + ret = (int)cmdbuf[1]; + if(ret==0)ret = (int)cmdbuf[2]; + if(ret<0)soc_errno = ret; + + if(ret<0)return -1; + return ret; +} + +int socuipc_cmda(int sockfd, const void *buf, int len, int flags, struct sockaddr *dest_addr, int addrlen) +{ + int ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u8 tmpaddr[8]; + int tmp_addrlen=0; + + memset(tmpaddr, 0, 8); + + cmdbuf[0] = 0x00090106; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)len; + cmdbuf[3] = (u32)flags; + cmdbuf[4] = (u32)tmp_addrlen; + cmdbuf[5] = 0x20; + cmdbuf[7] = (((u32)len)<<14) | 0x802; + cmdbuf[8] = (u32)buf; + cmdbuf[9] = (tmp_addrlen<<14) | 0x402; + cmdbuf[10] = (u32)tmpaddr; + + if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + + ret = (int)cmdbuf[1]; + if(ret==0)ret = (int)cmdbuf[2]; + if(ret<0)soc_errno = ret; + + if(ret<0)return -1; + return ret; +} + +int recvfrom(int sockfd, void *buf, int len, int flags, struct sockaddr *src_addr, int *addrlen)//UDP is not supported for these since the input/output sockaddr is not used. +{ + //if(len<0x20000)return socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen); + return socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen); +} + +int sendto(int sockfd, const void *buf, int len, int flags, const struct sockaddr *dest_addr, int addrlen) +{ + //if(len<0x20000)return socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen); + return socuipc_cmd9(sockfd, buf, len, flags, (struct sockaddr*)dest_addr, addrlen); +} + +int recv(int sockfd, void *buf, int len, int flags) +{ + return recvfrom(sockfd, buf, len, flags, NULL, 0); +} + +int send(int sockfd, const void *buf, int len, int flags) +{ + return sendto(sockfd, buf, len, flags, NULL, 0); +} +