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