From: John Hodge Date: Sun, 27 May 2012 05:07:50 +0000 (+0800) Subject: Usermode/libpsocket - Working on BSD/POSIX socket emulation X-Git-Tag: rel0.15~611^2~69 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=0dfc38f0ca6b391b15154e3173b5c9504df17f84;p=tpg%2Facess2.git Usermode/libpsocket - Working on BSD/POSIX socket emulation --- diff --git a/Usermode/Libraries/libpsocket.so_src/Makefile b/Usermode/Libraries/libpsocket.so_src/Makefile new file mode 100644 index 00000000..ee0b5795 --- /dev/null +++ b/Usermode/Libraries/libpsocket.so_src/Makefile @@ -0,0 +1,12 @@ +# Acess 2 - POSIX Sockets + +include ../Makefile.cfg + +CPPFLAGS += +CFLAGS += -Wall +LDFLAGS += -lc -soname libpsocket.so + +OBJ = main.o getaddrinfo.o socket.o +BIN = libpsocket.so + +include ../Makefile.tpl diff --git a/Usermode/Libraries/libpsocket.so_src/getaddrinfo.c b/Usermode/Libraries/libpsocket.so_src/getaddrinfo.c new file mode 100644 index 00000000..e122a5aa --- /dev/null +++ b/Usermode/Libraries/libpsocket.so_src/getaddrinfo.c @@ -0,0 +1,39 @@ +/* + * Acess2 POSIX Sockets Library + * - By John Hodge (thePowersGang) + * + * getaddrinfo.c + * - getaddrinfo/freeaddrinfo/getnameinfo/gai_strerror + */ +#include +#include + +// === CODE === +int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) +{ + static struct addrinfo info; + static struct sockaddr_in addr; + + addr.sin_family = 4; + addr.sin_addr.s_addr = 0x2701A8C0; + info.ai_family = 4; + info.ai_addr = (struct sockaddr *) &addr; + + return 1; +} + +void freeaddrinfo(struct addrinfo *res) +{ + +} + +const char *gai_strerror(int errnum) +{ + switch(errnum) + { + case 0: return "No error"; + case 1: return "Unimplemented"; + default: return "UNKNOWN"; + } +} + diff --git a/Usermode/Libraries/libpsocket.so_src/include_exp/netdb.h b/Usermode/Libraries/libpsocket.so_src/include_exp/netdb.h new file mode 100644 index 00000000..cea819c5 --- /dev/null +++ b/Usermode/Libraries/libpsocket.so_src/include_exp/netdb.h @@ -0,0 +1,24 @@ +#ifndef _LIBPSOCKET__NETDB_H_ +#define _LIBPSOCKET__NETDB_H_ + +typedef unsigned int socklen_t; + +struct addrinfo +{ + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + socklen_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; + struct addrinfo *ai_next; +}; + +extern int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); +extern void freeaddrinfo(struct addrinfo *res); +const char *gai_strerror(int errorcode); + + +#endif + diff --git a/Usermode/Libraries/libpsocket.so_src/include_exp/netinet/in.h b/Usermode/Libraries/libpsocket.so_src/include_exp/netinet/in.h new file mode 100644 index 00000000..4bde06db --- /dev/null +++ b/Usermode/Libraries/libpsocket.so_src/include_exp/netinet/in.h @@ -0,0 +1,33 @@ +#ifndef _LIBPSOCKET__NETINET__IN_H_ +#define _LIBPSOCKET__NETINET__IN_H_ + +#include + +struct in_addr +{ + unsigned long s_addr; +}; + +struct sockaddr_in +{ + uint16_t sin_family; + uint16_t sin_port; + struct in_addr sin_addr; +}; + +struct in6_addr +{ + unsigned char s6_addr[16]; +}; + +struct sockaddr_in6 +{ + uint16_t sin6_family; + uint16_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr sin6_addr; + uint32_t sin6_scope_id; +}; + +#endif + diff --git a/Usermode/Libraries/libpsocket.so_src/include_exp/sys/socket.h b/Usermode/Libraries/libpsocket.so_src/include_exp/sys/socket.h index 43cb3d66..ecf5ce86 100644 --- a/Usermode/Libraries/libpsocket.so_src/include_exp/sys/socket.h +++ b/Usermode/Libraries/libpsocket.so_src/include_exp/sys/socket.h @@ -9,13 +9,16 @@ #ifndef _SYS_SOCKETS_H_ #define _SYS_SOCKETS_H_ +#include + typedef int socklen_t; typedef enum { AF_UNSPEC = 0, + AF_PACKET = 1, AF_INET = 4, - AF_INET6 = 6 + AF_INET6 = 6, } sa_family_t; struct sockaddr @@ -71,5 +74,10 @@ extern int listen(int sockfd, int backlog); */ extern int accept(int sockfd, struct sockaddr *clientaddr, socklen_t addrlen); +extern int recvfrom(int sockfd, void *buffer, size_t length, int flags, struct sockaddr *clientaddr, socklen_t *addrlen); +extern int recv(int sockfd, void *buffer, size_t length, int flags); +extern int sendto(int sockfd, const void *buffer, size_t length, int flags, const struct sockaddr *clientaddr, socklen_t addrlen); +extern int send(int sockfd, void *buffer, size_t length, int flags); + #endif diff --git a/Usermode/Libraries/libpsocket.so_src/main.c b/Usermode/Libraries/libpsocket.so_src/main.c new file mode 100644 index 00000000..09b39879 --- /dev/null +++ b/Usermode/Libraries/libpsocket.so_src/main.c @@ -0,0 +1,13 @@ +/* + * Acess2 POSIX Sockets Library + * - By John Hodge (thePowersGang) + * + * main.c + * - Entrypoint and misc code + */ + +int SoMain(void) +{ + return 0; +} + diff --git a/Usermode/Libraries/libpsocket.so_src/socket.c b/Usermode/Libraries/libpsocket.so_src/socket.c new file mode 100644 index 00000000..913f72f7 --- /dev/null +++ b/Usermode/Libraries/libpsocket.so_src/socket.c @@ -0,0 +1,227 @@ +/* + * Acess2 POSIX Sockets Library + * - By John Hodge (thePowersGang) + * + * socket.c + * - sys/socket.h calls + */ +#include +#include +#include // malloc/free +#include +#include + +#define MAXFD 32 + +typedef struct s_sockinfo +{ + int fd; + char domain; + char type; + char protocol; + struct sockaddr *local; + struct sockaddr *remote; +} t_sockinfo; + +struct s_sockinfo gSockInfo[MAXFD]; +static int giNumPreinit = 0; + +// === CODE === +static t_sockinfo *_GetInfo(int FD) +{ + int i, nInit = 0;; + if( FD == 0 && giNumPreinit == MAXFD ) + return NULL; + for( i = 0; i < MAXFD; i ++ ) + { + if( gSockInfo[i].fd == FD ) + return &gSockInfo[i]; + if( gSockInfo[i].fd ) + nInit ++; + if( FD != 0 && nInit == giNumPreinit ) + return NULL; + } + return NULL; +} + +int socket(int domain, int type, int protocol) +{ + t_sockinfo *si = NULL; + + if( domain < 0 || domain > AF_INET6 ) return -1; + if( type < 0 || type > SOCK_RDM ) return -1; + + // Allocate an info struct + si = _GetInfo(0); + if( !si ) return -1; + + int fd = open("/Devices/null", O_RDWR); + if( fd == -1 ) return -1; + + giNumPreinit ++; + si->fd = fd; + si->domain = domain; + si->type = type; + si->protocol = protocol; + si->local = NULL; + si->remote = NULL; + + return fd; +} + +int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + t_sockinfo *si = _GetInfo(sockfd);; + if( !si ) return -1; + + if( si->local ) { + // Oops? + return -1; + } + + si->local = malloc( addrlen ); + memcpy(si->local, addr, addrlen); + + return 0; +} + +int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + t_sockinfo *si = _GetInfo(sockfd);; + if( !si ) return -1; + + if( si->remote ) { + // Oops? + return -1; + } + + si->remote = malloc( addrlen ); + memcpy(si->remote, addr, addrlen); + + return 0; +} + +int listen(int sockfd, int backlog) +{ + // TODO: Save this to the t_sockinfo structure + return 0; +} + +void _ClearInfo(t_sockinfo *si) +{ + if( si->local ) { + free(si->local); + si->local = NULL; + } + + if( si->remote ) { + free(si->remote); + si->remote = NULL; + } + + si->fd = 0; + giNumPreinit --; +} + +void _CommitServer(int sockfd) +{ + t_sockinfo *si = _GetInfo(sockfd); + if( !si ) return ; + + const char *file; + + file = "tcps"; + + if( !si->local ) { + // Um... oops? + return ; + } + + uint8_t *addrBuffer = NULL; + size_t addrLen = 0; + switch( si->local->sa_family ) + { + case AF_INET: + addrBuffer = (void*)&((struct sockaddr_in*)si->local)->sin_addr; + addrLen = 4; + break; + case AF_INET6: + addrBuffer = (void*)&((struct sockaddr_in6*)si->local)->sin6_addr; + addrLen = 16; + break; + default: + return ; + } + + char hexAddr[addrLen*2+1]; + int bNonZero = 0, i; + for( i = 0; i < addrLen; i ++ ) { + hexAddr[i*2+0] = "0123456789ABCDEF"[addrBuffer[i] >> 4]; + hexAddr[i*2+1] = "0123456789ABCDEF"[addrBuffer[i] & 15]; + if(addrBuffer[i]) bNonZero = 1; + } + + char *path; + if( bNonZero ) + path = mkstr("/Devices/ip/routes/@%i:%s/%s", si->local->sa_family, file); + else + path = mkstr("/Devices/ip/*%i/%s", si->local->sa_family, file); + + reopen(si->fd, path, O_RDWR); + // TODO: Error-check + + free(path); + + // TODO: Set up socket + + _ClearInfo(si); +} + +void _CommitClient(int sockfd) +{ + t_sockinfo *si = _GetInfo(sockfd); + if( !si ) return ; + + _ClearInfo(si); +} + +int accept(int sockfd, struct sockaddr *clientaddr, socklen_t addrlen) +{ + _CommitServer(sockfd); + int child; + + + child = _SysOpenChild(sockfd, "", O_RDWR); + if( child == -1 ) return -1; + + ioctl(child, 8, clientaddr); + + return child; +} + +int recvfrom(int sockfd, void *buffer, size_t length, int flags, struct sockaddr *clientaddr, socklen_t *addrlen) +{ + _CommitClient(sockfd); + // TODO: Determine socket type (TCP/UDP) and use a bounce-buffer for UDP + return read(sockfd, buffer, length); +} + +int recv(int sockfd, void *buffer, size_t length, int flags) +{ + _CommitClient(sockfd); + return read(sockfd, buffer, length); +} + +int sendto(int sockfd, const void *buffer, size_t length, int flags, const struct sockaddr *clientaddr, socklen_t addrlen) +{ + _CommitClient(sockfd); + // TODO: Determine socket type (TCP/UDP) and use a bounce-buffer for UDP + return write(sockfd, buffer, length); +} + +int send(int sockfd, void *buffer, size_t length, int flags) +{ + _CommitClient(sockfd); + return write(sockfd, buffer, length); +} +