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