static int tagmuxrpc(Muxrpc *r, void *tx) { int tag; Mux *mux; mux = r->mux; /* assign the tag, add selves to response queue */ qlock(&mux->lk); tag = gettag(mux, r); /*print("gettag %p %d\n", r, tag); */ enqueue(mux, r); qunlock(&mux->lk); /* actually send the packet */ if(tag < 0 || mux->settag(mux, tx, tag) < 0 || _muxsend(mux, tx) < 0){ werrstr("settag/send tag %d: %r", tag); fprint(2, "%r\n"); qlock(&mux->lk); dequeue(mux, r); puttag(mux, r); qunlock(&mux->lk); return -1; } return 0; }
int muxrpccanfinish(Muxrpc *r, void **vp) { void *p; Mux *mux; int ret; mux = r->mux; qlock(&mux->lk); ret = 1; if(!r->p && !mux->muxer){ mux->muxer = r; while(!r->p){ qunlock(&mux->lk); p = nil; if(!_muxrecv(mux, 0, &p)) ret = 0; if(p == nil){ qlock(&mux->lk); break; } muxmsgandqlock(mux, p); } electmuxer(mux); } p = r->p; if(p) puttag(mux, r); qunlock(&mux->lk); *vp = p; return ret; }
void* muxrpc(Mux *mux, void *tx) { int tag; Muxrpc *r; void *p; if((r = allocmuxrpc(mux)) == nil) return nil; if((tag = tagmuxrpc(r, tx)) < 0) return nil; qlock(&mux->lk); /* wait for our packet */ while(mux->muxer && mux->muxer != r && !r->p) rsleep(&r->r); /* if not done, there's no muxer: start muxing */ if(!r->p){ if(mux->muxer != nil && mux->muxer != r) abort(); mux->muxer = r; while(!r->p){ qunlock(&mux->lk); _muxrecv(mux, 1, &p); if(p == nil){ /* eof -- just give up and pass the buck */ qlock(&mux->lk); dequeue(mux, r); break; } muxmsgandqlock(mux, p); } electmuxer(mux); } p = r->p; puttag(mux, r); qunlock(&mux->lk); if(p == nil) werrstr("unexpected eof"); return p; }
Packet* _vtrpc(VtConn *z, Packet *p, VtFcall *tx) { int i; uchar tag, buf[2], *top; Rwait *r, *rr; /* must malloc because stack could be private */ r = vtmallocz(sizeof(Rwait)); qlock(&z->lk); r->r.l = &z->lk; tag = gettag(z, r); if(tx){ /* vtfcallrpc can't print packet because it doesn't have tag */ tx->tag = tag; if(chattyventi) fprint(2, "%s -> %F\n", argv0, tx); } /* slam tag into packet */ top = packetpeek(p, buf, 0, 2); if(top == nil){ packetfree(p); return nil; } if(top == buf){ werrstr("first two bytes must be in same packet fragment"); packetfree(p); vtfree(r); return nil; } top[1] = tag; qunlock(&z->lk); if(vtsend(z, p) < 0){ vtfree(r); return nil; } qlock(&z->lk); /* wait for the muxer to give us our packet */ r->sleeping = 1; z->nsleep++; while(z->muxer && !r->done) rsleep(&r->r); z->nsleep--; r->sleeping = 0; /* if not done, there's no muxer: start muxing */ if(!r->done){ if(z->muxer) abort(); z->muxer = 1; while(!r->done){ qunlock(&z->lk); if((p = vtrecv(z)) == nil){ werrstr("unexpected eof on venti connection"); z->muxer = 0; vtfree(r); return nil; } qlock(&z->lk); muxrpc(z, p); } z->muxer = 0; /* if there is anyone else sleeping, wake first unfinished to mux */ if(z->nsleep) for(i=0; i<256; i++){ rr = z->wait[i]; if(rr && rr->sleeping && !rr->done){ rwakeup(&rr->r); break; } } } p = r->p; puttag(z, r, tag); vtfree(r); qunlock(&z->lk); return p; }