Blame


1 551445b9 2004-04-21 devnull /*
2 551445b9 2004-04-21 devnull * Sun RPC client.
3 551445b9 2004-04-21 devnull */
4 551445b9 2004-04-21 devnull #include <u.h>
5 551445b9 2004-04-21 devnull #include <libc.h>
6 551445b9 2004-04-21 devnull #include <thread.h>
7 551445b9 2004-04-21 devnull #include <sunrpc.h>
8 551445b9 2004-04-21 devnull
9 551445b9 2004-04-21 devnull typedef struct Out Out;
10 551445b9 2004-04-21 devnull struct Out
11 551445b9 2004-04-21 devnull {
12 551445b9 2004-04-21 devnull char err[ERRMAX]; /* error string */
13 551445b9 2004-04-21 devnull Channel *creply; /* send to finish rpc */
14 551445b9 2004-04-21 devnull uchar *p; /* pending request packet */
15 551445b9 2004-04-21 devnull int n; /* size of request */
16 551445b9 2004-04-21 devnull ulong tag; /* flush tag of pending request */
17 551445b9 2004-04-21 devnull ulong xid; /* xid of pending request */
18 551445b9 2004-04-21 devnull ulong st; /* first send time */
19 551445b9 2004-04-21 devnull ulong t; /* resend time */
20 551445b9 2004-04-21 devnull int nresend; /* number of resends */
21 551445b9 2004-04-21 devnull SunRpc rpc; /* response rpc */
22 551445b9 2004-04-21 devnull };
23 551445b9 2004-04-21 devnull
24 551445b9 2004-04-21 devnull static void
25 551445b9 2004-04-21 devnull udpThread(void *v)
26 551445b9 2004-04-21 devnull {
27 551445b9 2004-04-21 devnull uchar *p, *buf;
28 551445b9 2004-04-21 devnull Ioproc *io;
29 551445b9 2004-04-21 devnull int n;
30 551445b9 2004-04-21 devnull SunClient *cli;
31 551445b9 2004-04-21 devnull enum { BufSize = 65536 };
32 551445b9 2004-04-21 devnull
33 551445b9 2004-04-21 devnull cli = v;
34 551445b9 2004-04-21 devnull buf = emalloc(BufSize);
35 551445b9 2004-04-21 devnull io = ioproc();
36 551445b9 2004-04-21 devnull p = nil;
37 551445b9 2004-04-21 devnull for(;;){
38 551445b9 2004-04-21 devnull n = ioread(io, cli->fd, buf, BufSize);
39 551445b9 2004-04-21 devnull if(n <= 0)
40 551445b9 2004-04-21 devnull break;
41 551445b9 2004-04-21 devnull p = emalloc(4+n);
42 551445b9 2004-04-21 devnull memmove(p+4, buf, n);
43 551445b9 2004-04-21 devnull p[0] = n>>24;
44 551445b9 2004-04-21 devnull p[1] = n>>16;
45 551445b9 2004-04-21 devnull p[2] = n>>8;
46 551445b9 2004-04-21 devnull p[3] = n;
47 551445b9 2004-04-21 devnull if(sendp(cli->readchan, p) == 0)
48 551445b9 2004-04-21 devnull break;
49 551445b9 2004-04-21 devnull p = nil;
50 551445b9 2004-04-21 devnull }
51 551445b9 2004-04-21 devnull free(p);
52 551445b9 2004-04-21 devnull closeioproc(io);
53 551445b9 2004-04-21 devnull while(send(cli->dying, nil) == -1)
54 551445b9 2004-04-21 devnull ;
55 551445b9 2004-04-21 devnull }
56 551445b9 2004-04-21 devnull
57 551445b9 2004-04-21 devnull static void
58 551445b9 2004-04-21 devnull netThread(void *v)
59 551445b9 2004-04-21 devnull {
60 551445b9 2004-04-21 devnull uchar *p, buf[4];
61 551445b9 2004-04-21 devnull Ioproc *io;
62 551445b9 2004-04-21 devnull uint n, tot;
63 551445b9 2004-04-21 devnull int done;
64 551445b9 2004-04-21 devnull SunClient *cli;
65 551445b9 2004-04-21 devnull
66 551445b9 2004-04-21 devnull cli = v;
67 551445b9 2004-04-21 devnull io = ioproc();
68 551445b9 2004-04-21 devnull tot = 0;
69 551445b9 2004-04-21 devnull p = nil;
70 551445b9 2004-04-21 devnull for(;;){
71 551445b9 2004-04-21 devnull n = ioreadn(io, cli->fd, buf, 4);
72 551445b9 2004-04-21 devnull if(n != 4)
73 551445b9 2004-04-21 devnull break;
74 551445b9 2004-04-21 devnull n = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3];
75 551445b9 2004-04-21 devnull if(cli->chatty)
76 551445b9 2004-04-21 devnull fprint(2, "%.8ux...", n);
77 551445b9 2004-04-21 devnull done = n&0x80000000;
78 551445b9 2004-04-21 devnull n &= ~0x80000000;
79 551445b9 2004-04-21 devnull if(tot == 0){
80 551445b9 2004-04-21 devnull p = emalloc(4+n);
81 551445b9 2004-04-21 devnull tot = 4;
82 551445b9 2004-04-21 devnull }else
83 551445b9 2004-04-21 devnull p = erealloc(p, tot+n);
84 551445b9 2004-04-21 devnull if(ioreadn(io, cli->fd, p+tot, n) != n)
85 551445b9 2004-04-21 devnull break;
86 551445b9 2004-04-21 devnull tot += n;
87 551445b9 2004-04-21 devnull if(done){
88 551445b9 2004-04-21 devnull p[0] = tot>>24;
89 551445b9 2004-04-21 devnull p[1] = tot>>16;
90 551445b9 2004-04-21 devnull p[2] = tot>>8;
91 551445b9 2004-04-21 devnull p[3] = tot;
92 551445b9 2004-04-21 devnull if(sendp(cli->readchan, p) == 0)
93 551445b9 2004-04-21 devnull break;
94 551445b9 2004-04-21 devnull p = nil;
95 551445b9 2004-04-21 devnull tot = 0;
96 551445b9 2004-04-21 devnull }
97 551445b9 2004-04-21 devnull }
98 551445b9 2004-04-21 devnull free(p);
99 551445b9 2004-04-21 devnull closeioproc(io);
100 551445b9 2004-04-21 devnull while(send(cli->dying, 0) == -1)
101 551445b9 2004-04-21 devnull ;
102 551445b9 2004-04-21 devnull }
103 551445b9 2004-04-21 devnull
104 551445b9 2004-04-21 devnull static void
105 551445b9 2004-04-21 devnull timerThread(void *v)
106 551445b9 2004-04-21 devnull {
107 551445b9 2004-04-21 devnull Ioproc *io;
108 551445b9 2004-04-21 devnull SunClient *cli;
109 551445b9 2004-04-21 devnull
110 551445b9 2004-04-21 devnull cli = v;
111 551445b9 2004-04-21 devnull io = ioproc();
112 551445b9 2004-04-21 devnull for(;;){
113 551445b9 2004-04-21 devnull if(iosleep(io, 200) < 0)
114 551445b9 2004-04-21 devnull break;
115 551445b9 2004-04-21 devnull if(sendul(cli->timerchan, 0) == 0)
116 551445b9 2004-04-21 devnull break;
117 551445b9 2004-04-21 devnull }
118 551445b9 2004-04-21 devnull closeioproc(io);
119 551445b9 2004-04-21 devnull while(send(cli->dying, 0) == -1)
120 551445b9 2004-04-21 devnull ;
121 551445b9 2004-04-21 devnull }
122 551445b9 2004-04-21 devnull
123 551445b9 2004-04-21 devnull static ulong
124 551445b9 2004-04-21 devnull msec(void)
125 551445b9 2004-04-21 devnull {
126 551445b9 2004-04-21 devnull return nsec()/1000000;
127 551445b9 2004-04-21 devnull }
128 551445b9 2004-04-21 devnull
129 551445b9 2004-04-21 devnull static ulong
130 551445b9 2004-04-21 devnull twait(ulong rtt, int nresend)
131 551445b9 2004-04-21 devnull {
132 551445b9 2004-04-21 devnull ulong t;
133 551445b9 2004-04-21 devnull
134 551445b9 2004-04-21 devnull t = rtt;
135 551445b9 2004-04-21 devnull if(nresend <= 1)
136 551445b9 2004-04-21 devnull {}
137 551445b9 2004-04-21 devnull else if(nresend <= 3)
138 551445b9 2004-04-21 devnull t *= 2;
139 551445b9 2004-04-21 devnull else if(nresend <= 18)
140 551445b9 2004-04-21 devnull t <<= nresend-2;
141 551445b9 2004-04-21 devnull else
142 551445b9 2004-04-21 devnull t = 60*1000;
143 551445b9 2004-04-21 devnull if(t > 60*1000)
144 551445b9 2004-04-21 devnull t = 60*1000;
145 551445b9 2004-04-21 devnull
146 551445b9 2004-04-21 devnull return t;
147 551445b9 2004-04-21 devnull }
148 551445b9 2004-04-21 devnull
149 551445b9 2004-04-21 devnull static void
150 551445b9 2004-04-21 devnull rpcMuxThread(void *v)
151 551445b9 2004-04-21 devnull {
152 551445b9 2004-04-21 devnull uchar *buf, *p, *ep;
153 551445b9 2004-04-21 devnull int i, n, nout, mout;
154 551445b9 2004-04-21 devnull ulong t, xidgen, tag;
155 551445b9 2004-04-21 devnull Alt a[5];
156 551445b9 2004-04-21 devnull Out *o, **out;
157 551445b9 2004-04-21 devnull SunRpc rpc;
158 551445b9 2004-04-21 devnull SunClient *cli;
159 551445b9 2004-04-21 devnull
160 551445b9 2004-04-21 devnull cli = v;
161 551445b9 2004-04-21 devnull mout = 16;
162 551445b9 2004-04-21 devnull nout = 0;
163 551445b9 2004-04-21 devnull out = emalloc(mout*sizeof(out[0]));
164 551445b9 2004-04-21 devnull xidgen = truerand();
165 551445b9 2004-04-21 devnull
166 551445b9 2004-04-21 devnull a[0].op = CHANRCV;
167 551445b9 2004-04-21 devnull a[0].c = cli->rpcchan;
168 551445b9 2004-04-21 devnull a[0].v = &o;
169 551445b9 2004-04-21 devnull a[1].op = CHANNOP;
170 551445b9 2004-04-21 devnull a[1].c = cli->timerchan;
171 551445b9 2004-04-21 devnull a[1].v = nil;
172 551445b9 2004-04-21 devnull a[2].op = CHANRCV;
173 551445b9 2004-04-21 devnull a[2].c = cli->flushchan;
174 551445b9 2004-04-21 devnull a[2].v = &tag;
175 551445b9 2004-04-21 devnull a[3].op = CHANRCV;
176 551445b9 2004-04-21 devnull a[3].c = cli->readchan;
177 551445b9 2004-04-21 devnull a[3].v = &buf;
178 551445b9 2004-04-21 devnull a[4].op = CHANEND;
179 551445b9 2004-04-21 devnull
180 551445b9 2004-04-21 devnull for(;;){
181 551445b9 2004-04-21 devnull switch(alt(a)){
182 551445b9 2004-04-21 devnull case 0: /* o = <-rpcchan */
183 551445b9 2004-04-21 devnull if(o == nil)
184 551445b9 2004-04-21 devnull goto Done;
185 551445b9 2004-04-21 devnull cli->nsend++;
186 551445b9 2004-04-21 devnull /* set xid */
187 551445b9 2004-04-21 devnull o->xid = ++xidgen;
188 551445b9 2004-04-21 devnull if(cli->needcount)
189 551445b9 2004-04-21 devnull p = o->p+4;
190 551445b9 2004-04-21 devnull else
191 551445b9 2004-04-21 devnull p = o->p;
192 551445b9 2004-04-21 devnull p[0] = xidgen>>24;
193 551445b9 2004-04-21 devnull p[1] = xidgen>>16;
194 551445b9 2004-04-21 devnull p[2] = xidgen>>8;
195 551445b9 2004-04-21 devnull p[3] = xidgen;
196 551445b9 2004-04-21 devnull if(write(cli->fd, o->p, o->n) != o->n){
197 551445b9 2004-04-21 devnull free(o->p);
198 551445b9 2004-04-21 devnull o->p = nil;
199 551445b9 2004-04-21 devnull snprint(o->err, sizeof o->err, "write: %r");
200 551445b9 2004-04-21 devnull sendp(o->creply, 0);
201 551445b9 2004-04-21 devnull break;
202 551445b9 2004-04-21 devnull }
203 551445b9 2004-04-21 devnull if(nout >= mout){
204 551445b9 2004-04-21 devnull mout *= 2;
205 551445b9 2004-04-21 devnull out = erealloc(out, mout*sizeof(out[0]));
206 551445b9 2004-04-21 devnull }
207 551445b9 2004-04-21 devnull o->st = msec();
208 551445b9 2004-04-21 devnull o->nresend = 0;
209 551445b9 2004-04-21 devnull o->t = o->st + twait(cli->rtt.avg, 0);
210 551445b9 2004-04-21 devnull if(cli->chatty) fprint(2, "send %lux %lud %lud\n", o->xid, o->st, o->t);
211 551445b9 2004-04-21 devnull out[nout++] = o;
212 551445b9 2004-04-21 devnull a[1].op = CHANRCV;
213 551445b9 2004-04-21 devnull break;
214 551445b9 2004-04-21 devnull
215 551445b9 2004-04-21 devnull case 1: /* <-timerchan */
216 551445b9 2004-04-21 devnull t = msec();
217 551445b9 2004-04-21 devnull for(i=0; i<nout; i++){
218 551445b9 2004-04-21 devnull o = out[i];
219 551445b9 2004-04-21 devnull if((int)(t - o->t) > 0){
220 551445b9 2004-04-21 devnull if(cli->chatty) fprint(2, "resend %lux %lud %lud\n", o->xid, t, o->t);
221 551445b9 2004-04-21 devnull if(cli->maxwait && t - o->st >= cli->maxwait){
222 551445b9 2004-04-21 devnull free(o->p);
223 551445b9 2004-04-21 devnull o->p = nil;
224 551445b9 2004-04-21 devnull strcpy(o->err, "timeout");
225 551445b9 2004-04-21 devnull sendp(o->creply, 0);
226 551445b9 2004-04-21 devnull out[i--] = out[--nout];
227 551445b9 2004-04-21 devnull continue;
228 551445b9 2004-04-21 devnull }
229 551445b9 2004-04-21 devnull cli->nresend++;
230 551445b9 2004-04-21 devnull o->nresend++;
231 551445b9 2004-04-21 devnull o->t = t + twait(cli->rtt.avg, o->nresend);
232 551445b9 2004-04-21 devnull if(write(cli->fd, o->p, o->n) != o->n){
233 551445b9 2004-04-21 devnull free(o->p);
234 551445b9 2004-04-21 devnull o->p = nil;
235 551445b9 2004-04-21 devnull snprint(o->err, sizeof o->err, "rewrite: %r");
236 551445b9 2004-04-21 devnull sendp(o->creply, 0);
237 551445b9 2004-04-21 devnull out[i--] = out[--nout];
238 551445b9 2004-04-21 devnull continue;
239 551445b9 2004-04-21 devnull }
240 551445b9 2004-04-21 devnull }
241 551445b9 2004-04-21 devnull }
242 551445b9 2004-04-21 devnull /* stop ticking if no work; rpcchan will turn it back on */
243 551445b9 2004-04-21 devnull if(nout == 0)
244 551445b9 2004-04-21 devnull a[1].op = CHANNOP;
245 551445b9 2004-04-21 devnull break;
246 fa325e9b 2020-01-10 cross
247 551445b9 2004-04-21 devnull case 2: /* tag = <-flushchan */
248 551445b9 2004-04-21 devnull for(i=0; i<nout; i++){
249 551445b9 2004-04-21 devnull o = out[i];
250 551445b9 2004-04-21 devnull if(o->tag == tag){
251 551445b9 2004-04-21 devnull out[i--] = out[--nout];
252 551445b9 2004-04-21 devnull strcpy(o->err, "flushed");
253 551445b9 2004-04-21 devnull free(o->p);
254 551445b9 2004-04-21 devnull o->p = nil;
255 551445b9 2004-04-21 devnull sendp(o->creply, 0);
256 551445b9 2004-04-21 devnull }
257 551445b9 2004-04-21 devnull }
258 551445b9 2004-04-21 devnull break;
259 551445b9 2004-04-21 devnull
260 551445b9 2004-04-21 devnull case 3: /* buf = <-readchan */
261 551445b9 2004-04-21 devnull p = buf;
262 551445b9 2004-04-21 devnull n = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
263 551445b9 2004-04-21 devnull p += 4;
264 551445b9 2004-04-21 devnull ep = p+n;
265 42fb767e 2005-10-29 devnull if(sunrpcunpack(p, ep, &p, &rpc) != SunSuccess){
266 551445b9 2004-04-21 devnull fprint(2, "%s: in: %.*H unpack failed\n", argv0, n, buf+4);
267 551445b9 2004-04-21 devnull free(buf);
268 551445b9 2004-04-21 devnull break;
269 551445b9 2004-04-21 devnull }
270 551445b9 2004-04-21 devnull if(cli->chatty)
271 551445b9 2004-04-21 devnull fprint(2, "in: %B\n", &rpc);
272 551445b9 2004-04-21 devnull if(rpc.iscall){
273 551445b9 2004-04-21 devnull fprint(2, "did not get reply\n");
274 551445b9 2004-04-21 devnull free(buf);
275 551445b9 2004-04-21 devnull break;
276 551445b9 2004-04-21 devnull }
277 551445b9 2004-04-21 devnull o = nil;
278 551445b9 2004-04-21 devnull for(i=0; i<nout; i++){
279 551445b9 2004-04-21 devnull o = out[i];
280 551445b9 2004-04-21 devnull if(o->xid == rpc.xid)
281 551445b9 2004-04-21 devnull break;
282 551445b9 2004-04-21 devnull }
283 551445b9 2004-04-21 devnull if(i==nout){
284 551445b9 2004-04-21 devnull if(cli->chatty) fprint(2, "did not find waiting request\n");
285 551445b9 2004-04-21 devnull free(buf);
286 551445b9 2004-04-21 devnull break;
287 551445b9 2004-04-21 devnull }
288 551445b9 2004-04-21 devnull out[i] = out[--nout];
289 551445b9 2004-04-21 devnull free(o->p);
290 551445b9 2004-04-21 devnull o->p = nil;
291 4c06b8ee 2005-05-19 devnull o->rpc = rpc;
292 551445b9 2004-04-21 devnull if(rpc.status == SunSuccess){
293 551445b9 2004-04-21 devnull o->p = buf;
294 551445b9 2004-04-21 devnull }else{
295 551445b9 2004-04-21 devnull o->p = nil;
296 551445b9 2004-04-21 devnull free(buf);
297 551445b9 2004-04-21 devnull sunerrstr(rpc.status);
298 551445b9 2004-04-21 devnull rerrstr(o->err, sizeof o->err);
299 551445b9 2004-04-21 devnull }
300 551445b9 2004-04-21 devnull sendp(o->creply, 0);
301 551445b9 2004-04-21 devnull break;
302 551445b9 2004-04-21 devnull }
303 551445b9 2004-04-21 devnull }
304 551445b9 2004-04-21 devnull Done:
305 551445b9 2004-04-21 devnull free(out);
306 551445b9 2004-04-21 devnull sendp(cli->dying, 0);
307 551445b9 2004-04-21 devnull }
308 551445b9 2004-04-21 devnull
309 551445b9 2004-04-21 devnull SunClient*
310 551445b9 2004-04-21 devnull sundial(char *address)
311 551445b9 2004-04-21 devnull {
312 551445b9 2004-04-21 devnull int fd;
313 551445b9 2004-04-21 devnull SunClient *cli;
314 551445b9 2004-04-21 devnull
315 551445b9 2004-04-21 devnull if((fd = dial(address, 0, 0, 0)) < 0)
316 551445b9 2004-04-21 devnull return nil;
317 551445b9 2004-04-21 devnull
318 551445b9 2004-04-21 devnull cli = emalloc(sizeof(SunClient));
319 551445b9 2004-04-21 devnull cli->fd = fd;
320 551445b9 2004-04-21 devnull cli->maxwait = 15000;
321 551445b9 2004-04-21 devnull cli->rtt.avg = 1000;
322 551445b9 2004-04-21 devnull cli->dying = chancreate(sizeof(void*), 0);
323 551445b9 2004-04-21 devnull cli->rpcchan = chancreate(sizeof(Out*), 0);
324 551445b9 2004-04-21 devnull cli->timerchan = chancreate(sizeof(ulong), 0);
325 551445b9 2004-04-21 devnull cli->flushchan = chancreate(sizeof(ulong), 0);
326 551445b9 2004-04-21 devnull cli->readchan = chancreate(sizeof(uchar*), 0);
327 551445b9 2004-04-21 devnull if(strstr(address, "udp!")){
328 551445b9 2004-04-21 devnull cli->needcount = 0;
329 551445b9 2004-04-21 devnull cli->nettid = threadcreate(udpThread, cli, SunStackSize);
330 551445b9 2004-04-21 devnull cli->timertid = threadcreate(timerThread, cli, SunStackSize);
331 551445b9 2004-04-21 devnull }else{
332 551445b9 2004-04-21 devnull cli->needcount = 1;
333 551445b9 2004-04-21 devnull cli->nettid = threadcreate(netThread, cli, SunStackSize);
334 551445b9 2004-04-21 devnull /* assume reliable: don't need timer */
335 551445b9 2004-04-21 devnull /* BUG: netThread should know how to redial */
336 551445b9 2004-04-21 devnull }
337 551445b9 2004-04-21 devnull threadcreate(rpcMuxThread, cli, SunStackSize);
338 551445b9 2004-04-21 devnull
339 551445b9 2004-04-21 devnull return cli;
340 551445b9 2004-04-21 devnull }
341 551445b9 2004-04-21 devnull
342 551445b9 2004-04-21 devnull void
343 551445b9 2004-04-21 devnull sunclientclose(SunClient *cli)
344 551445b9 2004-04-21 devnull {
345 551445b9 2004-04-21 devnull int n;
346 551445b9 2004-04-21 devnull
347 551445b9 2004-04-21 devnull /*
348 551445b9 2004-04-21 devnull * Threadints get you out of any stuck system calls
349 551445b9 2004-04-21 devnull * or thread rendezvouses, but do nothing if the thread
350 551445b9 2004-04-21 devnull * is in the ready state. Keep interrupting until it takes.
351 551445b9 2004-04-21 devnull */
352 551445b9 2004-04-21 devnull n = 0;
353 551445b9 2004-04-21 devnull if(!cli->timertid)
354 551445b9 2004-04-21 devnull n++;
355 551445b9 2004-04-21 devnull while(n < 2){
356 d7b202df 2005-07-13 devnull /*
357 d7b202df 2005-07-13 devnull threadint(cli->nettid);
358 d7b202df 2005-07-13 devnull if(cli->timertid)
359 d7b202df 2005-07-13 devnull threadint(cli->timertid);
360 d7b202df 2005-07-13 devnull */
361 d7b202df 2005-07-13 devnull
362 551445b9 2004-04-21 devnull yield();
363 551445b9 2004-04-21 devnull while(nbrecv(cli->dying, nil) == 1)
364 551445b9 2004-04-21 devnull n++;
365 551445b9 2004-04-21 devnull }
366 551445b9 2004-04-21 devnull
367 551445b9 2004-04-21 devnull sendp(cli->rpcchan, 0);
368 551445b9 2004-04-21 devnull recvp(cli->dying);
369 551445b9 2004-04-21 devnull
370 551445b9 2004-04-21 devnull /* everyone's gone: clean up */
371 551445b9 2004-04-21 devnull close(cli->fd);
372 551445b9 2004-04-21 devnull chanfree(cli->flushchan);
373 551445b9 2004-04-21 devnull chanfree(cli->readchan);
374 551445b9 2004-04-21 devnull chanfree(cli->timerchan);
375 551445b9 2004-04-21 devnull free(cli);
376 551445b9 2004-04-21 devnull }
377 fa325e9b 2020-01-10 cross
378 551445b9 2004-04-21 devnull void
379 551445b9 2004-04-21 devnull sunclientflushrpc(SunClient *cli, ulong tag)
380 551445b9 2004-04-21 devnull {
381 551445b9 2004-04-21 devnull sendul(cli->flushchan, tag);
382 551445b9 2004-04-21 devnull }
383 551445b9 2004-04-21 devnull
384 551445b9 2004-04-21 devnull void
385 551445b9 2004-04-21 devnull sunclientprog(SunClient *cli, SunProg *p)
386 551445b9 2004-04-21 devnull {
387 551445b9 2004-04-21 devnull if(cli->nprog%16 == 0)
388 551445b9 2004-04-21 devnull cli->prog = erealloc(cli->prog, (cli->nprog+16)*sizeof(cli->prog[0]));
389 551445b9 2004-04-21 devnull cli->prog[cli->nprog++] = p;
390 551445b9 2004-04-21 devnull }
391 551445b9 2004-04-21 devnull
392 551445b9 2004-04-21 devnull int
393 551445b9 2004-04-21 devnull sunclientrpc(SunClient *cli, ulong tag, SunCall *tx, SunCall *rx, uchar **tofree)
394 551445b9 2004-04-21 devnull {
395 551445b9 2004-04-21 devnull uchar *bp, *p, *ep;
396 551445b9 2004-04-21 devnull int i, n1, n2, n, nn;
397 551445b9 2004-04-21 devnull Out o;
398 551445b9 2004-04-21 devnull SunProg *prog;
399 551445b9 2004-04-21 devnull SunStatus ok;
400 551445b9 2004-04-21 devnull
401 551445b9 2004-04-21 devnull for(i=0; i<cli->nprog; i++)
402 551445b9 2004-04-21 devnull if(cli->prog[i]->prog == tx->rpc.prog && cli->prog[i]->vers == tx->rpc.vers)
403 551445b9 2004-04-21 devnull break;
404 551445b9 2004-04-21 devnull if(i==cli->nprog){
405 551445b9 2004-04-21 devnull werrstr("unknown sun rpc program %d version %d", tx->rpc.prog, tx->rpc.vers);
406 551445b9 2004-04-21 devnull return -1;
407 551445b9 2004-04-21 devnull }
408 551445b9 2004-04-21 devnull prog = cli->prog[i];
409 551445b9 2004-04-21 devnull
410 551445b9 2004-04-21 devnull if(cli->chatty){
411 551445b9 2004-04-21 devnull fprint(2, "out: %B\n", &tx->rpc);
412 551445b9 2004-04-21 devnull fprint(2, "\t%C\n", tx);
413 551445b9 2004-04-21 devnull }
414 551445b9 2004-04-21 devnull
415 551445b9 2004-04-21 devnull n1 = sunrpcsize(&tx->rpc);
416 551445b9 2004-04-21 devnull n2 = suncallsize(prog, tx);
417 551445b9 2004-04-21 devnull
418 551445b9 2004-04-21 devnull n = n1+n2;
419 551445b9 2004-04-21 devnull if(cli->needcount)
420 551445b9 2004-04-21 devnull n += 4;
421 551445b9 2004-04-21 devnull
422 551445b9 2004-04-21 devnull /*
423 551445b9 2004-04-21 devnull * The dance with 100 is to leave some padding in case
424 551445b9 2004-04-21 devnull * suncallsize is slightly underestimating. If this happens,
425 551445b9 2004-04-21 devnull * the pack will succeed and then we can give a good size
426 551445b9 2004-04-21 devnull * mismatch error below. Otherwise the pack fails with
427 551445b9 2004-04-21 devnull * garbage args, which is less helpful.
428 551445b9 2004-04-21 devnull */
429 551445b9 2004-04-21 devnull bp = emalloc(n+100);
430 551445b9 2004-04-21 devnull ep = bp+n+100;
431 551445b9 2004-04-21 devnull p = bp;
432 551445b9 2004-04-21 devnull if(cli->needcount){
433 551445b9 2004-04-21 devnull nn = n-4;
434 551445b9 2004-04-21 devnull p[0] = (nn>>24)|0x80;
435 551445b9 2004-04-21 devnull p[1] = nn>>16;
436 551445b9 2004-04-21 devnull p[2] = nn>>8;
437 551445b9 2004-04-21 devnull p[3] = nn;
438 551445b9 2004-04-21 devnull p += 4;
439 551445b9 2004-04-21 devnull }
440 551445b9 2004-04-21 devnull if((ok = sunrpcpack(p, ep, &p, &tx->rpc)) != SunSuccess
441 551445b9 2004-04-21 devnull || (ok = suncallpack(prog, p, ep, &p, tx)) != SunSuccess){
442 551445b9 2004-04-21 devnull sunerrstr(ok);
443 551445b9 2004-04-21 devnull free(bp);
444 551445b9 2004-04-21 devnull return -1;
445 551445b9 2004-04-21 devnull }
446 551445b9 2004-04-21 devnull ep -= 100;
447 551445b9 2004-04-21 devnull if(p != ep){
448 551445b9 2004-04-21 devnull werrstr("rpc: packet size mismatch %d %ld %ld", n, ep-bp, p-bp);
449 551445b9 2004-04-21 devnull free(bp);
450 551445b9 2004-04-21 devnull return -1;
451 551445b9 2004-04-21 devnull }
452 551445b9 2004-04-21 devnull
453 551445b9 2004-04-21 devnull memset(&o, 0, sizeof o);
454 551445b9 2004-04-21 devnull o.creply = chancreate(sizeof(void*), 0);
455 551445b9 2004-04-21 devnull o.tag = tag;
456 551445b9 2004-04-21 devnull o.p = bp;
457 551445b9 2004-04-21 devnull o.n = n;
458 551445b9 2004-04-21 devnull
459 551445b9 2004-04-21 devnull sendp(cli->rpcchan, &o);
460 551445b9 2004-04-21 devnull recvp(o.creply);
461 551445b9 2004-04-21 devnull chanfree(o.creply);
462 551445b9 2004-04-21 devnull
463 551445b9 2004-04-21 devnull if(o.p == nil){
464 551445b9 2004-04-21 devnull werrstr("%s", o.err);
465 551445b9 2004-04-21 devnull return -1;
466 551445b9 2004-04-21 devnull }
467 551445b9 2004-04-21 devnull
468 551445b9 2004-04-21 devnull p = o.rpc.data;
469 551445b9 2004-04-21 devnull ep = p+o.rpc.ndata;
470 551445b9 2004-04-21 devnull rx->rpc = o.rpc;
471 551445b9 2004-04-21 devnull rx->rpc.proc = tx->rpc.proc;
472 551445b9 2004-04-21 devnull rx->rpc.prog = tx->rpc.prog;
473 551445b9 2004-04-21 devnull rx->rpc.vers = tx->rpc.vers;
474 551445b9 2004-04-21 devnull rx->type = (rx->rpc.proc<<1)|1;
475 4c06b8ee 2005-05-19 devnull if(rx->rpc.status != SunSuccess){
476 4c06b8ee 2005-05-19 devnull sunerrstr(rx->rpc.status);
477 4c06b8ee 2005-05-19 devnull werrstr("unpack: %r");
478 4c06b8ee 2005-05-19 devnull free(o.p);
479 4c06b8ee 2005-05-19 devnull return -1;
480 4c06b8ee 2005-05-19 devnull }
481 4c06b8ee 2005-05-19 devnull
482 551445b9 2004-04-21 devnull if((ok = suncallunpack(prog, p, ep, &p, rx)) != SunSuccess){
483 551445b9 2004-04-21 devnull sunerrstr(ok);
484 551445b9 2004-04-21 devnull werrstr("unpack: %r");
485 551445b9 2004-04-21 devnull free(o.p);
486 551445b9 2004-04-21 devnull return -1;
487 551445b9 2004-04-21 devnull }
488 551445b9 2004-04-21 devnull
489 551445b9 2004-04-21 devnull if(cli->chatty){
490 551445b9 2004-04-21 devnull fprint(2, "in: %B\n", &rx->rpc);
491 551445b9 2004-04-21 devnull fprint(2, "in:\t%C\n", rx);
492 551445b9 2004-04-21 devnull }
493 551445b9 2004-04-21 devnull
494 551445b9 2004-04-21 devnull if(tofree)
495 551445b9 2004-04-21 devnull *tofree = o.p;
496 551445b9 2004-04-21 devnull else
497 551445b9 2004-04-21 devnull free(o.p);
498 551445b9 2004-04-21 devnull
499 551445b9 2004-04-21 devnull return 0;
500 551445b9 2004-04-21 devnull }