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 (5433B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <ip.h>
            4 #include <thread.h>
            5 #include <sunrpc.h>
            6 
            7 /*
            8  * Sun RPC server; for now, no reply cache
            9  */
           10 
           11 static void sunrpcproc(void*);
           12 static void sunrpcrequestthread(void*);
           13 static void sunrpcreplythread(void*);
           14 static void sunrpcforkthread(void*);
           15 static SunProg *sunfindprog(SunSrv*, SunMsg*, SunRpc*, Channel**);
           16 
           17 typedef struct Targ Targ;
           18 struct Targ
           19 {
           20         void (*fn)(void*);
           21         void *arg;
           22 };
           23 
           24 SunSrv*
           25 sunsrv(void)
           26 {
           27         SunSrv *srv;
           28 
           29         srv = emalloc(sizeof(SunSrv));
           30         srv->chatty = 0;
           31         srv->crequest = chancreate(sizeof(SunMsg*), 16);
           32         srv->creply = chancreate(sizeof(SunMsg*), 16);
           33         srv->cthread = chancreate(sizeof(Targ), 4);
           34 
           35         proccreate(sunrpcproc, srv, SunStackSize);
           36         return srv;
           37 }
           38 
           39 void
           40 sunsrvprog(SunSrv *srv, SunProg *prog, Channel *c)
           41 {
           42         if(srv->nprog%16 == 0){
           43                 srv->prog = erealloc(srv->prog, (srv->nprog+16)*sizeof(srv->prog[0]));
           44                 srv->cdispatch = erealloc(srv->cdispatch, (srv->nprog+16)*sizeof(srv->cdispatch[0]));
           45         }
           46         srv->prog[srv->nprog] = prog;
           47         srv->cdispatch[srv->nprog] = c;
           48         srv->nprog++;
           49 }
           50 
           51 static void
           52 sunrpcproc(void *v)
           53 {
           54         threadcreate(sunrpcreplythread, v, SunStackSize);
           55         threadcreate(sunrpcrequestthread, v, SunStackSize);
           56         threadcreate(sunrpcforkthread, v, SunStackSize);
           57 
           58 }
           59 
           60 static void
           61 sunrpcforkthread(void *v)
           62 {
           63         SunSrv *srv = v;
           64         Targ t;
           65 
           66         while(recv(srv->cthread, &t) == 1)
           67                 threadcreate(t.fn, t.arg, SunStackSize);
           68 }
           69 
           70 void
           71 sunsrvthreadcreate(SunSrv *srv, void (*fn)(void*), void *arg)
           72 {
           73         Targ t;
           74 
           75         t.fn = fn;
           76         t.arg = arg;
           77         send(srv->cthread, &t);
           78 }
           79 
           80 static void
           81 sunrpcrequestthread(void *v)
           82 {
           83         int status;
           84         uchar *p, *ep;
           85         Channel *c;
           86         SunSrv *srv = v;
           87         SunMsg *m;
           88         SunProg *pg;
           89         SunStatus ok;
           90 
           91         while((m = recvp(srv->crequest)) != nil){
           92                 /* could look up in cache here? */
           93 
           94 if(srv->chatty) fprint(2, "sun msg %p count %d\n", m, m->count);
           95                 m->srv = srv;
           96                 p = m->data;
           97                 ep = p+m->count;
           98                 status = m->rpc.status;
           99                 if(sunrpcunpack(p, ep, &p, &m->rpc) != SunSuccess){
          100                         fprint(2, "in: %.*H unpack failed\n", m->count, m->data);
          101                         sunmsgdrop(m);
          102                         continue;
          103                 }
          104                 if(srv->chatty)
          105                         fprint(2, "in: %B\n", &m->rpc);
          106                 if(status){
          107                         sunmsgreplyerror(m, status);
          108                         continue;
          109                 }
          110                 if(srv->alwaysreject){
          111                         if(srv->chatty)
          112                                 fprint(2, "\trejecting\n");
          113                         sunmsgreplyerror(m, SunAuthTooWeak);
          114                         continue;
          115                 }
          116 
          117                 if(!m->rpc.iscall){
          118                         sunmsgreplyerror(m, SunGarbageArgs);
          119                         continue;
          120                 }
          121 
          122                 if((pg = sunfindprog(srv, m, &m->rpc, &c)) == nil){
          123                         /* sunfindprog sent error */
          124                         continue;
          125                 }
          126 
          127                 p = m->rpc.data;
          128                 ep = p+m->rpc.ndata;
          129                 m->call = nil;
          130                 if((ok = suncallunpackalloc(pg, m->rpc.proc<<1, p, ep, &p, &m->call)) != SunSuccess){
          131                         sunmsgreplyerror(m, ok);
          132                         continue;
          133                 }
          134                 m->call->rpc = m->rpc;
          135 
          136                 if(srv->chatty)
          137                         fprint(2, "\t%C\n", m->call);
          138 
          139                 m->pg = pg;
          140                 sendp(c, m);
          141         }
          142 }
          143 
          144 static SunProg*
          145 sunfindprog(SunSrv *srv, SunMsg *m, SunRpc *rpc, Channel **pc)
          146 {
          147         int i, vlo, vhi, any;
          148         SunProg *pg;
          149 
          150         vlo = 0;
          151         vhi = 0;
          152         any = 0;
          153 
          154         for(i=0; i<srv->nprog; i++){
          155                 pg = srv->prog[i];
          156                 if(pg->prog != rpc->prog)
          157                         continue;
          158                 if(pg->vers == rpc->vers){
          159                         *pc = srv->cdispatch[i];
          160                         return pg;
          161                 }
          162                 /* right program, wrong version: record range */
          163                 if(!any++){
          164                         vlo = pg->vers;
          165                         vhi = pg->vers;
          166                 }else{
          167                         if(pg->vers < vlo)
          168                                 vlo = pg->vers;
          169                         if(pg->vers > vhi)
          170                                 vhi = pg->vers;
          171                 }
          172         }
          173         if(vhi == -1){
          174                 if(srv->chatty)
          175                         fprint(2, "\tprogram %ud unavailable\n", rpc->prog);
          176                 sunmsgreplyerror(m, SunProgUnavail);
          177         }else{
          178                 /* putting these in rpc is a botch */
          179                 rpc->low = vlo;
          180                 rpc->high = vhi;
          181                 if(srv->chatty)
          182                         fprint(2, "\tversion %ud unavailable; have %d-%d\n", rpc->vers, vlo, vhi);
          183                 sunmsgreplyerror(m, SunProgMismatch);
          184         }
          185         return nil;
          186 }
          187 
          188 static void
          189 sunrpcreplythread(void *v)
          190 {
          191         SunMsg *m;
          192         SunSrv *srv = v;
          193 
          194         while((m = recvp(srv->creply)) != nil){
          195                 /* could record in cache here? */
          196                 sendp(m->creply, m);
          197         }
          198 }
          199 
          200 int
          201 sunmsgreplyerror(SunMsg *m, SunStatus error)
          202 {
          203         uchar *p, *bp, *ep;
          204         int n;
          205 
          206         m->rpc.status = error;
          207         m->rpc.iscall = 0;
          208         m->rpc.verf.flavor = SunAuthNone;
          209         m->rpc.data = nil;
          210         m->rpc.ndata = 0;
          211 
          212         if(m->srv->chatty)
          213                 fprint(2, "out: %B\n", &m->rpc);
          214 
          215         n = sunrpcsize(&m->rpc);
          216         bp = emalloc(n);
          217         ep = bp+n;
          218         p = bp;
          219         if((int32)sunrpcpack(p, ep, &p, &m->rpc) < 0){
          220                 fprint(2, "sunrpcpack failed\n");
          221                 sunmsgdrop(m);
          222                 return 0;
          223         }
          224         if(p != ep){
          225                 fprint(2, "sunmsgreplyerror: rpc sizes didn't work out\n");
          226                 sunmsgdrop(m);
          227                 return 0;
          228         }
          229         free(m->data);
          230         m->data = bp;
          231         m->count = n;
          232         sendp(m->srv->creply, m);
          233         return 0;
          234 }
          235 
          236 int
          237 sunmsgreply(SunMsg *m, SunCall *c)
          238 {
          239         int n1, n2;
          240         uchar *bp, *p, *ep;
          241 
          242         c->type = m->call->type+1;
          243         c->rpc.iscall = 0;
          244         c->rpc.prog = m->rpc.prog;
          245         c->rpc.vers = m->rpc.vers;
          246         c->rpc.proc = m->rpc.proc;
          247         c->rpc.xid = m->rpc.xid;
          248 
          249         if(m->srv->chatty){
          250                 fprint(2, "out: %B\n", &c->rpc);
          251                 fprint(2, "\t%C\n", c);
          252         }
          253 
          254         n1 = sunrpcsize(&c->rpc);
          255         n2 = suncallsize(m->pg, c);
          256 
          257         bp = emalloc(n1+n2);
          258         ep = bp+n1+n2;
          259         p = bp;
          260         if(sunrpcpack(p, ep, &p, &c->rpc) != SunSuccess){
          261                 fprint(2, "sunrpcpack failed\n");
          262                 return sunmsgdrop(m);
          263         }
          264         if(suncallpack(m->pg, p, ep, &p, c) != SunSuccess){
          265                 fprint(2, "pg->pack failed\n");
          266                 return sunmsgdrop(m);
          267         }
          268         if(p != ep){
          269                 fprint(2, "sunmsgreply: sizes didn't work out\n");
          270                 return sunmsgdrop(m);
          271         }
          272         free(m->data);
          273         m->data = bp;
          274         m->count = n1+n2;
          275 
          276         sendp(m->srv->creply, m);
          277         return 0;
          278 }
          279 
          280 int
          281 sunmsgdrop(SunMsg *m)
          282 {
          283         free(m->data);
          284         free(m->call);
          285         memset(m, 0xFB, sizeof *m);
          286         free(m);
          287         return 0;
          288 }