Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <venti.h>
4 #include <thread.h>
5 #include "queue.h"
7 enum
8 {
9 STACK = 8192
10 };
12 typedef struct VtSconn VtSconn;
13 struct VtSconn
14 {
15 int ctl;
16 int ref;
17 QLock lk;
18 char dir[NETPATHLEN];
19 VtSrv *srv;
20 VtConn *c;
21 };
23 struct VtSrv
24 {
25 int afd;
26 int dead;
27 char adir[NETPATHLEN];
28 Queue *q; /* Queue(VtReq*) */
29 };
31 static void listenproc(void*);
32 static void connproc(void*);
34 char *VtServerLog = "libventi/server";
36 static void
37 scincref(VtSconn *sc)
38 {
39 qlock(&sc->lk);
40 sc->ref++;
41 qunlock(&sc->lk);
42 }
44 static void
45 scdecref(VtSconn *sc)
46 {
47 qlock(&sc->lk);
48 if(--sc->ref > 0){
49 qunlock(&sc->lk);
50 return;
51 }
52 if(sc->c)
53 vtfreeconn(sc->c);
54 vtfree(sc);
55 }
57 VtSrv*
58 vtlisten(char *addr)
59 {
60 VtSrv *s;
62 s = vtmallocz(sizeof(VtSrv));
63 s->afd = announce(addr, s->adir);
64 if(s->afd < 0){
65 free(s);
66 return nil;
67 }
68 s->q = _vtqalloc();
69 proccreate(listenproc, s, STACK);
70 return s;
71 }
73 static void
74 listenproc(void *v)
75 {
76 int ctl;
77 char dir[NETPATHLEN];
78 VtSrv *srv;
79 VtSconn *sc;
81 srv = v;
82 for(;;){
83 ctl = listen(srv->adir, dir);
84 if(ctl < 0){
85 srv->dead = 1;
86 break;
87 }
88 sc = vtmallocz(sizeof(VtSconn));
89 sc->ref = 1;
90 sc->ctl = ctl;
91 sc->srv = srv;
92 strcpy(sc->dir, dir);
93 proccreate(connproc, sc, STACK);
94 }
96 /* hangup */
97 }
99 static void
100 connproc(void *v)
102 VtSconn *sc;
103 VtConn *c;
104 Packet *p;
105 VtReq *r;
106 int fd;
107 static int first=1;
109 if(first && chattyventi){
110 first=0;
111 fmtinstall('F', vtfcallfmt);
113 r = nil;
114 sc = v;
115 sc->c = nil;
116 if(0) fprint(2, "new call %s on %d\n", sc->dir, sc->ctl);
117 fd = accept(sc->ctl, sc->dir);
118 close(sc->ctl);
119 if(fd < 0){
120 fprint(2, "accept %s: %r\n", sc->dir);
121 goto out;
124 c = vtconn(fd, fd);
125 sc->c = c;
126 if(vtversion(c) < 0){
127 fprint(2, "vtversion %s: %r\n", sc->dir);
128 goto out;
130 if(vtsrvhello(c) < 0){
131 fprint(2, "vtsrvhello %s: %r\n", sc->dir);
132 goto out;
135 if(0) fprint(2, "new proc %s\n", sc->dir);
136 proccreate(vtsendproc, c, STACK);
137 qlock(&c->lk);
138 while(!c->writeq)
139 rsleep(&c->rpcfork);
140 qunlock(&c->lk);
142 while((p = vtrecv(c)) != nil){
143 r = vtmallocz(sizeof(VtReq));
144 if(vtfcallunpack(&r->tx, p) < 0){
145 vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv bad packet %p: %r<br>\n", c->addr, p);
146 fprint(2, "bad packet on %s: %r\n", sc->dir);
147 packetfree(p);
148 continue;
150 vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv packet %p (%F)<br>\n", c->addr, p, &r->tx);
151 if(chattyventi)
152 fprint(2, "%s <- %F\n", argv0, &r->tx);
153 packetfree(p);
154 if(r->tx.msgtype == VtTgoodbye)
155 break;
156 r->rx.tag = r->tx.tag;
157 r->sc = sc;
158 scincref(sc);
159 if(_vtqsend(sc->srv->q, r) < 0){
160 scdecref(sc);
161 fprint(2, "hungup queue\n");
162 break;
164 r = nil;
167 if(0) fprint(2, "eof on %s\n", sc->dir);
169 out:
170 if(r){
171 vtfcallclear(&r->tx);
172 vtfree(r);
174 if(0) fprint(2, "freed %s\n", sc->dir);
175 scdecref(sc);
176 return;
179 VtReq*
180 vtgetreq(VtSrv *srv)
182 VtReq *r;
184 r = _vtqrecv(srv->q);
185 if (r != nil)
186 vtlog(VtServerLog, "<font size=-1>%T %s:</font> vtgetreq %F<br>\n", ((VtSconn*)r->sc)->c->addr, &r->tx);
187 return r;
190 void
191 vtrespond(VtReq *r)
193 Packet *p;
194 VtSconn *sc;
196 sc = r->sc;
197 if(r->rx.tag != r->tx.tag)
198 abort();
199 if(r->rx.msgtype != r->tx.msgtype+1 && r->rx.msgtype != VtRerror)
200 abort();
201 if(chattyventi)
202 fprint(2, "%s -> %F\n", argv0, &r->rx);
203 if((p = vtfcallpack(&r->rx)) == nil){
204 vtlog(VtServerLog, "%s: vtfcallpack %F: %r<br>\n", sc->c->addr, &r->rx);
205 fprint(2, "fcallpack on %s: %r\n", sc->dir);
206 packetfree(p);
207 vtfcallclear(&r->rx);
208 return;
210 vtlog(VtServerLog, "<font size=-1>%T %s:</font> send packet %p (%F)<br>\n", sc->c->addr, p, &r->rx);
211 if(vtsend(sc->c, p) < 0)
212 fprint(2, "vtsend %F: %r\n", &r->rx);
213 scdecref(sc);
214 vtfcallclear(&r->tx);
215 vtfcallclear(&r->rx);
216 vtfree(r);