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