Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <oventi.h>
4
#include "session.h"
5
 
6
static char EProtocolBotch[] = "venti protocol botch";
7
static char ELumpSize[] = "illegal lump size";
8
static char ENotConnected[] = "not connected to venti server";
9
 
10
static Packet *vtRPC(VtSession *z, int op, Packet *p);
11
 
12
VtSession *
13
vtClientAlloc(void)
14
{
15
	VtSession *z = vtAlloc();	
16
	return z;
17
}
18
 
19
VtSession *
20
vtDial(char *host, int canfail)
21
{
22
	VtSession *z;
23
	int fd;
24
	char *na;
25
	char e[ERRMAX];
26
 
27
	if(host == nil) 
28
		host = getenv("venti");
29
	if(host == nil)
30
		host = "$venti";
31
 
32
	if (host == nil) {
33
		if (!canfail)
34
			werrstr("no venti host set");
35
		na = "";
36
		fd = -1;
37
	} else {
38
		na = netmkaddr(host, 0, "venti");
39
		fd = dial(na, 0, 0, 0);
40
	}
41
	if(fd < 0){
42
		rerrstr(e, sizeof e);
43
		if(!canfail){
44
			vtSetError("venti dialstring %s: %s", na, e);
45
			return nil;
46
		}
47
	}
48
	z = vtClientAlloc();
49
	if(fd < 0)
50
		strcpy(z->fderror, e);
51
	vtSetFd(z, fd);
52
	return z;
53
}
54
 
55
int
56
vtRedial(VtSession *z, char *host)
57
{
58
	int fd;
59
	char *na;
60
 
61
	if(host == nil) 
62
		host = getenv("venti");
63
	if(host == nil)
64
		host = "$venti";
65
 
66
	na = netmkaddr(host, 0, "venti");
67
	fd = dial(na, 0, 0, 0);
68
	if(fd < 0){
69
		vtOSError();
70
		return 0;
71
	}
72
	vtReset(z);
73
	vtSetFd(z, fd);
74
	return 1;
75
}
76
 
77
VtSession *
78
vtStdioServer(char *server)
79
{
80
	int pfd[2];
81
	VtSession *z;
82
 
83
	if(server == nil)
84
		return nil;
85
 
86
	if(access(server, AEXEC) < 0) {
87
		vtOSError();
88
		return nil;
89
	}
90
 
91
	if(pipe(pfd) < 0) {
92
		vtOSError();
93
		return nil;
94
	}
95
 
96
	switch(fork()) {
97
	case -1:
98
		close(pfd[0]);
99
		close(pfd[1]);
100
		vtOSError();
101
		return nil;
102
	case 0:
103
		close(pfd[0]);
104
		dup(pfd[1], 0);
105
		dup(pfd[1], 1);
106
		execl(server, "ventiserver", "-i", nil);
107
		exits("exec failed");
108
	}
109
	close(pfd[1]);
110
 
111
	z = vtClientAlloc();
112
	vtSetFd(z, pfd[0]);
113
	return z;
114
}
115
 
116
int
117
vtPing(VtSession *z)
118
{
119
	Packet *p = packetAlloc();
120
 
121
	p = vtRPC(z, VtQPing, p);
122
	if(p == nil)
123
		return 0;
124
	packetFree(p);
125
	return 1;
126
}
127
 
128
int
129
vtHello(VtSession *z)
130
{
131
	Packet *p;
132
	uchar buf[10];
133
	char *sid;
134
	int crypto, codec;
135
 
136
	sid = nil;
137
 
138
	p = packetAlloc();
139
	if(!vtAddString(p, vtGetVersion(z)))
140
		goto Err;
141
	if(!vtAddString(p, vtGetUid(z)))
142
		goto Err;
143
	buf[0] = vtGetCryptoStrength(z);
144
	buf[1] = 0;
145
	buf[2] = 0;
146
	packetAppend(p, buf, 3);
147
	p = vtRPC(z, VtQHello, p);
148
	if(p == nil)
149
		return 0;
150
	if(!vtGetString(p, &sid))
151
		goto Err;
152
	if(!packetConsume(p, buf, 2))
153
		goto Err;
154
	if(packetSize(p) != 0) {
155
		vtSetError(EProtocolBotch);
156
		goto Err;
157
	}
158
	crypto = buf[0];
159
	codec = buf[1];
160
 
161
	USED(crypto);
162
	USED(codec);
163
 
164
	packetFree(p);
165
 
166
	vtLock(z->lk);
167
	z->sid = sid;
168
	z->auth.state = VtAuthOK;
169
	vtSha1Free(z->inHash);
170
	z->inHash = nil;
171
	vtSha1Free(z->outHash);
172
	z->outHash = nil;
173
	vtUnlock(z->lk);
174
 
175
	return 1;
176
Err:
177
	packetFree(p);
178
	vtMemFree(sid);
179
	return 0;
180
}
181
 
182
int
183
vtSync(VtSession *z)
184
{
185
	Packet *p = packetAlloc();
186
 
187
	p = vtRPC(z, VtQSync, p);
188
	if(p == nil)
189
		return 0;
190
	if(packetSize(p) != 0){
191
		vtSetError(EProtocolBotch);
192
		goto Err;
193
	}
194
	packetFree(p);
195
	return 1;
196
 
197
Err:
198
	packetFree(p);
199
	return 0;
200
}
201
 
202
int
203
vtWrite(VtSession *z, uchar score[VtScoreSize], int type, uchar *buf, int n)
204
{
205
	Packet *p = packetAlloc();
206
 
207
	packetAppend(p, buf, n);
208
	return vtWritePacket(z, score, type, p);
209
}
210
 
211
int
212
vtWritePacket(VtSession *z, uchar score[VtScoreSize], int type, Packet *p)
213
{
214
	int n = packetSize(p);
215
	uchar *hdr;
216
 
217
	if(n > VtMaxLumpSize || n < 0) {
218
		vtSetError(ELumpSize);
219
		goto Err;
220
	}
221
 
222
	if(n == 0) {
223
		memmove(score, vtZeroScore, VtScoreSize);
224
		return 1;
225
	}
226
 
227
	hdr = packetHeader(p, 4);
228
	hdr[0] = type;
229
	hdr[1] = 0;	/* pad */
230
	hdr[2] = 0;	/* pad */
231
	hdr[3] = 0;	/* pad */
232
	p = vtRPC(z, VtQWrite, p);
233
	if(p == nil)
234
		return 0;
235
	if(!packetConsume(p, score, VtScoreSize))
236
		goto Err;
237
	if(packetSize(p) != 0) {
238
		vtSetError(EProtocolBotch);
239
		goto Err;
240
	}
241
	packetFree(p);
242
	return 1;
243
Err:
244
	packetFree(p);
245
	return 0;
246
}
247
 
248
int
249
vtRead(VtSession *z, uchar score[VtScoreSize], int type, uchar *buf, int n)
250
{
251
	Packet *p;
252
 
253
	p = vtReadPacket(z, score, type, n);
254
	if(p == nil)
255
		return -1;
256
	n = packetSize(p);
257
	packetCopy(p, buf, 0, n);
258
	packetFree(p);
259
	return n;
260
}
261
 
262
Packet *
263
vtReadPacket(VtSession *z, uchar score[VtScoreSize], int type, int n)
264
{
265
	Packet *p;
266
	uchar buf[10];
267
 
268
	if(n < 0 || n > VtMaxLumpSize) {
269
		vtSetError(ELumpSize);
270
		return nil;
271
	}
272
 
273
	p = packetAlloc();
274
	if(memcmp(score, vtZeroScore, VtScoreSize) == 0)
275
		return p;
276
 
277
	packetAppend(p, score, VtScoreSize);
278
	buf[0] = type;
279
	buf[1] = 0;	/* pad */
280
	buf[2] = n >> 8;
281
	buf[3] = n;
282
	packetAppend(p, buf, 4);
283
	return vtRPC(z, VtQRead, p);
284
}
285
 
286
 
287
static Packet *
288
vtRPC(VtSession *z, int op, Packet *p)
289
{
290
	uchar *hdr, buf[2];
291
	char *err;
292
 
293
	if(z == nil){
294
		vtSetError(ENotConnected);
295
		return nil;
296
	}
297
 
298
	/*
299
	 * single threaded for the momment
300
	 */
301
	vtLock(z->lk);
302
	if(z->cstate != VtStateConnected){
303
		vtSetError(ENotConnected);
304
		goto Err;
305
	}
306
	hdr = packetHeader(p, 2);
307
	hdr[0] = op;	/* op */
308
	hdr[1] = 0;	/* tid */
309
	vtDebug(z, "client send: ");
310
	vtDebugMesg(z, p, "\n");
311
	if(!vtSendPacket(z, p)) {
312
		p = nil;
313
		goto Err;
314
	}
315
	p = vtRecvPacket(z);
316
	if(p == nil)
317
		goto Err;
318
	vtDebug(z, "client recv: ");
319
	vtDebugMesg(z, p, "\n");
320
	if(!packetConsume(p, buf, 2))
321
		goto Err;
322
	if(buf[0] == VtRError) {
323
		if(!vtGetString(p, &err)) {
324
			vtSetError(EProtocolBotch);
325
			goto Err;
326
		}
327
		vtSetError(err);
328
		vtMemFree(err);
329
		packetFree(p);
330
		vtUnlock(z->lk);
331
		return nil;
332
	}
333
	if(buf[0] != op+1 || buf[1] != 0) {
334
		vtSetError(EProtocolBotch);
335
		goto Err;
336
	}
337
	vtUnlock(z->lk);
338
	return p;
339
Err:
340
	vtDebug(z, "vtRPC failed: %s\n", vtGetError());
341
	if(p != nil)
342
		packetFree(p);
343
	vtUnlock(z->lk);
344
	vtDisconnect(z, 1);
345
	return nil;
346
}