server.c (3747B)
1 #include <u.h> 2 #include <libc.h> 3 #include <venti.h> 4 #include <thread.h> 5 #include "queue.h" 6 7 enum 8 { 9 STACK = 8192 10 }; 11 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 }; 22 23 struct VtSrv 24 { 25 int afd; 26 int dead; 27 char adir[NETPATHLEN]; 28 Queue *q; /* Queue(VtReq*) */ 29 }; 30 31 static void listenproc(void*); 32 static void connproc(void*); 33 34 char *VtServerLog = "libventi/server"; 35 36 static void 37 scincref(VtSconn *sc) 38 { 39 qlock(&sc->lk); 40 sc->ref++; 41 qunlock(&sc->lk); 42 } 43 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 } 56 57 VtSrv* 58 vtlisten(char *addr) 59 { 60 VtSrv *s; 61 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 } 72 73 static void 74 listenproc(void *v) 75 { 76 int ctl; 77 char dir[NETPATHLEN]; 78 VtSrv *srv; 79 VtSconn *sc; 80 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 } 95 96 /* hangup */ 97 } 98 99 static void 100 connproc(void *v) 101 { 102 VtSconn *sc; 103 VtConn *c; 104 Packet *p; 105 VtReq *r; 106 int fd; 107 static int first=1; 108 109 if(first && chattyventi){ 110 first=0; 111 fmtinstall('F', vtfcallfmt); 112 } 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; 122 } 123 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; 129 } 130 if(vtsrvhello(c) < 0){ 131 fprint(2, "vtsrvhello %s: %r\n", sc->dir); 132 goto out; 133 } 134 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); 141 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; 149 } 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; 163 } 164 r = nil; 165 } 166 167 if(0) fprint(2, "eof on %s\n", sc->dir); 168 169 out: 170 if(r){ 171 vtfcallclear(&r->tx); 172 vtfree(r); 173 } 174 if(0) fprint(2, "freed %s\n", sc->dir); 175 scdecref(sc); 176 return; 177 } 178 179 VtReq* 180 vtgetreq(VtSrv *srv) 181 { 182 VtReq *r; 183 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; 188 } 189 190 void 191 vtrespond(VtReq *r) 192 { 193 Packet *p; 194 VtSconn *sc; 195 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; 209 } 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); 217 }