123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- #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;
- }
|