7 * Sun RPC server; for now, no reply cache
10 static void sunRpcProc(void*);
11 static void sunRpcRequestThread(void*);
12 static void sunRpcReplyThread(void*);
13 static void sunRpcForkThread(void*);
14 static SunProg *sunFindProg(SunSrv*, SunMsg*, SunRpc*, Channel**);
16 typedef struct Targ Targ;
28 srv = emalloc(sizeof(SunSrv));
30 srv->crequest = chancreate(sizeof(SunMsg*), 16);
31 srv->creply = chancreate(sizeof(SunMsg*), 16);
32 srv->cthread = chancreate(sizeof(Targ), 4);
34 proccreate(sunRpcProc, srv, SunStackSize);
39 sunSrvProg(SunSrv *srv, SunProg *prog, Channel *c)
41 if(srv->nprog%16 == 0){
42 srv->prog = erealloc(srv->prog, (srv->nprog+16)*sizeof(srv->prog[0]));
43 srv->cdispatch = erealloc(srv->cdispatch, (srv->nprog+16)*sizeof(srv->cdispatch[0]));
45 srv->prog[srv->nprog] = prog;
46 srv->cdispatch[srv->nprog] = c;
53 threadcreate(sunRpcReplyThread, v, SunStackSize);
54 threadcreate(sunRpcRequestThread, v, SunStackSize);
55 threadcreate(sunRpcForkThread, v, SunStackSize);
60 sunRpcForkThread(void *v)
65 while(recv(srv->cthread, &t) == 1)
66 threadcreate(t.fn, t.arg, SunStackSize);
70 sunSrvThreadCreate(SunSrv *srv, void (*fn)(void*), void *arg)
76 send(srv->cthread, &t);
80 sunRpcRequestThread(void *v)
89 while((m = recvp(srv->crequest)) != nil){
90 /* could look up in cache here? */
92 if(srv->chatty) fprint(2, "sun msg %p count %d\n", m, m->count);
96 if(sunRpcUnpack(p, ep, &p, &m->rpc) != SunSuccess){
97 fprint(2, "in: %.*H unpack failed\n", m->count, m->data);
102 fprint(2, "in: %B\n", &m->rpc);
104 if(srv->alwaysReject){
106 fprint(2, "\trejecting\n");
107 sunMsgReplyError(m, SunAuthTooWeak);
112 sunMsgReplyError(m, SunGarbageArgs);
116 if((pg = sunFindProg(srv, m, &m->rpc, &c)) == nil){
117 /* sunFindProg sent error */
124 if((ok = sunCallUnpackAlloc(pg, m->rpc.proc<<1, p, ep, &p, &m->call)) != SunSuccess){
125 sunMsgReplyError(m, ok);
128 m->call->rpc = m->rpc;
131 fprint(2, "\t%C\n", m->call);
139 sunFindProg(SunSrv *srv, SunMsg *m, SunRpc *rpc, Channel **pc)
147 for(i=0; i<srv->nprog; i++){
149 if(pg->prog != rpc->prog)
151 if(pg->vers == rpc->vers){
152 *pc = srv->cdispatch[i];
155 /* right program, wrong version: record range */
163 fprint(2, "\tprogram %ud unavailable\n", rpc->prog);
164 sunMsgReplyError(m, SunProgUnavail);
166 /* putting these in rpc is a botch */
170 fprint(2, "\tversion %ud unavailable; have %d-%d\n", rpc->vers, vlo, vhi);
171 sunMsgReplyError(m, SunProgMismatch);
177 sunRpcReplyThread(void *v)
182 while((m = recvp(srv->creply)) != nil){
183 /* could record in cache here? */
189 sunMsgReplyError(SunMsg *m, SunStatus error)
194 m->rpc.status = error;
196 m->rpc.verf.flavor = SunAuthNone;
201 fprint(2, "out: %B\n", &m->rpc);
203 n = sunRpcSize(&m->rpc);
207 if(sunRpcPack(p, ep, &p, &m->rpc) < 0){
208 fprint(2, "sunRpcPack failed\n");
213 fprint(2, "sunMsgReplyError: rpc sizes didn't work out\n");
220 sendp(m->srv->creply, m);
225 sunMsgReply(SunMsg *m, SunCall *c)
230 c->type = m->call->type+1;
232 c->rpc.prog = m->rpc.prog;
233 c->rpc.vers = m->rpc.vers;
234 c->rpc.proc = m->rpc.proc;
235 c->rpc.xid = m->rpc.xid;
238 fprint(2, "out: %B\n", &c->rpc);
239 fprint(2, "\t%C\n", c);
242 n1 = sunRpcSize(&c->rpc);
243 n2 = sunCallSize(m->pg, c);
248 if(sunRpcPack(p, ep, &p, &c->rpc) != SunSuccess){
249 fprint(2, "sunRpcPack failed\n");
250 return sunMsgDrop(m);
252 if(sunCallPack(m->pg, p, ep, &p, c) != SunSuccess){
253 fprint(2, "pg->pack failed\n");
254 return sunMsgDrop(m);
257 fprint(2, "sunMsgReply: sizes didn't work out\n");
258 return sunMsgDrop(m);
264 sendp(m->srv->creply, m);
269 sunMsgDrop(SunMsg *m)
273 memset(m, 0xFB, sizeof *m);