/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <oventi.h>#include "session.h" static char EProtocolBotch[] = "venti protocol botch";static char ELumpSize[] = "illegal lump size";static char ENotConnected[] = "not connected to venti server"; static Packet *vtRPC(VtSession *z, int op, Packet *p); VtSession *vtClientAlloc(void){ VtSession *z = vtAlloc(); return z;} VtSession *vtDial(char *host, int canfail){ VtSession *z; int fd; char *na; char e[ERRMAX]; if(host == nil) host = getenv("venti"); if(host == nil) host = "$venti"; if (host == nil) { if (!canfail) werrstr("no venti host set"); na = ""; fd = -1; } else { na = netmkaddr(host, 0, "venti"); fd = dial(na, 0, 0, 0); } if(fd < 0){ rerrstr(e, sizeof e); if(!canfail){ vtSetError("venti dialstring %s: %s", na, e); return nil; } } z = vtClientAlloc(); if(fd < 0) strcpy(z->fderror, e); vtSetFd(z, fd); return z;} intvtRedial(VtSession *z, char *host){ int fd; char *na; if(host == nil) host = getenv("venti"); if(host == nil) host = "$venti"; na = netmkaddr(host, 0, "venti"); fd = dial(na, 0, 0, 0); if(fd < 0){ vtOSError(); return 0; } vtReset(z); vtSetFd(z, fd); return 1;} VtSession *vtStdioServer(char *server){ int pfd[2]; VtSession *z; if(server == nil) return nil; if(access(server, AEXEC) < 0) { vtOSError(); return nil; } if(pipe(pfd) < 0) { vtOSError(); return nil; } switch(fork()) { case -1: close(pfd[0]); close(pfd[1]); vtOSError(); return nil; case 0: close(pfd[0]); dup(pfd[1], 0); dup(pfd[1], 1); execl(server, "ventiserver", "-i", nil); exits("exec failed"); } close(pfd[1]); z = vtClientAlloc(); vtSetFd(z, pfd[0]); return z;} intvtPing(VtSession *z){ Packet *p = packetAlloc(); p = vtRPC(z, VtQPing, p); if(p == nil) return 0; packetFree(p); return 1;} intvtHello(VtSession *z){ Packet *p; uchar buf[10]; char *sid; int crypto, codec; sid = nil; p = packetAlloc(); if(!vtAddString(p, vtGetVersion(z))) goto Err; if(!vtAddString(p, vtGetUid(z))) goto Err; buf[0] = vtGetCryptoStrength(z); buf[1] = 0; buf[2] = 0; packetAppend(p, buf, 3); p = vtRPC(z, VtQHello, p); if(p == nil) return 0; if(!vtGetString(p, &sid)) goto Err; if(!packetConsume(p, buf, 2)) goto Err; if(packetSize(p) != 0) { vtSetError(EProtocolBotch); goto Err; } crypto = buf[0]; codec = buf[1]; USED(crypto); USED(codec); packetFree(p); vtLock(z->lk); z->sid = sid; z->auth.state = VtAuthOK; vtSha1Free(z->inHash); z->inHash = nil; vtSha1Free(z->outHash); z->outHash = nil; vtUnlock(z->lk); return 1;Err: packetFree(p); vtMemFree(sid); return 0;} intvtSync(VtSession *z){ Packet *p = packetAlloc(); p = vtRPC(z, VtQSync, p); if(p == nil) return 0; if(packetSize(p) != 0){ vtSetError(EProtocolBotch); goto Err; } packetFree(p); return 1; Err: packetFree(p); return 0;} intvtWrite(VtSession *z, uchar score[VtScoreSize], int type, uchar *buf, int n){ Packet *p = packetAlloc(); packetAppend(p, buf, n); return vtWritePacket(z, score, type, p);} intvtWritePacket(VtSession *z, uchar score[VtScoreSize], int type, Packet *p){ int n = packetSize(p); uchar *hdr; if(n > VtMaxLumpSize || n < 0) { vtSetError(ELumpSize); goto Err; } if(n == 0) { memmove(score, vtZeroScore, VtScoreSize); return 1; } hdr = packetHeader(p, 4); hdr[0] = type; hdr[1] = 0; /* pad */ hdr[2] = 0; /* pad */ hdr[3] = 0; /* pad */ p = vtRPC(z, VtQWrite, p); if(p == nil) return 0; if(!packetConsume(p, score, VtScoreSize)) goto Err; if(packetSize(p) != 0) { vtSetError(EProtocolBotch); goto Err; } packetFree(p); return 1;Err: packetFree(p); return 0;} intvtRead(VtSession *z, uchar score[VtScoreSize], int type, uchar *buf, int n){ Packet *p; p = vtReadPacket(z, score, type, n); if(p == nil) return -1; n = packetSize(p); packetCopy(p, buf, 0, n); packetFree(p); return n;} Packet *vtReadPacket(VtSession *z, uchar score[VtScoreSize], int type, int n){ Packet *p; uchar buf[10]; if(n < 0 || n > VtMaxLumpSize) { vtSetError(ELumpSize); return nil; } p = packetAlloc(); if(memcmp(score, vtZeroScore, VtScoreSize) == 0) return p; packetAppend(p, score, VtScoreSize); buf[0] = type; buf[1] = 0; /* pad */ buf[2] = n >> 8; buf[3] = n; packetAppend(p, buf, 4); return vtRPC(z, VtQRead, p);} static Packet *vtRPC(VtSession *z, int op, Packet *p){ uchar *hdr, buf[2]; char *err; if(z == nil){ vtSetError(ENotConnected); return nil; } /* * single threaded for the momment */ vtLock(z->lk); if(z->cstate != VtStateConnected){ vtSetError(ENotConnected); goto Err; } hdr = packetHeader(p, 2); hdr[0] = op; /* op */ hdr[1] = 0; /* tid */ vtDebug(z, "client send: "); vtDebugMesg(z, p, "\n"); if(!vtSendPacket(z, p)) { p = nil; goto Err; } p = vtRecvPacket(z); if(p == nil) goto Err; vtDebug(z, "client recv: "); vtDebugMesg(z, p, "\n"); if(!packetConsume(p, buf, 2)) goto Err; if(buf[0] == VtRError) { if(!vtGetString(p, &err)) { vtSetError(EProtocolBotch); goto Err; } vtSetError(err); vtMemFree(err); packetFree(p); vtUnlock(z->lk); return nil; } if(buf[0] != op+1 || buf[1] != 0) { vtSetError(EProtocolBotch); goto Err; } vtUnlock(z->lk); return p;Err: vtDebug(z, "vtRPC failed: %s\n", vtGetError()); if(p != nil) packetFree(p); vtUnlock(z->lk); vtDisconnect(z, 1); return nil;}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#include <u.h>
#include <libc.h>
#include <oventi.h>
#include "session.h"
static char EProtocolBotch[] = "venti protocol botch";
static char ELumpSize[] = "illegal lump size";
static char ENotConnected[] = "not connected to venti server";
static Packet *vtRPC(VtSession *z, int op, Packet *p);
VtSession *
vtClientAlloc(void)
{
VtSession *z = vtAlloc();
return z;
}
VtSession *
vtDial(char *host, int canfail)
{
VtSession *z;
int fd;
char *na;
char e[ERRMAX];
if(host == nil)
host = getenv("venti");
if(host == nil)
host = "$venti";
if (host == nil) {
if (!canfail)
werrstr("no venti host set");
na = "";
fd = -1;
} else {
na = netmkaddr(host, 0, "venti");
fd = dial(na, 0, 0, 0);
}
if(fd < 0){
rerrstr(e, sizeof e);
if(!canfail){
vtSetError("venti dialstring %s: %s", na, e);
return nil;
}
}
z = vtClientAlloc();
if(fd < 0)
strcpy(z->fderror, e);
vtSetFd(z, fd);
return z;
}
int
vtRedial(VtSession *z, char *host)
{
int fd;
char *na;
if(host == nil)
host = getenv("venti");
if(host == nil)
host = "$venti";
na = netmkaddr(host, 0, "venti");
fd = dial(na, 0, 0, 0);
if(fd < 0){
vtOSError();
return 0;
}
vtReset(z);
vtSetFd(z, fd);
return 1;
}
VtSession *
vtStdioServer(char *server)
{
int pfd[2];
VtSession *z;
if(server == nil)
return nil;
if(access(server, AEXEC) < 0) {
vtOSError();
return nil;
}
if(pipe(pfd) < 0) {
vtOSError();
return nil;
}
switch(fork()) {
case -1:
close(pfd[0]);
close(pfd[1]);
vtOSError();
return nil;
case 0:
close(pfd[0]);
dup(pfd[1], 0);
dup(pfd[1], 1);
execl(server, "ventiserver", "-i", nil);
exits("exec failed");
}
close(pfd[1]);
z = vtClientAlloc();
vtSetFd(z, pfd[0]);
return z;
}
int
vtPing(VtSession *z)
{
Packet *p = packetAlloc();
p = vtRPC(z, VtQPing, p);
if(p == nil)
return 0;
packetFree(p);
return 1;
}
int
vtHello(VtSession *z)
{
Packet *p;
uchar buf[10];
char *sid;
int crypto, codec;
sid = nil;
p = packetAlloc();
if(!vtAddString(p, vtGetVersion(z)))
goto Err;
if(!vtAddString(p, vtGetUid(z)))
goto Err;
buf[0] = vtGetCryptoStrength(z);
buf[1] = 0;
buf[2] = 0;
packetAppend(p, buf, 3);
p = vtRPC(z, VtQHello, p);
if(p == nil)
return 0;
if(!vtGetString(p, &sid))
goto Err;
if(!packetConsume(p, buf, 2))
goto Err;
if(packetSize(p) != 0) {
vtSetError(EProtocolBotch);
goto Err;
}
crypto = buf[0];
codec = buf[1];
USED(crypto);
USED(codec);
packetFree(p);
vtLock(z->lk);
z->sid = sid;
z->auth.state = VtAuthOK;
vtSha1Free(z->inHash);
z->inHash = nil;
vtSha1Free(z->outHash);
z->outHash = nil;
vtUnlock(z->lk);
return 1;
Err:
packetFree(p);
vtMemFree(sid);
return 0;
}
int
vtSync(VtSession *z)
{
Packet *p = packetAlloc();
p = vtRPC(z, VtQSync, p);
if(p == nil)
return 0;
if(packetSize(p) != 0){
vtSetError(EProtocolBotch);
goto Err;
}
packetFree(p);
return 1;
Err:
packetFree(p);
return 0;
}
int
vtWrite(VtSession *z, uchar score[VtScoreSize], int type, uchar *buf, int n)
{
Packet *p = packetAlloc();
packetAppend(p, buf, n);
return vtWritePacket(z, score, type, p);
}
int
vtWritePacket(VtSession *z, uchar score[VtScoreSize], int type, Packet *p)
{
int n = packetSize(p);
uchar *hdr;
if(n > VtMaxLumpSize || n < 0) {
vtSetError(ELumpSize);
goto Err;
}
if(n == 0) {
memmove(score, vtZeroScore, VtScoreSize);
return 1;
}
hdr = packetHeader(p, 4);
hdr[0] = type;
hdr[1] = 0; /* pad */
hdr[2] = 0; /* pad */
hdr[3] = 0; /* pad */
p = vtRPC(z, VtQWrite, p);
if(p == nil)
return 0;
if(!packetConsume(p, score, VtScoreSize))
goto Err;
if(packetSize(p) != 0) {
vtSetError(EProtocolBotch);
goto Err;
}
packetFree(p);
return 1;
Err:
packetFree(p);
return 0;
}
int
vtRead(VtSession *z, uchar score[VtScoreSize], int type, uchar *buf, int n)
{
Packet *p;
p = vtReadPacket(z, score, type, n);
if(p == nil)
return -1;
n = packetSize(p);
packetCopy(p, buf, 0, n);
packetFree(p);
return n;
}
Packet *
vtReadPacket(VtSession *z, uchar score[VtScoreSize], int type, int n)
{
Packet *p;
uchar buf[10];
if(n < 0 || n > VtMaxLumpSize) {
vtSetError(ELumpSize);
return nil;
}
p = packetAlloc();
if(memcmp(score, vtZeroScore, VtScoreSize) == 0)
return p;
packetAppend(p, score, VtScoreSize);
buf[0] = type;
buf[1] = 0; /* pad */
buf[2] = n >> 8;
buf[3] = n;
packetAppend(p, buf, 4);
return vtRPC(z, VtQRead, p);
}
static Packet *
vtRPC(VtSession *z, int op, Packet *p)
{
uchar *hdr, buf[2];
char *err;
if(z == nil){
vtSetError(ENotConnected);
return nil;
}
/*
* single threaded for the momment
*/
vtLock(z->lk);
if(z->cstate != VtStateConnected){
vtSetError(ENotConnected);
goto Err;
}
hdr = packetHeader(p, 2);
hdr[0] = op; /* op */
hdr[1] = 0; /* tid */
vtDebug(z, "client send: ");
vtDebugMesg(z, p, "\n");
if(!vtSendPacket(z, p)) {
p = nil;
goto Err;
}
p = vtRecvPacket(z);
if(p == nil)
goto Err;
vtDebug(z, "client recv: ");
vtDebugMesg(z, p, "\n");
if(!packetConsume(p, buf, 2))
goto Err;
if(buf[0] == VtRError) {
if(!vtGetString(p, &err)) {
vtSetError(EProtocolBotch);
goto Err;
}
vtSetError(err);
vtMemFree(err);
packetFree(p);
vtUnlock(z->lk);
return nil;
}
if(buf[0] != op+1 || buf[1] != 0) {
vtSetError(EProtocolBotch);
goto Err;
}
vtUnlock(z->lk);
return p;
Err:
vtDebug(z, "vtRPC failed: %s\n", vtGetError());
if(p != nil)
packetFree(p);
vtUnlock(z->lk);
vtDisconnect(z, 1);
return nil;
}