#include <u.h>#include <libc.h>#include <venti.h> static char *okvers[] = { "02", nil,}; /*static char EBigString[] = "string too long";static char EBigPacket[] = "packet too long";static char ENullString[] = "missing string";*/static char EBadVersion[] = "bad format in version string"; static intvtreadversion(VtConn *z, char *q, char *v, int nv){ int n; for(;;){ if(nv <= 1){ werrstr("version too long"); return -1; } n = read(z->infd, v, 1); if(n <= 0){ if(n == 0) werrstr("unexpected eof"); return -1; } if(*v == '\n'){ *v = 0; break; } if((uchar)*v < ' ' || (uchar)*v > 0x7f || (*q && *v != *q)){ werrstr(EBadVersion); return -1; } v++; nv--; if(*q) q++; } return 0;} intvtversion(VtConn *z){ char buf[VtMaxStringSize], *p, *ep, *prefix, *pp; int i; qlock(&z->lk); if(z->state != VtStateAlloc){ werrstr("bad session state"); qunlock(&z->lk); return -1; } qlock(&z->inlk); qlock(&z->outlk); p = buf; ep = buf + sizeof buf; prefix = "venti-"; p = seprint(p, ep, "%s", prefix); p += strlen(p); for(i=0; okvers[i]; i++) p = seprint(p, ep, "%s%s", i ? ":" : "", okvers[i]); p = seprint(p, ep, "-libventi\n"); assert(p-buf < sizeof buf); if(write(z->outfd, buf, p-buf) != p-buf) goto Err; vtdebug(z, "version string out: %s", buf); if(vtreadversion(z, prefix, buf, sizeof buf) < 0) goto Err; vtdebug(z, "version string in: %s", buf); p = buf+strlen(prefix); for(; *p; p=pp){ if(*p == ':' || *p == '-') p++; pp = strpbrk(p, ":-"); if(pp == nil) pp = p+strlen(p); for(i=0; okvers[i]; i++) if(strlen(okvers[i]) == pp-p && memcmp(okvers[i], p, pp-p) == 0){ *pp = 0; z->version = vtstrdup(p); goto Okay; } } werrstr("unable to negotiate version"); goto Err; Okay: z->state = VtStateConnected; qunlock(&z->inlk); qunlock(&z->outlk); qunlock(&z->lk); return 0; Err: werrstr("vtversion: %r"); if(z->infd >= 0) close(z->infd); if(z->outfd >= 0 && z->outfd != z->infd) close(z->outfd); z->infd = -1; z->outfd = -1; z->state = VtStateClosed; qunlock(&z->inlk); qunlock(&z->outlk); qunlock(&z->lk); return -1;}
#include <u.h>
#include <libc.h>
#include <venti.h>
static char *okvers[] = {
"02",
nil,
};
/*
static char EBigString[] = "string too long";
static char EBigPacket[] = "packet too long";
static char ENullString[] = "missing string";
*/
static char EBadVersion[] = "bad format in version string";
static int
vtreadversion(VtConn *z, char *q, char *v, int nv)
{
int n;
for(;;){
if(nv <= 1){
werrstr("version too long");
return -1;
}
n = read(z->infd, v, 1);
if(n <= 0){
if(n == 0)
werrstr("unexpected eof");
return -1;
}
if(*v == '\n'){
*v = 0;
break;
}
if((uchar)*v < ' ' || (uchar)*v > 0x7f || (*q && *v != *q)){
werrstr(EBadVersion);
return -1;
}
v++;
nv--;
if(*q)
q++;
}
return 0;
}
int
vtversion(VtConn *z)
{
char buf[VtMaxStringSize], *p, *ep, *prefix, *pp;
int i;
qlock(&z->lk);
if(z->state != VtStateAlloc){
werrstr("bad session state");
qunlock(&z->lk);
return -1;
}
qlock(&z->inlk);
qlock(&z->outlk);
p = buf;
ep = buf + sizeof buf;
prefix = "venti-";
p = seprint(p, ep, "%s", prefix);
p += strlen(p);
for(i=0; okvers[i]; i++)
p = seprint(p, ep, "%s%s", i ? ":" : "", okvers[i]);
p = seprint(p, ep, "-libventi\n");
assert(p-buf < sizeof buf);
if(write(z->outfd, buf, p-buf) != p-buf)
goto Err;
vtdebug(z, "version string out: %s", buf);
if(vtreadversion(z, prefix, buf, sizeof buf) < 0)
goto Err;
vtdebug(z, "version string in: %s", buf);
p = buf+strlen(prefix);
for(; *p; p=pp){
if(*p == ':' || *p == '-')
p++;
pp = strpbrk(p, ":-");
if(pp == nil)
pp = p+strlen(p);
for(i=0; okvers[i]; i++)
if(strlen(okvers[i]) == pp-p && memcmp(okvers[i], p, pp-p) == 0){
*pp = 0;
z->version = vtstrdup(p);
goto Okay;
}
}
werrstr("unable to negotiate version");
goto Err;
Okay:
z->state = VtStateConnected;
qunlock(&z->inlk);
qunlock(&z->outlk);
qunlock(&z->lk);
return 0;
Err:
werrstr("vtversion: %r");
if(z->infd >= 0)
close(z->infd);
if(z->outfd >= 0 && z->outfd != z->infd)
close(z->outfd);
z->infd = -1;
z->outfd = -1;
z->state = VtStateClosed;
qunlock(&z->inlk);
qunlock(&z->outlk);
qunlock(&z->lk);
return -1;
}