xref: /plan9/sys/src/libventi/server.c (revision 4f81ea256c7fac55da779894b772fbf5203568fa)
16b6b9ac8SDavid du Colombier #include <u.h>
26b6b9ac8SDavid du Colombier #include <libc.h>
36b6b9ac8SDavid du Colombier #include <venti.h>
4368c31abSDavid du Colombier #include <thread.h>
5368c31abSDavid du Colombier #include "queue.h"
66b6b9ac8SDavid du Colombier 
7368c31abSDavid du Colombier enum
86b6b9ac8SDavid du Colombier {
9368c31abSDavid du Colombier 	STACK = 8192
10368c31abSDavid du Colombier };
116b6b9ac8SDavid du Colombier 
12368c31abSDavid du Colombier typedef struct VtSconn VtSconn;
13368c31abSDavid du Colombier struct VtSconn
146b6b9ac8SDavid du Colombier {
15368c31abSDavid du Colombier 	int ctl;
16368c31abSDavid du Colombier 	int ref;
17368c31abSDavid du Colombier 	QLock lk;
18368c31abSDavid du Colombier 	char dir[NETPATHLEN];
19368c31abSDavid du Colombier 	VtSrv *srv;
20368c31abSDavid du Colombier 	VtConn *c;
21368c31abSDavid du Colombier };
226b6b9ac8SDavid du Colombier 
23368c31abSDavid du Colombier struct VtSrv
246b6b9ac8SDavid du Colombier {
25368c31abSDavid du Colombier 	int afd;
26368c31abSDavid du Colombier 	int dead;
27368c31abSDavid du Colombier 	char adir[NETPATHLEN];
28368c31abSDavid du Colombier 	Queue *q;	/* Queue(VtReq*) */
29368c31abSDavid du Colombier };
306b6b9ac8SDavid du Colombier 
31368c31abSDavid du Colombier static void listenproc(void*);
32368c31abSDavid du Colombier static void connproc(void*);
336b6b9ac8SDavid du Colombier 
34368c31abSDavid du Colombier static void
scincref(VtSconn * sc)35368c31abSDavid du Colombier scincref(VtSconn *sc)
366b6b9ac8SDavid du Colombier {
37368c31abSDavid du Colombier 	qlock(&sc->lk);
38368c31abSDavid du Colombier 	sc->ref++;
39368c31abSDavid du Colombier 	qunlock(&sc->lk);
406b6b9ac8SDavid du Colombier }
416b6b9ac8SDavid du Colombier 
42368c31abSDavid du Colombier static void
scdecref(VtSconn * sc)43368c31abSDavid du Colombier scdecref(VtSconn *sc)
446b6b9ac8SDavid du Colombier {
45368c31abSDavid du Colombier 	qlock(&sc->lk);
46368c31abSDavid du Colombier 	if(--sc->ref > 0){
47368c31abSDavid du Colombier 		qunlock(&sc->lk);
48368c31abSDavid du Colombier 		return;
496b6b9ac8SDavid du Colombier 	}
50368c31abSDavid du Colombier 	if(sc->c)
51368c31abSDavid du Colombier 		vtfreeconn(sc->c);
52368c31abSDavid du Colombier 	vtfree(sc);
536b6b9ac8SDavid du Colombier }
546b6b9ac8SDavid du Colombier 
55368c31abSDavid du Colombier VtSrv*
vtlisten(char * addr)56368c31abSDavid du Colombier vtlisten(char *addr)
576b6b9ac8SDavid du Colombier {
58368c31abSDavid du Colombier 	VtSrv *s;
59368c31abSDavid du Colombier 
60368c31abSDavid du Colombier 	s = vtmallocz(sizeof(VtSrv));
61368c31abSDavid du Colombier 	s->afd = announce(addr, s->adir);
62368c31abSDavid du Colombier 	if(s->afd < 0){
63368c31abSDavid du Colombier 		free(s);
64368c31abSDavid du Colombier 		return nil;
656b6b9ac8SDavid du Colombier 	}
66368c31abSDavid du Colombier 	s->q = _vtqalloc();
67368c31abSDavid du Colombier 	proccreate(listenproc, s, STACK);
68368c31abSDavid du Colombier 	return s;
696b6b9ac8SDavid du Colombier }
706b6b9ac8SDavid du Colombier 
71368c31abSDavid du Colombier static void
listenproc(void * v)72368c31abSDavid du Colombier listenproc(void *v)
736b6b9ac8SDavid du Colombier {
74368c31abSDavid du Colombier 	int ctl;
75368c31abSDavid du Colombier 	char dir[NETPATHLEN];
76368c31abSDavid du Colombier 	VtSrv *srv;
77368c31abSDavid du Colombier 	VtSconn *sc;
786b6b9ac8SDavid du Colombier 
79368c31abSDavid du Colombier 	srv = v;
806b6b9ac8SDavid du Colombier 	for(;;){
81368c31abSDavid du Colombier 		ctl = listen(srv->adir, dir);
82368c31abSDavid du Colombier 		if(ctl < 0){
83368c31abSDavid du Colombier 			srv->dead = 1;
846b6b9ac8SDavid du Colombier 			break;
856b6b9ac8SDavid du Colombier 		}
86368c31abSDavid du Colombier 		sc = vtmallocz(sizeof(VtSconn));
87368c31abSDavid du Colombier 		sc->ref = 1;
88368c31abSDavid du Colombier 		sc->ctl = ctl;
89368c31abSDavid du Colombier 		sc->srv = srv;
90368c31abSDavid du Colombier 		strcpy(sc->dir, dir);
91368c31abSDavid du Colombier 		proccreate(connproc, sc, STACK);
926b6b9ac8SDavid du Colombier 	}
936b6b9ac8SDavid du Colombier 
94368c31abSDavid du Colombier 	/* hangup */
956b6b9ac8SDavid du Colombier }
966b6b9ac8SDavid du Colombier 
97368c31abSDavid du Colombier static void
connproc(void * v)98368c31abSDavid du Colombier connproc(void *v)
99368c31abSDavid du Colombier {
100368c31abSDavid du Colombier 	VtSconn *sc;
101368c31abSDavid du Colombier 	VtConn *c;
102368c31abSDavid du Colombier 	Packet *p;
103368c31abSDavid du Colombier 	VtReq *r;
104368c31abSDavid du Colombier 	int fd;
105368c31abSDavid du Colombier static int first=1;
106368c31abSDavid du Colombier 
107368c31abSDavid du Colombier if(first && chattyventi){
108368c31abSDavid du Colombier 	first=0;
109368c31abSDavid du Colombier 	fmtinstall('F', vtfcallfmt);
110368c31abSDavid du Colombier }
111368c31abSDavid du Colombier 	r = nil;
112368c31abSDavid du Colombier 	sc = v;
113368c31abSDavid du Colombier 	sc->c = nil;
114368c31abSDavid du Colombier 	if(0) fprint(2, "new call %s on %d\n", sc->dir, sc->ctl);
115368c31abSDavid du Colombier 	fd = accept(sc->ctl, sc->dir);
116368c31abSDavid du Colombier 	close(sc->ctl);
117368c31abSDavid du Colombier 	if(fd < 0){
118368c31abSDavid du Colombier 		fprint(2, "accept %s: %r\n", sc->dir);
119368c31abSDavid du Colombier 		goto out;
120368c31abSDavid du Colombier 	}
121368c31abSDavid du Colombier 
122368c31abSDavid du Colombier 	c = vtconn(fd, fd);
123368c31abSDavid du Colombier 	sc->c = c;
124368c31abSDavid du Colombier 	if(vtversion(c) < 0){
125368c31abSDavid du Colombier 		fprint(2, "vtversion %s: %r\n", sc->dir);
126368c31abSDavid du Colombier 		goto out;
127368c31abSDavid du Colombier 	}
128368c31abSDavid du Colombier 	if(vtsrvhello(c) < 0){
129368c31abSDavid du Colombier 		fprint(2, "vtsrvhello %s: %r\n", sc->dir);
130368c31abSDavid du Colombier 		goto out;
131368c31abSDavid du Colombier 	}
132368c31abSDavid du Colombier 
133368c31abSDavid du Colombier 	if(0) fprint(2, "new proc %s\n", sc->dir);
134368c31abSDavid du Colombier 	proccreate(vtsendproc, c, STACK);
135368c31abSDavid du Colombier 	qlock(&c->lk);
136368c31abSDavid du Colombier 	while(!c->writeq)
137368c31abSDavid du Colombier 		rsleep(&c->rpcfork);
138368c31abSDavid du Colombier 	qunlock(&c->lk);
139368c31abSDavid du Colombier 
140368c31abSDavid du Colombier 	while((p = vtrecv(c)) != nil){
141368c31abSDavid du Colombier 		r = vtmallocz(sizeof(VtReq));
142368c31abSDavid du Colombier 		if(vtfcallunpack(&r->tx, p) < 0){
143368c31abSDavid du Colombier 			vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv bad packet %p: %r<br>\n", c->addr, p);
144368c31abSDavid du Colombier 			fprint(2, "bad packet on %s: %r\n", sc->dir);
145368c31abSDavid du Colombier 			packetfree(p);
146368c31abSDavid du Colombier 			continue;
147368c31abSDavid du Colombier 		}
148368c31abSDavid du Colombier 		vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv packet %p (%F)<br>\n", c->addr, p, &r->tx);
149368c31abSDavid du Colombier 		if(chattyventi)
150368c31abSDavid du Colombier 			fprint(2, "%s <- %F\n", argv0, &r->tx);
151368c31abSDavid du Colombier 		packetfree(p);
152368c31abSDavid du Colombier 		if(r->tx.msgtype == VtTgoodbye)
153368c31abSDavid du Colombier 			break;
154368c31abSDavid du Colombier 		r->rx.tag = r->tx.tag;
155368c31abSDavid du Colombier 		r->sc = sc;
156368c31abSDavid du Colombier 		scincref(sc);
157368c31abSDavid du Colombier 		if(_vtqsend(sc->srv->q, r) < 0){
158368c31abSDavid du Colombier 			scdecref(sc);
159368c31abSDavid du Colombier 			fprint(2, "hungup queue\n");
160368c31abSDavid du Colombier 			break;
161368c31abSDavid du Colombier 		}
162368c31abSDavid du Colombier 		r = nil;
163368c31abSDavid du Colombier 	}
164368c31abSDavid du Colombier 
165368c31abSDavid du Colombier 	if(0) fprint(2, "eof on %s\n", sc->dir);
166368c31abSDavid du Colombier 
167368c31abSDavid du Colombier out:
168368c31abSDavid du Colombier 	if(r){
169368c31abSDavid du Colombier 		vtfcallclear(&r->tx);
170368c31abSDavid du Colombier 		vtfree(r);
171368c31abSDavid du Colombier 	}
172368c31abSDavid du Colombier 	if(0) fprint(2, "freed %s\n", sc->dir);
173368c31abSDavid du Colombier 	scdecref(sc);
174368c31abSDavid du Colombier 	return;
175368c31abSDavid du Colombier }
176368c31abSDavid du Colombier 
177368c31abSDavid du Colombier VtReq*
vtgetreq(VtSrv * srv)178368c31abSDavid du Colombier vtgetreq(VtSrv *srv)
179368c31abSDavid du Colombier {
180368c31abSDavid du Colombier 	VtReq *r;
181368c31abSDavid du Colombier 
182368c31abSDavid du Colombier 	r = _vtqrecv(srv->q);
183*4f81ea25SDavid du Colombier 	if (r != nil)
184*4f81ea25SDavid du Colombier 		vtlog(VtServerLog, "<font size=-1>%T %s:</font> vtgetreq %F<br>\n",
185*4f81ea25SDavid du Colombier 			((VtSconn*)r->sc)->c->addr, &r->tx);
186368c31abSDavid du Colombier 	return r;
187368c31abSDavid du Colombier }
188368c31abSDavid du Colombier 
189368c31abSDavid du Colombier void
vtrespond(VtReq * r)190368c31abSDavid du Colombier vtrespond(VtReq *r)
191368c31abSDavid du Colombier {
192368c31abSDavid du Colombier 	Packet *p;
193368c31abSDavid du Colombier 	VtSconn *sc;
194368c31abSDavid du Colombier 
195368c31abSDavid du Colombier 	sc = r->sc;
196368c31abSDavid du Colombier 	if(r->rx.tag != r->tx.tag)
197368c31abSDavid du Colombier 		abort();
198368c31abSDavid du Colombier 	if(r->rx.msgtype != r->tx.msgtype+1 && r->rx.msgtype != VtRerror)
199368c31abSDavid du Colombier 		abort();
200368c31abSDavid du Colombier 	if(chattyventi)
201368c31abSDavid du Colombier 		fprint(2, "%s -> %F\n", argv0, &r->rx);
202368c31abSDavid du Colombier 	if((p = vtfcallpack(&r->rx)) == nil){
203368c31abSDavid du Colombier 		vtlog(VtServerLog, "%s: vtfcallpack %F: %r<br>\n", sc->c->addr, &r->rx);
204368c31abSDavid du Colombier 		fprint(2, "fcallpack on %s: %r\n", sc->dir);
205368c31abSDavid du Colombier 		packetfree(p);
206368c31abSDavid du Colombier 		vtfcallclear(&r->rx);
207368c31abSDavid du Colombier 		return;
208368c31abSDavid du Colombier 	}
209368c31abSDavid du Colombier 	vtlog(VtServerLog, "<font size=-1>%T %s:</font> send packet %p (%F)<br>\n", sc->c->addr, p, &r->rx);
210368c31abSDavid du Colombier 	if(vtsend(sc->c, p) < 0)
211368c31abSDavid du Colombier 		fprint(2, "vtsend %F: %r\n", &r->rx);
212368c31abSDavid du Colombier 	scdecref(sc);
213368c31abSDavid du Colombier 	vtfcallclear(&r->tx);
214368c31abSDavid du Colombier 	vtfcallclear(&r->rx);
215368c31abSDavid du Colombier 	vtfree(r);
2166b6b9ac8SDavid du Colombier }
2176b6b9ac8SDavid du Colombier 
218