xref: /inferno-os/tools/libstyx/Plan9.c (revision 46439007cf417cbd9ac8049bb4122c890097a0fa)
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