From 55608adaadeeda788c14fcc2c54b2dd987659929 Mon Sep 17 00:00:00 2001 From: mtheall Date: Thu, 20 Nov 2014 15:36:50 -0600 Subject: [PATCH] Overhauled soc service. --- libctru/Makefile | 1 + libctru/include/3ds/services/soc.h | 7 +- libctru/include/arpa/inet.h | 36 + libctru/include/netdb.h | 30 +- libctru/include/netinet/in.h | 40 +- libctru/include/netinet/tcp.h | 5 + libctru/include/poll.h | 34 + libctru/include/sys/ioctl.h | 13 + libctru/include/sys/select.h | 13 + libctru/include/sys/socket.h | 164 ++-- libctru/source/services/soc.c | 856 ------------------ libctru/source/services/soc/soc_accept.c | 43 + libctru/source/services/soc/soc_bind.c | 48 + libctru/source/services/soc/soc_closesocket.c | 21 + libctru/source/services/soc/soc_common.c | 104 +++ libctru/source/services/soc/soc_common.h | 9 + libctru/source/services/soc/soc_connect.c | 48 + libctru/source/services/soc/soc_fcntl.c | 50 + .../source/services/soc/soc_gethostbyname.c | 60 ++ libctru/source/services/soc/soc_gethostid.c | 16 + libctru/source/services/soc/soc_getpeername.c | 41 + libctru/source/services/soc/soc_getsockname.c | 41 + libctru/source/services/soc/soc_getsockopt.c | 36 + libctru/source/services/soc/soc_inet_addr.c | 9 + libctru/source/services/soc/soc_inet_aton.c | 85 ++ libctru/source/services/soc/soc_inet_ntoa.c | 32 + libctru/source/services/soc/soc_init.c | 44 + libctru/source/services/soc/soc_ioctl.c | 37 + libctru/source/services/soc/soc_listen.c | 22 + libctru/source/services/soc/soc_poll.c | 35 + libctru/source/services/soc/soc_recv.c | 7 + libctru/source/services/soc/soc_recvfrom.c | 107 +++ libctru/source/services/soc/soc_select.c | 90 ++ libctru/source/services/soc/soc_send.c | 7 + libctru/source/services/soc/soc_sendto.c | 113 +++ libctru/source/services/soc/soc_setsockopt.c | 26 + libctru/source/services/soc/soc_shutdown.c | 22 + libctru/source/services/soc/soc_sockatmark.c | 21 + libctru/source/services/soc/soc_socket.c | 22 + 39 files changed, 1406 insertions(+), 989 deletions(-) create mode 100644 libctru/include/arpa/inet.h create mode 100644 libctru/include/poll.h create mode 100644 libctru/include/sys/ioctl.h create mode 100644 libctru/include/sys/select.h delete mode 100644 libctru/source/services/soc.c create mode 100644 libctru/source/services/soc/soc_accept.c create mode 100644 libctru/source/services/soc/soc_bind.c create mode 100644 libctru/source/services/soc/soc_closesocket.c create mode 100644 libctru/source/services/soc/soc_common.c create mode 100644 libctru/source/services/soc/soc_common.h create mode 100644 libctru/source/services/soc/soc_connect.c create mode 100644 libctru/source/services/soc/soc_fcntl.c create mode 100644 libctru/source/services/soc/soc_gethostbyname.c create mode 100644 libctru/source/services/soc/soc_gethostid.c create mode 100644 libctru/source/services/soc/soc_getpeername.c create mode 100644 libctru/source/services/soc/soc_getsockname.c create mode 100644 libctru/source/services/soc/soc_getsockopt.c create mode 100644 libctru/source/services/soc/soc_inet_addr.c create mode 100644 libctru/source/services/soc/soc_inet_aton.c create mode 100644 libctru/source/services/soc/soc_inet_ntoa.c create mode 100644 libctru/source/services/soc/soc_init.c create mode 100644 libctru/source/services/soc/soc_ioctl.c create mode 100644 libctru/source/services/soc/soc_listen.c create mode 100644 libctru/source/services/soc/soc_poll.c create mode 100644 libctru/source/services/soc/soc_recv.c create mode 100644 libctru/source/services/soc/soc_recvfrom.c create mode 100644 libctru/source/services/soc/soc_select.c create mode 100644 libctru/source/services/soc/soc_send.c create mode 100644 libctru/source/services/soc/soc_sendto.c create mode 100644 libctru/source/services/soc/soc_setsockopt.c create mode 100644 libctru/source/services/soc/soc_shutdown.c create mode 100644 libctru/source/services/soc/soc_sockatmark.c create mode 100644 libctru/source/services/soc/soc_socket.c diff --git a/libctru/Makefile b/libctru/Makefile index 114d61b..919a471 100644 --- a/libctru/Makefile +++ b/libctru/Makefile @@ -21,6 +21,7 @@ SOURCES := source \ source/allocator \ source/gpu \ source/services \ + source/services/soc \ source/util DATA := data INCLUDES := include diff --git a/libctru/include/3ds/services/soc.h b/libctru/include/3ds/services/soc.h index 0b34775..55ff21e 100644 --- a/libctru/include/3ds/services/soc.h +++ b/libctru/include/3ds/services/soc.h @@ -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 index 0000000..197877b --- /dev/null +++ b/libctru/include/arpa/inet.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +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 diff --git a/libctru/include/netdb.h b/libctru/include/netdb.h index 8aa5d91..7f769a4 100644 --- a/libctru/include/netdb.h +++ b/libctru/include/netdb.h @@ -1,24 +1,28 @@ -#ifndef NETDB_H -#define NETDB_H +#pragma once + +#include + +#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 diff --git a/libctru/include/netinet/in.h b/libctru/include/netinet/in.h index 5e3acd3..bc8d6f8 100644 --- a/libctru/include/netinet/in.h +++ b/libctru/include/netinet/in.h @@ -1,34 +1,28 @@ -#ifndef NETINET_IN_H -#define NETINET_IN_H +#pragma once -#include "sys/socket.h" +#include +#include #define INADDR_ANY 0x00000000 #define INADDR_BROADCAST 0xFFFFFFFF #define INADDR_NONE 0xFFFFFFFF +#define INET_ADDRSTRLEN 16 + +//#define IPPROTO_IP ??? +//#define IPPROTO_TCP ??? +//#define IPPROTO_UDP ??? + +typedef uint16_t in_port_t; +typedef uint32_t in_addr_t; + struct in_addr { - unsigned long s_addr; + in_addr_t s_addr; }; struct sockaddr_in { - unsigned short sin_family; - unsigned short sin_port; - struct in_addr sin_addr; - unsigned char sin_zero[8]; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; + unsigned char sin_zero[8]; }; - -#ifdef __cplusplus -extern "C" { -#endif - - // 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); - -#ifdef __cplusplus -}; -#endif - -#endif // NETINET_IN_H diff --git a/libctru/include/netinet/tcp.h b/libctru/include/netinet/tcp.h index e69de29..b95b127 100644 --- a/libctru/include/netinet/tcp.h +++ b/libctru/include/netinet/tcp.h @@ -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 index 0000000..4315a43 --- /dev/null +++ b/libctru/include/poll.h @@ -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 index 0000000..bbd3f83 --- /dev/null +++ b/libctru/include/sys/ioctl.h @@ -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 index 0000000..d75f9d0 --- /dev/null +++ b/libctru/include/sys/select.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); + +#ifdef __cplusplus +} +#endif diff --git a/libctru/include/sys/socket.h b/libctru/include/sys/socket.h index 1ee3502..02fa98c 100644 --- a/libctru/include/sys/socket.h +++ b/libctru/include/sys/socket.h @@ -1,119 +1,91 @@ -#ifndef SYS_SOCKET_H -#define SYS_SOCKET_H +#pragma once +#include #include -/* - * 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 +#define MSG_EOR 0x04000000 +#define MSG_OOB 0x08000000 +#define MSG_PEEK 0x10000000 +#define MSG_TRUNC 0x20000000 +#define MSG_WAITALL 0x40000000 -// shutdown() flags: -#define SHUT_RD 1 -#define SHUT_WR 2 -#define SHUT_RDWR 3 +#define SHUT_RD 0 +#define SHUT_WR 1 +#define SHUT_RDWR 2 -/* - * 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_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 -#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 */ +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 index 6e70570..0000000 --- a/libctru/source/services/soc.c +++ /dev/null @@ -1,856 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#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 index 0000000..355a744 --- /dev/null +++ b/libctru/source/services/soc/soc_accept.c @@ -0,0 +1,43 @@ +#include "soc_common.h" +#include + +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 index 0000000..dba52e5 --- /dev/null +++ b/libctru/source/services/soc/soc_bind.c @@ -0,0 +1,48 @@ +#include "soc_common.h" +#include +#include + +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 index 0000000..85dcd52 --- /dev/null +++ b/libctru/source/services/soc/soc_closesocket.c @@ -0,0 +1,21 @@ +#include "soc_common.h" +#include + +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 index 0000000..8814453 --- /dev/null +++ b/libctru/source/services/soc/soc_common.c @@ -0,0 +1,104 @@ +#include "soc_common.h" +#include + +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 index 0000000..004235d --- /dev/null +++ b/libctru/source/services/soc/soc_common.h @@ -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 index 0000000..9577c77 --- /dev/null +++ b/libctru/source/services/soc/soc_connect.c @@ -0,0 +1,48 @@ +#include "soc_common.h" +#include +#include + +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 index 0000000..6179a69 --- /dev/null +++ b/libctru/source/services/soc/soc_fcntl.c @@ -0,0 +1,50 @@ +#include "soc_common.h" +#include +#include +#include + +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 index 0000000..4932378 --- /dev/null +++ b/libctru/source/services/soc/soc_gethostbyname.c @@ -0,0 +1,60 @@ +#include "soc_common.h" +#include + +#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 index 0000000..fb747c3 --- /dev/null +++ b/libctru/source/services/soc/soc_gethostid.c @@ -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 index 0000000..f20be86 --- /dev/null +++ b/libctru/source/services/soc/soc_getpeername.c @@ -0,0 +1,41 @@ +#include "soc_common.h" +#include + +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 index 0000000..80812af --- /dev/null +++ b/libctru/source/services/soc/soc_getsockname.c @@ -0,0 +1,41 @@ +#include "soc_common.h" +#include + +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 index 0000000..20bf148 --- /dev/null +++ b/libctru/source/services/soc/soc_getsockopt.c @@ -0,0 +1,36 @@ +#include "soc_common.h" +#include + +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 index 0000000..e75312c --- /dev/null +++ b/libctru/source/services/soc/soc_inet_addr.c @@ -0,0 +1,9 @@ +#include "soc_common.h" +#include + +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 index 0000000..6e1f206 --- /dev/null +++ b/libctru/source/services/soc/soc_inet_aton.c @@ -0,0 +1,85 @@ +#include "soc_common.h" +#include +#include +#include + +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 index 0000000..ae7a5b7 --- /dev/null +++ b/libctru/source/services/soc/soc_inet_ntoa.c @@ -0,0 +1,32 @@ +#include "soc_common.h" +#include +#include + +static char buffer[INET_ADDRSTRLEN]; + +char* inet_ntoa(struct in_addr in) +{ + unsigned char *addrbuf = (unsigned char*)∈ + 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 index 0000000..2b961fa --- /dev/null +++ b/libctru/source/services/soc/soc_init.c @@ -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 index 0000000..6fce0d7 --- /dev/null +++ b/libctru/source/services/soc/soc_ioctl.c @@ -0,0 +1,37 @@ +#include "soc_common.h" +#include +#include +#include +#include + +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 index 0000000..ce7ff05 --- /dev/null +++ b/libctru/source/services/soc/soc_listen.c @@ -0,0 +1,22 @@ +#include "soc_common.h" +#include + +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 index 0000000..8cf5b34 --- /dev/null +++ b/libctru/source/services/soc/soc_poll.c @@ -0,0 +1,35 @@ +#include "soc_common.h" +#include + +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 index 0000000..adc0df0 --- /dev/null +++ b/libctru/source/services/soc/soc_recv.c @@ -0,0 +1,7 @@ +#include "soc_common.h" +#include + +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 index 0000000..df5c56c --- /dev/null +++ b/libctru/source/services/soc/soc_recvfrom.c @@ -0,0 +1,107 @@ +#include "soc_common.h" +#include + +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 index 0000000..d2cd911 --- /dev/null +++ b/libctru/source/services/soc/soc_select.c @@ -0,0 +1,90 @@ +#include "soc_common.h" +#include +#include +#include +#include + +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 index 0000000..d99f0c1 --- /dev/null +++ b/libctru/source/services/soc/soc_send.c @@ -0,0 +1,7 @@ +#include "soc_common.h" +#include + +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 index 0000000..9afd36a --- /dev/null +++ b/libctru/source/services/soc/soc_sendto.c @@ -0,0 +1,113 @@ +#include "soc_common.h" +#include +#include + +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 index 0000000..ff142b2 --- /dev/null +++ b/libctru/source/services/soc/soc_setsockopt.c @@ -0,0 +1,26 @@ +#include "soc_common.h" +#include + +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 index 0000000..be86293 --- /dev/null +++ b/libctru/source/services/soc/soc_shutdown.c @@ -0,0 +1,22 @@ +#include "soc_common.h" +#include + +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 index 0000000..d445fb8 --- /dev/null +++ b/libctru/source/services/soc/soc_sockatmark.c @@ -0,0 +1,21 @@ +#include "soc_common.h" +#include + +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 index 0000000..628138b --- /dev/null +++ b/libctru/source/services/soc/soc_socket.c @@ -0,0 +1,22 @@ +#include "soc_common.h" +#include + +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]); +}