URI:
       tserver.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tserver.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 }