Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_posix/sys/src/libsunrpc/server.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <thread.h>
4
#include <sunrpc.h>
5
 
6
/*
7
 * Sun RPC server; for now, no reply cache
8
 */
9
 
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**);
15
 
16
typedef struct Targ Targ;
17
struct Targ
18
{
19
	void (*fn)(void*);
20
	void *arg;
21
};
22
 
23
SunSrv*
24
sunSrv(void)
25
{
26
	SunSrv *srv;
27
 
28
	srv = emalloc(sizeof(SunSrv));
29
	srv->chatty = 0;
30
	srv->crequest = chancreate(sizeof(SunMsg*), 16);
31
	srv->creply = chancreate(sizeof(SunMsg*), 16);
32
	srv->cthread = chancreate(sizeof(Targ), 4);
33
 
34
	proccreate(sunRpcProc, srv, SunStackSize);
35
	return srv;
36
}
37
 
38
void
39
sunSrvProg(SunSrv *srv, SunProg *prog, Channel *c)
40
{
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]));
44
	}
45
	srv->prog[srv->nprog] = prog;
46
	srv->cdispatch[srv->nprog] = c;
47
	srv->nprog++;
48
}
49
 
50
static void
51
sunRpcProc(void *v)
52
{
53
	threadcreate(sunRpcReplyThread, v, SunStackSize);
54
	threadcreate(sunRpcRequestThread, v, SunStackSize);
55
	threadcreate(sunRpcForkThread, v, SunStackSize);
56
 
57
}
58
 
59
static void
60
sunRpcForkThread(void *v)
61
{
62
	SunSrv *srv = v;
63
	Targ t;
64
 
65
	while(recv(srv->cthread, &t) == 1)
66
		threadcreate(t.fn, t.arg, SunStackSize);
67
}
68
 
69
void
70
sunSrvThreadCreate(SunSrv *srv, void (*fn)(void*), void *arg)
71
{
72
	Targ t;
73
 
74
	t.fn = fn;
75
	t.arg = arg;
76
	send(srv->cthread, &t);
77
}
78
 
79
static void
80
sunRpcRequestThread(void *v)
81
{
82
	uchar *p, *ep;
83
	Channel *c;
84
	SunSrv *srv = v;
85
	SunMsg *m;
86
	SunProg *pg;
87
	SunStatus ok;
88
 
89
	while((m = recvp(srv->crequest)) != nil){
90
		/* could look up in cache here? */
91
 
92
if(srv->chatty) fprint(2, "sun msg %p count %d\n", m, m->count);
93
		m->srv = srv;
94
		p = m->data;
95
		ep = p+m->count;
96
		if(sunRpcUnpack(p, ep, &p, &m->rpc) != SunSuccess){
97
			fprint(2, "in: %.*H unpack failed\n", m->count, m->data);
98
			sunMsgDrop(m);
99
			continue;
100
		}
101
		if(srv->chatty)
102
			fprint(2, "in: %B\n", &m->rpc);
103
 
104
		if(srv->alwaysReject){
105
			if(srv->chatty)
106
				fprint(2, "\trejecting\n");
107
			sunMsgReplyError(m, SunAuthTooWeak);
108
			continue;
109
		}
110
 
111
		if(!m->rpc.iscall){
112
			sunMsgReplyError(m, SunGarbageArgs);
113
			continue;
114
		}
115
 
116
		if((pg = sunFindProg(srv, m, &m->rpc, &c)) == nil){
117
			/* sunFindProg sent error */
118
			continue;
119
		}
120
 
121
		p = m->rpc.data;
122
		ep = p+m->rpc.ndata;
123
		m->call = nil;
124
		if((ok = sunCallUnpackAlloc(pg, m->rpc.proc<<1, p, ep, &p, &m->call)) != SunSuccess){
125
			sunMsgReplyError(m, ok);
126
			continue;
127
		}
128
		m->call->rpc = m->rpc;
129
 
130
		if(srv->chatty)
131
			fprint(2, "\t%C\n", m->call);
132
 
133
		m->pg = pg;
134
		sendp(c, m);
135
	}
136
}
137
 
138
static SunProg*
139
sunFindProg(SunSrv *srv, SunMsg *m, SunRpc *rpc, Channel **pc)
140
{
141
	int i, vlo, vhi;
142
	SunProg *pg;
143
 
144
	vlo = 0x7fffffff;
145
	vhi = -1;
146
 
147
	for(i=0; i<srv->nprog; i++){
148
		pg = srv->prog[i];
149
		if(pg->prog != rpc->prog)
150
			continue;
151
		if(pg->vers == rpc->vers){
152
			*pc = srv->cdispatch[i];
153
			return pg;
154
		}
155
		/* right program, wrong version: record range */
156
		if(pg->vers < vlo)
157
			vlo = pg->vers;
158
		if(pg->vers > vhi)
159
			vhi = pg->vers;
160
	}
161
	if(vhi == -1){
162
		if(srv->chatty)
163
			fprint(2, "\tprogram %ud unavailable\n", rpc->prog);
164
		sunMsgReplyError(m, SunProgUnavail);
165
	}else{
166
		/* putting these in rpc is a botch */
167
		rpc->low = vlo;
168
		rpc->high = vhi;
169
		if(srv->chatty)
170
			fprint(2, "\tversion %ud unavailable; have %d-%d\n", rpc->vers, vlo, vhi);
171
		sunMsgReplyError(m, SunProgMismatch);
172
	}
173
	return nil;
174
}
175
 
176
static void
177
sunRpcReplyThread(void *v)
178
{
179
	SunMsg *m;
180
	SunSrv *srv = v;
181
 
182
	while((m = recvp(srv->creply)) != nil){
183
		/* could record in cache here? */
184
		sendp(m->creply, m);
185
	}	
186
}
187
 
188
int
189
sunMsgReplyError(SunMsg *m, SunStatus error)
190
{
191
	uchar *p, *bp, *ep;
192
	int n;
193
 
194
	m->rpc.status = error;
195
	m->rpc.iscall = 0;
196
	m->rpc.verf.flavor = SunAuthNone;
197
	m->rpc.data = nil;
198
	m->rpc.ndata = 0;
199
 
200
	if(m->srv->chatty)
201
		fprint(2, "out: %B\n", &m->rpc);
202
 
203
	n = sunRpcSize(&m->rpc);
204
	bp = emalloc(n);
205
	ep = bp+n;
206
	p = bp;
207
	if(sunRpcPack(p, ep, &p, &m->rpc) < 0){
208
		fprint(2, "sunRpcPack failed\n");
209
		sunMsgDrop(m);
210
		return 0;
211
	}
212
	if(p != ep){
213
		fprint(2, "sunMsgReplyError: rpc sizes didn't work out\n");
214
		sunMsgDrop(m);
215
		return 0;
216
	}
217
	free(m->data);
218
	m->data = bp;
219
	m->count = n;
220
	sendp(m->srv->creply, m);
221
	return 0;
222
}
223
 
224
int
225
sunMsgReply(SunMsg *m, SunCall *c)
226
{
227
	int n1, n2;
228
	uchar *bp, *p, *ep;
229
 
230
	c->type = m->call->type+1;
231
	c->rpc.iscall = 0;
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;
236
 
237
	if(m->srv->chatty){
238
		fprint(2, "out: %B\n", &c->rpc);
239
		fprint(2, "\t%C\n", c);
240
	}
241
 
242
	n1 = sunRpcSize(&c->rpc);
243
	n2 = sunCallSize(m->pg, c);
244
 
245
	bp = emalloc(n1+n2);
246
	ep = bp+n1+n2;
247
	p = bp;
248
	if(sunRpcPack(p, ep, &p, &c->rpc) != SunSuccess){
249
		fprint(2, "sunRpcPack failed\n");
250
		return sunMsgDrop(m);
251
	}
252
	if(sunCallPack(m->pg, p, ep, &p, c) != SunSuccess){
253
		fprint(2, "pg->pack failed\n");
254
		return sunMsgDrop(m);
255
	}
256
	if(p != ep){
257
		fprint(2, "sunMsgReply: sizes didn't work out\n");
258
		return sunMsgDrop(m);
259
	}
260
	free(m->data);
261
	m->data = bp;
262
	m->count = n1+n2;
263
 
264
	sendp(m->srv->creply, m);
265
	return 0;
266
}
267
 
268
int
269
sunMsgDrop(SunMsg *m)
270
{
271
	free(m->data);
272
	free(m->call);
273
	memset(m, 0xFB, sizeof *m);
274
	free(m);
275
	return 0;
276
}
277