]> Chaos Git - corbenik/ctrulib.git/commitdiff
Overhauled soc service.
authormtheall <pigman46@gmail.com>
Thu, 20 Nov 2014 21:36:50 +0000 (15:36 -0600)
committermtheall <pigman46@gmail.com>
Thu, 20 Nov 2014 21:36:50 +0000 (15:36 -0600)
39 files changed:
libctru/Makefile
libctru/include/3ds/services/soc.h
libctru/include/arpa/inet.h [new file with mode: 0644]
libctru/include/netdb.h
libctru/include/netinet/in.h
libctru/include/netinet/tcp.h
libctru/include/poll.h [new file with mode: 0644]
libctru/include/sys/ioctl.h [new file with mode: 0644]
libctru/include/sys/select.h [new file with mode: 0644]
libctru/include/sys/socket.h
libctru/source/services/soc.c [deleted file]
libctru/source/services/soc/soc_accept.c [new file with mode: 0644]
libctru/source/services/soc/soc_bind.c [new file with mode: 0644]
libctru/source/services/soc/soc_closesocket.c [new file with mode: 0644]
libctru/source/services/soc/soc_common.c [new file with mode: 0644]
libctru/source/services/soc/soc_common.h [new file with mode: 0644]
libctru/source/services/soc/soc_connect.c [new file with mode: 0644]
libctru/source/services/soc/soc_fcntl.c [new file with mode: 0644]
libctru/source/services/soc/soc_gethostbyname.c [new file with mode: 0644]
libctru/source/services/soc/soc_gethostid.c [new file with mode: 0644]
libctru/source/services/soc/soc_getpeername.c [new file with mode: 0644]
libctru/source/services/soc/soc_getsockname.c [new file with mode: 0644]
libctru/source/services/soc/soc_getsockopt.c [new file with mode: 0644]
libctru/source/services/soc/soc_inet_addr.c [new file with mode: 0644]
libctru/source/services/soc/soc_inet_aton.c [new file with mode: 0644]
libctru/source/services/soc/soc_inet_ntoa.c [new file with mode: 0644]
libctru/source/services/soc/soc_init.c [new file with mode: 0644]
libctru/source/services/soc/soc_ioctl.c [new file with mode: 0644]
libctru/source/services/soc/soc_listen.c [new file with mode: 0644]
libctru/source/services/soc/soc_poll.c [new file with mode: 0644]
libctru/source/services/soc/soc_recv.c [new file with mode: 0644]
libctru/source/services/soc/soc_recvfrom.c [new file with mode: 0644]
libctru/source/services/soc/soc_select.c [new file with mode: 0644]
libctru/source/services/soc/soc_send.c [new file with mode: 0644]
libctru/source/services/soc/soc_sendto.c [new file with mode: 0644]
libctru/source/services/soc/soc_setsockopt.c [new file with mode: 0644]
libctru/source/services/soc/soc_shutdown.c [new file with mode: 0644]
libctru/source/services/soc/soc_sockatmark.c [new file with mode: 0644]
libctru/source/services/soc/soc_socket.c [new file with mode: 0644]

index 114d61bdd60c05af7d3c7f0e1c205935cf7b4fc6..919a471c8e3df91390d028b8456c89d4e0232fe7 100644 (file)
@@ -21,6 +21,7 @@ SOURCES               :=      source \
                        source/allocator \
                        source/gpu \
                        source/services \
+                       source/services/soc \
                        source/util
 DATA           :=      data
 INCLUDES       :=      include
index 0b347754d837df0dccd85aa9d06a945d33464ed8..55ff21e99baa8e8b3050b2767c2f103e84e6054e 100644 (file)
@@ -4,4 +4,9 @@ Result SOC_Initialize(u32 *context_addr, u32 context_size);//Example context_siz
 Result SOC_Shutdown();
 int SOC_GetErrno();
 
-long gethostid();
+Result SOC_Shutdown(void);
+int SOC_GetErrno(void);
+
+/* this is supposed to be in unistd.h but newlib only puts it for cygwin */
+long gethostid(void);
+
diff --git a/libctru/include/arpa/inet.h b/libctru/include/arpa/inet.h
new file mode 100644 (file)
index 0000000..197877b
--- /dev/null
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <netinet/in.h>
+#include <stdint.h>
+
+static inline uint32_t htonl(uint32_t hostlong)
+{
+       return __builtin_bswap32(hostlong);
+}
+
+static inline uint16_t htons(uint16_t hostshort)
+{
+       return __builtin_bswap16(hostshort);
+}
+
+static inline uint32_t ntohl(uint32_t netlong)
+{
+       return __builtin_bswap32(netlong);
+}
+
+static inline uint16_t ntohs(uint16_t netshort)
+{
+       return __builtin_bswap16(netshort);
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+       in_addr_t       inet_addr(const char *cp);
+       int             inet_aton(const char *cp, struct in_addr *inp);
+       char*           inet_ntoa(struct in_addr in);
+
+#ifdef __cplusplus
+}
+#endif
index 8aa5d9128fda4b325e45b3d85852c31fe6c5419e..7f769a49d8cbc40ef784e850341ec65262fe0875 100644 (file)
@@ -1,24 +1,28 @@
-#ifndef NETDB_H
-#define NETDB_H
+#pragma once
+
+#include <netinet/in.h>
+
+#define HOST_NOT_FOUND 1
+#define NO_DATA                2
+#define NO_ADDRESS     NO_DATA
+#define NO_RECOVERY    3
+#define TRY_AGAIN      4
 
 struct hostent {
-       char h_name;
-       char ** h_aliases;
-       int h_addrtype;
-       int h_length;
-       char ** h_addr_list;
+       char    *h_name;
+       char    **h_aliases;
+       int     h_addrtype;
+       int     h_length;
+       char    **h_addr_list;
 };
 
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-       struct hostent * gethostbyname(const char * name);
+       extern int      h_errno;
+       struct hostent* gethostbyname(const char *name);
 
 #ifdef __cplusplus
-};
+}
 #endif
-
-
-#endif // NETDB_H
index 5e3acd3dcc15b98a2c394b1e02ea30604f8802fa..bc8d6f82ee02536f36ecabd22940314336f917d6 100644 (file)
@@ -1,34 +1,28 @@
-#ifndef NETINET_IN_H
-#define NETINET_IN_H
+#pragma once
 
-#include "sys/socket.h"
+#include <stdint.h>
+#include <sys/socket.h>
 
 #define INADDR_ANY             0x00000000
 #define INADDR_BROADCAST       0xFFFFFFFF
 #define INADDR_NONE            0xFFFFFFFF
 
-struct in_addr {
-       unsigned long s_addr;
-};
-
-struct sockaddr_in {
-       unsigned short          sin_family;
-       unsigned short          sin_port;
-       struct in_addr          sin_addr;
-       unsigned char           sin_zero[8];
-};
+#define INET_ADDRSTRLEN                16
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+//#define IPPROTO_IP           ???
+//#define IPPROTO_TCP          ???
+//#define IPPROTO_UDP          ???
 
-       // actually from arpa/inet.h - but is included through netinet/in.h
-       unsigned long inet_addr(const char *cp);
-       int inet_aton(const char *cp, struct in_addr *inp);
-       char *inet_ntoa(struct in_addr in);
+typedef uint16_t in_port_t;
+typedef uint32_t in_addr_t;
 
-#ifdef __cplusplus
+struct in_addr {
+       in_addr_t       s_addr;
 };
-#endif
 
-#endif // NETINET_IN_H
+struct sockaddr_in {
+       sa_family_t     sin_family;
+       in_port_t       sin_port;
+       struct in_addr  sin_addr;
+       unsigned char   sin_zero[8];
+};
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b95b1276e6f43bbfe3fc54a9161db93d9159015f 100644 (file)
@@ -0,0 +1,5 @@
+#pragma once
+
+//#define SOL_TCP      ???
+
+//#define TCP_NODELAY  ???
diff --git a/libctru/include/poll.h b/libctru/include/poll.h
new file mode 100644 (file)
index 0000000..4315a43
--- /dev/null
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <3ds/types.h>
+
+/* only POLLIN confirmed to work so far */
+#define POLLIN         0x001
+#define POLLPRI                0x002
+#define POLLOUT                0x004
+#define POLLERR                0x008
+#define POLLHUP                0x010
+#define POLLNVAL       0x020
+#define POLLRDNORM     0x040
+#define POLLRDBAND     0x080
+#define POLLWRNORM     0x100
+#define POLLWRBAND     0x200
+
+typedef u32 nfds_t;
+
+struct pollfd
+{
+       int     fd;
+       int     events;
+       int     revents;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+       int     poll(struct pollfd *fds, nfds_t nfsd, int timeout);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libctru/include/sys/ioctl.h b/libctru/include/sys/ioctl.h
new file mode 100644 (file)
index 0000000..bbd3f83
--- /dev/null
@@ -0,0 +1,13 @@
+#pragma once
+
+#define FIONBIO                1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+       int     ioctl(int fd, int request, ...);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libctru/include/sys/select.h b/libctru/include/sys/select.h
new file mode 100644 (file)
index 0000000..d75f9d0
--- /dev/null
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <sys/time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+       int     select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
+
+#ifdef __cplusplus
+}
+#endif
index 1ee3502073cf8af239cf87d87f7dab5de90785e6..02fa98cfac99182db6978c8ac8dcaf6dad0af17e 100644 (file)
-#ifndef SYS_SOCKET_H
-#define SYS_SOCKET_H
+#pragma once
 
+#include <stdint.h>
 #include <sys/time.h>
 
-/*
- * Level number for (get/set)sockopt() to apply to socket itself.
- */
-#define  SOL_SOCKET  0xfff    /* options for socket level */
-# define SOL_TCP                6       /* TCP level */
+#define SOL_SOCKET     0xFFFF
 
-#define PF_UNSPEC              0
-#define PF_INET                        2
-#define PF_INET6               10
+#define PF_UNSPEC      0
+#define PF_INET                2
+#define PF_INET6       10
 
-#define AF_UNSPEC              PF_UNSPEC
-#define AF_INET                        PF_INET
-#define AF_INET6               PF_INET6
+#define AF_UNSPEC      PF_UNSPEC
+#define AF_INET                PF_INET
+#define AF_INET6       PF_INET6
 
-#define SOCK_STREAM            1
-#define SOCK_DGRAM             2
+#define SOCK_STREAM    1
+#define SOCK_DGRAM     2
 
-// need to sync FIO* values with commonly accepted ones sometime
-#define FIONBIO                        1
-#define FIONREAD               2
-
-#define SOCKET_ERROR   -1
-
-// send()/recv()/etc flags
-// at present, only MSG_PEEK is implemented though.
-#define MSG_WAITALL            0x40000000
-#define MSG_TRUNC              0x20000000
-#define MSG_PEEK               0x10000000
-#define MSG_OOB                        0x08000000
-#define MSG_EOR                        0x04000000
+#define MSG_CTRUNC     0x01000000
 #define MSG_DONTROUTE  0x02000000
-#define MSG_CTRUNC             0x01000000
-
-// shutdown() flags:
-#define SHUT_RD                        1
-#define SHUT_WR                        2
-#define SHUT_RDWR              3
-
-/*
- * Option flags per-socket.
- */
-#define  SO_DEBUG  0x0001    /* turn on debugging info recording */
-#define  SO_ACCEPTCONN  0x0002    /* socket has had listen() */
-#define  SO_REUSEADDR  0x0004    /* allow local address reuse */
-#define  SO_KEEPALIVE  0x0008    /* keep connections alive */
-#define  SO_DONTROUTE  0x0010    /* just use interface addresses */
-#define  SO_BROADCAST  0x0020    /* permit sending of broadcast msgs */
-#define  SO_USELOOPBACK  0x0040    /* bypass hardware when possible */
-#define  SO_LINGER  0x0080    /* linger on close if data present */
-#define  SO_OOBINLINE  0x0100    /* leave received OOB data in line */
-#define  SO_REUSEPORT   0x0200      /* allow local address & port reuse */
-
-#define SO_DONTLINGER   (int)(~SO_LINGER)
-
-/*
- * Additional options, not kept in so_options.
- */
-#define SO_SNDBUF  0x1001    /* send buffer size */
-#define SO_RCVBUF  0x1002    /* receive buffer size */
-#define SO_SNDLOWAT  0x1003    /* send low-water mark */
-#define SO_RCVLOWAT  0x1004    /* receive low-water mark */
-#define SO_SNDTIMEO  0x1005    /* send timeout */
-#define SO_RCVTIMEO  0x1006    /* receive timeout */
-#define  SO_ERROR  0x1007    /* get error status and clear */
-#define  SO_TYPE    0x1008    /* get socket type */
+#define MSG_EOR                0x04000000
+#define MSG_OOB                0x08000000
+#define MSG_PEEK       0x10000000
+#define MSG_TRUNC      0x20000000
+#define MSG_WAITALL    0x40000000
+
+#define SHUT_RD                0
+#define SHUT_WR                1
+#define SHUT_RDWR      2
+
+#define SO_DEBUG       0x0001
+#define SO_ACCEPTCONN  0x0002
+#define SO_REUSEADDR   0x0004
+#define SO_KEEPALIVE   0x0008
+#define SO_DONTROUTE   0x0010
+#define SO_BROADCAST   0x0020
+#define SO_USELOOPBACK 0x0040
+#define SO_LINGER      0x0080
+#define SO_OOBINLINE   0x0100
+#define SO_REUSEPORT   0x0200
+#define SO_SNDBUF      0x1001
+#define SO_RCVBUF      0x1002
+#define SO_SNDLOWAT    0x1003
+#define SO_RCVLOWAT    0x1004
+#define SO_SNDTIMEO    0x1005
+#define SO_RCVTIMEO    0x1006
+#define SO_ERROR       0x1007
+#define SO_TYPE                0x1008
+
+typedef uint32_t socklen_t;
+typedef uint16_t sa_family_t;
 
 struct sockaddr {
-       unsigned short  sa_family;
-       char            sa_data[14];
+       sa_family_t     sa_family;
+       char            sa_data[];
 };
 
-#ifndef ntohs
-#define ntohs(num) htons(num)
-#define ntohl(num) htonl(num)
-#endif
+struct sockaddr_storage {
+       sa_family_t     ss_family;
+       char            __ss_padding[14];
+};
+
+struct linger {
+       int l_onoff;
+       int l_linger;
+};
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-       int socket(int domain, int type, int protocol);
-       int bind(int socket, const struct sockaddr * addr, int addr_len);
-       int connect(int socket, const struct sockaddr * addr, int addr_len);
-       int send(int socket, const void * data, int sendlength, int flags);
-       int recv(int socket, void * data, int recvlength, int flags);
-       int sendto(int socket, const void * data, int sendlength, int flags, const struct sockaddr * addr, int addr_len);
-       int recvfrom(int socket, void * data, int recvlength, int flags, struct sockaddr * addr, int * addr_len);
-       int listen(int socket, int max_connections);
-       int accept(int socket, struct sockaddr * addr, int * addr_len);
-       int shutdown(int socket, int shutdown_type);
-       int closesocket(int socket);
-
-       int ioctl(int socket, long cmd, void * arg);
-
-       int setsockopt(int socket, int level, int option_name, const void * data, int data_len);
-       int getsockopt(int socket, int level, int option_name, void * data, int * data_len);
-
-       int getpeername(int socket, struct sockaddr *addr, int * addr_len);
-       int getsockname(int socket, struct sockaddr *addr, int * addr_len);
-
-       int gethostname(char *name, size_t len);
-       int sethostname(const char *name, size_t len);
-
-       unsigned short htons(unsigned short num);
-       unsigned long htonl(unsigned long num);
-
-       extern int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
+       int     accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+       int     bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+       int     closesocket(int sockfd);
+       int     connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+       int     getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+       int     getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+       int     getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
+       int     listen(int sockfd, int backlog);
+       ssize_t recv(int sockfd, void *buf, size_t len, int flags);
+       ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
+       ssize_t send(int sockfd, const void *buf, size_t len, int flags);
+       ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
+       int     setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
+       int     shutdown(int sockfd, int how);
+       int     socket(int domain, int type, int protocol);
+       int     sockatmark(int sockfd);
 
 #ifdef __cplusplus
-};
+}
 #endif
-
-
-#endif // SYS_SOCKET_H
diff --git a/libctru/source/services/soc.c b/libctru/source/services/soc.c
deleted file mode 100644 (file)
index 6e70570..0000000
+++ /dev/null
@@ -1,856 +0,0 @@
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <string.h>
-#include <3ds.h>
-
-Handle SOCU_handle = 0;
-static int SOCU_errno = 0;
-static Handle socMemhandle = 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;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
-       cmdbuf[0] = 0x00010044;
-       cmdbuf[1] = memsize;
-       cmdbuf[2] = 0x20;
-       cmdbuf[4] = 0;
-       cmdbuf[5] = memhandle;
-
-       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
-
-       return cmdbuf[1];
-}
-
-Result SOC_Shutdown()
-{
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
-       cmdbuf[0] = 0x00190000;
-
-       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
-
-       svcCloseHandle(SOCU_handle);
-       svcCloseHandle(socMemhandle);
-
-       return cmdbuf[1];
-}
-
-Result SOC_Initialize(u32 *context_addr, u32 context_size)
-{
-       Result ret=0;
-
-       ret = svcCreateMemoryBlock(&socMemhandle, (u32)context_addr, context_size, 0, 3);
-       if(ret!=0)return ret;
-
-       if((ret = srvGetServiceHandle(&SOCU_handle, "soc:U"))!=0)return ret;
-
-       return socu_cmd1(socMemhandle, context_size);
-}
-
-int SOC_GetErrno()
-{
-       return SOCU_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 = svcSendSyncRequest(SOCU_handle))!=0)return ret;
-
-       ret = (int)cmdbuf[1];
-       SOCU_errno = ret;
-
-       if(ret!=0)return -1;
-       return _net_convert_error(cmdbuf[2]);
-}
-
-int closesocket(int sockfd)
-{
-       int ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
-       cmdbuf[0] = 0x000B0042;
-       cmdbuf[1] = (u32)sockfd;
-       cmdbuf[2] = 0x20;
-
-       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
-
-       ret = (int)cmdbuf[1];
-       if(ret==0)ret =_net_convert_error(cmdbuf[2]);
-       SOCU_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 = svcSendSyncRequest(SOCU_handle))!=0)return ret;
-
-       ret = (int)cmdbuf[1];
-       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
-       SOCU_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 = svcSendSyncRequest(SOCU_handle))!=0)return ret;
-
-       ret = (int)cmdbuf[1];
-       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
-       SOCU_errno = ret;
-
-       if(ret!=0)return -1;
-       return 0;
-}
-
-int accept(int sockfd, struct sockaddr *addr, int *addrlen)
-{
-       int ret=0;
-       int tmp_addrlen=0x1c;
-       u32 *cmdbuf = getThreadCommandBuffer();
-       u8 tmpaddr[0x1c];
-       u32 saved_threadstorage[2];
-
-       memset(tmpaddr, 0, 0x1c);
-
-       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 = svcSendSyncRequest(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!=NULL)
-       {
-               addr->sa_family = tmpaddr[1];
-               if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
-               memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
-       }
-
-       if(ret<0)return -1;
-       return ret;
-}
-
-int bind(int sockfd, const struct sockaddr *addr, int addrlen)
-{
-       int ret=0;
-       int tmp_addrlen=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-       u8 tmpaddr[0x1c];
-
-       memset(tmpaddr, 0, 0x1c);
-
-       if(addr->sa_family == AF_INET)
-       {
-               tmp_addrlen = 8;
-       }
-       else
-       {
-               tmp_addrlen = 0x1c;
-       }
-
-       if(addrlen < tmp_addrlen)
-       {
-               SOCU_errno = -EINVAL;
-               return -1;
-       }
-
-       tmpaddr[0] = tmp_addrlen;
-       tmpaddr[1] = addr->sa_family;
-       memcpy(&tmpaddr[2], &addr->sa_data, tmp_addrlen-2);
-
-       cmdbuf[0] = 0x00050084;
-       cmdbuf[1] = (u32)sockfd;
-       cmdbuf[2] = (u32)tmp_addrlen;
-       cmdbuf[3] = 0x20;
-       cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2;
-       cmdbuf[6] = (u32)tmpaddr;
-
-       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
-
-       ret = (int)cmdbuf[1];
-       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
-       SOCU_errno = ret;
-
-       if(ret<0)return -1;
-       return 0;
-}
-
-int connect(int sockfd, const struct sockaddr *addr, int addrlen)
-{
-       int ret=0;
-       int tmp_addrlen=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-       u8 tmpaddr[0x1c];
-
-       memset(tmpaddr, 0, 0x1c);
-
-       if(addr->sa_family == AF_INET)
-       {
-               tmp_addrlen = 8;
-       }
-       else
-       {
-               tmp_addrlen = 0x1c;
-       }
-
-       if(addrlen < tmp_addrlen)
-       {
-               SOCU_errno = -EINVAL;
-               return -1;
-       }
-
-       tmpaddr[0] = tmp_addrlen;
-       tmpaddr[1] = addr->sa_family;
-       memcpy(&tmpaddr[2], &addr->sa_data, tmp_addrlen-2);
-
-       cmdbuf[0] = 0x00060084;
-       cmdbuf[1] = (u32)sockfd;
-       cmdbuf[2] = (u32)addrlen;
-       cmdbuf[3] = 0x20;
-       cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2;
-       cmdbuf[6] = (u32)tmpaddr;
-
-       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
-
-       ret = (int)cmdbuf[1];
-       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
-       SOCU_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();
-       u32 tmp_addrlen=0;
-       u8 tmpaddr[0x1c];
-       u32 saved_threadstorage[2];
-
-       memset(tmpaddr, 0, 0x1c);
-
-       if(src_addr)tmp_addrlen = 0x1c;
-
-       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 = svcSendSyncRequest(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 && src_addr!=NULL)
-       {
-               src_addr->sa_family = tmpaddr[1];
-               if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
-               memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
-       }
-
-       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(); 
-       u32 tmp_addrlen=0;
-       u8 tmpaddr[0x1c];
-       u32 saved_threadstorage[4];
-
-       if(src_addr)tmp_addrlen = 0x1c;
-
-       memset(tmpaddr, 0, 0x1c);
-
-       cmdbuf[0] = 0x00080102;
-       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 = svcSendSyncRequest(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 = _net_convert_error(cmdbuf[2]);
-       if(ret<0)SOCU_errno = ret;
-
-       if(ret>0 && src_addr!=NULL)
-       {
-               src_addr->sa_family = tmpaddr[1];
-               if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
-               memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
-       }
-
-       if(ret<0)return -1;
-       return ret;
-}
-
-int socuipc_cmd9(int sockfd, const void *buf, int len, int flags, const struct sockaddr *dest_addr, int addrlen)
-{
-       int ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-       u32 tmp_addrlen=0;
-       u8 tmpaddr[0x1c];
-
-       memset(tmpaddr, 0, 0x1c);
-
-       if(dest_addr)
-       {
-               if(dest_addr->sa_family == AF_INET)
-               {
-                       tmp_addrlen = 8;
-               }
-               else
-               {
-                       tmp_addrlen = 0x1c;
-               }
-
-               if(addrlen < tmp_addrlen)
-               {
-                       SOCU_errno = -EINVAL;
-                       return -1;
-               }
-
-               tmpaddr[0] = tmp_addrlen;
-               tmpaddr[1] = dest_addr->sa_family;
-               memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2);
-       }
-
-       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 = svcSendSyncRequest(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 socuipc_cmda(int sockfd, const void *buf, int len, int flags, const struct sockaddr *dest_addr, int addrlen)
-{
-       int ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-       u32 tmp_addrlen=0;
-       u8 tmpaddr[0x1c];
-
-       memset(tmpaddr, 0, 0x1c);
-
-       if(dest_addr)
-       {
-               if(dest_addr->sa_family == AF_INET)
-               {
-                       tmp_addrlen = 8;
-               }
-               else
-               {
-                       tmp_addrlen = 0x1c;
-               }
-
-               if(addrlen < tmp_addrlen)
-               {
-                       SOCU_errno = -EINVAL;
-                       return -1;
-               }
-
-               tmpaddr[0] = tmp_addrlen;
-               tmpaddr[1] = dest_addr->sa_family;
-               memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2);
-       }
-
-       cmdbuf[0] = 0x000A0106;
-       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 = svcSendSyncRequest(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 recvfrom(int sockfd, void *buf, int len, int flags, struct sockaddr *src_addr, int *addrlen)
-{
-       if(len<0x2000)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<0x2000)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);
-}
-
-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 = svcSendSyncRequest(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 = svcSendSyncRequest(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;
-
-       if(cmd!=F_GETFL && cmd!=F_SETFL)
-       {
-               SOCU_errno = -EINVAL;
-               return -1;
-       }
-
-       va_start(args, cmd);
-       if(cmd==F_SETFL)
-       {
-               arg = va_arg(args, int);
-
-               if(arg && arg!=O_NONBLOCK)
-               {
-                       SOCU_errno = -EINVAL;
-                       va_end(args);
-                       return -1;
-               }
-
-               if(arg==O_NONBLOCK)arg = 0x4;
-       }
-       va_end(args);
-
-       cmdbuf[0] = 0x001300C2;
-       cmdbuf[1] = (u32)sockfd;
-       cmdbuf[2] = (u32)cmd;
-       cmdbuf[3] = (u32)arg;
-       cmdbuf[4] = 0x20;
-
-       if((ret = svcSendSyncRequest(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 = svcSendSyncRequest(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 = svcSendSyncRequest(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 = svcSendSyncRequest(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];
-               memset(addr, 0, sizeof(struct sockaddr));
-               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 = svcSendSyncRequest(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];
-               memset(addr, 0, sizeof(struct sockaddr));
-               memcpy(addr->sa_data, &tmpaddr[2], *addr_len - 2);
-       }
-
-       if(ret<0)return -1;
-       return ret;
-}
-
-#define MAX_HOSTENT_RESULTS 16
-static struct hostent SOC_hostent;
-static char           *SOC_hostent_results[MAX_HOSTENT_RESULTS+1];
-static char           *SOC_hostent_alias = NULL;
-
-struct hostent * gethostbyname(const char * name)
-{
-       int ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-       u32 saved_threadstorage[2];
-       static u8 outbuf[0x1A88];
-
-       cmdbuf[0] = 0x000D0082;
-       cmdbuf[1] = strlen(name)+1;
-       cmdbuf[2] = sizeof(outbuf);
-       cmdbuf[3] = ((strlen(name)+1) << 14) | 0xC02;
-       cmdbuf[4] = (u32)name;
-
-       saved_threadstorage[0] = cmdbuf[0x100>>2];
-       saved_threadstorage[1] = cmdbuf[0x104>>2];
-
-       cmdbuf[0x100>>2] = (sizeof(outbuf) << 14) | 2;
-       cmdbuf[0x104>>2] = (u32)outbuf;
-
-       if(( ret = svcSendSyncRequest(SOCU_handle))!=0)return NULL;
-
-       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)return NULL;
-
-       u32 num_results, i;
-       memcpy(&num_results, (char*)outbuf+4, sizeof(num_results));
-       if(num_results > MAX_HOSTENT_RESULTS)
-               num_results = MAX_HOSTENT_RESULTS;
-
-       SOC_hostent.h_name      = (char*)outbuf + 8;
-       SOC_hostent.h_aliases   = &SOC_hostent_alias;
-       SOC_hostent.h_addrtype  = AF_INET;
-       SOC_hostent.h_length    = 4;
-       SOC_hostent.h_addr_list = SOC_hostent_results;
-
-       SOC_hostent_alias = NULL;
-
-       for(i = 0; i < num_results; ++i)
-               SOC_hostent_results[i] = (char*)outbuf + 0x1908 + i*0x10;
-       SOC_hostent_results[num_results] = NULL;
-
-       return &SOC_hostent;
-}
diff --git a/libctru/source/services/soc/soc_accept.c b/libctru/source/services/soc/soc_accept.c
new file mode 100644 (file)
index 0000000..355a744
--- /dev/null
@@ -0,0 +1,43 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+       int ret=0;
+       int tmp_addrlen=0x1c;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u8 tmpaddr[0x1c];
+       u32 saved_threadstorage[2];
+
+       memset(tmpaddr, 0, 0x1c);
+
+       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 = svcSendSyncRequest(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!=NULL)
+       {
+               addr->sa_family = tmpaddr[1];
+               if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
+               memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
+       }
+
+       if(ret<0)return -1;
+       return ret;
+}
diff --git a/libctru/source/services/soc/soc_bind.c b/libctru/source/services/soc/soc_bind.c
new file mode 100644 (file)
index 0000000..dba52e5
--- /dev/null
@@ -0,0 +1,48 @@
+#include "soc_common.h"
+#include <errno.h>
+#include <sys/socket.h>
+
+int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+       int ret=0;
+       int tmp_addrlen=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u8 tmpaddr[0x1c];
+
+       memset(tmpaddr, 0, 0x1c);
+
+       if(addr->sa_family == AF_INET)
+       {
+               tmp_addrlen = 8;
+       }
+       else
+       {
+               tmp_addrlen = 0x1c;
+       }
+
+       if(addrlen < tmp_addrlen)
+       {
+               SOCU_errno = EINVAL;
+               return -1;
+       }
+
+       tmpaddr[0] = tmp_addrlen;
+       tmpaddr[1] = addr->sa_family;
+       memcpy(&tmpaddr[2], &addr->sa_data, tmp_addrlen-2);
+
+       cmdbuf[0] = 0x00050084;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = (u32)tmp_addrlen;
+       cmdbuf[3] = 0x20;
+       cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2;
+       cmdbuf[6] = (u32)tmpaddr;
+
+       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
+       SOCU_errno = ret;
+
+       if(ret<0)return -1;
+       return 0;
+}
diff --git a/libctru/source/services/soc/soc_closesocket.c b/libctru/source/services/soc/soc_closesocket.c
new file mode 100644 (file)
index 0000000..85dcd52
--- /dev/null
@@ -0,0 +1,21 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+int closesocket(int sockfd)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       cmdbuf[0] = 0x000B0042;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = 0x20;
+
+       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret =_net_convert_error(cmdbuf[2]);
+       SOCU_errno = ret;
+
+       if(ret!=0)return -1;
+       return 0;
+}
diff --git a/libctru/source/services/soc/soc_common.c b/libctru/source/services/soc/soc_common.c
new file mode 100644 (file)
index 0000000..8814453
--- /dev/null
@@ -0,0 +1,104 @@
+#include "soc_common.h"
+#include <errno.h>
+
+Handle SOCU_handle = 0;
+int    SOCU_errno = 0;
+Handle socMemhandle = 0;
+
+//This is based on the array from libogc network_wii.c.
+static u8 _net_error_code_map[] = {
+       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,
+};
+
+#define NET_UNKNOWN_ERROR_OFFSET       -10000//This is from libogc network_wii.c.
+
+//This is based on the function from libogc network_wii.c.
+s32 _net_convert_error(s32 sock_retval)
+{
+       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];
+}
+
+int SOC_GetErrno(void)
+{
+       return SOCU_errno;
+}
diff --git a/libctru/source/services/soc/soc_common.h b/libctru/source/services/soc/soc_common.h
new file mode 100644 (file)
index 0000000..004235d
--- /dev/null
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <3ds.h>
+
+extern Handle  SOCU_handle;
+extern int     SOCU_errno;
+extern Handle  socMemhandle;
+
+s32 _net_convert_error(s32 sock_retval);
diff --git a/libctru/source/services/soc/soc_connect.c b/libctru/source/services/soc/soc_connect.c
new file mode 100644 (file)
index 0000000..9577c77
--- /dev/null
@@ -0,0 +1,48 @@
+#include "soc_common.h"
+#include <errno.h>
+#include <sys/socket.h>
+
+int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+       int ret=0;
+       int tmp_addrlen=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u8 tmpaddr[0x1c];
+
+       memset(tmpaddr, 0, 0x1c);
+
+       if(addr->sa_family == AF_INET)
+       {
+               tmp_addrlen = 8;
+       }
+       else
+       {
+               tmp_addrlen = 0x1c;
+       }
+
+       if(addrlen < tmp_addrlen)
+       {
+               SOCU_errno = -EINVAL;
+               return -1;
+       }
+
+       tmpaddr[0] = tmp_addrlen;
+       tmpaddr[1] = addr->sa_family;
+       memcpy(&tmpaddr[2], &addr->sa_data, tmp_addrlen-2);
+
+       cmdbuf[0] = 0x00060084;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = (u32)addrlen;
+       cmdbuf[3] = 0x20;
+       cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2;
+       cmdbuf[6] = (u32)tmpaddr;
+
+       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
+       SOCU_errno = ret;
+
+       if(ret<0)return -1;
+       return 0;
+}
diff --git a/libctru/source/services/soc/soc_fcntl.c b/libctru/source/services/soc/soc_fcntl.c
new file mode 100644 (file)
index 0000000..6179a69
--- /dev/null
@@ -0,0 +1,50 @@
+#include "soc_common.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+int fcntl(int fd, int cmd, ...)
+{
+       int ret=0;
+       int arg=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       va_list args;
+
+       if(cmd!=F_GETFL && cmd!=F_SETFL)
+       {
+               SOCU_errno = -EINVAL;
+               return -1;
+       }
+
+       va_start(args, cmd);
+       if(cmd==F_SETFL)
+       {
+               arg = va_arg(args, int);
+
+               if(arg && arg!=O_NONBLOCK)
+               {
+                       SOCU_errno = -EINVAL;
+                       va_end(args);
+                       return -1;
+               }
+
+               if(arg==O_NONBLOCK)arg = 0x4;
+       }
+       va_end(args);
+
+       cmdbuf[0] = 0x001300C2;
+       cmdbuf[1] = (u32)fd;
+       cmdbuf[2] = (u32)cmd;
+       cmdbuf[3] = (u32)arg;
+       cmdbuf[4] = 0x20;
+
+       if((ret = svcSendSyncRequest(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;
+}
diff --git a/libctru/source/services/soc/soc_gethostbyname.c b/libctru/source/services/soc/soc_gethostbyname.c
new file mode 100644 (file)
index 0000000..4932378
--- /dev/null
@@ -0,0 +1,60 @@
+#include "soc_common.h"
+#include <netdb.h>
+
+#define MAX_HOSTENT_RESULTS 16
+static struct hostent SOC_hostent;
+static char           *SOC_hostent_results[MAX_HOSTENT_RESULTS+1];
+static char           *SOC_hostent_alias = NULL;
+
+int h_errno = 0;
+
+struct hostent* gethostbyname(const char *name)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u32 saved_threadstorage[2];
+       static u8 outbuf[0x1A88];
+
+       cmdbuf[0] = 0x000D0082;
+       cmdbuf[1] = strlen(name)+1;
+       cmdbuf[2] = sizeof(outbuf);
+       cmdbuf[3] = ((strlen(name)+1) << 14) | 0xC02;
+       cmdbuf[4] = (u32)name;
+
+       saved_threadstorage[0] = cmdbuf[0x100>>2];
+       saved_threadstorage[1] = cmdbuf[0x104>>2];
+
+       cmdbuf[0x100>>2] = (sizeof(outbuf) << 14) | 2;
+       cmdbuf[0x104>>2] = (u32)outbuf;
+
+       if(( ret = svcSendSyncRequest(SOCU_handle))!=0)return NULL;
+
+       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;
+       /* TODO: set h_errno based on SOCU_errno */
+
+       if(ret<0)return NULL;
+
+       u32 num_results, i;
+       memcpy(&num_results, (char*)outbuf+4, sizeof(num_results));
+       if(num_results > MAX_HOSTENT_RESULTS)
+               num_results = MAX_HOSTENT_RESULTS;
+
+       SOC_hostent.h_name      = (char*)outbuf + 8;
+       SOC_hostent.h_aliases   = &SOC_hostent_alias;
+       SOC_hostent.h_addrtype  = AF_INET;
+       SOC_hostent.h_length    = 4;
+       SOC_hostent.h_addr_list = SOC_hostent_results;
+
+       SOC_hostent_alias = NULL;
+
+       for(i = 0; i < num_results; ++i)
+               SOC_hostent_results[i] = (char*)outbuf + 0x1908 + i*0x10;
+       SOC_hostent_results[num_results] = NULL;
+
+       return &SOC_hostent;
+}
diff --git a/libctru/source/services/soc/soc_gethostid.c b/libctru/source/services/soc/soc_gethostid.c
new file mode 100644 (file)
index 0000000..fb747c3
--- /dev/null
@@ -0,0 +1,16 @@
+#include "soc_common.h"
+
+long gethostid(void)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       cmdbuf[0] = 0x00160000;
+
+       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret = cmdbuf[2];
+
+       return ret;
+}
diff --git a/libctru/source/services/soc/soc_getpeername.c b/libctru/source/services/soc/soc_getpeername.c
new file mode 100644 (file)
index 0000000..f20be86
--- /dev/null
@@ -0,0 +1,41 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+       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 = svcSendSyncRequest(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)
+       {
+               if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
+               memset(addr, 0, sizeof(struct sockaddr));
+               addr->sa_family = tmpaddr[1];
+               memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
+       }
+
+       if(ret<0)return -1;
+       return ret;
+}
diff --git a/libctru/source/services/soc/soc_getsockname.c b/libctru/source/services/soc/soc_getsockname.c
new file mode 100644 (file)
index 0000000..80812af
--- /dev/null
@@ -0,0 +1,41 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+       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 = svcSendSyncRequest(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)
+       {
+               if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
+               memset(addr, 0, sizeof(struct sockaddr));
+               addr->sa_family = tmpaddr[1];
+               memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
+       }
+
+       if(ret<0)return -1;
+       return ret;
+}
diff --git a/libctru/source/services/soc/soc_getsockopt.c b/libctru/source/services/soc/soc_getsockopt.c
new file mode 100644 (file)
index 0000000..20bf148
--- /dev/null
@@ -0,0 +1,36 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u32 saved_threadstorage[2];
+
+       cmdbuf[0] = 0x00110102;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = (u32)level;
+       cmdbuf[3] = (u32)optname;
+       cmdbuf[4] = (u32)*optlen;
+       cmdbuf[5] = 0x20;
+
+       saved_threadstorage[0] = cmdbuf[0x100>>2];
+       saved_threadstorage[1] = cmdbuf[0x104>>2];
+
+       cmdbuf[0x100>>2] = ((*optlen)<<14) | 2;
+       cmdbuf[0x104>>2] = (u32)optval;
+
+       if((ret = svcSendSyncRequest(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)*optlen = cmdbuf[3];
+
+       if(ret<0)return -1;
+       return ret;
+}
diff --git a/libctru/source/services/soc/soc_inet_addr.c b/libctru/source/services/soc/soc_inet_addr.c
new file mode 100644 (file)
index 0000000..e75312c
--- /dev/null
@@ -0,0 +1,9 @@
+#include "soc_common.h"
+#include <arpa/inet.h>
+
+in_addr_t inet_addr(const char *cp)
+{
+       struct in_addr addr = { .s_addr = INADDR_BROADCAST };
+       inet_aton(cp, &addr);
+       return addr.s_addr;
+}
diff --git a/libctru/source/services/soc/soc_inet_aton.c b/libctru/source/services/soc/soc_inet_aton.c
new file mode 100644 (file)
index 0000000..6e1f206
--- /dev/null
@@ -0,0 +1,85 @@
+#include "soc_common.h"
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <stdint.h>
+
+int inet_aton(const char *cp, struct in_addr *inp)
+{
+       int      base;
+       uint32_t val;
+       int      c;
+       char     bytes[4];
+       size_t   num_bytes = 0;
+
+       c = *cp;
+       for(;;) {
+               if(!isdigit(c)) return 0;
+
+               val = 0;
+               base = 10;
+               if(c == '0') {
+                       c = *++cp;
+                       if(c == 'x' || c == 'X') {
+                               base = 16;
+                               c = *++cp;
+                       }
+                       else base = 8;
+               }
+
+               for(;;) {
+                       if(isdigit(c)) {
+                               if(base == 8 && c >= '8') return 0;
+                               val *= base;
+                               val += c - '0';
+                               c    = *++cp;
+                       }
+                       else if(base == 16 && isxdigit(c)) {
+                               val *= base;
+                               val += c + 10 - (islower(c) ? 'a' : 'A');
+                               c    = *++cp;
+                       }
+                       else break;
+               }
+
+               if(c == '.') {
+                       if(num_bytes > 3) return 0;
+                       if(val > 0xFF) return 0;
+                       bytes[num_bytes++] = val;
+                       c = *++cp;
+               }
+               else break;
+       }
+
+       if(c != 0) return 0;
+
+       switch(num_bytes) {
+       case 0:
+               return 0;
+
+       case 1:
+               break;
+
+       case 2:
+               if(val > 0xFFFFFF) return 0;
+               val |= bytes[0] << 24;
+               break;
+
+       case 3:
+               if(val > 0xFFFF) return 0;
+               val |= bytes[0] << 24;
+               val |= bytes[1] << 16;
+               break;
+
+       case 4:
+               if(val > 0xFF) return 0;
+               val |= bytes[0] << 24;
+               val |= bytes[1] << 16;
+               val |= bytes[2] << 8;
+               break;
+       }
+
+       if(inp)
+               inp->s_addr = htonl(val);
+
+       return 1;
+}
diff --git a/libctru/source/services/soc/soc_inet_ntoa.c b/libctru/source/services/soc/soc_inet_ntoa.c
new file mode 100644 (file)
index 0000000..ae7a5b7
--- /dev/null
@@ -0,0 +1,32 @@
+#include "soc_common.h"
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+static char buffer[INET_ADDRSTRLEN];
+
+char* inet_ntoa(struct in_addr in)
+{
+       unsigned char *addrbuf = (unsigned char*)&in;
+       char *p;
+       size_t i;
+       unsigned int n;
+
+       memset(buffer, 0, sizeof(buffer));
+       for(p = buffer, i = 0; i < 4; ++i) {
+               if(i > 0) *p++ = '.';
+
+               n = addrbuf[i];
+               if(n >= 100) {
+                       *p++ = n/100 + '0';
+                       n %= 100;
+               }
+               if(n >= 10 || addrbuf[i] >= 100) {
+                       *p++ = n/10 + '0';
+                       n %= 10;
+               }
+               *p++ = n + '0';
+       }
+       *p = 0;
+
+       return buffer;
+}
diff --git a/libctru/source/services/soc/soc_init.c b/libctru/source/services/soc/soc_init.c
new file mode 100644 (file)
index 0000000..2b961fa
--- /dev/null
@@ -0,0 +1,44 @@
+#include "soc_common.h"
+
+static 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 = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+
+       return cmdbuf[1];
+}
+
+Result SOC_Initialize(u32 *context_addr, u32 context_size)
+{
+       Result ret=0;
+
+       ret = svcCreateMemoryBlock(&socMemhandle, (u32)context_addr, context_size, 0, 3);
+       if(ret!=0)return ret;
+
+       if((ret = srvGetServiceHandle(&SOCU_handle, "soc:U"))!=0)return ret;
+
+       return socu_cmd1(socMemhandle, context_size);
+}
+
+Result SOC_Shutdown(void)
+{
+       Result ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       cmdbuf[0] = 0x00190000;
+
+       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+
+       svcCloseHandle(SOCU_handle);
+       svcCloseHandle(socMemhandle);
+
+       return cmdbuf[1];
+}
diff --git a/libctru/source/services/soc/soc_ioctl.c b/libctru/source/services/soc/soc_ioctl.c
new file mode 100644 (file)
index 0000000..6fce0d7
--- /dev/null
@@ -0,0 +1,37 @@
+#include "soc_common.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <sys/ioctl.h>
+
+int ioctl(int fd, int request, ...)
+{
+       int ret;
+       int flags;
+       int *value;
+       va_list ap;
+
+       va_start(ap, request);
+
+       switch(request) {
+       case FIONBIO:
+               value = va_arg(ap, int*);
+               if(value == NULL) ret = -1;
+               else if(*value) {
+                       flags = fcntl(fd, F_GETFL, 0);
+                       ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+               }
+               else {
+                       flags = fcntl(fd, F_GETFL, 0);
+                       ret = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+               }
+               break;
+
+       default:
+               errno = ENOTTY;
+               ret = -1;
+               break;
+       }
+
+       return ret;
+}
diff --git a/libctru/source/services/soc/soc_listen.c b/libctru/source/services/soc/soc_listen.c
new file mode 100644 (file)
index 0000000..ce7ff05
--- /dev/null
@@ -0,0 +1,22 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+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 = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
+       SOCU_errno = ret;
+
+       if(ret!=0)return -1;
+       return 0;
+}
diff --git a/libctru/source/services/soc/soc_poll.c b/libctru/source/services/soc/soc_poll.c
new file mode 100644 (file)
index 0000000..8cf5b34
--- /dev/null
@@ -0,0 +1,35 @@
+#include "soc_common.h"
+#include <poll.h>
+
+int poll(struct pollfd *fds, nfds_t nfsd, int timeout)
+{
+       int ret = 0;
+       u32 size = sizeof(struct pollfd)*nfsd;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u32 saved_threadstorage[2];
+
+       cmdbuf[0] = 0x00140084;
+       cmdbuf[1] = (u32)nfsd;
+       cmdbuf[2] = (u32)timeout;
+       cmdbuf[3] = 0x20;
+       cmdbuf[5] = (size<<14) | 0x2802;
+       cmdbuf[6] = (u32)fds;
+
+       saved_threadstorage[0] = cmdbuf[0x100>>2];
+       saved_threadstorage[1] = cmdbuf[0x104>>2];
+
+       cmdbuf[0x100>>2] = (size<<14) | 2;
+       cmdbuf[0x104>>2] = (u32)fds;
+
+       if((ret = svcSendSyncRequest(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)return -1;
+       return ret;
+}
diff --git a/libctru/source/services/soc/soc_recv.c b/libctru/source/services/soc/soc_recv.c
new file mode 100644 (file)
index 0000000..adc0df0
--- /dev/null
@@ -0,0 +1,7 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+ssize_t recv(int sockfd, void *buf, size_t len, int flags)
+{
+       return recvfrom(sockfd, buf, len, flags, NULL, 0);
+}
diff --git a/libctru/source/services/soc/soc_recvfrom.c b/libctru/source/services/soc/soc_recvfrom.c
new file mode 100644 (file)
index 0000000..df5c56c
--- /dev/null
@@ -0,0 +1,107 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+ssize_t socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u32 tmp_addrlen=0;
+       u8 tmpaddr[0x1c];
+       u32 saved_threadstorage[2];
+
+       memset(tmpaddr, 0, 0x1c);
+
+       if(src_addr)tmp_addrlen = 0x1c;
+
+       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 = svcSendSyncRequest(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 && src_addr!=NULL)
+       {
+               src_addr->sa_family = tmpaddr[1];
+               if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
+               memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
+       }
+
+       if(ret<0)return -1;
+       return ret;
+}
+
+ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer(); 
+       u32 tmp_addrlen=0;
+       u8 tmpaddr[0x1c];
+       u32 saved_threadstorage[4];
+
+       if(src_addr)tmp_addrlen = 0x1c;
+
+       memset(tmpaddr, 0, 0x1c);
+
+       cmdbuf[0] = 0x00080102;
+       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 = svcSendSyncRequest(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 = _net_convert_error(cmdbuf[2]);
+       if(ret<0)SOCU_errno = ret;
+
+       if(ret>0 && src_addr!=NULL)
+       {
+               src_addr->sa_family = tmpaddr[1];
+               if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
+               memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
+       }
+
+       if(ret<0)return -1;
+       return ret;
+}
+
+
+ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
+{
+       if(len<0x2000)return socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen);
+       return socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen);
+}
diff --git a/libctru/source/services/soc/soc_select.c b/libctru/source/services/soc/soc_select.c
new file mode 100644 (file)
index 0000000..d2cd911
--- /dev/null
@@ -0,0 +1,90 @@
+#include "soc_common.h"
+#include <errno.h>
+#include <poll.h>
+#include <stdlib.h>
+#include <sys/select.h>
+
+int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
+{
+       struct pollfd *pollinfo;
+       nfds_t numfds = 0;
+       size_t i, j;
+       int rc, found;
+
+       for(i = 0; i < nfds; ++i) {
+               if((readfds && FD_ISSET(i, readfds))
+               || (writefds && FD_ISSET(i, writefds))
+               || (exceptfds && FD_ISSET(i, exceptfds)))
+                       ++numfds;
+       }
+
+       pollinfo = (struct pollfd*)calloc(numfds, sizeof(struct pollfd));
+       if(pollinfo == NULL) {
+               SOCU_errno = ENOMEM;
+               return -1;
+       }
+
+       for(i = 0, j = 0; i < nfds; ++i) {
+               if((readfds && FD_ISSET(i, readfds))
+               || (writefds && FD_ISSET(i, writefds))
+               || (exceptfds && FD_ISSET(i, exceptfds))) {
+                       pollinfo[j].fd      = i;
+                       pollinfo[j].events  = 0;
+                       pollinfo[j].revents = 0;
+
+                       if(readfds && FD_ISSET(i, readfds))
+                               pollinfo[j].events |= POLLIN;
+                       if(writefds && FD_ISSET(i, writefds))
+                               pollinfo[j].events |= POLLOUT;
+
+                       ++j;
+               }
+       }
+
+       if(timeout)
+               rc = poll(pollinfo, numfds, timeout->tv_sec*1000 + timeout->tv_usec/1000);
+       else
+               rc = poll(pollinfo, numfds, -1);
+
+       if(rc < 0) {
+               free(pollinfo);
+               return rc;
+       }
+
+       for(i = 0, j = 0, rc = 0; i < nfds; ++i) {
+               found = 0;
+
+               if((readfds && FD_ISSET(i, readfds))
+               || (writefds && FD_ISSET(i, writefds))
+               || (exceptfds && FD_ISSET(i, exceptfds))) {
+
+                       if(readfds && FD_ISSET(i, readfds)) {
+                               if(pollinfo[j].events & (POLLIN|POLLHUP))
+                                       found = 1;
+                               else
+                                       FD_CLR(i, readfds);
+                       }
+
+                       if(writefds && FD_ISSET(i, writefds)) {
+                               if(pollinfo[j].events & (POLLOUT|POLLHUP))
+                                       found = 1;
+                               else
+                                       FD_CLR(i, writefds);
+                       }
+
+                       if(exceptfds && FD_ISSET(i, exceptfds)) {
+                               if(pollinfo[j].events & POLLERR)
+                                       found = 1;
+                               else
+                                       FD_CLR(i, exceptfds);
+                       }
+
+                       if(found) ++rc;
+                       ++j;
+               }
+       }
+
+       free(pollinfo);
+
+       return rc;
+}
diff --git a/libctru/source/services/soc/soc_send.c b/libctru/source/services/soc/soc_send.c
new file mode 100644 (file)
index 0000000..d99f0c1
--- /dev/null
@@ -0,0 +1,7 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+ssize_t send(int sockfd, const void *buf, size_t len, int flags)
+{
+       return sendto(sockfd, buf, len, flags, NULL, 0);
+}
diff --git a/libctru/source/services/soc/soc_sendto.c b/libctru/source/services/soc/soc_sendto.c
new file mode 100644 (file)
index 0000000..9afd36a
--- /dev/null
@@ -0,0 +1,113 @@
+#include "soc_common.h"
+#include <errno.h>
+#include <sys/socket.h>
+
+ssize_t socuipc_cmd9(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u32 tmp_addrlen=0;
+       u8 tmpaddr[0x1c];
+
+       memset(tmpaddr, 0, 0x1c);
+
+       if(dest_addr)
+       {
+               if(dest_addr->sa_family == AF_INET)
+               {
+                       tmp_addrlen = 8;
+               }
+               else
+               {
+                       tmp_addrlen = 0x1c;
+               }
+
+               if(addrlen < tmp_addrlen)
+               {
+                       SOCU_errno = -EINVAL;
+                       return -1;
+               }
+
+               tmpaddr[0] = tmp_addrlen;
+               tmpaddr[1] = dest_addr->sa_family;
+               memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2);
+       }
+
+       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 = svcSendSyncRequest(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;
+}
+
+ssize_t socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+       u32 tmp_addrlen=0;
+       u8 tmpaddr[0x1c];
+
+       memset(tmpaddr, 0, 0x1c);
+
+       if(dest_addr)
+       {
+               if(dest_addr->sa_family == AF_INET)
+               {
+                       tmp_addrlen = 8;
+               }
+               else
+               {
+                       tmp_addrlen = 0x1c;
+               }
+
+               if(addrlen < tmp_addrlen)
+               {
+                       SOCU_errno = -EINVAL;
+                       return -1;
+               }
+
+               tmpaddr[0] = tmp_addrlen;
+               tmpaddr[1] = dest_addr->sa_family;
+               memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2);
+       }
+
+       cmdbuf[0] = 0x000A0106;
+       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 = svcSendSyncRequest(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;
+}
+
+ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+       if(len<0x2000)return socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen);
+       return socuipc_cmd9(sockfd, buf, len, flags, (struct sockaddr*)dest_addr, addrlen);
+}
diff --git a/libctru/source/services/soc/soc_setsockopt.c b/libctru/source/services/soc/soc_setsockopt.c
new file mode 100644 (file)
index 0000000..ff142b2
--- /dev/null
@@ -0,0 +1,26 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       cmdbuf[0] = 0x00120104;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = (u32)level;
+       cmdbuf[3] = (u32)optname;
+       cmdbuf[4] = (u32)optlen;
+       cmdbuf[5] = 0x20;
+       cmdbuf[7] = (optlen<<14) | 0x2402;
+       cmdbuf[8] = (u32)optval;
+
+       if((ret = svcSendSyncRequest(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;
+}
diff --git a/libctru/source/services/soc/soc_shutdown.c b/libctru/source/services/soc/soc_shutdown.c
new file mode 100644 (file)
index 0000000..be86293
--- /dev/null
@@ -0,0 +1,22 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+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 = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
+       SOCU_errno = ret;
+
+       if(ret!=0)return -1;
+       return 0;
+}
diff --git a/libctru/source/services/soc/soc_sockatmark.c b/libctru/source/services/soc/soc_sockatmark.c
new file mode 100644 (file)
index 0000000..d445fb8
--- /dev/null
@@ -0,0 +1,21 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+int sockatmark(int sockfd)
+{
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       cmdbuf[0] = 0x00150042;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = 0x20;
+
+       if((ret = svcSendSyncRequest(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;
+}
diff --git a/libctru/source/services/soc/soc_socket.c b/libctru/source/services/soc/soc_socket.c
new file mode 100644 (file)
index 0000000..628138b
--- /dev/null
@@ -0,0 +1,22 @@
+#include "soc_common.h"
+#include <sys/socket.h>
+
+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 = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       SOCU_errno = ret;
+
+       if(ret!=0)return -1;
+       return _net_convert_error(cmdbuf[2]);
+}