2 * Acess2 POSIX Sockets Library
3 * - By John Hodge (thePowersGang)
8 #include <sys/socket.h>
10 #include <stdlib.h> // malloc/free
12 #include <netinet/in.h>
18 #define IOCTL_TCPC_PORT 5
19 #define IOCTL_TCPC_HOST 6
20 #define IOCTL_TCPC_CONNECT 7
21 #define IOCTL_TCPS_PORT 5
23 typedef struct s_sockinfo
29 struct sockaddr *local;
30 struct sockaddr *remote;
34 void _CommitClient(int sockfd);
36 struct s_sockinfo gSockInfo[MAXFD];
37 static int giNumPreinit = 0;
40 static t_sockinfo *_GetInfo(int FD)
43 if( FD == 0 && giNumPreinit == MAXFD )
45 for( i = 0; i < MAXFD; i ++ )
47 if( gSockInfo[i].fd == FD )
51 if( FD != 0 && nInit == giNumPreinit )
57 int socket(int domain, int type, int protocol)
59 t_sockinfo *si = NULL;
61 if( domain < 0 || domain > AF_INET6 ) {
62 _SysDebug("socket: Domain %i invalid", domain);
66 if( type < 0 || type > SOCK_RDM ) {
67 _SysDebug("socket: Type %i invalid", type);
72 // Allocate an info struct
79 int fd = _SysOpen("/Devices/null", OPENFLAG_RDWR);
80 if( fd == -1 ) return -1;
86 si->protocol = protocol;
90 _SysDebug("socket(%i,%i,%i) = %i", domain, type, protocol, fd);
94 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
96 t_sockinfo *si = _GetInfo(sockfd);;
104 si->local = malloc( addrlen );
105 memcpy(si->local, addr, addrlen);
110 size_t _getAddrData(const struct sockaddr *addr, const void **dataptr, int *port)
113 const struct sockaddr_in *in4 = (void*)addr;
114 const struct sockaddr_in6 *in6 = (void*)addr;
115 switch( addr->sa_family )
118 *dataptr = &in4->sin_addr;
120 *port = in4->sin_port;
123 *dataptr = &in6->sin6_addr;
125 *port = in6->sin6_port;
128 _SysDebug("libpsocket _getAddrData: Unkown sa_family %i", addr->sa_family);
134 int _OpenIf(int DestFD, const struct sockaddr *addr, const char *file, int *port)
136 const uint8_t *addrBuffer = NULL;
139 addrLen = _getAddrData(addr, (const void **)&addrBuffer, port);
145 char hexAddr[addrLen*2+1];
147 for( int i = 0; i < addrLen; i ++ ) {
148 hexAddr[i*2+0] = "0123456789ABCDEF"[addrBuffer[i] >> 4];
149 hexAddr[i*2+1] = "0123456789ABCDEF"[addrBuffer[i] & 15];
150 if(addrBuffer[i]) bNonZero = 1;
152 hexAddr[addrLen*2] = 0;
156 path = mkstr("/Devices/ip/routes/@%i:%s/%s", addr->sa_family, hexAddr, file);
158 path = mkstr("/Devices/ip/*%i/%s", addr->sa_family, file);
160 int ret = _SysReopen(DestFD, path, OPENFLAG_RDWR);
161 _SysDebug("libpsocket: _SysReopen(%i, '%s') = %i", DestFD, path, ret);
163 // TODO: Error-check?
167 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
169 t_sockinfo *si = _GetInfo(sockfd);
170 if( !si || si->remote ) {
171 _SysDebug("connect: FD %i already connected", sockfd);
176 si->remote = malloc( addrlen );
177 memcpy(si->remote, addr, addrlen);
180 if( si->type == SOCK_STREAM )
183 const struct sockaddr *bindaddr = (si->local ? si->local : addr);
184 ret = _OpenIf(sockfd, bindaddr, "tcpc", &lport);
189 //_SysIOCtl(sockfd, IOCTL_TCPC_LPORT, &lport);
190 _SysDebug("connect: TODO - Bind to local port");
194 const void *addrdata;
195 _getAddrData(addr, &addrdata, &port);
197 _SysIOCtl(sockfd, IOCTL_TCPC_PORT, &port);
198 _SysIOCtl(sockfd, IOCTL_TCPC_HOST, (void*)addrdata);
199 ret = _SysIOCtl(sockfd, IOCTL_TCPC_CONNECT, NULL);
200 _SysDebug("connect: :%i = %i", port, ret);
204 _SysDebug("connect: TODO - non-TCP clients (%i)", si->type);
207 _CommitClient(sockfd);
212 int listen(int sockfd, int backlog)
214 // TODO: Save this to the t_sockinfo structure
218 void _ClearInfo(t_sockinfo *si)
234 void _CommitServer(int sockfd)
236 t_sockinfo *si = _GetInfo(sockfd);
244 if( si->type != SOCK_STREAM ) {
245 _SysDebug("TODO: Non-tcp servers");
249 // Bind to the local address
251 int ret = _OpenIf(sockfd, si->local, "tcps", &port);
257 // TODO: Set up socket
258 _SysIOCtl(sockfd, IOCTL_TCPS_PORT, &port);
263 void _CommitClient(int sockfd)
265 t_sockinfo *si = _GetInfo(sockfd);
271 int accept(int sockfd, struct sockaddr *clientaddr, socklen_t *addrlen)
273 _CommitServer(sockfd);
277 child = _SysOpenChild(sockfd, "", OPENFLAG_RDWR);
278 if( child == -1 ) return -1;
280 _SysIOCtl(child, 8, clientaddr);
286 int recvfrom(int sockfd, void *buffer, size_t length, int flags, struct sockaddr *clientaddr, socklen_t *addrlen)
288 _CommitClient(sockfd);
289 // TODO: Determine socket type (TCP/UDP) and use a bounce-buffer for UDP
290 return _SysRead(sockfd, buffer, length);
293 int recv(int sockfd, void *buffer, size_t length, int flags)
295 _CommitClient(sockfd);
296 return _SysRead(sockfd, buffer, length);
299 int sendto(int sockfd, const void *buffer, size_t length, int flags, const struct sockaddr *clientaddr, socklen_t addrlen)
301 _CommitClient(sockfd);
302 // TODO: Determine socket type (TCP/UDP) and use a bounce-buffer for UDP
303 return _SysWrite(sockfd, buffer, length);
306 int send(int sockfd, void *buffer, size_t length, int flags)
308 _CommitClient(sockfd);
309 return _SysWrite(sockfd, buffer, length);
313 int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len)
318 int getsockopt(int socket, int level, int option_name, void *option_value, socklen_t *option_len)
323 int getsockname(int socket, struct sockaddr *addr, socklen_t *addrlen)
328 int getpeername(int socket, struct sockaddr *addr, socklen_t *addrlen)
333 int shutdown(int socket, int how)