xref: /plan9/sys/src/liboventi/client.c (revision 368c31ab13393dea083228fdd1c3445076f83a4b)
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 *
vtClientAlloc(void)13 vtClientAlloc(void)
14 {
15 	VtSession *z = vtAlloc();
16 	return z;
17 }
18 
19 VtSession *
vtDial(char * host,int canfail)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
vtRedial(VtSession * z,char * host)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 *
vtStdioServer(char * server)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
vtPing(VtSession * z)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
vtHello(VtSession * z)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
vtSync(VtSession * z)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
vtWrite(VtSession * z,uchar score[VtScoreSize],int type,uchar * buf,int n)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
vtWritePacket(VtSession * z,uchar score[VtScoreSize],int type,Packet * p)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
vtRead(VtSession * z,uchar score[VtScoreSize],int type,uchar * buf,int n)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 *
vtReadPacket(VtSession * z,uchar score[VtScoreSize],int type,int n)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 *
vtRPC(VtSession * z,int op,Packet * p)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 }
347