Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <venti.h>
5 static char *okvers[] = {
6 "02",
7 nil,
8 };
10 /*
11 static char EBigString[] = "string too long";
12 static char EBigPacket[] = "packet too long";
13 static char ENullString[] = "missing string";
14 */
15 static char EBadVersion[] = "bad format in version string";
17 static int
18 vtreadversion(VtConn *z, char *q, char *v, int nv)
19 {
20 int n;
22 for(;;){
23 if(nv <= 1){
24 werrstr("version too long");
25 return -1;
26 }
27 n = read(z->infd, v, 1);
28 if(n <= 0){
29 if(n == 0)
30 werrstr("unexpected eof");
31 return -1;
32 }
33 if(*v == '\n'){
34 *v = 0;
35 break;
36 }
37 if((uchar)*v < ' ' || (uchar)*v > 0x7f || (*q && *v != *q)){
38 werrstr(EBadVersion);
39 return -1;
40 }
41 v++;
42 nv--;
43 if(*q)
44 q++;
45 }
46 return 0;
47 }
49 int
50 vtversion(VtConn *z)
51 {
52 char buf[VtMaxStringSize], *p, *ep, *prefix, *pp;
53 int i;
55 qlock(&z->lk);
56 if(z->state != VtStateAlloc){
57 werrstr("bad session state");
58 qunlock(&z->lk);
59 return -1;
60 }
62 qlock(&z->inlk);
63 qlock(&z->outlk);
65 p = buf;
66 ep = buf + sizeof buf;
67 prefix = "venti-";
68 p = seprint(p, ep, "%s", prefix);
69 p += strlen(p);
70 for(i=0; okvers[i]; i++)
71 p = seprint(p, ep, "%s%s", i ? ":" : "", okvers[i]);
72 p = seprint(p, ep, "-libventi\n");
73 assert(p-buf < sizeof buf);
75 if(write(z->outfd, buf, p-buf) != p-buf)
76 goto Err;
77 vtdebug(z, "version string out: %s", buf);
79 if(vtreadversion(z, prefix, buf, sizeof buf) < 0)
80 goto Err;
81 vtdebug(z, "version string in: %s", buf);
83 p = buf+strlen(prefix);
84 for(; *p; p=pp){
85 if(*p == ':' || *p == '-')
86 p++;
87 pp = strpbrk(p, ":-");
88 if(pp == nil)
89 pp = p+strlen(p);
90 for(i=0; okvers[i]; i++)
91 if(strlen(okvers[i]) == pp-p && memcmp(okvers[i], p, pp-p) == 0){
92 *pp = 0;
93 z->version = vtstrdup(p);
94 goto Okay;
95 }
96 }
97 werrstr("unable to negotiate version");
98 goto Err;
100 Okay:
101 z->state = VtStateConnected;
102 qunlock(&z->inlk);
103 qunlock(&z->outlk);
104 qunlock(&z->lk);
105 return 0;
107 Err:
108 werrstr("vtversion: %r");
109 if(z->infd >= 0)
110 close(z->infd);
111 if(z->outfd >= 0 && z->outfd != z->infd)
112 close(z->outfd);
113 z->infd = -1;
114 z->outfd = -1;
115 z->state = VtStateClosed;
116 qunlock(&z->inlk);
117 qunlock(&z->outlk);
118 qunlock(&z->lk);
119 return -1;