1 #include <lib9.h>
2 #include "styxserver.h"
3 #include "styxaux.h"
4
5 typedef struct Listener Listener;
6 typedef struct Reader Reader;
7 typedef struct Union Union;
8
9 struct Listener
10 {
11 int fd;
12 char *dir;
13 Listener *next;
14 };
15
16 struct Reader
17 {
18 int pid;
19 int fd;
20 int n;
21 char buf[MSGMAX];
22 char rbuf[MSGMAX];
23 Reader *next;
24 };
25
26 struct Union
27 {
28 int pid;
29 Lock lock;
30 Listener *lr;
31 Reader *rr;
32 };
33
xlock(Lock * l)34 void xlock(Lock *l){ lock(l); }
xunlock(Lock * l)35 void xunlock(Lock *l){ unlock(l); }
36
37 static Reader*
findr(Styxserver * server,int fd)38 findr(Styxserver *server, int fd)
39 {
40 Reader *r;
41 Union *u;
42
43 u = server->priv;
44 xlock(&u->lock);
45 for(r = u->rr; r != nil; r = r->next)
46 if(r->fd == fd)
47 break;
48 xunlock(&u->lock);
49 return r;
50 }
51
52 int
styxinitsocket(void)53 styxinitsocket(void)
54 {
55 return 0;
56 }
57
58 void
styxendsocket(void)59 styxendsocket(void)
60 {
61 }
62
63 void
styxclosesocket(int fd)64 styxclosesocket(int fd)
65 {
66 close(fd);
67 }
68
69 static void
listener(Styxserver * server,int afd,char * adir)70 listener(Styxserver *server, int afd, char *adir)
71 {
72 int s;
73 Listener *l;
74 Union *u;
75 char ld[40];
76
77 USED(afd);
78 u = server->priv;
79 for(;;){
80 s = listen(adir, ld);
81 /* fprint(2, "listen %d %s %s\n", s, adir, ld); */
82 if(s < 0){
83 u->pid = -1;
84 break;
85 }
86 l = malloc(sizeof(Listener));
87 l->fd = s;
88 l->dir = strdup(ld);
89 xlock(&u->lock);
90 l->next = u->lr;
91 u->lr = l;
92 xunlock(&u->lock);
93 }
94 }
95
96 int
styxannounce(Styxserver * server,char * port)97 styxannounce(Styxserver *server, char *port)
98 {
99 int s, pid;
100 Union *u;
101 char adr[32], adir[40];
102
103 server->priv = u = malloc(sizeof(Union));
104 u->lock.val = 0;
105 u->lr = nil;
106 u->rr = nil;
107 sprint(adr, "tcp!*!%s", port);
108 s = announce(adr, adir);
109 /* fprint(2, "announce %d %s %s\n", s, adr, adir); */
110 if(s < 0)
111 return s;
112 switch((pid = rfork(RFPROC|RFREND|RFMEM))){
113 case 0:
114 listener(server, s, strdup(adir));
115 break;
116 default:
117 u->pid = pid;
118 break;
119 }
120 return s;
121 }
122
123 static void
reader(Styxserver * server,Reader * r)124 reader(Styxserver *server, Reader *r)
125 {
126 int m, n, s;
127 Union *u;
128
129 u = server->priv;
130 s = r->fd;
131 for(;;){
132 n = r->n;
133 if(n < 0){
134 r->pid = -1;
135 exits(nil);
136 }
137 m = read(s, r->rbuf, MSGMAX-n);
138 xlock(&u->lock);
139 n = r->n;
140 if(m < 0)
141 r->n = n == 0 ? m : n;
142 else{
143 memmove(r->buf+n, r->rbuf, m);
144 r->n = m+n;
145 }
146 xunlock(&u->lock);
147 }
148 }
149
150 int
styxaccept(Styxserver * server)151 styxaccept(Styxserver *server)
152 {
153 int s, fd, pid;
154 Reader *r;
155 Listener *l;
156 Union *u;
157 char *dir;
158
159 u = server->priv;
160 xlock(&u->lock);
161 if((l = u->lr) == nil){
162 xunlock(&u->lock);
163 return -1;
164 }
165 u->lr = l->next;
166 xunlock(&u->lock);
167 fd = l->fd;
168 dir = l->dir;
169 free(l);
170 s = accept(fd, dir);
171 /* fprint(2, "accept %d\n", s); */
172 free(dir);
173 if(s < 0)
174 return s;
175 r = malloc(sizeof(struct Reader));
176 r->fd = s;
177 r->n = 0;
178 xlock(&u->lock);
179 r->next = u->rr;
180 u->rr = r;
181 xunlock(&u->lock);
182 switch((pid = rfork(RFPROC|RFREND|RFMEM))){
183 case 0:
184 reader(server, r);
185 break;
186 case 1:
187 r->pid = pid;
188 break;
189 }
190 return s;
191 }
192
193 void
styxinitwait(Styxserver * server)194 styxinitwait(Styxserver *server)
195 {
196 USED(server);
197 }
198
199 int
styxnewcall(Styxserver * server)200 styxnewcall(Styxserver *server)
201 {
202 Union *u;
203
204 u = server->priv;
205 return u->lr != nil;
206 }
207
208 int
styxnewmsg(Styxserver * server,int fd)209 styxnewmsg(Styxserver *server, int fd)
210 {
211 Reader *r;
212
213 r = findr(server, fd);
214 return r != nil && r->n != 0;
215 }
216
217 void
styxnewclient(Styxserver * server,int fd)218 styxnewclient(Styxserver *server, int fd)
219 {
220 USED(server);
221 USED(fd);
222 }
223
224 void
styxfreeclient(Styxserver * server,int fd)225 styxfreeclient(Styxserver *server, int fd)
226 {
227 Reader *r, **rp;
228 Union *u;
229
230 u = server->priv;
231 r = findr(server, fd);
232 if(r == nil)
233 return;
234 xlock(&u->lock);
235 for(rp = &u->rr; *rp != nil; rp = &(*rp)->next)
236 if(r == *rp){
237 *rp = r->next;
238 break;
239 }
240 xunlock(&u->lock);
241 if(r->pid >= 0)
242 postnote(PNPROC, r->pid, "kill");
243 free(r);
244 }
245
246 char*
styxwaitmsg(Styxserver * server)247 styxwaitmsg(Styxserver *server)
248 {
249 int i;
250 Reader *r;
251 Union *u;
252
253 u = server->priv;
254 for(i = 0; i < 100; i++){
255 if(u->lr != nil)
256 return nil;
257 xlock(&u->lock);
258 for(r = u->rr; r != nil; r = r->next)
259 if(r->n != 0){
260 xunlock(&u->lock);
261 return nil;
262 }
263 xunlock(&u->lock);
264 sleep(100);
265 }
266 return nil;
267 }
268
269 int
styxrecv(Styxserver * server,int fd,char * buf,int n,int m)270 styxrecv(Styxserver *server, int fd, char *buf, int n, int m)
271 {
272 Reader *r;
273 Union *u;
274 int rn;
275 char *rbuf;
276
277 USED(m);
278 r = findr(server, fd);
279 if(r == nil)
280 return -1;
281 u = server->priv;
282 xlock(&u->lock);
283 rn = r->n;
284 rbuf = r->buf;
285 if(rn < 0){
286 xunlock(&u->lock);
287 return rn;
288 }
289 if(n > rn)
290 n = rn;
291 memmove(buf, rbuf, n);
292 rn -= n;
293 memmove(rbuf, rbuf+n, rn);
294 r->n = rn;
295 xunlock(&u->lock);
296 return n;
297 }
298
299 int
styxsend(Styxserver * server,int fd,char * buf,int n,int m)300 styxsend(Styxserver *server, int fd, char *buf, int n, int m)
301 {
302 USED(server);
303 USED(m);
304 return write(fd, buf, n);
305 }
306
307 void
styxexit(int n)308 styxexit(int n)
309 {
310 if(n)
311 exits("error");
312 else
313 exits(nil);
314 }
315