Usermode - POSIX and C conformance changes
[tpg/acess2.git] / Usermode / Libraries / libpsocket.so_src / socket.c
1 /*
2  * Acess2 POSIX Sockets Library
3  * - By John Hodge (thePowersGang)
4  *
5  * socket.c
6  * - sys/socket.h calls
7  */
8 #include <sys/socket.h>
9 #include <acess/sys.h>
10 #include <stdlib.h>     // malloc/free
11 #include <string.h>
12 #include <netinet/in.h>
13 #include "common.h"
14
15 #define MAXFD   32
16
17 typedef struct s_sockinfo
18 {
19          int    fd;
20         char    domain;
21         char    type;
22         char    protocol;
23         struct sockaddr *local;
24         struct sockaddr *remote;
25 } t_sockinfo;
26
27 struct s_sockinfo       gSockInfo[MAXFD];
28 static int      giNumPreinit = 0;
29
30 // === CODE ===
31 static t_sockinfo *_GetInfo(int FD)
32 {
33          int    i, nInit = 0;;
34         if( FD == 0 && giNumPreinit == MAXFD )
35                 return NULL;
36         for( i = 0; i < MAXFD; i ++ )
37         {
38                 if( gSockInfo[i].fd == FD )
39                         return &gSockInfo[i];
40                 if( gSockInfo[i].fd )
41                         nInit ++;
42                 if( FD != 0 && nInit == giNumPreinit )
43                         return NULL;
44         }
45         return NULL;
46 }
47
48 int socket(int domain, int type, int protocol)
49 {
50         t_sockinfo      *si = NULL;
51         
52         if( domain < 0 || domain > AF_INET6 )   return -1;
53         if( type < 0 || type > SOCK_RDM )       return -1;
54
55         // Allocate an info struct
56         si = _GetInfo(0);
57         if( !si )       return -1;
58
59         int fd = _SysOpen("/Devices/null", OPENFLAG_RDWR);
60         if( fd == -1 )  return -1;
61
62         giNumPreinit ++;
63         si->fd = fd;
64         si->domain = domain;
65         si->type = type;
66         si->protocol = protocol;
67         si->local = NULL;
68         si->remote = NULL;
69
70         return fd;
71
72
73 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
74 {
75         t_sockinfo      *si = _GetInfo(sockfd);;
76         if( !si )       return -1;
77
78         if( si->local ) {
79                 // Oops?
80                 return -1;
81         }
82
83         si->local = malloc( addrlen );
84         memcpy(si->local, addr, addrlen);
85
86         return 0;
87 }
88
89 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
90 {
91         t_sockinfo      *si = _GetInfo(sockfd);;
92         if( !si )       return -1;
93
94         if( si->remote ) {
95                 // Oops?
96                 return -1;
97         }
98
99         si->remote = malloc( addrlen );
100         memcpy(si->remote, addr, addrlen);
101
102         return 0;
103 }
104
105 int listen(int sockfd, int backlog)
106 {
107         // TODO: Save this to the t_sockinfo structure
108         return 0;
109 }
110
111 void _ClearInfo(t_sockinfo *si)
112 {
113         if( si->local ) {
114                 free(si->local);
115                 si->local = NULL;
116         }
117         
118         if( si->remote ) {
119                 free(si->remote);
120                 si->remote = NULL;
121         }
122         
123         si->fd = 0;
124         giNumPreinit --;
125 }
126
127 void _CommitServer(int sockfd)
128 {
129         t_sockinfo      *si = _GetInfo(sockfd);
130         if( !si )       return ;
131
132         const char      *file;
133         
134         file = "tcps";
135
136         if( !si->local ) {
137                 // Um... oops?
138                 return ;
139         }       
140
141         uint8_t *addrBuffer = NULL;
142         size_t addrLen = 0;
143         switch( si->local->sa_family )
144         {
145         case AF_INET:
146                 addrBuffer = (void*)&((struct sockaddr_in*)si->local)->sin_addr;
147                 addrLen = 4;
148                 break;
149         case AF_INET6:
150                 addrBuffer = (void*)&((struct sockaddr_in6*)si->local)->sin6_addr;
151                 addrLen = 16;
152                 break;
153         default:
154                 return ;
155         }
156         
157         char    hexAddr[addrLen*2+1];
158          int    bNonZero = 0, i;
159         for( i = 0; i < addrLen; i ++ ) {
160                 hexAddr[i*2+0] = "0123456789ABCDEF"[addrBuffer[i] >> 4];
161                 hexAddr[i*2+1] = "0123456789ABCDEF"[addrBuffer[i] & 15];
162                 if(addrBuffer[i]) bNonZero = 1;
163         }
164         
165         char    *path;
166         if( bNonZero )
167                 path = mkstr("/Devices/ip/routes/@%i:%s/%s", si->local->sa_family, file);
168         else
169                 path = mkstr("/Devices/ip/*%i/%s", si->local->sa_family, file);
170
171         _SysReopen(si->fd, path, OPENFLAG_RDWR);
172         // TODO: Error-check
173         
174         free(path);
175
176         // TODO: Set up socket
177
178         _ClearInfo(si);
179 }
180
181 void _CommitClient(int sockfd)
182 {
183         t_sockinfo      *si = _GetInfo(sockfd);
184         if( !si )       return ;
185
186         _ClearInfo(si);
187 }
188
189 int accept(int sockfd, struct sockaddr *clientaddr, socklen_t addrlen)
190 {
191         _CommitServer(sockfd);
192          int    child;
193
194
195         child = _SysOpenChild(sockfd, "", OPENFLAG_RDWR);
196         if( child == -1 )       return -1;
197         
198         _SysIOCtl(child, 8, clientaddr);
199
200         
201         return child;
202 }
203
204 int recvfrom(int sockfd, void *buffer, size_t length, int flags, struct sockaddr *clientaddr, socklen_t *addrlen)
205 {
206         _CommitClient(sockfd);
207         // TODO: Determine socket type (TCP/UDP) and use a bounce-buffer for UDP
208         return _SysRead(sockfd, buffer, length);
209 }
210
211 int recv(int sockfd, void *buffer, size_t length, int flags)
212 {
213         _CommitClient(sockfd);
214         return _SysRead(sockfd, buffer, length);
215 }
216
217 int sendto(int sockfd, const void *buffer, size_t length, int flags, const struct sockaddr *clientaddr, socklen_t addrlen)
218 {
219         _CommitClient(sockfd);
220         // TODO: Determine socket type (TCP/UDP) and use a bounce-buffer for UDP
221         return _SysWrite(sockfd, buffer, length);
222 }
223
224 int send(int sockfd, void *buffer, size_t length, int flags)
225 {
226         _CommitClient(sockfd);
227         return _SysWrite(sockfd, buffer, length);
228 }
229
230
231 int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len)
232 {
233         return 0;
234 }
235
236 int getsockopt(int socket, int level, int option_name, void *option_value, socklen_t *option_len)
237 {
238         return 0;
239 }
240
241 int getsockname(int socket, struct sockaddr *addr, socklen_t *addrlen)
242 {
243         return 0;
244 }
245
246 int getpeername(int socket, struct sockaddr *addr, socklen_t *addrlen)
247 {
248         return 0;
249 }
250

UCC git Repository :: git.ucc.asn.au