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