X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Flibpsocket.so_src%2Fsocket.c;h=747ebe455815a4d95e9f72e38534e6e026564118;hb=98bd9c0c8985c50c42231c116a4e18fedd47761e;hp=913f72f733a35fcfa48f23710046effb1900b955;hpb=d0b4559f2936f6d9f06be0f7c3c51527a480ec0d;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/libpsocket.so_src/socket.c b/Usermode/Libraries/libpsocket.so_src/socket.c index 913f72f7..747ebe45 100644 --- a/Usermode/Libraries/libpsocket.so_src/socket.c +++ b/Usermode/Libraries/libpsocket.so_src/socket.c @@ -6,13 +6,20 @@ * - sys/socket.h calls */ #include -#include +#include #include // malloc/free #include #include +#include +#include "common.h" #define MAXFD 32 +#define IOCTL_TCPC_PORT 5 +#define IOCTL_TCPC_HOST 6 +#define IOCTL_TCPC_CONNECT 7 +#define IOCTL_TCPS_PORT 5 + typedef struct s_sockinfo { int fd; @@ -23,6 +30,9 @@ typedef struct s_sockinfo struct sockaddr *remote; } t_sockinfo; +// === PROTOTYPES === +void _CommitClient(int sockfd); + struct s_sockinfo gSockInfo[MAXFD]; static int giNumPreinit = 0; @@ -48,14 +58,25 @@ 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; + if( domain < 0 || domain > AF_INET6 ) { + _SysDebug("socket: Domain %i invalid", domain); + errno = EINVAL; + return -1; + } + if( type < 0 || type > SOCK_RDM ) { + _SysDebug("socket: Type %i invalid", type); + errno = EINVAL; + return -1; + } // Allocate an info struct si = _GetInfo(0); - if( !si ) return -1; + if( !si ) { + errno = ENOMEM; + return -1; + } - int fd = open("/Devices/null", O_RDWR); + int fd = _SysOpen("/Devices/null", OPENFLAG_RDWR); if( fd == -1 ) return -1; giNumPreinit ++; @@ -65,7 +86,8 @@ int socket(int domain, int type, int protocol) si->protocol = protocol; si->local = NULL; si->remote = NULL; - + + _SysDebug("socket(%i,%i,%i) = %i", domain, type, protocol, fd); return fd; } @@ -85,20 +107,106 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) return 0; } -int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +size_t _getAddrData(const struct sockaddr *addr, const void **dataptr, int *port) { - t_sockinfo *si = _GetInfo(sockfd);; - if( !si ) return -1; + size_t addrLen = 0; + const struct sockaddr_in *in4 = (void*)addr; + const struct sockaddr_in6 *in6 = (void*)addr; + switch( addr->sa_family ) + { + case AF_INET: + *dataptr = &in4->sin_addr; + addrLen = 4; + *port = in4->sin_port; + break; + case AF_INET6: + *dataptr = &in6->sin6_addr; + addrLen = 16; + *port = in6->sin6_port; + break; + default: + _SysDebug("libpsocket _getAddrData: Unkown sa_family %i", addr->sa_family); + return 0; + } + return addrLen; +} - if( si->remote ) { - // Oops? +int _OpenIf(int DestFD, const struct sockaddr *addr, const char *file, int *port) +{ + const uint8_t *addrBuffer = NULL; + size_t addrLen = 0; + + addrLen = _getAddrData(addr, (const void **)&addrBuffer, port); + if( addrLen == 0 ) { + errno = EINVAL; + return -1; + } + + char hexAddr[addrLen*2+1]; + int bNonZero = 0; + for( int 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; + } + hexAddr[addrLen*2] = 0; + + char *path; + if( bNonZero ) + path = mkstr("/Devices/ip/routes/@%i:%s/%s", addr->sa_family, hexAddr, file); + else + path = mkstr("/Devices/ip/*%i/%s", addr->sa_family, file); + + int ret = _SysReopen(DestFD, path, OPENFLAG_RDWR); + _SysDebug("libpsocket: _SysReopen(%i, '%s') = %i", DestFD, path, ret); + free(path); + // TODO: Error-check? + return ret; +} + +int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + t_sockinfo *si = _GetInfo(sockfd); + if( !si || si->remote ) { + _SysDebug("connect: FD %i already connected", sockfd); + errno = EALREADY; return -1; } si->remote = malloc( addrlen ); memcpy(si->remote, addr, addrlen); - return 0; + int ret = 0; + if( si->type == SOCK_STREAM ) + { + int lport = 0; + const struct sockaddr *bindaddr = (si->local ? si->local : addr); + ret = _OpenIf(sockfd, bindaddr, "tcpc", &lport); + if(ret == -1) + return ret; + + if( si->local ) { + //_SysIOCtl(sockfd, IOCTL_TCPC_LPORT, &lport); + _SysDebug("connect: TODO - Bind to local port"); + } + + int port; + const void *addrdata; + _getAddrData(addr, &addrdata, &port); + + _SysIOCtl(sockfd, IOCTL_TCPC_PORT, &port); + _SysIOCtl(sockfd, IOCTL_TCPC_HOST, (void*)addrdata); + ret = _SysIOCtl(sockfd, IOCTL_TCPC_CONNECT, NULL); + _SysDebug("connect: :%i = %i", port, ret); + } + else + { + _SysDebug("connect: TODO - non-TCP clients (%i)", si->type); + } + + _CommitClient(sockfd); + + return ret; } int listen(int sockfd, int backlog) @@ -128,51 +236,26 @@ 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: + if( si->type != SOCK_STREAM ) { + _SysDebug("TODO: Non-tcp servers"); 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 + // Bind to the local address + int port; + int ret = _OpenIf(sockfd, si->local, "tcps", &port); + if( ret == -1 ) { + return ; + } - free(path); - + // Bind to port // TODO: Set up socket + _SysIOCtl(sockfd, IOCTL_TCPS_PORT, &port); _ClearInfo(si); } @@ -185,16 +268,17 @@ void _CommitClient(int sockfd) _ClearInfo(si); } -int accept(int sockfd, struct sockaddr *clientaddr, socklen_t addrlen) +int accept(int sockfd, struct sockaddr *clientaddr, socklen_t *addrlen) { _CommitServer(sockfd); int child; - child = _SysOpenChild(sockfd, "", O_RDWR); + child = _SysOpenChild(sockfd, "", OPENFLAG_RDWR); if( child == -1 ) return -1; - ioctl(child, 8, clientaddr); + _SysIOCtl(child, 8, clientaddr); + return child; } @@ -203,25 +287,51 @@ int recvfrom(int sockfd, void *buffer, size_t length, int flags, struct sockaddr { _CommitClient(sockfd); // TODO: Determine socket type (TCP/UDP) and use a bounce-buffer for UDP - return read(sockfd, buffer, length); + return _SysRead(sockfd, buffer, length); } int recv(int sockfd, void *buffer, size_t length, int flags) { _CommitClient(sockfd); - return read(sockfd, buffer, length); + return _SysRead(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); + return _SysWrite(sockfd, buffer, length); } int send(int sockfd, void *buffer, size_t length, int flags) { _CommitClient(sockfd); - return write(sockfd, buffer, length); + return _SysWrite(sockfd, buffer, length); +} + + +int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len) +{ + return 0; +} + +int getsockopt(int socket, int level, int option_name, void *option_value, socklen_t *option_len) +{ + return 0; +} + +int getsockname(int socket, struct sockaddr *addr, socklen_t *addrlen) +{ + return 0; +} + +int getpeername(int socket, struct sockaddr *addr, socklen_t *addrlen) +{ + return 0; +} + +int shutdown(int socket, int how) +{ + return 0; }