]> Chaos Git - corbenik/ctrulib.git/commitdiff
Added SOC error conversion, and implemented getsockopt, setsockopt, fcntl, sockatmark...
authoryellows8 <yellowstar6@gmail.com>
Mon, 5 May 2014 01:55:59 +0000 (21:55 -0400)
committeryellows8 <yellowstar6@gmail.com>
Mon, 5 May 2014 01:55:59 +0000 (21:55 -0400)
libctru/source/SOC.c

index 2ebddac221b8e1781779f885a7fd6d0f43c5ee0b..e9f54723a40e40523c5a60fa8c60fde98003b756 100644 (file)
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <string.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netdb.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
 
 Handle SOCU_handle = 0;
 static int SOCU_errno = 0;
 
+#define NET_UNKNOWN_ERROR_OFFSET       -10000//This is from libogc network_wii.c.
+
+static u8 _net_error_code_map[] = { //This is based on the array from libogc network_wii.c.
+       0, // 0
+       E2BIG,
+       EACCES,
+       EADDRINUSE,
+       EADDRNOTAVAIL,
+       EAFNOSUPPORT, // 5
+       EAGAIN,
+       EALREADY,
+       EBADF,
+       EBADMSG,
+       EBUSY, // 10
+       ECANCELED,
+       ECHILD,
+       ECONNABORTED,
+       ECONNREFUSED,
+       ECONNRESET, // 15
+       EDEADLK,
+       EDESTADDRREQ,
+       EDOM,
+       EDQUOT,
+       EEXIST, // 20
+       EFAULT,
+       EFBIG,
+       EHOSTUNREACH,
+       EIDRM,
+       EILSEQ, // 25
+       EINPROGRESS,
+       EINTR,
+       EINVAL,
+       EIO,
+       EISCONN, // 30
+       EISDIR,
+       ELOOP,
+       EMFILE,
+       EMLINK,
+       EMSGSIZE, // 35
+       EMULTIHOP,
+       ENAMETOOLONG,
+       ENETDOWN,
+       ENETRESET,
+       ENETUNREACH, // 40
+       ENFILE,
+       ENOBUFS,
+       ENODATA,
+       ENODEV,
+       ENOENT, // 45
+       ENOEXEC,
+       ENOLCK,
+       ENOLINK,
+       ENOMEM,
+       ENOMSG, // 50
+       ENOPROTOOPT,
+       ENOSPC,
+       ENOSR,
+       ENOSTR,
+       ENOSYS, // 55
+       ENOTCONN,
+       ENOTDIR,
+       ENOTEMPTY,
+       ENOTSOCK,
+       ENOTSUP, // 60
+       ENOTTY,
+       ENXIO,
+       EOPNOTSUPP,
+       EOVERFLOW,
+       EPERM, // 65
+       EPIPE,
+       EPROTO,
+       EPROTONOSUPPORT,
+       EPROTOTYPE,
+       ERANGE, // 70
+       EROFS,
+       ESPIPE,
+       ESRCH,
+       ESTALE,
+       ETIME, // 75
+       ETIMEDOUT,
+};
+
+static s32 _net_convert_error(s32 sock_retval)//This is based on the function from libogc network_wii.c.
+{
+       if (sock_retval >= 0) return sock_retval;
+       if (sock_retval < -sizeof(_net_error_code_map)
+               || !_net_error_code_map[-sock_retval])
+                       return NET_UNKNOWN_ERROR_OFFSET + sock_retval;
+       return -_net_error_code_map[-sock_retval];
+}
+
 Result socu_cmd1(Handle memhandle, u32 memsize)
 {
        Result ret=0;
@@ -78,7 +173,7 @@ int socket(int domain, int type, int protocol)
        SOCU_errno = ret;
 
        if(ret!=0)return -1;
-       return (int)cmdbuf[2];
+       return _net_convert_error(cmdbuf[2]);
 }
 
 int closesocket(int sockfd)
@@ -93,7 +188,7 @@ int closesocket(int sockfd)
        if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = (int)cmdbuf[2];
+       if(ret==0)ret =_net_convert_error(cmdbuf[2]);
        SOCU_errno = ret;
 
        if(ret!=0)return -1;
@@ -113,7 +208,7 @@ int shutdown(int sockfd, int shutdown_type)
        if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = (int)cmdbuf[2];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
        SOCU_errno = ret;
 
        if(ret!=0)return -1;
@@ -133,7 +228,7 @@ int listen(int sockfd, int max_connections)
        if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = (int)cmdbuf[2];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
        SOCU_errno = ret;
 
        if(ret!=0)return -1;
@@ -167,7 +262,7 @@ int accept(int sockfd, struct sockaddr *addr, int *addrlen)
        cmdbuf[0x104>>2] = saved_threadstorage[1];
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = (int)cmdbuf[2];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
        if(ret<0)SOCU_errno = ret;
 
        if(ret>=0 && addr!=NULL)
@@ -204,7 +299,7 @@ int bind(int sockfd, const struct sockaddr *addr, int addrlen)
        if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = (int)cmdbuf[2];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
        SOCU_errno = ret;
 
        if(ret<0)return -1;
@@ -233,7 +328,7 @@ int connect(int sockfd, const struct sockaddr *addr, int addrlen)
        if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = (int)cmdbuf[2];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
        SOCU_errno = ret;
 
        if(ret<0)return -1;
@@ -271,7 +366,7 @@ int socuipc_cmd7(int sockfd, void *buf, int len, int flags, struct sockaddr *src
        cmdbuf[0x104>>2] = saved_threadstorage[1];
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = (int)cmdbuf[2];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
        if(ret<0)SOCU_errno = ret;
 
        if(ret<0)return -1;
@@ -313,7 +408,7 @@ int socuipc_cmd8(int sockfd, void *buf, int len, int flags, struct sockaddr *src
        cmdbuf[0x10c>>2] = saved_threadstorage[3];
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = (int)cmdbuf[2];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
        if(ret<0)SOCU_errno = ret;
 
        if(ret<0)return -1;
@@ -343,7 +438,7 @@ int socuipc_cmd9(int sockfd, const void *buf, int len, int flags, const struct s
        if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = (int)cmdbuf[2];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
        if(ret<0)SOCU_errno = ret;
 
        if(ret<0)return -1;
@@ -373,7 +468,7 @@ int socuipc_cmda(int sockfd, const void *buf, int len, int flags, const struct s
        if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = (int)cmdbuf[2];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
        if(ret<0)SOCU_errno = ret;
 
        if(ret<0)return -1;
@@ -402,3 +497,215 @@ int send(int sockfd, const void *buf, int len, int flags)
        return sendto(sockfd, buf, len, flags, NULL, 0);
 }
 
+int getsockopt(int sockfd, int level, int option_name, void * data, int * data_len)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u32 saved_threadstorage[2];
+
+       cmdbuf[0] = 0x00110102;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = (u32)level;
+       cmdbuf[3] = (u32)option_name;
+       cmdbuf[4] = (u32)*data_len;
+       cmdbuf[5] = 0x20;
+
+       saved_threadstorage[0] = cmdbuf[0x100>>2];
+       saved_threadstorage[1] = cmdbuf[0x104>>2];
+
+       cmdbuf[0x100>>2] = ((*data_len)<<14) | 2;
+       cmdbuf[0x104>>2] = (u32)data;
+
+       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 = _net_convert_error(cmdbuf[2]);
+       if(ret<0)SOCU_errno = ret;
+
+       if(ret==0)*data_len = cmdbuf[3];
+
+       if(ret<0)return -1;
+       return ret;
+}
+
+int setsockopt(int sockfd, int level, int option_name, const void * data, int data_len)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       cmdbuf[0] = 0x00120104;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = (u32)level;
+       cmdbuf[3] = (u32)option_name;
+       cmdbuf[4] = (u32)data_len;
+       cmdbuf[5] = 0x20;
+       cmdbuf[7] = (data_len<<14) | 0x2402;
+       cmdbuf[8] = (u32)data;
+
+       if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
+       if(ret<0)SOCU_errno = ret;
+
+       if(ret<0)return -1;
+       return ret;
+}
+
+int fcntl(int sockfd, int cmd, ...)
+{
+       int ret=0;
+       int arg=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       va_list args;
+       va_start(args, cmd);
+
+       if(cmd!=F_GETFL && cmd!=F_SETFL)
+       {
+               SOCU_errno = -EINVAL;
+               return -1;
+       }
+
+       if(cmd==F_SETFL)
+       {
+               arg = va_arg(args, int);
+
+               if(arg && arg!=O_NONBLOCK)
+               {
+                       SOCU_errno = -EINVAL;
+                       return -1;
+               }
+
+               if(arg==O_NONBLOCK)arg = 0x4;
+       }
+
+       cmdbuf[0] = 0x001300C2;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = (u32)cmd;
+       cmdbuf[3] = (u32)arg;
+       cmdbuf[4] = 0x20;
+
+       if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
+       if(ret<0)SOCU_errno = ret;
+
+       if(ret<0)return -1;
+       return ret;
+}
+
+int sockatmark(int sockfd)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       cmdbuf[0] = 0x00150042;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = 0x20;
+
+       if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
+       if(ret<0)SOCU_errno = ret;
+
+       if(ret<0)return -1;
+       return ret;
+}
+
+long gethostid()
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       cmdbuf[0] = 0x00160000;
+
+       if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret = cmdbuf[2];
+
+       return ret;
+}
+
+int getsockname(int sockfd, struct sockaddr *addr, int * addr_len)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u32 saved_threadstorage[2];
+       u8 tmpaddr[0x1c];
+
+       cmdbuf[0] = 0x00170082;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = 0x1c;
+       cmdbuf[3] = 0x20;
+
+       saved_threadstorage[0] = cmdbuf[0x100>>2];
+       saved_threadstorage[1] = cmdbuf[0x104>>2];
+
+       cmdbuf[0x100>>2] = (0x1c<<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 = _net_convert_error(cmdbuf[2]);
+       if(ret<0)SOCU_errno = ret;
+
+       if(ret==0)
+       {
+               addr->sa_family = tmpaddr[1];
+               if(*addr_len > tmpaddr[0])*addr_len = tmpaddr[0];
+               memcpy(addr->sa_data, &tmpaddr[2], *addr_len - 2);
+       }
+
+       if(ret<0)return -1;
+       return ret;
+}
+
+int getpeername(int sockfd, struct sockaddr *addr, int * addr_len)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u32 saved_threadstorage[2];
+       u8 tmpaddr[0x1c];
+
+       cmdbuf[0] = 0x00180082;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = 0x1c;
+       cmdbuf[3] = 0x20;
+
+       saved_threadstorage[0] = cmdbuf[0x100>>2];
+       saved_threadstorage[1] = cmdbuf[0x104>>2];
+
+       cmdbuf[0x100>>2] = (0x1c<<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 = _net_convert_error(cmdbuf[2]);
+       if(ret<0)SOCU_errno = ret;
+
+       if(ret==0)
+       {
+               addr->sa_family = tmpaddr[1];
+               if(*addr_len > tmpaddr[0])*addr_len = tmpaddr[0];
+               memcpy(addr->sa_data, &tmpaddr[2], *addr_len - 2);
+       }
+
+       if(ret<0)return -1;
+       return ret;
+}
+