2 * Multiplexed Venti client. It would be nice if we
3 * could turn this into a generic library routine rather
4 * than keep it Venti specific. A user-level 9P client
5 * could use something like this too.
7 * This is a little more complicated than it might be
8 * because we want it to work well within and without libthread.
10 * The mux code is inspired by tra's, which is inspired by the Plan 9 kernel.
17 typedef struct Rwait Rwait;
26 static int gettag(VtConn*, Rwait*);
27 static void puttag(VtConn*, Rwait*, int);
28 static void muxrpc(VtConn*, Packet*);
29 Packet *vtrpc(VtConn*, Packet*);
32 vtrpc(VtConn *z, Packet *p)
35 uchar tag, buf[2], *top;
38 /* must malloc because stack could be private */
39 r = vtmallocz(sizeof(Rwait));
45 /* slam tag into packet */
46 top = packetpeek(p, buf, 0, 2);
52 werrstr("first two bytes must be in same packet fragment");
62 /* wait for the muxer to give us our packet */
65 while(z->muxer && !r->done)
70 /* if not done, there's no muxer: start muxing */
77 if((p = vtrecv(z)) == nil){
85 /* if there is anyone else sleeping, wake them to mux */
88 if(z->wait[i] != nil && ((Rwait*)z->wait[i])->sleeping)
91 fprint(2, "libventi: nsleep botch\n");
93 rwakeup(&((Rwait*)z->wait[i])->r);
105 gettag(VtConn *z, Rwait *r)
110 while(z->ntag == 256)
118 fprint(2, "libventi: ntag botch\n");
123 puttag(VtConn *z, Rwait *r, int tag)
125 assert(z->wait[tag] == r);
128 rwakeup(&z->tagrend);
132 muxrpc(VtConn *z, Packet *p)
134 uchar tag, buf[2], *top;
137 if((top = packetpeek(p, buf, 0, 2)) == nil){
138 fprint(2, "libventi: short packet in vtrpc\n");
144 if((r = z->wait[tag]) == nil){
145 fprint(2, "libventi: unexpected packet tag %d in vtrpc\n", tag);