]> git.lizzy.rs Git - plan9front.git/blob - sys/src/liboventi/client.c
ether8169: fix Macv45
[plan9front.git] / sys / src / liboventi / client.c
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 *
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         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
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 *
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
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
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
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
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
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
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 *
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 *
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 }