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