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

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