Blame


1 056fe1ba 2003-11-23 devnull /*
2 056fe1ba 2003-11-23 devnull * Multiplexed Venti client. It would be nice if we
3 056fe1ba 2003-11-23 devnull * could turn this into a generic library routine rather
4 056fe1ba 2003-11-23 devnull * than keep it Venti specific. A user-level 9P client
5 056fe1ba 2003-11-23 devnull * could use something like this too.
6 056fe1ba 2003-11-23 devnull *
7 056fe1ba 2003-11-23 devnull * This is a little more complicated than it might be
8 056fe1ba 2003-11-23 devnull * because we want it to work well within and without libthread.
9 056fe1ba 2003-11-23 devnull *
10 056fe1ba 2003-11-23 devnull * The mux code is inspired by tra's, which is inspired by the Plan 9 kernel.
11 056fe1ba 2003-11-23 devnull */
12 056fe1ba 2003-11-23 devnull
13 056fe1ba 2003-11-23 devnull #include <u.h>
14 056fe1ba 2003-11-23 devnull #include <libc.h>
15 056fe1ba 2003-11-23 devnull #include <venti.h>
16 056fe1ba 2003-11-23 devnull
17 056fe1ba 2003-11-23 devnull typedef struct Rwait Rwait;
18 056fe1ba 2003-11-23 devnull struct Rwait
19 056fe1ba 2003-11-23 devnull {
20 056fe1ba 2003-11-23 devnull Rendez r;
21 056fe1ba 2003-11-23 devnull Packet *p;
22 056fe1ba 2003-11-23 devnull int done;
23 056fe1ba 2003-11-23 devnull int sleeping;
24 056fe1ba 2003-11-23 devnull };
25 056fe1ba 2003-11-23 devnull
26 056fe1ba 2003-11-23 devnull static int gettag(VtConn*, Rwait*);
27 056fe1ba 2003-11-23 devnull static void puttag(VtConn*, Rwait*, int);
28 056fe1ba 2003-11-23 devnull static void muxrpc(VtConn*, Packet*);
29 056fe1ba 2003-11-23 devnull Packet *vtrpc(VtConn*, Packet*);
30 056fe1ba 2003-11-23 devnull
31 056fe1ba 2003-11-23 devnull Packet*
32 056fe1ba 2003-11-23 devnull vtrpc(VtConn *z, Packet *p)
33 056fe1ba 2003-11-23 devnull {
34 056fe1ba 2003-11-23 devnull int i;
35 056fe1ba 2003-11-23 devnull uchar tag, buf[2], *top;
36 056fe1ba 2003-11-23 devnull Rwait *r;
37 056fe1ba 2003-11-23 devnull
38 056fe1ba 2003-11-23 devnull /* must malloc because stack could be private */
39 056fe1ba 2003-11-23 devnull r = vtmallocz(sizeof(Rwait));
40 056fe1ba 2003-11-23 devnull
41 056fe1ba 2003-11-23 devnull qlock(&z->lk);
42 056fe1ba 2003-11-23 devnull r->r.l = &z->lk;
43 056fe1ba 2003-11-23 devnull tag = gettag(z, r);
44 056fe1ba 2003-11-23 devnull
45 056fe1ba 2003-11-23 devnull /* slam tag into packet */
46 056fe1ba 2003-11-23 devnull top = packetpeek(p, buf, 0, 2);
47 056fe1ba 2003-11-23 devnull if(top == nil){
48 056fe1ba 2003-11-23 devnull packetfree(p);
49 056fe1ba 2003-11-23 devnull return nil;
50 056fe1ba 2003-11-23 devnull }
51 056fe1ba 2003-11-23 devnull if(top == buf){
52 056fe1ba 2003-11-23 devnull werrstr("first two bytes must be in same packet fragment");
53 056fe1ba 2003-11-23 devnull packetfree(p);
54 056fe1ba 2003-11-23 devnull return nil;
55 056fe1ba 2003-11-23 devnull }
56 056fe1ba 2003-11-23 devnull top[1] = tag;
57 056fe1ba 2003-11-23 devnull qunlock(&z->lk);
58 056fe1ba 2003-11-23 devnull if(vtsend(z, p) < 0)
59 056fe1ba 2003-11-23 devnull return nil;
60 056fe1ba 2003-11-23 devnull
61 056fe1ba 2003-11-23 devnull qlock(&z->lk);
62 056fe1ba 2003-11-23 devnull /* wait for the muxer to give us our packet */
63 056fe1ba 2003-11-23 devnull r->sleeping = 1;
64 056fe1ba 2003-11-23 devnull z->nsleep++;
65 056fe1ba 2003-11-23 devnull while(z->muxer && !r->done)
66 056fe1ba 2003-11-23 devnull rsleep(&r->r);
67 056fe1ba 2003-11-23 devnull z->nsleep--;
68 056fe1ba 2003-11-23 devnull r->sleeping = 0;
69 056fe1ba 2003-11-23 devnull
70 056fe1ba 2003-11-23 devnull /* if not done, there's no muxer: start muxing */
71 056fe1ba 2003-11-23 devnull if(!r->done){
72 056fe1ba 2003-11-23 devnull if(z->muxer)
73 056fe1ba 2003-11-23 devnull abort();
74 056fe1ba 2003-11-23 devnull z->muxer = 1;
75 056fe1ba 2003-11-23 devnull while(!r->done){
76 056fe1ba 2003-11-23 devnull qunlock(&z->lk);
77 056fe1ba 2003-11-23 devnull if((p = vtrecv(z)) == nil){
78 056fe1ba 2003-11-23 devnull z->muxer = 0;
79 056fe1ba 2003-11-23 devnull return nil;
80 056fe1ba 2003-11-23 devnull }
81 056fe1ba 2003-11-23 devnull qlock(&z->lk);
82 056fe1ba 2003-11-23 devnull muxrpc(z, p);
83 056fe1ba 2003-11-23 devnull }
84 056fe1ba 2003-11-23 devnull z->muxer = 0;
85 056fe1ba 2003-11-23 devnull /* if there is anyone else sleeping, wake them to mux */
86 056fe1ba 2003-11-23 devnull if(z->nsleep){
87 056fe1ba 2003-11-23 devnull for(i=0; i<256; i++)
88 056fe1ba 2003-11-23 devnull if(z->wait[i] != nil && ((Rwait*)z->wait[i])->sleeping)
89 056fe1ba 2003-11-23 devnull break;
90 056fe1ba 2003-11-23 devnull if(i==256)
91 056fe1ba 2003-11-23 devnull fprint(2, "libventi: nsleep botch\n");
92 056fe1ba 2003-11-23 devnull else
93 056fe1ba 2003-11-23 devnull rwakeup(&((Rwait*)z->wait[i])->r);
94 056fe1ba 2003-11-23 devnull }
95 056fe1ba 2003-11-23 devnull }
96 056fe1ba 2003-11-23 devnull
97 056fe1ba 2003-11-23 devnull p = r->p;
98 056fe1ba 2003-11-23 devnull puttag(z, r, tag);
99 056fe1ba 2003-11-23 devnull vtfree(r);
100 056fe1ba 2003-11-23 devnull qunlock(&z->lk);
101 056fe1ba 2003-11-23 devnull return p;
102 056fe1ba 2003-11-23 devnull }
103 056fe1ba 2003-11-23 devnull
104 056fe1ba 2003-11-23 devnull static int
105 056fe1ba 2003-11-23 devnull gettag(VtConn *z, Rwait *r)
106 056fe1ba 2003-11-23 devnull {
107 056fe1ba 2003-11-23 devnull int i;
108 056fe1ba 2003-11-23 devnull
109 056fe1ba 2003-11-23 devnull Again:
110 056fe1ba 2003-11-23 devnull while(z->ntag == 256)
111 056fe1ba 2003-11-23 devnull rsleep(&z->tagrend);
112 056fe1ba 2003-11-23 devnull for(i=0; i<256; i++)
113 056fe1ba 2003-11-23 devnull if(z->wait[i] == 0){
114 056fe1ba 2003-11-23 devnull z->ntag++;
115 056fe1ba 2003-11-23 devnull z->wait[i] = r;
116 056fe1ba 2003-11-23 devnull return i;
117 056fe1ba 2003-11-23 devnull }
118 056fe1ba 2003-11-23 devnull fprint(2, "libventi: ntag botch\n");
119 056fe1ba 2003-11-23 devnull goto Again;
120 056fe1ba 2003-11-23 devnull }
121 056fe1ba 2003-11-23 devnull
122 056fe1ba 2003-11-23 devnull static void
123 056fe1ba 2003-11-23 devnull puttag(VtConn *z, Rwait *r, int tag)
124 056fe1ba 2003-11-23 devnull {
125 056fe1ba 2003-11-23 devnull assert(z->wait[tag] == r);
126 056fe1ba 2003-11-23 devnull z->wait[tag] = nil;
127 056fe1ba 2003-11-23 devnull z->ntag--;
128 056fe1ba 2003-11-23 devnull rwakeup(&z->tagrend);
129 056fe1ba 2003-11-23 devnull }
130 056fe1ba 2003-11-23 devnull
131 056fe1ba 2003-11-23 devnull static void
132 056fe1ba 2003-11-23 devnull muxrpc(VtConn *z, Packet *p)
133 056fe1ba 2003-11-23 devnull {
134 056fe1ba 2003-11-23 devnull uchar tag, buf[2], *top;
135 056fe1ba 2003-11-23 devnull Rwait *r;
136 056fe1ba 2003-11-23 devnull
137 056fe1ba 2003-11-23 devnull if((top = packetpeek(p, buf, 0, 2)) == nil){
138 056fe1ba 2003-11-23 devnull fprint(2, "libventi: short packet in vtrpc\n");
139 056fe1ba 2003-11-23 devnull packetfree(p);
140 056fe1ba 2003-11-23 devnull return;
141 056fe1ba 2003-11-23 devnull }
142 056fe1ba 2003-11-23 devnull
143 056fe1ba 2003-11-23 devnull tag = top[1];
144 056fe1ba 2003-11-23 devnull if((r = z->wait[tag]) == nil){
145 056fe1ba 2003-11-23 devnull fprint(2, "libventi: unexpected packet tag %d in vtrpc\n", tag);
146 056fe1ba 2003-11-23 devnull abort();
147 056fe1ba 2003-11-23 devnull packetfree(p);
148 056fe1ba 2003-11-23 devnull return;
149 056fe1ba 2003-11-23 devnull }
150 056fe1ba 2003-11-23 devnull
151 056fe1ba 2003-11-23 devnull r->p = p;
152 056fe1ba 2003-11-23 devnull r->done = 1;
153 056fe1ba 2003-11-23 devnull rwakeup(&r->r);
154 056fe1ba 2003-11-23 devnull }
155 056fe1ba 2003-11-23 devnull