134e04225SDavid du Colombier /* 234e04225SDavid du Colombier * Sun RPC client. 334e04225SDavid du Colombier */ 434e04225SDavid du Colombier #include <u.h> 534e04225SDavid du Colombier #include <libc.h> 634e04225SDavid du Colombier #include <thread.h> 734e04225SDavid du Colombier #include <sunrpc.h> 834e04225SDavid du Colombier 934e04225SDavid du Colombier typedef struct Out Out; 1034e04225SDavid du Colombier struct Out 1134e04225SDavid du Colombier { 1234e04225SDavid du Colombier char err[ERRMAX]; /* error string */ 1334e04225SDavid du Colombier Channel *creply; /* send to finish rpc */ 1434e04225SDavid du Colombier uchar *p; /* pending request packet */ 1534e04225SDavid du Colombier int n; /* size of request */ 1634e04225SDavid du Colombier ulong tag; /* flush tag of pending request */ 1734e04225SDavid du Colombier ulong xid; /* xid of pending request */ 1834e04225SDavid du Colombier ulong st; /* first send time */ 1934e04225SDavid du Colombier ulong t; /* resend time */ 2034e04225SDavid du Colombier int nresend; /* number of resends */ 2134e04225SDavid du Colombier SunRpc rpc; /* response rpc */ 2234e04225SDavid du Colombier }; 2334e04225SDavid du Colombier 2434e04225SDavid du Colombier static void 2534e04225SDavid du Colombier udpThread(void *v) 2634e04225SDavid du Colombier { 2734e04225SDavid du Colombier uchar *p, *buf; 2834e04225SDavid du Colombier Ioproc *io; 2934e04225SDavid du Colombier int n; 3034e04225SDavid du Colombier SunClient *cli; 3134e04225SDavid du Colombier enum { BufSize = 65536 }; 3234e04225SDavid du Colombier 3334e04225SDavid du Colombier cli = v; 3434e04225SDavid du Colombier buf = emalloc(BufSize); 3534e04225SDavid du Colombier io = ioproc(); 3634e04225SDavid du Colombier p = nil; 3734e04225SDavid du Colombier for(;;){ 3834e04225SDavid du Colombier n = ioread(io, cli->fd, buf, BufSize); 3934e04225SDavid du Colombier if(n <= 0) 4034e04225SDavid du Colombier break; 4134e04225SDavid du Colombier p = emalloc(4+n); 4234e04225SDavid du Colombier memmove(p+4, buf, n); 4334e04225SDavid du Colombier p[0] = n>>24; 4434e04225SDavid du Colombier p[1] = n>>16; 4534e04225SDavid du Colombier p[2] = n>>8; 4634e04225SDavid du Colombier p[3] = n; 4734e04225SDavid du Colombier if(sendp(cli->readchan, p) == 0) 4834e04225SDavid du Colombier break; 4934e04225SDavid du Colombier p = nil; 5034e04225SDavid du Colombier } 5134e04225SDavid du Colombier free(p); 5234e04225SDavid du Colombier closeioproc(io); 5334e04225SDavid du Colombier while(send(cli->dying, nil) == -1) 5434e04225SDavid du Colombier ; 5534e04225SDavid du Colombier } 5634e04225SDavid du Colombier 5734e04225SDavid du Colombier static void 5834e04225SDavid du Colombier netThread(void *v) 5934e04225SDavid du Colombier { 6034e04225SDavid du Colombier uchar *p, buf[4]; 6134e04225SDavid du Colombier Ioproc *io; 6234e04225SDavid du Colombier uint n, tot; 6334e04225SDavid du Colombier int done; 6434e04225SDavid du Colombier SunClient *cli; 6534e04225SDavid du Colombier 6634e04225SDavid du Colombier cli = v; 6734e04225SDavid du Colombier io = ioproc(); 6834e04225SDavid du Colombier tot = 0; 6934e04225SDavid du Colombier p = nil; 7034e04225SDavid du Colombier for(;;){ 7134e04225SDavid du Colombier n = ioreadn(io, cli->fd, buf, 4); 7234e04225SDavid du Colombier if(n != 4) 7334e04225SDavid du Colombier break; 7434e04225SDavid du Colombier n = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; 7534e04225SDavid du Colombier if(cli->chatty) 7634e04225SDavid du Colombier fprint(2, "%.8ux...", n); 7734e04225SDavid du Colombier done = n&0x80000000; 7834e04225SDavid du Colombier n &= ~0x80000000; 7934e04225SDavid du Colombier if(tot == 0){ 8034e04225SDavid du Colombier p = emalloc(4+n); 8134e04225SDavid du Colombier tot = 4; 8234e04225SDavid du Colombier }else 8334e04225SDavid du Colombier p = erealloc(p, tot+n); 8434e04225SDavid du Colombier if(ioreadn(io, cli->fd, p+tot, n) != n) 8534e04225SDavid du Colombier break; 8634e04225SDavid du Colombier tot += n; 8734e04225SDavid du Colombier if(done){ 8834e04225SDavid du Colombier p[0] = tot>>24; 8934e04225SDavid du Colombier p[1] = tot>>16; 9034e04225SDavid du Colombier p[2] = tot>>8; 9134e04225SDavid du Colombier p[3] = tot; 9234e04225SDavid du Colombier if(sendp(cli->readchan, p) == 0) 9334e04225SDavid du Colombier break; 9434e04225SDavid du Colombier p = nil; 9534e04225SDavid du Colombier tot = 0; 9634e04225SDavid du Colombier } 9734e04225SDavid du Colombier } 9834e04225SDavid du Colombier free(p); 9934e04225SDavid du Colombier closeioproc(io); 10034e04225SDavid du Colombier while(send(cli->dying, 0) == -1) 10134e04225SDavid du Colombier ; 10234e04225SDavid du Colombier } 10334e04225SDavid du Colombier 10434e04225SDavid du Colombier static void 10534e04225SDavid du Colombier timerThread(void *v) 10634e04225SDavid du Colombier { 10734e04225SDavid du Colombier Ioproc *io; 10834e04225SDavid du Colombier SunClient *cli; 10934e04225SDavid du Colombier 11034e04225SDavid du Colombier cli = v; 11134e04225SDavid du Colombier io = ioproc(); 11234e04225SDavid du Colombier for(;;){ 11334e04225SDavid du Colombier if(iosleep(io, 200) < 0) 11434e04225SDavid du Colombier break; 11534e04225SDavid du Colombier if(sendul(cli->timerchan, 0) == 0) 11634e04225SDavid du Colombier break; 11734e04225SDavid du Colombier } 11834e04225SDavid du Colombier closeioproc(io); 11934e04225SDavid du Colombier while(send(cli->dying, 0) == -1) 12034e04225SDavid du Colombier ; 12134e04225SDavid du Colombier } 12234e04225SDavid du Colombier 12334e04225SDavid du Colombier static ulong 12434e04225SDavid du Colombier msec(void) 12534e04225SDavid du Colombier { 12634e04225SDavid du Colombier return nsec()/1000000; 12734e04225SDavid du Colombier } 12834e04225SDavid du Colombier 12934e04225SDavid du Colombier static ulong 13034e04225SDavid du Colombier twait(ulong rtt, int nresend) 13134e04225SDavid du Colombier { 13234e04225SDavid du Colombier ulong t; 13334e04225SDavid du Colombier 13434e04225SDavid du Colombier t = rtt; 13534e04225SDavid du Colombier if(nresend <= 1) 13634e04225SDavid du Colombier {} 13734e04225SDavid du Colombier else if(nresend <= 3) 13834e04225SDavid du Colombier t *= 2; 13934e04225SDavid du Colombier else if(nresend <= 18) 14034e04225SDavid du Colombier t <<= nresend-2; 14134e04225SDavid du Colombier else 14234e04225SDavid du Colombier t = 60*1000; 14334e04225SDavid du Colombier if(t > 60*1000) 14434e04225SDavid du Colombier t = 60*1000; 14534e04225SDavid du Colombier 14634e04225SDavid du Colombier return t; 14734e04225SDavid du Colombier } 14834e04225SDavid du Colombier 14934e04225SDavid du Colombier static void 15034e04225SDavid du Colombier rpcMuxThread(void *v) 15134e04225SDavid du Colombier { 15234e04225SDavid du Colombier uchar *buf, *p, *ep; 15334e04225SDavid du Colombier int i, n, nout, mout; 15434e04225SDavid du Colombier ulong t, xidgen, tag; 15534e04225SDavid du Colombier Alt a[5]; 15634e04225SDavid du Colombier Out *o, **out; 15734e04225SDavid du Colombier SunRpc rpc; 15834e04225SDavid du Colombier SunClient *cli; 15934e04225SDavid du Colombier 16034e04225SDavid du Colombier cli = v; 16134e04225SDavid du Colombier mout = 16; 16234e04225SDavid du Colombier nout = 0; 16334e04225SDavid du Colombier out = emalloc(mout*sizeof(out[0])); 16434e04225SDavid du Colombier xidgen = truerand(); 16534e04225SDavid du Colombier 16634e04225SDavid du Colombier a[0].op = CHANRCV; 16734e04225SDavid du Colombier a[0].c = cli->rpcchan; 16834e04225SDavid du Colombier a[0].v = &o; 16934e04225SDavid du Colombier a[1].op = CHANNOP; 17034e04225SDavid du Colombier a[1].c = cli->timerchan; 17134e04225SDavid du Colombier a[1].v = nil; 17234e04225SDavid du Colombier a[2].op = CHANRCV; 17334e04225SDavid du Colombier a[2].c = cli->flushchan; 17434e04225SDavid du Colombier a[2].v = &tag; 17534e04225SDavid du Colombier a[3].op = CHANRCV; 17634e04225SDavid du Colombier a[3].c = cli->readchan; 17734e04225SDavid du Colombier a[3].v = &buf; 17834e04225SDavid du Colombier a[4].op = CHANEND; 17934e04225SDavid du Colombier 18034e04225SDavid du Colombier for(;;){ 18134e04225SDavid du Colombier switch(alt(a)){ 18234e04225SDavid du Colombier case 0: /* rpcchan */ 18334e04225SDavid du Colombier if(o == nil) 18434e04225SDavid du Colombier goto Done; 18534e04225SDavid du Colombier cli->nsend++; 18634e04225SDavid du Colombier /* set xid */ 18734e04225SDavid du Colombier o->xid = ++xidgen; 18834e04225SDavid du Colombier if(cli->needcount) 18934e04225SDavid du Colombier p = o->p+4; 19034e04225SDavid du Colombier else 19134e04225SDavid du Colombier p = o->p; 19234e04225SDavid du Colombier p[0] = xidgen>>24; 19334e04225SDavid du Colombier p[1] = xidgen>>16; 19434e04225SDavid du Colombier p[2] = xidgen>>8; 19534e04225SDavid du Colombier p[3] = xidgen; 19634e04225SDavid du Colombier if(write(cli->fd, o->p, o->n) != o->n){ 19734e04225SDavid du Colombier free(o->p); 19834e04225SDavid du Colombier o->p = nil; 19934e04225SDavid du Colombier snprint(o->err, sizeof o->err, "write: %r"); 20034e04225SDavid du Colombier sendp(o->creply, 0); 20134e04225SDavid du Colombier break; 20234e04225SDavid du Colombier } 20334e04225SDavid du Colombier if(nout >= mout){ 20434e04225SDavid du Colombier mout *= 2; 20534e04225SDavid du Colombier out = erealloc(out, mout*sizeof(out[0])); 20634e04225SDavid du Colombier } 20734e04225SDavid du Colombier o->st = msec(); 20834e04225SDavid du Colombier o->nresend = 0; 20934e04225SDavid du Colombier o->t = o->st + twait(cli->rtt.avg, 0); 21034e04225SDavid du Colombier if(cli->chatty) print("send %lux %lud %lud\n", o->xid, o->st, o->t); 21134e04225SDavid du Colombier out[nout++] = o; 21234e04225SDavid du Colombier a[1].op = CHANRCV; 21334e04225SDavid du Colombier break; 21434e04225SDavid du Colombier 21534e04225SDavid du Colombier case 1: /* timerchan */ 21634e04225SDavid du Colombier t = msec(); 21734e04225SDavid du Colombier for(i=0; i<nout; i++){ 21834e04225SDavid du Colombier o = out[i]; 21934e04225SDavid du Colombier if((int)(t - o->t) > 0){ 22034e04225SDavid du Colombier if(cli->chatty) print("resend %lux %lud %lud\n", o->xid, t, o->t); 22134e04225SDavid du Colombier if(cli->maxwait && t - o->st >= cli->maxwait){ 22234e04225SDavid du Colombier free(o->p); 22334e04225SDavid du Colombier o->p = nil; 22434e04225SDavid du Colombier strcpy(o->err, "timeout"); 22534e04225SDavid du Colombier sendp(o->creply, 0); 22634e04225SDavid du Colombier out[i--] = out[--nout]; 22734e04225SDavid du Colombier continue; 22834e04225SDavid du Colombier } 22934e04225SDavid du Colombier cli->nresend++; 23034e04225SDavid du Colombier o->nresend++; 23134e04225SDavid du Colombier o->t = t + twait(cli->rtt.avg, o->nresend); 23234e04225SDavid du Colombier if(write(cli->fd, o->p, o->n) != o->n){ 23334e04225SDavid du Colombier free(o->p); 23434e04225SDavid du Colombier o->p = nil; 23534e04225SDavid du Colombier snprint(o->err, sizeof o->err, "rewrite: %r"); 23634e04225SDavid du Colombier sendp(o->creply, 0); 23734e04225SDavid du Colombier out[i--] = out[--nout]; 23834e04225SDavid du Colombier continue; 23934e04225SDavid du Colombier } 24034e04225SDavid du Colombier } 24134e04225SDavid du Colombier } 24234e04225SDavid du Colombier /* stop ticking if no work; rpcchan will turn it back on */ 24334e04225SDavid du Colombier if(nout == 0) 24434e04225SDavid du Colombier a[1].op = CHANNOP; 24534e04225SDavid du Colombier break; 24634e04225SDavid du Colombier 24734e04225SDavid du Colombier case 2: /* flushchan */ 24834e04225SDavid du Colombier for(i=0; i<nout; i++){ 24934e04225SDavid du Colombier o = out[i]; 25034e04225SDavid du Colombier if(o->tag == tag){ 25134e04225SDavid du Colombier o[i--] = o[--nout]; 25234e04225SDavid du Colombier strcpy(o->err, "flushed"); 25334e04225SDavid du Colombier free(o->p); 25434e04225SDavid du Colombier o->p = nil; 25534e04225SDavid du Colombier sendp(o->creply, 0); 25634e04225SDavid du Colombier } 25734e04225SDavid du Colombier } 25834e04225SDavid du Colombier break; 25934e04225SDavid du Colombier 26034e04225SDavid du Colombier case 3: /* readchan */ 26134e04225SDavid du Colombier p = buf; 26234e04225SDavid du Colombier n = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; 26334e04225SDavid du Colombier p += 4; 26434e04225SDavid du Colombier ep = p+n; 26534e04225SDavid du Colombier if(sunRpcUnpack(p, ep, &p, &rpc) < 0){ 26634e04225SDavid du Colombier print("in: %.*H unpack failed\n", n, buf+4); 26734e04225SDavid du Colombier free(buf); 26834e04225SDavid du Colombier break; 26934e04225SDavid du Colombier } 27034e04225SDavid du Colombier if(cli->chatty) 27134e04225SDavid du Colombier print("in: %B\n", &rpc); 27234e04225SDavid du Colombier if(rpc.iscall){ 27334e04225SDavid du Colombier print("did not get reply\n"); 27434e04225SDavid du Colombier free(buf); 27534e04225SDavid du Colombier break; 27634e04225SDavid du Colombier } 27734e04225SDavid du Colombier for(i=0; i<nout; i++) 27834e04225SDavid du Colombier if(o->xid == rpc.xid) 27934e04225SDavid du Colombier break; 28034e04225SDavid du Colombier if(i==nout){ 28134e04225SDavid du Colombier if(cli->chatty) print("did not find waiting request\n"); 28234e04225SDavid du Colombier free(buf); 28334e04225SDavid du Colombier break; 28434e04225SDavid du Colombier } 28534e04225SDavid du Colombier out[i] = out[--nout]; 28634e04225SDavid du Colombier free(o->p); 287*62ec5179SDavid du Colombier o->p = nil; 28834e04225SDavid du Colombier if(rpc.status == SunSuccess){ 28934e04225SDavid du Colombier o->p = buf; 29034e04225SDavid du Colombier o->rpc = rpc; 29134e04225SDavid du Colombier }else{ 29234e04225SDavid du Colombier o->p = nil; 29334e04225SDavid du Colombier free(buf); 29434e04225SDavid du Colombier sunErrstr(rpc.status); 29534e04225SDavid du Colombier rerrstr(o->err, sizeof o->err); 29634e04225SDavid du Colombier } 29734e04225SDavid du Colombier sendp(o->creply, 0); 29834e04225SDavid du Colombier break; 29934e04225SDavid du Colombier } 30034e04225SDavid du Colombier } 30134e04225SDavid du Colombier Done: 30234e04225SDavid du Colombier free(out); 30334e04225SDavid du Colombier sendp(cli->dying, 0); 30434e04225SDavid du Colombier } 30534e04225SDavid du Colombier 30634e04225SDavid du Colombier SunClient* 30734e04225SDavid du Colombier sunDial(char *address) 30834e04225SDavid du Colombier { 30934e04225SDavid du Colombier int fd; 31034e04225SDavid du Colombier SunClient *cli; 31134e04225SDavid du Colombier 31234e04225SDavid du Colombier if((fd = dial(address, 0, 0, 0)) < 0) 31334e04225SDavid du Colombier return nil; 31434e04225SDavid du Colombier 31534e04225SDavid du Colombier cli = emalloc(sizeof(SunClient)); 31634e04225SDavid du Colombier cli->fd = fd; 31734e04225SDavid du Colombier cli->maxwait = 15000; 31834e04225SDavid du Colombier cli->rtt.avg = 1000; 31934e04225SDavid du Colombier cli->dying = chancreate(sizeof(void*), 0); 32034e04225SDavid du Colombier cli->rpcchan = chancreate(sizeof(Out*), 0); 32134e04225SDavid du Colombier cli->timerchan = chancreate(sizeof(ulong), 0); 32234e04225SDavid du Colombier cli->flushchan = chancreate(sizeof(ulong), 0); 32334e04225SDavid du Colombier cli->readchan = chancreate(sizeof(uchar*), 0); 32434e04225SDavid du Colombier if(strstr(address, "udp!")){ 32534e04225SDavid du Colombier cli->needcount = 0; 32634e04225SDavid du Colombier cli->nettid = threadcreate(udpThread, cli, SunStackSize); 32734e04225SDavid du Colombier cli->timertid = threadcreate(timerThread, cli, SunStackSize); 32834e04225SDavid du Colombier }else{ 32934e04225SDavid du Colombier cli->needcount = 1; 33034e04225SDavid du Colombier cli->nettid = threadcreate(netThread, cli, SunStackSize); 33134e04225SDavid du Colombier /* assume reliable: don't need timer */ 33234e04225SDavid du Colombier /* BUG: netThread should know how to redial */ 33334e04225SDavid du Colombier } 33434e04225SDavid du Colombier threadcreate(rpcMuxThread, cli, SunStackSize); 33534e04225SDavid du Colombier 33634e04225SDavid du Colombier return cli; 33734e04225SDavid du Colombier } 33834e04225SDavid du Colombier 33934e04225SDavid du Colombier void 34034e04225SDavid du Colombier sunClientClose(SunClient *cli) 34134e04225SDavid du Colombier { 34234e04225SDavid du Colombier int n; 34334e04225SDavid du Colombier 34434e04225SDavid du Colombier /* 34534e04225SDavid du Colombier * Threadints get you out of any stuck system calls 34634e04225SDavid du Colombier * or thread rendezvouses, but do nothing if the thread 34734e04225SDavid du Colombier * is in the ready state. Keep interrupting until it takes. 34834e04225SDavid du Colombier */ 34934e04225SDavid du Colombier n = 0; 35034e04225SDavid du Colombier if(!cli->timertid) 35134e04225SDavid du Colombier n++; 35234e04225SDavid du Colombier while(n < 2){ 35334e04225SDavid du Colombier threadint(cli->nettid); 35434e04225SDavid du Colombier if(cli->timertid) 35534e04225SDavid du Colombier threadint(cli->timertid); 35634e04225SDavid du Colombier yield(); 35734e04225SDavid du Colombier while(nbrecv(cli->dying, nil) == 1) 35834e04225SDavid du Colombier n++; 35934e04225SDavid du Colombier } 36034e04225SDavid du Colombier 36134e04225SDavid du Colombier sendp(cli->rpcchan, 0); 36234e04225SDavid du Colombier recvp(cli->dying); 36334e04225SDavid du Colombier 36434e04225SDavid du Colombier /* everyone's gone: clean up */ 36534e04225SDavid du Colombier close(cli->fd); 36634e04225SDavid du Colombier chanfree(cli->flushchan); 36734e04225SDavid du Colombier chanfree(cli->readchan); 36834e04225SDavid du Colombier chanfree(cli->timerchan); 36934e04225SDavid du Colombier free(cli); 37034e04225SDavid du Colombier } 37134e04225SDavid du Colombier 37234e04225SDavid du Colombier void 37334e04225SDavid du Colombier sunClientFlushRpc(SunClient *cli, ulong tag) 37434e04225SDavid du Colombier { 37534e04225SDavid du Colombier sendul(cli->flushchan, tag); 37634e04225SDavid du Colombier } 37734e04225SDavid du Colombier 37834e04225SDavid du Colombier void 37934e04225SDavid du Colombier sunClientProg(SunClient *cli, SunProg *p) 38034e04225SDavid du Colombier { 38134e04225SDavid du Colombier if(cli->nprog%16 == 0) 38234e04225SDavid du Colombier cli->prog = erealloc(cli->prog, (cli->nprog+16)*sizeof(cli->prog[0])); 38334e04225SDavid du Colombier cli->prog[cli->nprog++] = p; 38434e04225SDavid du Colombier } 38534e04225SDavid du Colombier 38634e04225SDavid du Colombier int 38734e04225SDavid du Colombier sunClientRpc(SunClient *cli, ulong tag, SunCall *tx, SunCall *rx, uchar **tofree) 38834e04225SDavid du Colombier { 38934e04225SDavid du Colombier uchar *bp, *p, *ep; 39034e04225SDavid du Colombier int i, n1, n2, n, nn; 39134e04225SDavid du Colombier Out o; 39234e04225SDavid du Colombier SunProg *prog; 39334e04225SDavid du Colombier SunStatus ok; 39434e04225SDavid du Colombier 39534e04225SDavid du Colombier for(i=0; i<cli->nprog; i++) 39634e04225SDavid du Colombier if(cli->prog[i]->prog == tx->rpc.prog && cli->prog[i]->vers == tx->rpc.vers) 39734e04225SDavid du Colombier break; 39834e04225SDavid du Colombier if(i==cli->nprog){ 39934e04225SDavid du Colombier werrstr("unknown sun rpc program %d version %d", tx->rpc.prog, tx->rpc.vers); 40034e04225SDavid du Colombier return -1; 40134e04225SDavid du Colombier } 40234e04225SDavid du Colombier prog = cli->prog[i]; 40334e04225SDavid du Colombier 40434e04225SDavid du Colombier if(cli->chatty){ 40534e04225SDavid du Colombier print("out: %B\n", &tx->rpc); 40634e04225SDavid du Colombier print("\t%C\n", tx); 40734e04225SDavid du Colombier } 40834e04225SDavid du Colombier 40934e04225SDavid du Colombier n1 = sunRpcSize(&tx->rpc); 41034e04225SDavid du Colombier n2 = sunCallSize(prog, tx); 41134e04225SDavid du Colombier 41234e04225SDavid du Colombier n = n1+n2; 41334e04225SDavid du Colombier if(cli->needcount) 41434e04225SDavid du Colombier n += 4; 41534e04225SDavid du Colombier 41634e04225SDavid du Colombier bp = emalloc(n); 41734e04225SDavid du Colombier ep = bp+n; 41834e04225SDavid du Colombier p = bp; 41934e04225SDavid du Colombier if(cli->needcount){ 42034e04225SDavid du Colombier nn = n-4; 42134e04225SDavid du Colombier p[0] = (nn>>24)|0x80; 42234e04225SDavid du Colombier p[1] = nn>>16; 42334e04225SDavid du Colombier p[2] = nn>>8; 42434e04225SDavid du Colombier p[3] = nn; 42534e04225SDavid du Colombier p += 4; 42634e04225SDavid du Colombier } 42734e04225SDavid du Colombier if((ok = sunRpcPack(p, ep, &p, &tx->rpc)) != SunSuccess 42834e04225SDavid du Colombier || (ok = sunCallPack(prog, p, ep, &p, tx)) != SunSuccess){ 42934e04225SDavid du Colombier sunErrstr(ok); 43034e04225SDavid du Colombier free(bp); 43134e04225SDavid du Colombier return -1; 43234e04225SDavid du Colombier } 43334e04225SDavid du Colombier if(p != ep){ 43434e04225SDavid du Colombier werrstr("rpc: packet size mismatch"); 43534e04225SDavid du Colombier free(bp); 43634e04225SDavid du Colombier return -1; 43734e04225SDavid du Colombier } 43834e04225SDavid du Colombier 43934e04225SDavid du Colombier memset(&o, 0, sizeof o); 44034e04225SDavid du Colombier o.creply = chancreate(sizeof(void*), 0); 44134e04225SDavid du Colombier o.tag = tag; 44234e04225SDavid du Colombier o.p = bp; 44334e04225SDavid du Colombier o.n = n; 44434e04225SDavid du Colombier 44534e04225SDavid du Colombier sendp(cli->rpcchan, &o); 44634e04225SDavid du Colombier recvp(o.creply); 44734e04225SDavid du Colombier chanfree(o.creply); 44834e04225SDavid du Colombier 44934e04225SDavid du Colombier if(o.p == nil){ 45034e04225SDavid du Colombier werrstr("%s", o.err); 45134e04225SDavid du Colombier return -1; 45234e04225SDavid du Colombier } 45334e04225SDavid du Colombier 45434e04225SDavid du Colombier p = o.rpc.data; 45534e04225SDavid du Colombier ep = p+o.rpc.ndata; 45634e04225SDavid du Colombier rx->rpc = o.rpc; 45734e04225SDavid du Colombier rx->rpc.proc = tx->rpc.proc; 45834e04225SDavid du Colombier rx->rpc.prog = tx->rpc.prog; 45934e04225SDavid du Colombier rx->rpc.vers = tx->rpc.vers; 46034e04225SDavid du Colombier rx->type = (rx->rpc.proc<<1)|1; 46134e04225SDavid du Colombier if((ok = sunCallUnpack(prog, p, ep, &p, rx)) != SunSuccess){ 46234e04225SDavid du Colombier sunErrstr(ok); 46334e04225SDavid du Colombier werrstr("unpack: %r"); 46434e04225SDavid du Colombier free(o.p); 46534e04225SDavid du Colombier return -1; 46634e04225SDavid du Colombier } 46734e04225SDavid du Colombier 46834e04225SDavid du Colombier if(cli->chatty){ 46934e04225SDavid du Colombier print("in: %B\n", &rx->rpc); 47034e04225SDavid du Colombier print("in:\t%C\n", rx); 47134e04225SDavid du Colombier } 47234e04225SDavid du Colombier 47334e04225SDavid du Colombier if(tofree) 47434e04225SDavid du Colombier *tofree = o.p; 47534e04225SDavid du Colombier else 47634e04225SDavid du Colombier free(o.p); 47734e04225SDavid du Colombier 47834e04225SDavid du Colombier return 0; 47934e04225SDavid du Colombier } 480