remove unused liboventi
This commit is contained in:
parent
ffb0199247
commit
a5268a5413
23 changed files with 0 additions and 4289 deletions
|
@ -1,271 +0,0 @@
|
|||
#pragma lib "liboventi.a"
|
||||
#pragma src "/sys/src/liboventi"
|
||||
|
||||
typedef struct VtSession VtSession;
|
||||
typedef struct VtSha1 VtSha1;
|
||||
typedef struct Packet Packet;
|
||||
typedef struct VtLock VtLock;
|
||||
typedef struct VtRendez VtRendez;
|
||||
typedef struct VtRoot VtRoot;
|
||||
typedef struct VtEntry VtEntry;
|
||||
typedef struct VtServerVtbl VtServerVtbl;
|
||||
|
||||
#pragma incomplete VtSession
|
||||
#pragma incomplete VtSha1
|
||||
#pragma incomplete Packet
|
||||
#pragma incomplete VtLock
|
||||
#pragma incomplete VtRendez
|
||||
|
||||
enum {
|
||||
VtScoreSize = 20, /* Venti */
|
||||
VtMaxLumpSize = 56*1024,
|
||||
VtPointerDepth = 7,
|
||||
VtEntrySize = 40,
|
||||
VtRootSize = 300,
|
||||
VtMaxStringSize = 1000,
|
||||
VtAuthSize = 1024, /* size of auth group - in bits - must be multiple of 8 */
|
||||
MaxFragSize = 9*1024,
|
||||
VtMaxFileSize = (1ULL<<48) - 1,
|
||||
VtRootVersion = 2,
|
||||
};
|
||||
|
||||
/* crypto strengths */
|
||||
enum {
|
||||
VtCryptoStrengthNone,
|
||||
VtCryptoStrengthAuth,
|
||||
VtCryptoStrengthWeak,
|
||||
VtCryptoStrengthStrong,
|
||||
};
|
||||
|
||||
/* crypto suites */
|
||||
enum {
|
||||
VtCryptoNone,
|
||||
VtCryptoSSL3,
|
||||
VtCryptoTLS1,
|
||||
|
||||
VtCryptoMax
|
||||
};
|
||||
|
||||
/* codecs */
|
||||
enum {
|
||||
VtCodecNone,
|
||||
|
||||
VtCodecDeflate,
|
||||
VtCodecThwack,
|
||||
|
||||
VtCodecMax
|
||||
};
|
||||
|
||||
/* Lump Types */
|
||||
enum {
|
||||
VtErrType, /* illegal */
|
||||
|
||||
VtRootType,
|
||||
VtDirType,
|
||||
VtPointerType0,
|
||||
VtPointerType1,
|
||||
VtPointerType2,
|
||||
VtPointerType3,
|
||||
VtPointerType4,
|
||||
VtPointerType5,
|
||||
VtPointerType6,
|
||||
VtPointerType7, /* not used */
|
||||
VtPointerType8, /* not used */
|
||||
VtPointerType9, /* not used */
|
||||
VtDataType,
|
||||
|
||||
VtMaxType
|
||||
};
|
||||
|
||||
/* Dir Entry flags */
|
||||
enum {
|
||||
VtEntryActive = (1<<0), /* entry is in use */
|
||||
VtEntryDir = (1<<1), /* a directory */
|
||||
VtEntryDepthShift = 2, /* shift for pointer depth */
|
||||
VtEntryDepthMask = (0x7<<2), /* mask for pointer depth */
|
||||
VtEntryLocal = (1<<5), /* used for local storage: should not be set for Venti blocks */
|
||||
VtEntryNoArchive = (1<<6), /* used for local storage: should not be set for Venti blocks */
|
||||
};
|
||||
|
||||
struct VtRoot {
|
||||
ushort version;
|
||||
char name[128];
|
||||
char type[128];
|
||||
uchar score[VtScoreSize]; /* to a Dir block */
|
||||
ushort blockSize; /* maximum block size */
|
||||
uchar prev[VtScoreSize]; /* last root block */
|
||||
};
|
||||
|
||||
struct VtEntry {
|
||||
ulong gen; /* generation number */
|
||||
ushort psize; /* pointer block size */
|
||||
ushort dsize; /* data block size */
|
||||
uchar depth; /* unpacked from flags */
|
||||
uchar flags;
|
||||
uvlong size;
|
||||
uchar score[VtScoreSize];
|
||||
};
|
||||
|
||||
struct VtServerVtbl {
|
||||
Packet *(*read)(VtSession*, uchar score[VtScoreSize], int type, int n);
|
||||
int (*write)(VtSession*, uchar score[VtScoreSize], int type, Packet *p);
|
||||
void (*closing)(VtSession*, int clean);
|
||||
void (*sync)(VtSession*);
|
||||
};
|
||||
|
||||
/* versions */
|
||||
enum {
|
||||
/* experimental versions */
|
||||
VtVersion01 = 1,
|
||||
VtVersion02,
|
||||
};
|
||||
|
||||
/* score of zero length block */
|
||||
extern uchar vtZeroScore[VtScoreSize];
|
||||
|
||||
/* both sides */
|
||||
void vtAttach(void);
|
||||
void vtDetach(void);
|
||||
void vtClose(VtSession *s);
|
||||
void vtFree(VtSession *s);
|
||||
char *vtGetUid(VtSession *s);
|
||||
char *vtGetSid(VtSession *s);
|
||||
int vtSetDebug(VtSession *s, int);
|
||||
int vtGetDebug(VtSession *s);
|
||||
int vtSetFd(VtSession *s, int fd);
|
||||
int vtGetFd(VtSession *s);
|
||||
int vtConnect(VtSession *s, char *password);
|
||||
int vtSetCryptoStrength(VtSession *s, int);
|
||||
int vtGetCryptoStrength(VtSession *s);
|
||||
int vtSetCompression(VtSession *s, int);
|
||||
int vtGetCompression(VtSession *s);
|
||||
int vtGetCrypto(VtSession *s);
|
||||
int vtGetCodec(VtSession *s);
|
||||
char *vtGetVersion(VtSession *s);
|
||||
char *vtGetError(void);
|
||||
int vtErrFmt(Fmt *fmt);
|
||||
void vtDebug(VtSession*, char *, ...);
|
||||
void vtDebugMesg(VtSession *z, Packet *p, char *s);
|
||||
|
||||
/* internal */
|
||||
VtSession *vtAlloc(void);
|
||||
void vtReset(VtSession*);
|
||||
int vtAddString(Packet*, char*);
|
||||
int vtGetString(Packet*, char**);
|
||||
int vtSendPacket(VtSession*, Packet*);
|
||||
Packet *vtRecvPacket(VtSession*);
|
||||
void vtDisconnect(VtSession*, int);
|
||||
int vtHello(VtSession*);
|
||||
|
||||
/* client side */
|
||||
VtSession *vtClientAlloc(void);
|
||||
VtSession *vtDial(char *server, int canfail);
|
||||
int vtRedial(VtSession*, char *server);
|
||||
VtSession *vtStdioServer(char *server);
|
||||
int vtPing(VtSession *s);
|
||||
int vtSetUid(VtSession*, char *uid);
|
||||
int vtRead(VtSession*, uchar score[VtScoreSize], int type, uchar *buf, int n);
|
||||
int vtWrite(VtSession*, uchar score[VtScoreSize], int type, uchar *buf, int n);
|
||||
Packet *vtReadPacket(VtSession*, uchar score[VtScoreSize], int type, int n);
|
||||
int vtWritePacket(VtSession*, uchar score[VtScoreSize], int type, Packet *p);
|
||||
int vtSync(VtSession *s);
|
||||
|
||||
int vtZeroExtend(int type, uchar *buf, int n, int nn);
|
||||
int vtZeroTruncate(int type, uchar *buf, int n);
|
||||
int vtParseScore(char*, uint, uchar[VtScoreSize]);
|
||||
|
||||
void vtRootPack(VtRoot*, uchar*);
|
||||
int vtRootUnpack(VtRoot*, uchar*);
|
||||
void vtEntryPack(VtEntry*, uchar*, int index);
|
||||
int vtEntryUnpack(VtEntry*, uchar*, int index);
|
||||
|
||||
/* server side */
|
||||
VtSession *vtServerAlloc(VtServerVtbl*);
|
||||
int vtSetSid(VtSession *s, char *sid);
|
||||
int vtExport(VtSession *s);
|
||||
|
||||
/* sha1 */
|
||||
VtSha1* vtSha1Alloc(void);
|
||||
void vtSha1Free(VtSha1*);
|
||||
void vtSha1Init(VtSha1*);
|
||||
void vtSha1Update(VtSha1*, uchar *, int n);
|
||||
void vtSha1Final(VtSha1*, uchar sha1[VtScoreSize]);
|
||||
void vtSha1(uchar score[VtScoreSize], uchar *, int);
|
||||
int vtSha1Check(uchar score[VtScoreSize], uchar *, int);
|
||||
int vtScoreFmt(Fmt *fmt);
|
||||
|
||||
/* Packet */
|
||||
Packet *packetAlloc(void);
|
||||
void packetFree(Packet*);
|
||||
Packet *packetForeign(uchar *buf, int n, void (*free)(void *a), void *a);
|
||||
Packet *packetDup(Packet*, int offset, int n);
|
||||
Packet *packetSplit(Packet*, int n);
|
||||
int packetConsume(Packet*, uchar *buf, int n);
|
||||
int packetTrim(Packet*, int offset, int n);
|
||||
uchar *packetHeader(Packet*, int n);
|
||||
uchar *packetTrailer(Packet*, int n);
|
||||
int packetPrefix(Packet*, uchar *buf, int n);
|
||||
int packetAppend(Packet*, uchar *buf, int n);
|
||||
int packetConcat(Packet*, Packet*);
|
||||
uchar *packetPeek(Packet*, uchar *buf, int offset, int n);
|
||||
int packetCopy(Packet*, uchar *buf, int offset, int n);
|
||||
int packetFragments(Packet*, IOchunk*, int nio, int offset);
|
||||
int packetSize(Packet*);
|
||||
int packetAllocatedSize(Packet*);
|
||||
void packetSha1(Packet*, uchar sha1[VtScoreSize]);
|
||||
int packetCompact(Packet*);
|
||||
int packetCmp(Packet*, Packet*);
|
||||
void packetStats(void);
|
||||
|
||||
/* portability stuff - should be a seperate library */
|
||||
|
||||
void vtMemFree(void *);
|
||||
void *vtMemAlloc(int);
|
||||
void *vtMemAllocZ(int);
|
||||
void *vtMemRealloc(void *p, int);
|
||||
void *vtMemBrk(int n);
|
||||
char *vtStrDup(char *);
|
||||
void vtFatal(char *, ...);
|
||||
char *vtGetError(void);
|
||||
char *vtSetError(char *, ...);
|
||||
char *vtOSError(void);
|
||||
|
||||
/* locking/threads */
|
||||
int vtThread(void (*f)(void*), void *rock);
|
||||
void vtThreadSetName(char*);
|
||||
|
||||
VtLock *vtLockAlloc(void);
|
||||
/* void vtLockInit(VtLock**); */
|
||||
void vtLock(VtLock*);
|
||||
int vtCanLock(VtLock*);
|
||||
void vtRLock(VtLock*);
|
||||
int vtCanRLock(VtLock*);
|
||||
void vtUnlock(VtLock*);
|
||||
void vtRUnlock(VtLock*);
|
||||
void vtLockFree(VtLock*);
|
||||
|
||||
VtRendez *vtRendezAlloc(VtLock*);
|
||||
void vtRendezFree(VtRendez*);
|
||||
int vtSleep(VtRendez*);
|
||||
int vtWakeup(VtRendez*);
|
||||
int vtWakeupAll(VtRendez*);
|
||||
|
||||
/* fd functions - really network (socket) functions */
|
||||
void vtFdClose(int);
|
||||
int vtFdRead(int, uchar*, int);
|
||||
int vtFdReadFully(int, uchar*, int);
|
||||
int vtFdWrite(int, uchar*, int);
|
||||
|
||||
/*
|
||||
* formatting
|
||||
* other than noted, these formats all ignore
|
||||
* the width and precision arguments, and all flags
|
||||
*
|
||||
* V a venti score
|
||||
* R venti error
|
||||
*/
|
||||
#pragma varargck type "V" uchar*
|
||||
#pragma varargck type "R" void
|
||||
|
||||
#pragma varargck argpos vtSetError 1
|
||||
|
|
@ -1,346 +0,0 @@
|
|||
#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;
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
#include "session.h"
|
||||
|
||||
void vtDumpSome(Packet*);
|
||||
|
||||
void
|
||||
vtDebug(VtSession *s, char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
if(!s->debug)
|
||||
return;
|
||||
|
||||
va_start(arg, fmt);
|
||||
vfprint(2, fmt, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
void
|
||||
vtDebugMesg(VtSession *z, Packet *p, char *s)
|
||||
{
|
||||
int op;
|
||||
int tid;
|
||||
int n;
|
||||
uchar buf[100], *b;
|
||||
|
||||
|
||||
if(!z->debug)
|
||||
return;
|
||||
n = packetSize(p);
|
||||
if(n < 2) {
|
||||
fprint(2, "runt packet%s", s);
|
||||
return;
|
||||
}
|
||||
b = packetPeek(p, buf, 0, 2);
|
||||
op = b[0];
|
||||
tid = b[1];
|
||||
|
||||
fprint(2, "%c%d[%d] %d", ((op&1)==0)?'R':'Q', op, tid, n);
|
||||
vtDumpSome(p);
|
||||
fprint(2, "%s", s);
|
||||
}
|
||||
|
||||
void
|
||||
vtDumpSome(Packet *pkt)
|
||||
{
|
||||
int printable;
|
||||
int i, n;
|
||||
char buf[200], *q, *eq;
|
||||
uchar data[32], *p;
|
||||
|
||||
n = packetSize(pkt);
|
||||
printable = 1;
|
||||
q = buf;
|
||||
eq = buf + sizeof(buf);
|
||||
q = seprint(q, eq, "(%d) '", n);
|
||||
|
||||
if(n > sizeof(data))
|
||||
n = sizeof(data);
|
||||
p = packetPeek(pkt, data, 0, n);
|
||||
for(i=0; i<n && printable; i++)
|
||||
if((p[i]<32 && p[i] !='\n' && p[i] !='\t') || p[i]>127)
|
||||
printable = 0;
|
||||
if(printable) {
|
||||
for(i=0; i<n; i++)
|
||||
q = seprint(q, eq, "%c", p[i]);
|
||||
} else {
|
||||
for(i=0; i<n; i++) {
|
||||
if(i>0 && i%4==0)
|
||||
q = seprint(q, eq, " ");
|
||||
q = seprint(q, eq, "%.2X", p[i]);
|
||||
}
|
||||
}
|
||||
seprint(q, eq, "'");
|
||||
fprint(2, "%s", buf);
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
|
||||
int
|
||||
vtErrFmt(Fmt *f)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = vtGetError();
|
||||
return fmtstrcpy(f, s);
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
|
||||
void
|
||||
vtFatal(char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, fmt);
|
||||
fprint(2, "fatal error: ");
|
||||
vfprint(2, fmt, arg);
|
||||
fprint(2, "\n");
|
||||
va_end(arg);
|
||||
exits("vtFatal");
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
LIB=/$objtype/lib/liboventi.a
|
||||
|
||||
SYS=plan9
|
||||
|
||||
OFILES=\
|
||||
client.$O\
|
||||
debug.$O\
|
||||
errfmt.$O\
|
||||
fatal.$O\
|
||||
pack.$O\
|
||||
packet.$O\
|
||||
parsescore.$O\
|
||||
readfully.$O\
|
||||
rpc.$O\
|
||||
scorefmt.$O\
|
||||
server.$O\
|
||||
strdup.$O\
|
||||
zero.$O\
|
||||
$SYS-io.$O\
|
||||
$SYS-sha1.$O\
|
||||
$SYS-thread.$O\
|
||||
|
||||
HFILES=\
|
||||
packet.h\
|
||||
session.h\
|
||||
|
||||
UPDATE=\
|
||||
mkfile\
|
||||
$HFILES\
|
||||
${OFILES:%.$O=%.c}\
|
||||
${LIB:/$objtype/%=/386/%}\
|
||||
|
||||
CFLAGS=$CFLAGS
|
||||
|
||||
</sys/src/cmd/mksyslib
|
||||
|
||||
$O.vttest: vttest.$O $OFILES
|
||||
$LD $LDFLAGS -o $target $prereq
|
||||
|
||||
acid: $HFILES packet.c
|
||||
$CC $INC -a packet.c > acid || rm acid
|
||||
|
||||
test: $O.vttest
|
||||
$O.vttest
|
|
@ -1,147 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
|
||||
/*
|
||||
* integer conversion routines
|
||||
*/
|
||||
#define U8GET(p) ((p)[0])
|
||||
#define U16GET(p) (((p)[0]<<8)|(p)[1])
|
||||
#define U32GET(p) ((u32int)(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]))
|
||||
#define U48GET(p) (((vlong)U16GET(p)<<32)|(vlong)U32GET((p)+2))
|
||||
#define U64GET(p) (((vlong)U32GET(p)<<32)|(vlong)U32GET((p)+4))
|
||||
|
||||
#define U8PUT(p,v) (p)[0]=(v)
|
||||
#define U16PUT(p,v) (p)[0]=(v)>>8;(p)[1]=(v)
|
||||
#define U32PUT(p,v) (p)[0]=(v)>>24;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)
|
||||
#define U48PUT(p,v,t32) t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)
|
||||
#define U64PUT(p,v,t32) t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
|
||||
|
||||
static int
|
||||
checkSize(int n)
|
||||
{
|
||||
if(n < 256 || n > VtMaxLumpSize) {
|
||||
vtSetError("bad block size");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
vtRootPack(VtRoot *r, uchar *p)
|
||||
{
|
||||
uchar *op = p;
|
||||
|
||||
U16PUT(p, r->version);
|
||||
p += 2;
|
||||
memmove(p, r->name, sizeof(r->name));
|
||||
p += sizeof(r->name);
|
||||
memmove(p, r->type, sizeof(r->type));
|
||||
p += sizeof(r->type);
|
||||
memmove(p, r->score, VtScoreSize);
|
||||
p += VtScoreSize;
|
||||
U16PUT(p, r->blockSize);
|
||||
p += 2;
|
||||
memmove(p, r->prev, VtScoreSize);
|
||||
p += VtScoreSize;
|
||||
|
||||
assert(p-op == VtRootSize);
|
||||
}
|
||||
|
||||
int
|
||||
vtRootUnpack(VtRoot *r, uchar *p)
|
||||
{
|
||||
uchar *op = p;
|
||||
|
||||
memset(r, 0, sizeof(*r));
|
||||
|
||||
r->version = U16GET(p);
|
||||
if(r->version != VtRootVersion) {
|
||||
vtSetError("unknown root version");
|
||||
return 0;
|
||||
}
|
||||
p += 2;
|
||||
memmove(r->name, p, sizeof(r->name));
|
||||
r->name[sizeof(r->name)-1] = 0;
|
||||
p += sizeof(r->name);
|
||||
memmove(r->type, p, sizeof(r->type));
|
||||
r->type[sizeof(r->type)-1] = 0;
|
||||
p += sizeof(r->type);
|
||||
memmove(r->score, p, VtScoreSize);
|
||||
p += VtScoreSize;
|
||||
r->blockSize = U16GET(p);
|
||||
if(!checkSize(r->blockSize))
|
||||
return 0;
|
||||
p += 2;
|
||||
memmove(r->prev, p, VtScoreSize);
|
||||
p += VtScoreSize;
|
||||
|
||||
assert(p-op == VtRootSize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
vtEntryPack(VtEntry *e, uchar *p, int index)
|
||||
{
|
||||
ulong t32;
|
||||
int flags;
|
||||
uchar *op;
|
||||
|
||||
p += index * VtEntrySize;
|
||||
op = p;
|
||||
|
||||
U32PUT(p, e->gen);
|
||||
p += 4;
|
||||
U16PUT(p, e->psize);
|
||||
p += 2;
|
||||
U16PUT(p, e->dsize);
|
||||
p += 2;
|
||||
flags = e->flags | ((e->depth << VtEntryDepthShift) & VtEntryDepthMask);
|
||||
U8PUT(p, flags);
|
||||
p++;
|
||||
memset(p, 0, 5);
|
||||
p += 5;
|
||||
U48PUT(p, e->size, t32);
|
||||
p += 6;
|
||||
memmove(p, e->score, VtScoreSize);
|
||||
p += VtScoreSize;
|
||||
|
||||
assert(p-op == VtEntrySize);
|
||||
}
|
||||
|
||||
int
|
||||
vtEntryUnpack(VtEntry *e, uchar *p, int index)
|
||||
{
|
||||
uchar *op;
|
||||
|
||||
p += index * VtEntrySize;
|
||||
op = p;
|
||||
|
||||
e->gen = U32GET(p);
|
||||
p += 4;
|
||||
e->psize = U16GET(p);
|
||||
p += 2;
|
||||
e->dsize = U16GET(p);
|
||||
p += 2;
|
||||
e->flags = U8GET(p);
|
||||
e->depth = (e->flags & VtEntryDepthMask) >> VtEntryDepthShift;
|
||||
e->flags &= ~VtEntryDepthMask;
|
||||
p++;
|
||||
p += 5;
|
||||
e->size = U48GET(p);
|
||||
p += 6;
|
||||
memmove(e->score, p, VtScoreSize);
|
||||
p += VtScoreSize;
|
||||
|
||||
assert(p-op == VtEntrySize);
|
||||
|
||||
if(!(e->flags & VtEntryActive))
|
||||
return 1;
|
||||
|
||||
if(!checkSize(e->psize) || !checkSize(e->dsize))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1,848 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
#include "packet.h"
|
||||
|
||||
static Frag *fragAlloc(Packet*, int n, int pos, Frag *next);
|
||||
static Frag *fragDup(Packet*, Frag*);
|
||||
static void fragFree(Frag*);
|
||||
|
||||
static Mem *memAlloc(int, int);
|
||||
static void memFree(Mem*);
|
||||
static int memHead(Mem *m, uchar *rp, int n);
|
||||
static int memTail(Mem *m, uchar *wp, int n);
|
||||
|
||||
static char EPacketSize[] = "bad packet size";
|
||||
static char EPacketOffset[] = "bad packet offset";
|
||||
static char EBadSize[] = "bad size";
|
||||
|
||||
static struct {
|
||||
Lock lk;
|
||||
Packet *packet;
|
||||
int npacket;
|
||||
Frag *frag;
|
||||
int nfrag;
|
||||
Mem *bigMem;
|
||||
int nbigMem;
|
||||
Mem *smallMem;
|
||||
int nsmallMem;
|
||||
} freeList;
|
||||
|
||||
#define FRAGSIZE(f) ((f)->wp - (f)->rp)
|
||||
#define FRAGASIZE(f) ((f)->mem->ep - (f)->mem->bp)
|
||||
|
||||
#define NOTFREE(p) assert((p)->size>=0)
|
||||
|
||||
Packet *
|
||||
packetAlloc(void)
|
||||
{
|
||||
Packet *p;
|
||||
|
||||
lock(&freeList.lk);
|
||||
p = freeList.packet;
|
||||
if(p != nil)
|
||||
freeList.packet = p->next;
|
||||
else
|
||||
freeList.npacket++;
|
||||
unlock(&freeList.lk);
|
||||
|
||||
if(p == nil)
|
||||
p = vtMemBrk(sizeof(Packet));
|
||||
else
|
||||
assert(p->size == -1);
|
||||
p->size = 0;
|
||||
p->asize = 0;
|
||||
p->first = nil;
|
||||
p->last = nil;
|
||||
p->next = nil;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
packetFree(Packet *p)
|
||||
{
|
||||
Frag *f, *ff;
|
||||
|
||||
if(0)fprint(2, "packetFree %p\n", p);
|
||||
|
||||
NOTFREE(p);
|
||||
p->size = -1;
|
||||
|
||||
for(f=p->first; f!=nil; f=ff) {
|
||||
ff = f->next;
|
||||
fragFree(f);
|
||||
}
|
||||
p->first = nil;
|
||||
p->last = nil;
|
||||
|
||||
lock(&freeList.lk);
|
||||
p->next = freeList.packet;
|
||||
freeList.packet = p;
|
||||
unlock(&freeList.lk);
|
||||
}
|
||||
|
||||
Packet *
|
||||
packetDup(Packet *p, int offset, int n)
|
||||
{
|
||||
Frag *f, *ff;
|
||||
Packet *pp;
|
||||
|
||||
NOTFREE(p);
|
||||
if(offset < 0 || n < 0 || offset+n > p->size) {
|
||||
vtSetError(EBadSize);
|
||||
return nil;
|
||||
}
|
||||
|
||||
pp = packetAlloc();
|
||||
if(n == 0)
|
||||
return pp;
|
||||
|
||||
pp->size = n;
|
||||
|
||||
/* skip offset */
|
||||
for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
|
||||
offset -= FRAGSIZE(f);
|
||||
|
||||
/* first frag */
|
||||
ff = fragDup(pp, f);
|
||||
ff->rp += offset;
|
||||
pp->first = ff;
|
||||
n -= FRAGSIZE(ff);
|
||||
pp->asize += FRAGASIZE(ff);
|
||||
|
||||
/* the remaining */
|
||||
while(n > 0) {
|
||||
f = f->next;
|
||||
ff->next = fragDup(pp, f);
|
||||
ff = ff->next;
|
||||
n -= FRAGSIZE(ff);
|
||||
pp->asize += FRAGASIZE(ff);
|
||||
}
|
||||
|
||||
/* fix up last frag: note n <= 0 */
|
||||
ff->wp += n;
|
||||
ff->next = nil;
|
||||
pp->last = ff;
|
||||
|
||||
return pp;
|
||||
}
|
||||
|
||||
Packet *
|
||||
packetSplit(Packet *p, int n)
|
||||
{
|
||||
Packet *pp;
|
||||
Frag *f, *ff;
|
||||
|
||||
NOTFREE(p);
|
||||
if(n < 0 || n > p->size) {
|
||||
vtSetError(EPacketSize);
|
||||
return nil;
|
||||
}
|
||||
|
||||
pp = packetAlloc();
|
||||
if(n == 0)
|
||||
return pp;
|
||||
|
||||
pp->size = n;
|
||||
p->size -= n;
|
||||
ff = nil;
|
||||
for(f=p->first; n > 0 && n >= FRAGSIZE(f); f=f->next) {
|
||||
n -= FRAGSIZE(f);
|
||||
p->asize -= FRAGASIZE(f);
|
||||
pp->asize += FRAGASIZE(f);
|
||||
ff = f;
|
||||
}
|
||||
|
||||
/* split shared frag */
|
||||
if(n > 0) {
|
||||
ff = f;
|
||||
f = fragDup(pp, ff);
|
||||
pp->asize += FRAGASIZE(ff);
|
||||
ff->next = nil;
|
||||
ff->wp = ff->rp + n;
|
||||
f->rp += n;
|
||||
}
|
||||
|
||||
pp->first = p->first;
|
||||
pp->last = ff;
|
||||
p->first = f;
|
||||
return pp;
|
||||
}
|
||||
|
||||
int
|
||||
packetConsume(Packet *p, uchar *buf, int n)
|
||||
{
|
||||
NOTFREE(p);
|
||||
if(buf && !packetCopy(p, buf, 0, n))
|
||||
return 0;
|
||||
return packetTrim(p, n, p->size-n);
|
||||
}
|
||||
|
||||
int
|
||||
packetTrim(Packet *p, int offset, int n)
|
||||
{
|
||||
Frag *f, *ff;
|
||||
|
||||
NOTFREE(p);
|
||||
if(offset < 0 || offset > p->size) {
|
||||
vtSetError(EPacketOffset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(n < 0 || offset + n > p->size) {
|
||||
vtSetError(EPacketOffset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p->size = n;
|
||||
|
||||
/* easy case */
|
||||
if(n == 0) {
|
||||
for(f=p->first; f != nil; f=ff) {
|
||||
ff = f->next;
|
||||
fragFree(f);
|
||||
}
|
||||
p->first = p->last = nil;
|
||||
p->asize = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* free before offset */
|
||||
for(f=p->first; offset >= FRAGSIZE(f); f=ff) {
|
||||
p->asize -= FRAGASIZE(f);
|
||||
offset -= FRAGSIZE(f);
|
||||
ff = f->next;
|
||||
fragFree(f);
|
||||
}
|
||||
|
||||
/* adjust frag */
|
||||
f->rp += offset;
|
||||
p->first = f;
|
||||
|
||||
/* skip middle */
|
||||
for(; n > 0 && n > FRAGSIZE(f); f=f->next)
|
||||
n -= FRAGSIZE(f);
|
||||
|
||||
/* adjust end */
|
||||
f->wp = f->rp + n;
|
||||
p->last = f;
|
||||
ff = f->next;
|
||||
f->next = nil;
|
||||
|
||||
/* free after */
|
||||
for(f=ff; f != nil; f=ff) {
|
||||
p->asize -= FRAGASIZE(f);
|
||||
ff = f->next;
|
||||
fragFree(f);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uchar *
|
||||
packetHeader(Packet *p, int n)
|
||||
{
|
||||
Frag *f;
|
||||
Mem *m;
|
||||
|
||||
NOTFREE(p);
|
||||
if(n <= 0 || n > MaxFragSize) {
|
||||
vtSetError(EPacketSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p->size += n;
|
||||
|
||||
/* try and fix in current frag */
|
||||
f = p->first;
|
||||
if(f != nil) {
|
||||
m = f->mem;
|
||||
if(n <= f->rp - m->bp)
|
||||
if(m->ref == 1 || memHead(m, f->rp, n)) {
|
||||
f->rp -= n;
|
||||
return f->rp;
|
||||
}
|
||||
}
|
||||
|
||||
/* add frag to front */
|
||||
f = fragAlloc(p, n, PEnd, p->first);
|
||||
p->asize += FRAGASIZE(f);
|
||||
if(p->first == nil)
|
||||
p->last = f;
|
||||
p->first = f;
|
||||
return f->rp;
|
||||
}
|
||||
|
||||
uchar *
|
||||
packetTrailer(Packet *p, int n)
|
||||
{
|
||||
Mem *m;
|
||||
Frag *f;
|
||||
|
||||
NOTFREE(p);
|
||||
if(n <= 0 || n > MaxFragSize) {
|
||||
vtSetError(EPacketSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p->size += n;
|
||||
|
||||
/* try and fix in current frag */
|
||||
if(p->first != nil) {
|
||||
f = p->last;
|
||||
m = f->mem;
|
||||
if(n <= m->ep - f->wp)
|
||||
if(m->ref == 1 || memTail(m, f->wp, n)) {
|
||||
f->wp += n;
|
||||
return f->wp - n;
|
||||
}
|
||||
}
|
||||
|
||||
/* add frag to end */
|
||||
f = fragAlloc(p, n, (p->first == nil)?PMiddle:PFront, nil);
|
||||
p->asize += FRAGASIZE(f);
|
||||
if(p->first == nil)
|
||||
p->first = f;
|
||||
else
|
||||
p->last->next = f;
|
||||
p->last = f;
|
||||
return f->rp;
|
||||
}
|
||||
|
||||
int
|
||||
packetPrefix(Packet *p, uchar *buf, int n)
|
||||
{
|
||||
Frag *f;
|
||||
int nn;
|
||||
Mem *m;
|
||||
|
||||
NOTFREE(p);
|
||||
if(n <= 0)
|
||||
return 1;
|
||||
|
||||
p->size += n;
|
||||
|
||||
/* try and fix in current frag */
|
||||
f = p->first;
|
||||
if(f != nil) {
|
||||
m = f->mem;
|
||||
nn = f->rp - m->bp;
|
||||
if(nn > n)
|
||||
nn = n;
|
||||
if(m->ref == 1 || memHead(m, f->rp, nn)) {
|
||||
f->rp -= nn;
|
||||
n -= nn;
|
||||
memmove(f->rp, buf+n, nn);
|
||||
}
|
||||
}
|
||||
|
||||
while(n > 0) {
|
||||
nn = n;
|
||||
if(nn > MaxFragSize)
|
||||
nn = MaxFragSize;
|
||||
f = fragAlloc(p, nn, PEnd, p->first);
|
||||
p->asize += FRAGASIZE(f);
|
||||
if(p->first == nil)
|
||||
p->last = f;
|
||||
p->first = f;
|
||||
n -= nn;
|
||||
memmove(f->rp, buf+n, nn);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
packetAppend(Packet *p, uchar *buf, int n)
|
||||
{
|
||||
Frag *f;
|
||||
int nn;
|
||||
Mem *m;
|
||||
|
||||
NOTFREE(p);
|
||||
if(n <= 0)
|
||||
return 1;
|
||||
|
||||
p->size += n;
|
||||
/* try and fix in current frag */
|
||||
if(p->first != nil) {
|
||||
f = p->last;
|
||||
m = f->mem;
|
||||
nn = m->ep - f->wp;
|
||||
if(nn > n)
|
||||
nn = n;
|
||||
if(m->ref == 1 || memTail(m, f->wp, nn)) {
|
||||
memmove(f->wp, buf, nn);
|
||||
f->wp += nn;
|
||||
buf += nn;
|
||||
n -= nn;
|
||||
}
|
||||
}
|
||||
|
||||
while(n > 0) {
|
||||
nn = n;
|
||||
if(nn > MaxFragSize)
|
||||
nn = MaxFragSize;
|
||||
f = fragAlloc(p, nn, (p->first == nil)?PMiddle:PFront, nil);
|
||||
p->asize += FRAGASIZE(f);
|
||||
if(p->first == nil)
|
||||
p->first = f;
|
||||
else
|
||||
p->last->next = f;
|
||||
p->last = f;
|
||||
memmove(f->rp, buf, nn);
|
||||
buf += nn;
|
||||
n -= nn;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
packetConcat(Packet *p, Packet *pp)
|
||||
{
|
||||
NOTFREE(p);
|
||||
NOTFREE(pp);
|
||||
if(pp->size == 0)
|
||||
return 1;
|
||||
p->size += pp->size;
|
||||
p->asize += pp->asize;
|
||||
|
||||
if(p->first != nil)
|
||||
p->last->next = pp->first;
|
||||
else
|
||||
p->first = pp->first;
|
||||
p->last = pp->last;
|
||||
pp->size = 0;
|
||||
pp->asize = 0;
|
||||
pp->first = nil;
|
||||
pp->last = nil;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uchar *
|
||||
packetPeek(Packet *p, uchar *buf, int offset, int n)
|
||||
{
|
||||
Frag *f;
|
||||
int nn;
|
||||
uchar *b;
|
||||
|
||||
NOTFREE(p);
|
||||
if(n == 0)
|
||||
return buf;
|
||||
|
||||
if(offset < 0 || offset >= p->size) {
|
||||
vtSetError(EPacketOffset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(n < 0 || offset + n > p->size) {
|
||||
vtSetError(EPacketSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* skip up to offset */
|
||||
for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
|
||||
offset -= FRAGSIZE(f);
|
||||
|
||||
/* easy case */
|
||||
if(offset + n <= FRAGSIZE(f))
|
||||
return f->rp + offset;
|
||||
|
||||
for(b=buf; n>0; n -= nn) {
|
||||
nn = FRAGSIZE(f) - offset;
|
||||
if(nn > n)
|
||||
nn = n;
|
||||
memmove(b, f->rp+offset, nn);
|
||||
offset = 0;
|
||||
f = f->next;
|
||||
b += nn;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
packetCopy(Packet *p, uchar *buf, int offset, int n)
|
||||
{
|
||||
uchar *b;
|
||||
|
||||
NOTFREE(p);
|
||||
b = packetPeek(p, buf, offset, n);
|
||||
if(b == nil)
|
||||
return 0;
|
||||
if(b != buf)
|
||||
memmove(buf, b, n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
packetFragments(Packet *p, IOchunk *io, int nio, int offset)
|
||||
{
|
||||
Frag *f;
|
||||
int size;
|
||||
IOchunk *eio;
|
||||
|
||||
NOTFREE(p);
|
||||
if(p->size == 0 || nio <= 0)
|
||||
return 0;
|
||||
|
||||
if(offset < 0 || offset > p->size) {
|
||||
vtSetError(EPacketOffset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
|
||||
offset -= FRAGSIZE(f);
|
||||
|
||||
size = 0;
|
||||
eio = io + nio;
|
||||
for(; f != nil && io < eio; f=f->next) {
|
||||
io->addr = f->rp + offset;
|
||||
io->len = f->wp - (f->rp + offset);
|
||||
offset = 0;
|
||||
size += io->len;
|
||||
io++;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void
|
||||
packetStats(void)
|
||||
{
|
||||
Packet *p;
|
||||
Frag *f;
|
||||
Mem *m;
|
||||
|
||||
int np, nf, nsm, nbm;
|
||||
|
||||
lock(&freeList.lk);
|
||||
np = 0;
|
||||
for(p=freeList.packet; p; p=p->next)
|
||||
np++;
|
||||
nf = 0;
|
||||
for(f=freeList.frag; f; f=f->next)
|
||||
nf++;
|
||||
nsm = 0;
|
||||
for(m=freeList.smallMem; m; m=m->next)
|
||||
nsm++;
|
||||
nbm = 0;
|
||||
for(m=freeList.bigMem; m; m=m->next)
|
||||
nbm++;
|
||||
|
||||
fprint(2, "packet: %d/%d frag: %d/%d small mem: %d/%d big mem: %d/%d\n",
|
||||
np, freeList.npacket,
|
||||
nf, freeList.nfrag,
|
||||
nsm, freeList.nsmallMem,
|
||||
nbm, freeList.nbigMem);
|
||||
|
||||
unlock(&freeList.lk);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
packetSize(Packet *p)
|
||||
{
|
||||
NOTFREE(p);
|
||||
if(0) {
|
||||
Frag *f;
|
||||
int size = 0;
|
||||
|
||||
for(f=p->first; f; f=f->next)
|
||||
size += FRAGSIZE(f);
|
||||
if(size != p->size)
|
||||
fprint(2, "packetSize %d %d\n", size, p->size);
|
||||
assert(size == p->size);
|
||||
}
|
||||
return p->size;
|
||||
}
|
||||
|
||||
int
|
||||
packetAllocatedSize(Packet *p)
|
||||
{
|
||||
NOTFREE(p);
|
||||
if(0) {
|
||||
Frag *f;
|
||||
int asize = 0;
|
||||
|
||||
for(f=p->first; f; f=f->next)
|
||||
asize += FRAGASIZE(f);
|
||||
if(asize != p->asize)
|
||||
fprint(2, "packetAllocatedSize %d %d\n", asize, p->asize);
|
||||
assert(asize == p->asize);
|
||||
}
|
||||
return p->asize;
|
||||
}
|
||||
|
||||
void
|
||||
packetSha1(Packet *p, uchar sha1[VtScoreSize])
|
||||
{
|
||||
Frag *f;
|
||||
VtSha1 *s;
|
||||
int size;
|
||||
|
||||
NOTFREE(p);
|
||||
s = vtSha1Alloc();
|
||||
size = p->size;
|
||||
for(f=p->first; f; f=f->next) {
|
||||
vtSha1Update(s, f->rp, FRAGSIZE(f));
|
||||
size -= FRAGSIZE(f);
|
||||
}
|
||||
assert(size == 0);
|
||||
vtSha1Final(s, sha1);
|
||||
vtSha1Free(s);
|
||||
}
|
||||
|
||||
int
|
||||
packetCmp(Packet *pkt0, Packet *pkt1)
|
||||
{
|
||||
Frag *f0, *f1;
|
||||
int n0, n1, x;
|
||||
|
||||
NOTFREE(pkt0);
|
||||
NOTFREE(pkt1);
|
||||
f0 = pkt0->first;
|
||||
f1 = pkt1->first;
|
||||
|
||||
if(f0 == nil)
|
||||
return (f1 == nil)?0:-1;
|
||||
if(f1 == nil)
|
||||
return 1;
|
||||
n0 = FRAGSIZE(f0);
|
||||
n1 = FRAGSIZE(f1);
|
||||
|
||||
for(;;) {
|
||||
if(n0 < n1) {
|
||||
x = memcmp(f0->wp - n0, f1->wp - n1, n0);
|
||||
if(x != 0)
|
||||
return x;
|
||||
n1 -= n0;
|
||||
f0 = f0->next;
|
||||
if(f0 == nil)
|
||||
return -1;
|
||||
n0 = FRAGSIZE(f0);
|
||||
} else if (n0 > n1) {
|
||||
x = memcmp(f0->wp - n0, f1->wp - n1, n1);
|
||||
if(x != 0)
|
||||
return x;
|
||||
n0 -= n1;
|
||||
f1 = f1->next;
|
||||
if(f1 == nil)
|
||||
return 1;
|
||||
n1 = FRAGSIZE(f1);
|
||||
} else { /* n0 == n1 */
|
||||
x = memcmp(f0->wp - n0, f1->wp - n1, n0);
|
||||
if(x != 0)
|
||||
return x;
|
||||
f0 = f0->next;
|
||||
f1 = f1->next;
|
||||
if(f0 == nil)
|
||||
return (f1 == nil)?0:-1;
|
||||
if(f1 == nil)
|
||||
return 1;
|
||||
n0 = FRAGSIZE(f0);
|
||||
n1 = FRAGSIZE(f1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Frag *
|
||||
fragAlloc(Packet *p, int n, int pos, Frag *next)
|
||||
{
|
||||
Frag *f, *ef;
|
||||
Mem *m;
|
||||
|
||||
/* look for local frag */
|
||||
f = &p->local[0];
|
||||
ef = &p->local[NLocalFrag];
|
||||
for(;f<ef; f++) {
|
||||
if(f->state == FragLocalFree) {
|
||||
f->state = FragLocalAlloc;
|
||||
goto Found;
|
||||
}
|
||||
}
|
||||
lock(&freeList.lk);
|
||||
f = freeList.frag;
|
||||
if(f != nil)
|
||||
freeList.frag = f->next;
|
||||
else
|
||||
freeList.nfrag++;
|
||||
unlock(&freeList.lk);
|
||||
|
||||
if(f == nil) {
|
||||
f = vtMemBrk(sizeof(Frag));
|
||||
f->state = FragGlobal;
|
||||
}
|
||||
|
||||
Found:
|
||||
if(n == 0)
|
||||
return f;
|
||||
|
||||
if(pos == PEnd && next == nil)
|
||||
pos = PMiddle;
|
||||
m = memAlloc(n, pos);
|
||||
f->mem = m;
|
||||
f->rp = m->rp;
|
||||
f->wp = m->wp;
|
||||
f->next = next;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static Frag *
|
||||
fragDup(Packet *p, Frag *f)
|
||||
{
|
||||
Frag *ff;
|
||||
Mem *m;
|
||||
|
||||
m = f->mem;
|
||||
|
||||
/*
|
||||
* m->rp && m->wp can be out of date when ref == 1
|
||||
* also, potentially reclaims space from previous frags
|
||||
*/
|
||||
if(m->ref == 1) {
|
||||
m->rp = f->rp;
|
||||
m->wp = f->wp;
|
||||
}
|
||||
|
||||
ff = fragAlloc(p, 0, 0, nil);
|
||||
*ff = *f;
|
||||
lock(&m->lk);
|
||||
m->ref++;
|
||||
unlock(&m->lk);
|
||||
return ff;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fragFree(Frag *f)
|
||||
{
|
||||
memFree(f->mem);
|
||||
|
||||
if(f->state == FragLocalAlloc) {
|
||||
f->state = FragLocalFree;
|
||||
return;
|
||||
}
|
||||
|
||||
lock(&freeList.lk);
|
||||
f->next = freeList.frag;
|
||||
freeList.frag = f;
|
||||
unlock(&freeList.lk);
|
||||
}
|
||||
|
||||
static Mem *
|
||||
memAlloc(int n, int pos)
|
||||
{
|
||||
Mem *m;
|
||||
int nn;
|
||||
|
||||
if(n < 0 || n > MaxFragSize) {
|
||||
vtSetError(EPacketSize);
|
||||
return 0;
|
||||
}
|
||||
if(n <= SmallMemSize) {
|
||||
lock(&freeList.lk);
|
||||
m = freeList.smallMem;
|
||||
if(m != nil)
|
||||
freeList.smallMem = m->next;
|
||||
else
|
||||
freeList.nsmallMem++;
|
||||
unlock(&freeList.lk);
|
||||
nn = SmallMemSize;
|
||||
} else {
|
||||
lock(&freeList.lk);
|
||||
m = freeList.bigMem;
|
||||
if(m != nil)
|
||||
freeList.bigMem = m->next;
|
||||
else
|
||||
freeList.nbigMem++;
|
||||
unlock(&freeList.lk);
|
||||
nn = BigMemSize;
|
||||
}
|
||||
|
||||
if(m == nil) {
|
||||
m = vtMemBrk(sizeof(Mem));
|
||||
m->bp = vtMemBrk(nn);
|
||||
m->ep = m->bp + nn;
|
||||
}
|
||||
assert(m->ref == 0);
|
||||
m->ref = 1;
|
||||
|
||||
switch(pos) {
|
||||
default:
|
||||
assert(0);
|
||||
case PFront:
|
||||
m->rp = m->bp;
|
||||
break;
|
||||
case PMiddle:
|
||||
/* leave a little bit at end */
|
||||
m->rp = m->ep - n - 32;
|
||||
break;
|
||||
case PEnd:
|
||||
m->rp = m->ep - n;
|
||||
break;
|
||||
}
|
||||
/* check we did not blow it */
|
||||
if(m->rp < m->bp)
|
||||
m->rp = m->bp;
|
||||
m->wp = m->rp + n;
|
||||
assert(m->rp >= m->bp && m->wp <= m->ep);
|
||||
return m;
|
||||
}
|
||||
|
||||
static void
|
||||
memFree(Mem *m)
|
||||
{
|
||||
lock(&m->lk);
|
||||
m->ref--;
|
||||
if(m->ref > 0) {
|
||||
unlock(&m->lk);
|
||||
return;
|
||||
}
|
||||
unlock(&m->lk);
|
||||
assert(m->ref == 0);
|
||||
|
||||
switch(m->ep - m->bp) {
|
||||
default:
|
||||
assert(0);
|
||||
case SmallMemSize:
|
||||
lock(&freeList.lk);
|
||||
m->next = freeList.smallMem;
|
||||
freeList.smallMem = m;
|
||||
unlock(&freeList.lk);
|
||||
break;
|
||||
case BigMemSize:
|
||||
lock(&freeList.lk);
|
||||
m->next = freeList.bigMem;
|
||||
freeList.bigMem = m;
|
||||
unlock(&freeList.lk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
memHead(Mem *m, uchar *rp, int n)
|
||||
{
|
||||
lock(&m->lk);
|
||||
if(m->rp != rp) {
|
||||
unlock(&m->lk);
|
||||
return 0;
|
||||
}
|
||||
m->rp -= n;
|
||||
unlock(&m->lk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
memTail(Mem *m, uchar *wp, int n)
|
||||
{
|
||||
lock(&m->lk);
|
||||
if(m->wp != wp) {
|
||||
unlock(&m->lk);
|
||||
return 0;
|
||||
}
|
||||
m->wp += n;
|
||||
unlock(&m->lk);
|
||||
return 1;
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
typedef struct Packet Packet;
|
||||
typedef struct Mem Mem;
|
||||
typedef struct Frag Frag;
|
||||
|
||||
enum {
|
||||
BigMemSize = MaxFragSize,
|
||||
SmallMemSize = BigMemSize/8,
|
||||
NLocalFrag = 2,
|
||||
};
|
||||
|
||||
/* position to carve out of a Mem */
|
||||
enum {
|
||||
PFront,
|
||||
PMiddle,
|
||||
PEnd,
|
||||
};
|
||||
|
||||
struct Mem
|
||||
{
|
||||
Lock lk;
|
||||
int ref;
|
||||
uchar *bp;
|
||||
uchar *ep;
|
||||
uchar *rp;
|
||||
uchar *wp;
|
||||
Mem *next;
|
||||
};
|
||||
|
||||
enum {
|
||||
FragLocalFree,
|
||||
FragLocalAlloc,
|
||||
FragGlobal,
|
||||
};
|
||||
|
||||
struct Frag
|
||||
{
|
||||
int state;
|
||||
Mem *mem;
|
||||
uchar *rp;
|
||||
uchar *wp;
|
||||
Frag *next;
|
||||
};
|
||||
|
||||
struct Packet
|
||||
{
|
||||
int size;
|
||||
int asize; /* allocated memmory - always greater than size */
|
||||
|
||||
Packet *next;
|
||||
|
||||
Frag *first;
|
||||
Frag *last;
|
||||
|
||||
Frag local[NLocalFrag];
|
||||
};
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
|
||||
int
|
||||
vtParseScore(char *buf, uint n, uchar score[VtScoreSize])
|
||||
{
|
||||
int i, c;
|
||||
|
||||
memset(score, 0, VtScoreSize);
|
||||
|
||||
if(n != VtScoreSize*2)
|
||||
return 0;
|
||||
for(i=0; i<VtScoreSize*2; i++){
|
||||
if(buf[i] >= '0' && buf[i] <= '9')
|
||||
c = buf[i] - '0';
|
||||
else if(buf[i] >= 'a' && buf[i] <= 'f')
|
||||
c = buf[i] - 'a' + 10;
|
||||
else if(buf[i] >= 'A' && buf[i] <= 'F')
|
||||
c = buf[i] - 'A' + 10;
|
||||
else
|
||||
return 0;
|
||||
|
||||
if((i & 1) == 0)
|
||||
c <<= 4;
|
||||
|
||||
score[i>>1] |= c;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
|
||||
enum {
|
||||
IdealAlignment = 32,
|
||||
ChunkSize = 128*1024,
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
vtMemFree(void *p)
|
||||
{
|
||||
if(p == 0)
|
||||
return;
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
vtMemAlloc(int size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = malloc(size);
|
||||
if(p == 0)
|
||||
vtFatal("vtMemAlloc: out of memory");
|
||||
setmalloctag(p, getcallerpc(&size));
|
||||
return p;
|
||||
}
|
||||
|
||||
void *
|
||||
vtMemAllocZ(int size)
|
||||
{
|
||||
void *p = vtMemAlloc(size);
|
||||
memset(p, 0, size);
|
||||
setmalloctag(p, getcallerpc(&size));
|
||||
return p;
|
||||
}
|
||||
|
||||
void *
|
||||
vtMemRealloc(void *p, int size)
|
||||
{
|
||||
if(p == nil)
|
||||
return vtMemAlloc(size);
|
||||
p = realloc(p, size);
|
||||
if(p == 0)
|
||||
vtFatal("vtRealloc: out of memory");
|
||||
setrealloctag(p, getcallerpc(&size));
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
vtMemBrk(int n)
|
||||
{
|
||||
static Lock lk;
|
||||
static uchar *buf;
|
||||
static int nbuf;
|
||||
static int nchunk;
|
||||
int align, pad;
|
||||
void *p;
|
||||
|
||||
if(n >= IdealAlignment)
|
||||
align = IdealAlignment;
|
||||
else if(n > 8)
|
||||
align = 8;
|
||||
else
|
||||
align = 4;
|
||||
|
||||
lock(&lk);
|
||||
pad = (align - (uintptr)buf) & (align-1);
|
||||
if(n + pad > nbuf) {
|
||||
buf = vtMemAllocZ(ChunkSize);
|
||||
setmalloctag(buf, getcallerpc(&n));
|
||||
nbuf = ChunkSize;
|
||||
pad = (align - (uintptr)buf) & (align-1);
|
||||
nchunk++;
|
||||
}
|
||||
|
||||
assert(n + pad <= nbuf);
|
||||
|
||||
p = buf + pad;
|
||||
buf += pad + n;
|
||||
nbuf -= pad + n;
|
||||
unlock(&lk);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
vtThreadSetName(char *name)
|
||||
{
|
||||
int fd;
|
||||
char buf[32];
|
||||
|
||||
sprint(buf, "/proc/%d/args", getpid());
|
||||
if((fd = open(buf, OWRITE)) >= 0){
|
||||
write(fd, name, strlen(name));
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
vtFdRead(int fd, uchar *buf, int n)
|
||||
{
|
||||
n = read(fd, buf, n);
|
||||
if(n < 0) {
|
||||
vtOSError();
|
||||
return -1;
|
||||
}
|
||||
if(n == 0) {
|
||||
vtSetError("unexpected EOF");
|
||||
return 0;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
vtFdWrite(int fd, uchar *buf, int n)
|
||||
{
|
||||
int nn;
|
||||
|
||||
nn = write(fd, buf, n);
|
||||
if(nn < 0) {
|
||||
vtOSError();
|
||||
return 0;
|
||||
}
|
||||
if(n != nn) {
|
||||
vtSetError("truncated write");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
vtFdClose(int fd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
char *
|
||||
vtOSError(void)
|
||||
{
|
||||
return vtSetError("%r");
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
#include <libsec.h>
|
||||
|
||||
static void encode(uchar*, u32int*, ulong);
|
||||
extern void vtSha1Block(u32int *s, uchar *p, ulong len);
|
||||
|
||||
struct VtSha1
|
||||
{
|
||||
DigestState *s;
|
||||
};
|
||||
|
||||
VtSha1 *
|
||||
vtSha1Alloc(void)
|
||||
{
|
||||
VtSha1 *s;
|
||||
|
||||
s = vtMemAlloc(sizeof(VtSha1));
|
||||
vtSha1Init(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
vtSha1Free(VtSha1 *s)
|
||||
{
|
||||
if(s == nil)
|
||||
return;
|
||||
if(s->s != nil)
|
||||
free(s->s);
|
||||
vtMemFree(s);
|
||||
}
|
||||
|
||||
void
|
||||
vtSha1Init(VtSha1 *s)
|
||||
{
|
||||
s->s = nil;
|
||||
}
|
||||
|
||||
void
|
||||
vtSha1Update(VtSha1 *s, uchar *p, int len)
|
||||
{
|
||||
s->s = sha1(p, len, nil, s->s);
|
||||
}
|
||||
|
||||
void
|
||||
vtSha1Final(VtSha1 *s, uchar *digest)
|
||||
{
|
||||
sha1(nil, 0, digest, s->s);
|
||||
s->s = nil;
|
||||
}
|
||||
|
||||
void
|
||||
vtSha1(uchar sha1[VtScoreSize], uchar *p, int n)
|
||||
{
|
||||
VtSha1 s;
|
||||
|
||||
vtSha1Init(&s);
|
||||
vtSha1Update(&s, p, n);
|
||||
vtSha1Final(&s, sha1);
|
||||
}
|
||||
|
||||
int
|
||||
vtSha1Check(uchar score[VtScoreSize], uchar *p, int n)
|
||||
{
|
||||
VtSha1 s;
|
||||
uchar score2[VtScoreSize];
|
||||
|
||||
vtSha1Init(&s);
|
||||
vtSha1Update(&s, p, n);
|
||||
vtSha1Final(&s, score2);
|
||||
|
||||
if(memcmp(score, score2, VtScoreSize) != 0) {
|
||||
vtSetError("vtSha1Check failed");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -1,531 +0,0 @@
|
|||
sizeof_1_ = 8;
|
||||
aggr _1_
|
||||
{
|
||||
'U' 0 lo;
|
||||
'U' 4 hi;
|
||||
};
|
||||
|
||||
defn
|
||||
_1_(addr) {
|
||||
complex _1_ addr;
|
||||
print(" lo ", addr.lo, "\n");
|
||||
print(" hi ", addr.hi, "\n");
|
||||
};
|
||||
|
||||
sizeofFPdbleword = 8;
|
||||
aggr FPdbleword
|
||||
{
|
||||
'F' 0 x;
|
||||
{
|
||||
'U' 0 lo;
|
||||
'U' 4 hi;
|
||||
};
|
||||
};
|
||||
|
||||
defn
|
||||
FPdbleword(addr) {
|
||||
complex FPdbleword addr;
|
||||
print(" x ", addr.x, "\n");
|
||||
print("_1_ {\n");
|
||||
_1_(addr+0);
|
||||
print("}\n");
|
||||
};
|
||||
|
||||
UTFmax = 3;
|
||||
Runesync = 128;
|
||||
Runeself = 128;
|
||||
Runeerror = 65533;
|
||||
sizeofFmt = 48;
|
||||
aggr Fmt
|
||||
{
|
||||
'b' 0 runes;
|
||||
'X' 4 start;
|
||||
'X' 8 to;
|
||||
'X' 12 stop;
|
||||
'X' 16 flush;
|
||||
'X' 20 farg;
|
||||
'D' 24 nfmt;
|
||||
'X' 28 args;
|
||||
'D' 32 r;
|
||||
'D' 36 width;
|
||||
'D' 40 prec;
|
||||
'U' 44 flags;
|
||||
};
|
||||
|
||||
defn
|
||||
Fmt(addr) {
|
||||
complex Fmt addr;
|
||||
print(" runes ", addr.runes, "\n");
|
||||
print(" start ", addr.start\X, "\n");
|
||||
print(" to ", addr.to\X, "\n");
|
||||
print(" stop ", addr.stop\X, "\n");
|
||||
print(" flush ", addr.flush\X, "\n");
|
||||
print(" farg ", addr.farg\X, "\n");
|
||||
print(" nfmt ", addr.nfmt, "\n");
|
||||
print(" args ", addr.args\X, "\n");
|
||||
print(" r ", addr.r, "\n");
|
||||
print(" width ", addr.width, "\n");
|
||||
print(" prec ", addr.prec, "\n");
|
||||
print(" flags ", addr.flags, "\n");
|
||||
};
|
||||
|
||||
FmtWidth = 1;
|
||||
FmtLeft = 2;
|
||||
FmtPrec = 4;
|
||||
FmtSharp = 8;
|
||||
FmtSpace = 16;
|
||||
FmtSign = 32;
|
||||
FmtZero = 64;
|
||||
FmtUnsigned = 128;
|
||||
FmtShort = 256;
|
||||
FmtLong = 512;
|
||||
FmtVLong = 1024;
|
||||
FmtComma = 2048;
|
||||
FmtByte = 4096;
|
||||
FmtFlag = 8192;
|
||||
sizeofTm = 40;
|
||||
aggr Tm
|
||||
{
|
||||
'D' 0 sec;
|
||||
'D' 4 min;
|
||||
'D' 8 hour;
|
||||
'D' 12 mday;
|
||||
'D' 16 mon;
|
||||
'D' 20 year;
|
||||
'D' 24 wday;
|
||||
'D' 28 yday;
|
||||
'a' 32 zone;
|
||||
'D' 36 tzoff;
|
||||
};
|
||||
|
||||
defn
|
||||
Tm(addr) {
|
||||
complex Tm addr;
|
||||
print(" sec ", addr.sec, "\n");
|
||||
print(" min ", addr.min, "\n");
|
||||
print(" hour ", addr.hour, "\n");
|
||||
print(" mday ", addr.mday, "\n");
|
||||
print(" mon ", addr.mon, "\n");
|
||||
print(" year ", addr.year, "\n");
|
||||
print(" wday ", addr.wday, "\n");
|
||||
print(" yday ", addr.yday, "\n");
|
||||
print(" zone ", addr.zone, "\n");
|
||||
print(" tzoff ", addr.tzoff, "\n");
|
||||
};
|
||||
|
||||
PNPROC = 1;
|
||||
PNGROUP = 2;
|
||||
Profoff = 0;
|
||||
Profuser = 1;
|
||||
Profkernel = 2;
|
||||
Proftime = 3;
|
||||
Profsample = 4;
|
||||
sizeofLock = 4;
|
||||
aggr Lock
|
||||
{
|
||||
'D' 0 val;
|
||||
};
|
||||
|
||||
defn
|
||||
Lock(addr) {
|
||||
complex Lock addr;
|
||||
print(" val ", addr.val, "\n");
|
||||
};
|
||||
|
||||
sizeofQLp = 12;
|
||||
aggr QLp
|
||||
{
|
||||
'D' 0 inuse;
|
||||
'A' QLp 4 next;
|
||||
'C' 8 state;
|
||||
};
|
||||
|
||||
defn
|
||||
QLp(addr) {
|
||||
complex QLp addr;
|
||||
print(" inuse ", addr.inuse, "\n");
|
||||
print(" next ", addr.next\X, "\n");
|
||||
print(" state ", addr.state, "\n");
|
||||
};
|
||||
|
||||
sizeofQLock = 16;
|
||||
aggr QLock
|
||||
{
|
||||
Lock 0 lock;
|
||||
'D' 4 locked;
|
||||
'A' QLp 8 $head;
|
||||
'A' QLp 12 $tail;
|
||||
};
|
||||
|
||||
defn
|
||||
QLock(addr) {
|
||||
complex QLock addr;
|
||||
print("Lock lock {\n");
|
||||
Lock(addr.lock);
|
||||
print("}\n");
|
||||
print(" locked ", addr.locked, "\n");
|
||||
print(" $head ", addr.$head\X, "\n");
|
||||
print(" $tail ", addr.$tail\X, "\n");
|
||||
};
|
||||
|
||||
sizeofRWLock = 20;
|
||||
aggr RWLock
|
||||
{
|
||||
Lock 0 lock;
|
||||
'D' 4 readers;
|
||||
'D' 8 writer;
|
||||
'A' QLp 12 $head;
|
||||
'A' QLp 16 $tail;
|
||||
};
|
||||
|
||||
defn
|
||||
RWLock(addr) {
|
||||
complex RWLock addr;
|
||||
print("Lock lock {\n");
|
||||
Lock(addr.lock);
|
||||
print("}\n");
|
||||
print(" readers ", addr.readers, "\n");
|
||||
print(" writer ", addr.writer, "\n");
|
||||
print(" $head ", addr.$head\X, "\n");
|
||||
print(" $tail ", addr.$tail\X, "\n");
|
||||
};
|
||||
|
||||
sizeofRendez = 12;
|
||||
aggr Rendez
|
||||
{
|
||||
'A' QLock 0 l;
|
||||
'A' QLp 4 $head;
|
||||
'A' QLp 8 $tail;
|
||||
};
|
||||
|
||||
defn
|
||||
Rendez(addr) {
|
||||
complex Rendez addr;
|
||||
print(" l ", addr.l\X, "\n");
|
||||
print(" $head ", addr.$head\X, "\n");
|
||||
print(" $tail ", addr.$tail\X, "\n");
|
||||
};
|
||||
|
||||
sizeofNetConnInfo = 36;
|
||||
aggr NetConnInfo
|
||||
{
|
||||
'X' 0 dir;
|
||||
'X' 4 root;
|
||||
'X' 8 spec;
|
||||
'X' 12 lsys;
|
||||
'X' 16 lserv;
|
||||
'X' 20 rsys;
|
||||
'X' 24 rserv;
|
||||
'X' 28 laddr;
|
||||
'X' 32 raddr;
|
||||
};
|
||||
|
||||
defn
|
||||
NetConnInfo(addr) {
|
||||
complex NetConnInfo addr;
|
||||
print(" dir ", addr.dir\X, "\n");
|
||||
print(" root ", addr.root\X, "\n");
|
||||
print(" spec ", addr.spec\X, "\n");
|
||||
print(" lsys ", addr.lsys\X, "\n");
|
||||
print(" lserv ", addr.lserv\X, "\n");
|
||||
print(" rsys ", addr.rsys\X, "\n");
|
||||
print(" rserv ", addr.rserv\X, "\n");
|
||||
print(" laddr ", addr.laddr\X, "\n");
|
||||
print(" raddr ", addr.raddr\X, "\n");
|
||||
};
|
||||
|
||||
RFNAMEG = 1;
|
||||
RFENVG = 2;
|
||||
RFFDG = 4;
|
||||
RFNOTEG = 8;
|
||||
RFPROC = 16;
|
||||
RFMEM = 32;
|
||||
RFNOWAIT = 64;
|
||||
RFCNAMEG = 1024;
|
||||
RFCENVG = 2048;
|
||||
RFCFDG = 4096;
|
||||
RFREND = 8192;
|
||||
RFNOMNT = 16384;
|
||||
sizeofQid = 16;
|
||||
aggr Qid
|
||||
{
|
||||
'W' 0 path;
|
||||
'U' 8 vers;
|
||||
'b' 12 type;
|
||||
};
|
||||
|
||||
defn
|
||||
Qid(addr) {
|
||||
complex Qid addr;
|
||||
print(" path ", addr.path, "\n");
|
||||
print(" vers ", addr.vers, "\n");
|
||||
print(" type ", addr.type, "\n");
|
||||
};
|
||||
|
||||
sizeofDir = 60;
|
||||
aggr Dir
|
||||
{
|
||||
'u' 0 type;
|
||||
'U' 4 dev;
|
||||
Qid 8 qid;
|
||||
'U' 24 mode;
|
||||
'U' 28 atime;
|
||||
'U' 32 mtime;
|
||||
'V' 36 length;
|
||||
'X' 44 name;
|
||||
'X' 48 uid;
|
||||
'X' 52 gid;
|
||||
'X' 56 muid;
|
||||
};
|
||||
|
||||
defn
|
||||
Dir(addr) {
|
||||
complex Dir addr;
|
||||
print(" type ", addr.type, "\n");
|
||||
print(" dev ", addr.dev, "\n");
|
||||
print("Qid qid {\n");
|
||||
Qid(addr.qid);
|
||||
print("}\n");
|
||||
print(" mode ", addr.mode, "\n");
|
||||
print(" atime ", addr.atime, "\n");
|
||||
print(" mtime ", addr.mtime, "\n");
|
||||
print(" length ", addr.length, "\n");
|
||||
print(" name ", addr.name\X, "\n");
|
||||
print(" uid ", addr.uid\X, "\n");
|
||||
print(" gid ", addr.gid\X, "\n");
|
||||
print(" muid ", addr.muid\X, "\n");
|
||||
};
|
||||
|
||||
sizeofWaitmsg = 20;
|
||||
aggr Waitmsg
|
||||
{
|
||||
'D' 0 pid;
|
||||
'a' 4 time;
|
||||
'X' 16 msg;
|
||||
};
|
||||
|
||||
defn
|
||||
Waitmsg(addr) {
|
||||
complex Waitmsg addr;
|
||||
print(" pid ", addr.pid, "\n");
|
||||
print(" time ", addr.time, "\n");
|
||||
print(" msg ", addr.msg\X, "\n");
|
||||
};
|
||||
|
||||
sizeofIOchunk = 8;
|
||||
aggr IOchunk
|
||||
{
|
||||
'X' 0 addr;
|
||||
'U' 4 len;
|
||||
};
|
||||
|
||||
defn
|
||||
IOchunk(addr) {
|
||||
complex IOchunk addr;
|
||||
print(" addr ", addr.addr\X, "\n");
|
||||
print(" len ", addr.len, "\n");
|
||||
};
|
||||
|
||||
VtScoreSize = 20;
|
||||
VtMaxLumpSize = 57344;
|
||||
VtPointerDepth = 7;
|
||||
VtEntrySize = 40;
|
||||
VtRootSize = 300;
|
||||
VtMaxStringSize = 1000;
|
||||
VtAuthSize = 1024;
|
||||
MaxFragSize = 9216;
|
||||
VtMaxFileSize = 281474976710655;
|
||||
VtRootVersion = 2;
|
||||
VtCryptoStrengthNone = 0;
|
||||
VtCryptoStrengthAuth = 1;
|
||||
VtCryptoStrengthWeak = 2;
|
||||
VtCryptoStrengthStrong = 3;
|
||||
VtCryptoNone = 0;
|
||||
VtCryptoSSL3 = 1;
|
||||
VtCryptoTLS1 = 2;
|
||||
VtCryptoMax = 3;
|
||||
VtCodecNone = 0;
|
||||
VtCodecDeflate = 1;
|
||||
VtCodecThwack = 2;
|
||||
VtCodecMax = 3;
|
||||
VtErrType = 0;
|
||||
VtRootType = 1;
|
||||
VtDirType = 2;
|
||||
VtPointerType0 = 3;
|
||||
VtPointerType1 = 4;
|
||||
VtPointerType2 = 5;
|
||||
VtPointerType3 = 6;
|
||||
VtPointerType4 = 7;
|
||||
VtPointerType5 = 8;
|
||||
VtPointerType6 = 9;
|
||||
VtPointerType7 = 10;
|
||||
VtPointerType8 = 11;
|
||||
VtPointerType9 = 12;
|
||||
VtDataType = 13;
|
||||
VtMaxType = 14;
|
||||
VtEntryActive = 1;
|
||||
VtEntryDir = 2;
|
||||
VtEntryDepthShift = 2;
|
||||
VtEntryDepthMask = 28;
|
||||
VtEntryLocal = 32;
|
||||
VtEntryNoArchive = 64;
|
||||
sizeofVtRoot = 300;
|
||||
aggr VtRoot
|
||||
{
|
||||
'u' 0 version;
|
||||
'a' 2 name;
|
||||
'a' 130 type;
|
||||
'a' 258 score;
|
||||
'u' 278 blockSize;
|
||||
'a' 280 prev;
|
||||
};
|
||||
|
||||
defn
|
||||
VtRoot(addr) {
|
||||
complex VtRoot addr;
|
||||
print(" version ", addr.version, "\n");
|
||||
print(" name ", addr.name, "\n");
|
||||
print(" type ", addr.type, "\n");
|
||||
print(" score ", addr.score, "\n");
|
||||
print(" blockSize ", addr.blockSize, "\n");
|
||||
print(" prev ", addr.prev, "\n");
|
||||
};
|
||||
|
||||
sizeofVtEntry = 40;
|
||||
aggr VtEntry
|
||||
{
|
||||
'U' 0 gen;
|
||||
'u' 4 psize;
|
||||
'u' 6 dsize;
|
||||
'b' 8 depth;
|
||||
'b' 9 flags;
|
||||
'W' 12 size;
|
||||
'a' 20 score;
|
||||
};
|
||||
|
||||
defn
|
||||
VtEntry(addr) {
|
||||
complex VtEntry addr;
|
||||
print(" gen ", addr.gen, "\n");
|
||||
print(" psize ", addr.psize, "\n");
|
||||
print(" dsize ", addr.dsize, "\n");
|
||||
print(" depth ", addr.depth, "\n");
|
||||
print(" flags ", addr.flags, "\n");
|
||||
print(" size ", addr.size, "\n");
|
||||
print(" score ", addr.score, "\n");
|
||||
};
|
||||
|
||||
sizeofVtServerVtbl = 16;
|
||||
aggr VtServerVtbl
|
||||
{
|
||||
'X' 0 read;
|
||||
'X' 4 write;
|
||||
'X' 8 closing;
|
||||
'X' 12 sync;
|
||||
};
|
||||
|
||||
defn
|
||||
VtServerVtbl(addr) {
|
||||
complex VtServerVtbl addr;
|
||||
print(" read ", addr.read\X, "\n");
|
||||
print(" write ", addr.write\X, "\n");
|
||||
print(" closing ", addr.closing\X, "\n");
|
||||
print(" sync ", addr.sync\X, "\n");
|
||||
};
|
||||
|
||||
VtVersion01 = 1;
|
||||
VtVersion02 = 2;
|
||||
QueuingW = 0;
|
||||
QueuingR = 1;
|
||||
sizeofThread = 20;
|
||||
aggr Thread
|
||||
{
|
||||
'D' 0 pid;
|
||||
'D' 4 ref;
|
||||
'X' 8 error;
|
||||
'D' 12 state;
|
||||
'A' Thread 16 next;
|
||||
};
|
||||
|
||||
defn
|
||||
Thread(addr) {
|
||||
complex Thread addr;
|
||||
print(" pid ", addr.pid, "\n");
|
||||
print(" ref ", addr.ref, "\n");
|
||||
print(" error ", addr.error\X, "\n");
|
||||
print(" state ", addr.state, "\n");
|
||||
print(" next ", addr.next\X, "\n");
|
||||
};
|
||||
|
||||
sizeofVtLock = 20;
|
||||
aggr VtLock
|
||||
{
|
||||
Lock 0 lk;
|
||||
'A' Thread 4 writer;
|
||||
'D' 8 readers;
|
||||
'A' Thread 12 qfirst;
|
||||
'A' Thread 16 qlast;
|
||||
};
|
||||
|
||||
defn
|
||||
VtLock(addr) {
|
||||
complex VtLock addr;
|
||||
print("Lock lk {\n");
|
||||
Lock(addr.lk);
|
||||
print("}\n");
|
||||
print(" writer ", addr.writer\X, "\n");
|
||||
print(" readers ", addr.readers, "\n");
|
||||
print(" qfirst ", addr.qfirst\X, "\n");
|
||||
print(" qlast ", addr.qlast\X, "\n");
|
||||
};
|
||||
|
||||
sizeofVtRendez = 12;
|
||||
aggr VtRendez
|
||||
{
|
||||
'A' VtLock 0 lk;
|
||||
'A' Thread 4 wfirst;
|
||||
'A' Thread 8 wlast;
|
||||
};
|
||||
|
||||
defn
|
||||
VtRendez(addr) {
|
||||
complex VtRendez addr;
|
||||
print(" lk ", addr.lk\X, "\n");
|
||||
print(" wfirst ", addr.wfirst\X, "\n");
|
||||
print(" wlast ", addr.wlast\X, "\n");
|
||||
};
|
||||
|
||||
ERROR = 0;
|
||||
complex Thread vtRock;
|
||||
complex Thread vtAttach:p;
|
||||
complex Lock lk$4;
|
||||
complex Thread vtDetach:p;
|
||||
complex Thread vtSetError:p;
|
||||
complex Lock lk$12;
|
||||
complex VtLock vtLockFree:p;
|
||||
complex VtLock vtRendezAlloc:p;
|
||||
complex VtRendez vtRendezAlloc:q;
|
||||
complex VtRendez vtRendezFree:q;
|
||||
complex VtLock vtCanLock:p;
|
||||
complex Thread vtCanLock:t;
|
||||
complex VtLock vtLock:p;
|
||||
complex Thread vtLock:t;
|
||||
complex VtLock vtCanRLock:p;
|
||||
complex VtLock vtRLock:p;
|
||||
complex Thread vtRLock:t;
|
||||
complex VtLock vtUnlock:p;
|
||||
complex Thread vtUnlock:t;
|
||||
complex Thread vtUnlock:tt;
|
||||
complex VtLock vtRUnlock:p;
|
||||
complex Thread vtRUnlock:t;
|
||||
complex VtRendez vtSleep:q;
|
||||
complex Thread vtSleep:s;
|
||||
complex Thread vtSleep:t;
|
||||
complex Thread vtSleep:tt;
|
||||
complex VtLock vtSleep:p;
|
||||
complex VtRendez vtWakeup:q;
|
||||
complex Thread vtWakeup:t;
|
||||
complex VtLock vtWakeup:p;
|
||||
complex VtRendez vtWakeupAll:q;
|
||||
complex Thread threadSleep:t;
|
||||
complex Thread threadWakeup:t;
|
|
@ -1,468 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
|
||||
enum
|
||||
{
|
||||
QueuingW, /* queuing for write lock */
|
||||
QueuingR, /* queuing for read lock */
|
||||
};
|
||||
|
||||
|
||||
typedef struct Thread Thread;
|
||||
|
||||
struct Thread {
|
||||
int pid;
|
||||
int ref;
|
||||
char *error;
|
||||
int state;
|
||||
Thread *next;
|
||||
};
|
||||
|
||||
struct VtLock {
|
||||
Lock lk;
|
||||
Thread *writer; /* thread writering write lock */
|
||||
int readers; /* number writering read lock */
|
||||
Thread *qfirst;
|
||||
Thread *qlast;
|
||||
};
|
||||
|
||||
struct VtRendez {
|
||||
VtLock *lk;
|
||||
Thread *wfirst;
|
||||
Thread *wlast;
|
||||
};
|
||||
|
||||
enum {
|
||||
ERROR = 0,
|
||||
};
|
||||
|
||||
static Thread **vtRock;
|
||||
|
||||
static void vtThreadInit(void);
|
||||
static void threadSleep(Thread*);
|
||||
static void threadWakeup(Thread*);
|
||||
|
||||
int
|
||||
vtThread(void (*f)(void*), void *rock)
|
||||
{
|
||||
int tid;
|
||||
|
||||
tid = rfork(RFNOWAIT|RFMEM|RFPROC);
|
||||
switch(tid){
|
||||
case -1:
|
||||
vtOSError();
|
||||
return -1;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return tid;
|
||||
}
|
||||
vtAttach();
|
||||
(*f)(rock);
|
||||
vtDetach();
|
||||
_exits(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Thread *
|
||||
threadLookup(void)
|
||||
{
|
||||
return *vtRock;
|
||||
}
|
||||
|
||||
void
|
||||
vtAttach(void)
|
||||
{
|
||||
int pid;
|
||||
Thread *p;
|
||||
static int init;
|
||||
static Lock lk;
|
||||
|
||||
lock(&lk);
|
||||
if(!init) {
|
||||
rfork(RFREND);
|
||||
vtThreadInit();
|
||||
init = 1;
|
||||
}
|
||||
unlock(&lk);
|
||||
|
||||
pid = getpid();
|
||||
p = *vtRock;
|
||||
if(p != nil && p->pid == pid) {
|
||||
p->ref++;
|
||||
return;
|
||||
}
|
||||
p = vtMemAllocZ(sizeof(Thread));
|
||||
p->ref = 1;
|
||||
p->pid = pid;
|
||||
*vtRock = p;
|
||||
}
|
||||
|
||||
void
|
||||
vtDetach(void)
|
||||
{
|
||||
Thread *p;
|
||||
|
||||
p = *vtRock;
|
||||
assert(p != nil);
|
||||
p->ref--;
|
||||
if(p->ref == 0) {
|
||||
vtMemFree(p->error);
|
||||
vtMemFree(p);
|
||||
*vtRock = nil;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
vtGetError(void)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if(ERROR)
|
||||
fprint(2, "vtGetError: %s\n", threadLookup()->error);
|
||||
s = threadLookup()->error;
|
||||
if(s == nil)
|
||||
return "unknown error";
|
||||
return s;
|
||||
}
|
||||
|
||||
char*
|
||||
vtSetError(char* fmt, ...)
|
||||
{
|
||||
Thread *p;
|
||||
char *s;
|
||||
va_list args;
|
||||
|
||||
p = threadLookup();
|
||||
|
||||
va_start(args, fmt);
|
||||
s = vsmprint(fmt, args);
|
||||
vtMemFree(p->error);
|
||||
p->error = s;
|
||||
va_end(args);
|
||||
if(ERROR)
|
||||
fprint(2, "vtSetError: %s\n", p->error);
|
||||
werrstr("%s", p->error);
|
||||
return p->error;
|
||||
}
|
||||
|
||||
static void
|
||||
vtThreadInit(void)
|
||||
{
|
||||
static Lock lk;
|
||||
|
||||
lock(&lk);
|
||||
if(vtRock != nil) {
|
||||
unlock(&lk);
|
||||
return;
|
||||
}
|
||||
vtRock = privalloc();
|
||||
if(vtRock == nil)
|
||||
vtFatal("can't allocate thread-private storage");
|
||||
unlock(&lk);
|
||||
}
|
||||
|
||||
VtLock*
|
||||
vtLockAlloc(void)
|
||||
{
|
||||
return vtMemAllocZ(sizeof(VtLock));
|
||||
}
|
||||
|
||||
/*
|
||||
* RSC: I think the test is backward. Let's see who uses it.
|
||||
*
|
||||
void
|
||||
vtLockInit(VtLock **p)
|
||||
{
|
||||
static Lock lk;
|
||||
|
||||
lock(&lk);
|
||||
if(*p != nil)
|
||||
*p = vtLockAlloc();
|
||||
unlock(&lk);
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
vtLockFree(VtLock *p)
|
||||
{
|
||||
if(p == nil)
|
||||
return;
|
||||
assert(p->writer == nil);
|
||||
assert(p->readers == 0);
|
||||
assert(p->qfirst == nil);
|
||||
vtMemFree(p);
|
||||
}
|
||||
|
||||
VtRendez*
|
||||
vtRendezAlloc(VtLock *p)
|
||||
{
|
||||
VtRendez *q;
|
||||
|
||||
q = vtMemAllocZ(sizeof(VtRendez));
|
||||
q->lk = p;
|
||||
setmalloctag(q, getcallerpc(&p));
|
||||
return q;
|
||||
}
|
||||
|
||||
void
|
||||
vtRendezFree(VtRendez *q)
|
||||
{
|
||||
if(q == nil)
|
||||
return;
|
||||
assert(q->wfirst == nil);
|
||||
vtMemFree(q);
|
||||
}
|
||||
|
||||
int
|
||||
vtCanLock(VtLock *p)
|
||||
{
|
||||
Thread *t;
|
||||
|
||||
lock(&p->lk);
|
||||
t = *vtRock;
|
||||
if(p->writer == nil && p->readers == 0) {
|
||||
p->writer = t;
|
||||
unlock(&p->lk);
|
||||
return 1;
|
||||
}
|
||||
unlock(&p->lk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
vtLock(VtLock *p)
|
||||
{
|
||||
Thread *t;
|
||||
|
||||
lock(&p->lk);
|
||||
t = *vtRock;
|
||||
if(p->writer == nil && p->readers == 0) {
|
||||
p->writer = t;
|
||||
unlock(&p->lk);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* venti currently contains code that assume locks can be passed between threads :-(
|
||||
* assert(p->writer != t);
|
||||
*/
|
||||
|
||||
if(p->qfirst == nil)
|
||||
p->qfirst = t;
|
||||
else
|
||||
p->qlast->next = t;
|
||||
p->qlast = t;
|
||||
t->next = nil;
|
||||
t->state = QueuingW;
|
||||
unlock(&p->lk);
|
||||
|
||||
threadSleep(t);
|
||||
assert(p->writer == t && p->readers == 0);
|
||||
}
|
||||
|
||||
int
|
||||
vtCanRLock(VtLock *p)
|
||||
{
|
||||
lock(&p->lk);
|
||||
if(p->writer == nil && p->qfirst == nil) {
|
||||
p->readers++;
|
||||
unlock(&p->lk);
|
||||
return 1;
|
||||
}
|
||||
unlock(&p->lk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
vtRLock(VtLock *p)
|
||||
{
|
||||
Thread *t;
|
||||
|
||||
lock(&p->lk);
|
||||
t = *vtRock;
|
||||
if(p->writer == nil && p->qfirst == nil) {
|
||||
p->readers++;
|
||||
unlock(&p->lk);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* venti currently contains code that assumes locks can be passed between threads
|
||||
* assert(p->writer != t);
|
||||
*/
|
||||
if(p->qfirst == nil)
|
||||
p->qfirst = t;
|
||||
else
|
||||
p->qlast->next = t;
|
||||
p->qlast = t;
|
||||
t->next = nil;
|
||||
t->state = QueuingR;
|
||||
unlock(&p->lk);
|
||||
|
||||
threadSleep(t);
|
||||
assert(p->writer == nil && p->readers > 0);
|
||||
}
|
||||
|
||||
void
|
||||
vtUnlock(VtLock *p)
|
||||
{
|
||||
Thread *t, *tt;
|
||||
|
||||
lock(&p->lk);
|
||||
/*
|
||||
* venti currently has code that assumes lock can be passed between threads :-)
|
||||
* assert(p->writer == *vtRock);
|
||||
*/
|
||||
assert(p->writer != nil);
|
||||
assert(p->readers == 0);
|
||||
t = p->qfirst;
|
||||
if(t == nil) {
|
||||
p->writer = nil;
|
||||
unlock(&p->lk);
|
||||
return;
|
||||
}
|
||||
if(t->state == QueuingW) {
|
||||
p->qfirst = t->next;
|
||||
p->writer = t;
|
||||
unlock(&p->lk);
|
||||
threadWakeup(t);
|
||||
return;
|
||||
}
|
||||
|
||||
p->writer = nil;
|
||||
while(t != nil && t->state == QueuingR) {
|
||||
tt = t;
|
||||
t = t->next;
|
||||
p->readers++;
|
||||
threadWakeup(tt);
|
||||
}
|
||||
p->qfirst = t;
|
||||
unlock(&p->lk);
|
||||
}
|
||||
|
||||
void
|
||||
vtRUnlock(VtLock *p)
|
||||
{
|
||||
Thread *t;
|
||||
|
||||
lock(&p->lk);
|
||||
assert(p->writer == nil && p->readers > 0);
|
||||
p->readers--;
|
||||
t = p->qfirst;
|
||||
if(p->readers > 0 || t == nil) {
|
||||
unlock(&p->lk);
|
||||
return;
|
||||
}
|
||||
assert(t->state == QueuingW);
|
||||
|
||||
p->qfirst = t->next;
|
||||
p->writer = t;
|
||||
unlock(&p->lk);
|
||||
|
||||
threadWakeup(t);
|
||||
}
|
||||
|
||||
int
|
||||
vtSleep(VtRendez *q)
|
||||
{
|
||||
Thread *s, *t, *tt;
|
||||
VtLock *p;
|
||||
|
||||
p = q->lk;
|
||||
lock(&p->lk);
|
||||
s = *vtRock;
|
||||
/*
|
||||
* venti currently contains code that assume locks can be passed between threads :-(
|
||||
* assert(p->writer != s);
|
||||
*/
|
||||
assert(p->writer != nil);
|
||||
assert(p->readers == 0);
|
||||
t = p->qfirst;
|
||||
if(t == nil) {
|
||||
p->writer = nil;
|
||||
} else if(t->state == QueuingW) {
|
||||
p->qfirst = t->next;
|
||||
p->writer = t;
|
||||
threadWakeup(t);
|
||||
} else {
|
||||
p->writer = nil;
|
||||
while(t != nil && t->state == QueuingR) {
|
||||
tt = t;
|
||||
t = t->next;
|
||||
p->readers++;
|
||||
threadWakeup(tt);
|
||||
}
|
||||
}
|
||||
|
||||
if(q->wfirst == nil)
|
||||
q->wfirst = s;
|
||||
else
|
||||
q->wlast->next = s;
|
||||
q->wlast = s;
|
||||
s->next = nil;
|
||||
unlock(&p->lk);
|
||||
|
||||
threadSleep(s);
|
||||
assert(p->writer == s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
vtWakeup(VtRendez *q)
|
||||
{
|
||||
Thread *t;
|
||||
VtLock *p;
|
||||
|
||||
/*
|
||||
* take off wait and put on front of queue
|
||||
* put on front so guys that have been waiting will not get starved
|
||||
*/
|
||||
p = q->lk;
|
||||
lock(&p->lk);
|
||||
/*
|
||||
* venti currently has code that assumes lock can be passed between threads :-)
|
||||
* assert(p->writer == *vtRock);
|
||||
*/
|
||||
assert(p->writer != nil);
|
||||
t = q->wfirst;
|
||||
if(t == nil) {
|
||||
unlock(&p->lk);
|
||||
return 0;
|
||||
}
|
||||
q->wfirst = t->next;
|
||||
if(p->qfirst == nil)
|
||||
p->qlast = t;
|
||||
t->next = p->qfirst;
|
||||
p->qfirst = t;
|
||||
t->state = QueuingW;
|
||||
unlock(&p->lk);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
vtWakeupAll(VtRendez *q)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; vtWakeup(q); i++)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
threadSleep(Thread *t)
|
||||
{
|
||||
if(rendezvous(t, (void*)0x22bbdfd6) != (void*)0x44391f14)
|
||||
sysfatal("threadSleep: rendezvous failed: %r");
|
||||
}
|
||||
|
||||
static void
|
||||
threadWakeup(Thread *t)
|
||||
{
|
||||
if(rendezvous(t, (void*)0x44391f14) != (void*)0x22bbdfd6)
|
||||
sysfatal("threadWakeup: rendezvous failed: %r");
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
#include "session.h"
|
||||
|
||||
int
|
||||
vtFdReadFully(int fd, uchar *p, int n)
|
||||
{
|
||||
int nn;
|
||||
|
||||
while(n > 0) {
|
||||
nn = vtFdRead(fd, p, n);
|
||||
if(nn <= 0)
|
||||
return 0;
|
||||
n -= nn;
|
||||
p += nn;
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -1,471 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
#include "session.h"
|
||||
|
||||
struct {
|
||||
int version;
|
||||
char *s;
|
||||
} vtVersions[] = {
|
||||
VtVersion02, "02",
|
||||
0, 0,
|
||||
};
|
||||
|
||||
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 Packet *vtRPC(VtSession *z, int op, Packet *p);
|
||||
|
||||
|
||||
VtSession *
|
||||
vtAlloc(void)
|
||||
{
|
||||
VtSession *z;
|
||||
|
||||
z = vtMemAllocZ(sizeof(VtSession));
|
||||
z->lk = vtLockAlloc();
|
||||
// z->inHash = vtSha1Alloc();
|
||||
z->inLock = vtLockAlloc();
|
||||
z->part = packetAlloc();
|
||||
// z->outHash = vtSha1Alloc();
|
||||
z->outLock = vtLockAlloc();
|
||||
z->fd = -1;
|
||||
z->uid = vtStrDup("anonymous");
|
||||
z->sid = vtStrDup("anonymous");
|
||||
return z;
|
||||
}
|
||||
|
||||
void
|
||||
vtReset(VtSession *z)
|
||||
{
|
||||
vtLock(z->lk);
|
||||
z->cstate = VtStateAlloc;
|
||||
if(z->fd >= 0){
|
||||
vtFdClose(z->fd);
|
||||
z->fd = -1;
|
||||
}
|
||||
vtUnlock(z->lk);
|
||||
}
|
||||
|
||||
int
|
||||
vtConnected(VtSession *z)
|
||||
{
|
||||
return z->cstate == VtStateConnected;
|
||||
}
|
||||
|
||||
void
|
||||
vtDisconnect(VtSession *z, int error)
|
||||
{
|
||||
Packet *p;
|
||||
uchar *b;
|
||||
|
||||
vtDebug(z, "vtDisconnect\n");
|
||||
vtLock(z->lk);
|
||||
if(z->cstate == VtStateConnected && !error && z->vtbl == nil) {
|
||||
/* clean shutdown */
|
||||
p = packetAlloc();
|
||||
b = packetHeader(p, 2);
|
||||
b[0] = VtQGoodbye;
|
||||
b[1] = 0;
|
||||
vtSendPacket(z, p);
|
||||
}
|
||||
if(z->fd >= 0)
|
||||
vtFdClose(z->fd);
|
||||
z->fd = -1;
|
||||
z->cstate = VtStateClosed;
|
||||
vtUnlock(z->lk);
|
||||
}
|
||||
|
||||
void
|
||||
vtClose(VtSession *z)
|
||||
{
|
||||
vtDisconnect(z, 0);
|
||||
}
|
||||
|
||||
void
|
||||
vtFree(VtSession *z)
|
||||
{
|
||||
if(z == nil)
|
||||
return;
|
||||
vtLockFree(z->lk);
|
||||
vtSha1Free(z->inHash);
|
||||
vtLockFree(z->inLock);
|
||||
packetFree(z->part);
|
||||
vtSha1Free(z->outHash);
|
||||
vtLockFree(z->outLock);
|
||||
vtMemFree(z->uid);
|
||||
vtMemFree(z->sid);
|
||||
vtMemFree(z->vtbl);
|
||||
|
||||
memset(z, 0, sizeof(VtSession));
|
||||
z->fd = -1;
|
||||
|
||||
vtMemFree(z);
|
||||
}
|
||||
|
||||
char *
|
||||
vtGetUid(VtSession *s)
|
||||
{
|
||||
return s->uid;
|
||||
}
|
||||
|
||||
char *
|
||||
vtGetSid(VtSession *z)
|
||||
{
|
||||
return z->sid;
|
||||
}
|
||||
|
||||
int
|
||||
vtSetDebug(VtSession *z, int debug)
|
||||
{
|
||||
int old;
|
||||
vtLock(z->lk);
|
||||
old = z->debug;
|
||||
z->debug = debug;
|
||||
vtUnlock(z->lk);
|
||||
return old;
|
||||
}
|
||||
|
||||
int
|
||||
vtSetFd(VtSession *z, int fd)
|
||||
{
|
||||
vtLock(z->lk);
|
||||
if(z->cstate != VtStateAlloc) {
|
||||
vtSetError("bad state");
|
||||
vtUnlock(z->lk);
|
||||
return 0;
|
||||
}
|
||||
if(z->fd >= 0)
|
||||
vtFdClose(z->fd);
|
||||
z->fd = fd;
|
||||
vtUnlock(z->lk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
vtGetFd(VtSession *z)
|
||||
{
|
||||
return z->fd;
|
||||
}
|
||||
|
||||
int
|
||||
vtSetCryptoStrength(VtSession *z, int c)
|
||||
{
|
||||
if(z->cstate != VtStateAlloc) {
|
||||
vtSetError("bad state");
|
||||
return 0;
|
||||
}
|
||||
if(c != VtCryptoStrengthNone) {
|
||||
vtSetError("not supported yet");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
vtGetCryptoStrength(VtSession *s)
|
||||
{
|
||||
return s->cryptoStrength;
|
||||
}
|
||||
|
||||
int
|
||||
vtSetCompression(VtSession *z, int fd)
|
||||
{
|
||||
vtLock(z->lk);
|
||||
if(z->cstate != VtStateAlloc) {
|
||||
vtSetError("bad state");
|
||||
vtUnlock(z->lk);
|
||||
return 0;
|
||||
}
|
||||
z->fd = fd;
|
||||
vtUnlock(z->lk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
vtGetCompression(VtSession *s)
|
||||
{
|
||||
return s->compression;
|
||||
}
|
||||
|
||||
int
|
||||
vtGetCrypto(VtSession *s)
|
||||
{
|
||||
return s->crypto;
|
||||
}
|
||||
|
||||
int
|
||||
vtGetCodec(VtSession *s)
|
||||
{
|
||||
return s->codec;
|
||||
}
|
||||
|
||||
char *
|
||||
vtGetVersion(VtSession *z)
|
||||
{
|
||||
int v, i;
|
||||
|
||||
v = z->version;
|
||||
if(v == 0)
|
||||
return "unknown";
|
||||
for(i=0; vtVersions[i].version; i++)
|
||||
if(vtVersions[i].version == v)
|
||||
return vtVersions[i].s;
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hold z->inLock */
|
||||
static int
|
||||
vtVersionRead(VtSession *z, char *prefix, int *ret)
|
||||
{
|
||||
char c;
|
||||
char buf[VtMaxStringSize];
|
||||
char *q, *p, *pp;
|
||||
int i;
|
||||
|
||||
q = prefix;
|
||||
p = buf;
|
||||
for(;;) {
|
||||
if(p >= buf + sizeof(buf)) {
|
||||
vtSetError(EBadVersion);
|
||||
return 0;
|
||||
}
|
||||
if(!vtFdReadFully(z->fd, (uchar*)&c, 1))
|
||||
return 0;
|
||||
if(z->inHash)
|
||||
vtSha1Update(z->inHash, (uchar*)&c, 1);
|
||||
if(c == '\n') {
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
if(c < ' ' || *q && c != *q) {
|
||||
vtSetError(EBadVersion);
|
||||
return 0;
|
||||
}
|
||||
*p++ = c;
|
||||
if(*q)
|
||||
q++;
|
||||
}
|
||||
|
||||
vtDebug(z, "version string in: %s\n", buf);
|
||||
|
||||
p = buf + strlen(prefix);
|
||||
for(;;) {
|
||||
for(pp=p; *pp && *pp != ':' && *pp != '-'; pp++)
|
||||
;
|
||||
for(i=0; vtVersions[i].version; i++) {
|
||||
if(strlen(vtVersions[i].s) != pp-p)
|
||||
continue;
|
||||
if(memcmp(vtVersions[i].s, p, pp-p) == 0) {
|
||||
*ret = vtVersions[i].version;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
p = pp;
|
||||
if(*p != ':')
|
||||
return 0;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
Packet*
|
||||
vtRecvPacket(VtSession *z)
|
||||
{
|
||||
uchar buf[10], *b;
|
||||
int n;
|
||||
Packet *p;
|
||||
int size, len;
|
||||
|
||||
if(z->cstate != VtStateConnected) {
|
||||
vtSetError("session not connected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
vtLock(z->inLock);
|
||||
p = z->part;
|
||||
/* get enough for head size */
|
||||
size = packetSize(p);
|
||||
while(size < 2) {
|
||||
b = packetTrailer(p, MaxFragSize);
|
||||
assert(b != nil);
|
||||
n = vtFdRead(z->fd, b, MaxFragSize);
|
||||
if(n <= 0)
|
||||
goto Err;
|
||||
size += n;
|
||||
packetTrim(p, 0, size);
|
||||
}
|
||||
|
||||
if(!packetConsume(p, buf, 2))
|
||||
goto Err;
|
||||
len = (buf[0] << 8) | buf[1];
|
||||
size -= 2;
|
||||
|
||||
while(size < len) {
|
||||
n = len - size;
|
||||
if(n > MaxFragSize)
|
||||
n = MaxFragSize;
|
||||
b = packetTrailer(p, n);
|
||||
if(!vtFdReadFully(z->fd, b, n))
|
||||
goto Err;
|
||||
size += n;
|
||||
}
|
||||
p = packetSplit(p, len);
|
||||
vtUnlock(z->inLock);
|
||||
return p;
|
||||
Err:
|
||||
vtUnlock(z->inLock);
|
||||
return nil;
|
||||
}
|
||||
|
||||
int
|
||||
vtSendPacket(VtSession *z, Packet *p)
|
||||
{
|
||||
IOchunk ioc;
|
||||
int n;
|
||||
uchar buf[2];
|
||||
|
||||
/* add framing */
|
||||
n = packetSize(p);
|
||||
if(n >= (1<<16)) {
|
||||
vtSetError(EBigPacket);
|
||||
packetFree(p);
|
||||
return 0;
|
||||
}
|
||||
buf[0] = n>>8;
|
||||
buf[1] = n;
|
||||
packetPrefix(p, buf, 2);
|
||||
|
||||
for(;;) {
|
||||
n = packetFragments(p, &ioc, 1, 0);
|
||||
if(n == 0)
|
||||
break;
|
||||
if(!vtFdWrite(z->fd, ioc.addr, ioc.len)) {
|
||||
packetFree(p);
|
||||
return 0;
|
||||
}
|
||||
packetConsume(p, nil, n);
|
||||
}
|
||||
packetFree(p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
vtGetString(Packet *p, char **ret)
|
||||
{
|
||||
uchar buf[2];
|
||||
int n;
|
||||
char *s;
|
||||
|
||||
if(!packetConsume(p, buf, 2))
|
||||
return 0;
|
||||
n = (buf[0]<<8) + buf[1];
|
||||
if(n > VtMaxStringSize) {
|
||||
vtSetError(EBigString);
|
||||
return 0;
|
||||
}
|
||||
s = vtMemAlloc(n+1);
|
||||
setmalloctag(s, getcallerpc(&p));
|
||||
if(!packetConsume(p, (uchar*)s, n)) {
|
||||
vtMemFree(s);
|
||||
return 0;
|
||||
}
|
||||
s[n] = 0;
|
||||
*ret = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
vtAddString(Packet *p, char *s)
|
||||
{
|
||||
uchar buf[2];
|
||||
int n;
|
||||
|
||||
if(s == nil) {
|
||||
vtSetError(ENullString);
|
||||
return 0;
|
||||
}
|
||||
n = strlen(s);
|
||||
if(n > VtMaxStringSize) {
|
||||
vtSetError(EBigString);
|
||||
return 0;
|
||||
}
|
||||
buf[0] = n>>8;
|
||||
buf[1] = n;
|
||||
packetAppend(p, buf, 2);
|
||||
packetAppend(p, (uchar*)s, n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
vtConnect(VtSession *z, char *password)
|
||||
{
|
||||
char buf[VtMaxStringSize], *p, *ep, *prefix;
|
||||
int i;
|
||||
|
||||
USED(password);
|
||||
vtLock(z->lk);
|
||||
if(z->cstate != VtStateAlloc) {
|
||||
vtSetError("bad session state");
|
||||
vtUnlock(z->lk);
|
||||
return 0;
|
||||
}
|
||||
if(z->fd < 0){
|
||||
vtSetError("%s", z->fderror);
|
||||
vtUnlock(z->lk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* be a little anal */
|
||||
vtLock(z->inLock);
|
||||
vtLock(z->outLock);
|
||||
|
||||
prefix = "venti-";
|
||||
p = buf;
|
||||
ep = buf + sizeof(buf);
|
||||
p = seprint(p, ep, "%s", prefix);
|
||||
p += strlen(p);
|
||||
for(i=0; vtVersions[i].version; i++) {
|
||||
if(i != 0)
|
||||
*p++ = ':';
|
||||
p = seprint(p, ep, "%s", vtVersions[i].s);
|
||||
}
|
||||
p = seprint(p, ep, "-libventi\n");
|
||||
assert(p-buf < sizeof(buf));
|
||||
if(z->outHash)
|
||||
vtSha1Update(z->outHash, (uchar*)buf, p-buf);
|
||||
if(!vtFdWrite(z->fd, (uchar*)buf, p-buf))
|
||||
goto Err;
|
||||
|
||||
vtDebug(z, "version string out: %s", buf);
|
||||
|
||||
if(!vtVersionRead(z, prefix, &z->version))
|
||||
goto Err;
|
||||
|
||||
vtDebug(z, "version = %d: %s\n", z->version, vtGetVersion(z));
|
||||
|
||||
vtUnlock(z->inLock);
|
||||
vtUnlock(z->outLock);
|
||||
z->cstate = VtStateConnected;
|
||||
vtUnlock(z->lk);
|
||||
|
||||
if(z->vtbl)
|
||||
return 1;
|
||||
|
||||
if(!vtHello(z))
|
||||
goto Err;
|
||||
return 1;
|
||||
Err:
|
||||
if(z->fd >= 0)
|
||||
vtFdClose(z->fd);
|
||||
z->fd = -1;
|
||||
vtUnlock(z->inLock);
|
||||
vtUnlock(z->outLock);
|
||||
z->cstate = VtStateClosed;
|
||||
vtUnlock(z->lk);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
|
||||
int
|
||||
vtScoreFmt(Fmt *f)
|
||||
{
|
||||
uchar *v;
|
||||
int i;
|
||||
|
||||
v = va_arg(f->args, uchar*);
|
||||
if(v == nil){
|
||||
fmtprint(f, "*");
|
||||
}else{
|
||||
for(i = 0; i < VtScoreSize; i++)
|
||||
fmtprint(f, "%2.2ux", v[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,265 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
#include "session.h"
|
||||
|
||||
static char EAuthState[] = "bad authentication state";
|
||||
static char ENotServer[] = "not a server session";
|
||||
static char EVersion[] = "incorrect version number";
|
||||
static char EProtocolBotch[] = "venti protocol botch";
|
||||
|
||||
VtSession *
|
||||
vtServerAlloc(VtServerVtbl *vtbl)
|
||||
{
|
||||
VtSession *z = vtAlloc();
|
||||
z->vtbl = vtMemAlloc(sizeof(VtServerVtbl));
|
||||
setmalloctag(z->vtbl, getcallerpc(&vtbl));
|
||||
*z->vtbl = *vtbl;
|
||||
return z;
|
||||
}
|
||||
|
||||
static int
|
||||
srvHello(VtSession *z, char *version, char *uid, int , uchar *, int , uchar *, int )
|
||||
{
|
||||
vtLock(z->lk);
|
||||
if(z->auth.state != VtAuthHello) {
|
||||
vtSetError(EAuthState);
|
||||
goto Err;
|
||||
}
|
||||
if(strcmp(version, vtGetVersion(z)) != 0) {
|
||||
vtSetError(EVersion);
|
||||
goto Err;
|
||||
}
|
||||
vtMemFree(z->uid);
|
||||
z->uid = vtStrDup(uid);
|
||||
z->auth.state = VtAuthOK;
|
||||
vtUnlock(z->lk);
|
||||
return 1;
|
||||
Err:
|
||||
z->auth.state = VtAuthFailed;
|
||||
vtUnlock(z->lk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dispatchHello(VtSession *z, Packet **pkt)
|
||||
{
|
||||
char *version, *uid;
|
||||
uchar *crypto, *codec;
|
||||
uchar buf[10];
|
||||
int ncrypto, ncodec, cryptoStrength;
|
||||
int ret;
|
||||
Packet *p;
|
||||
|
||||
p = *pkt;
|
||||
|
||||
version = nil;
|
||||
uid = nil;
|
||||
crypto = nil;
|
||||
codec = nil;
|
||||
|
||||
ret = 0;
|
||||
if(!vtGetString(p, &version))
|
||||
goto Err;
|
||||
if(!vtGetString(p, &uid))
|
||||
goto Err;
|
||||
if(!packetConsume(p, buf, 2))
|
||||
goto Err;
|
||||
cryptoStrength = buf[0];
|
||||
ncrypto = buf[1];
|
||||
crypto = vtMemAlloc(ncrypto);
|
||||
if(!packetConsume(p, crypto, ncrypto))
|
||||
goto Err;
|
||||
|
||||
if(!packetConsume(p, buf, 1))
|
||||
goto Err;
|
||||
ncodec = buf[0];
|
||||
codec = vtMemAlloc(ncodec);
|
||||
if(!packetConsume(p, codec, ncodec))
|
||||
goto Err;
|
||||
|
||||
if(packetSize(p) != 0) {
|
||||
vtSetError(EProtocolBotch);
|
||||
goto Err;
|
||||
}
|
||||
if(!srvHello(z, version, uid, cryptoStrength, crypto, ncrypto, codec, ncodec)) {
|
||||
packetFree(p);
|
||||
*pkt = nil;
|
||||
} else {
|
||||
if(!vtAddString(p, vtGetSid(z)))
|
||||
goto Err;
|
||||
buf[0] = vtGetCrypto(z);
|
||||
buf[1] = vtGetCodec(z);
|
||||
packetAppend(p, buf, 2);
|
||||
}
|
||||
ret = 1;
|
||||
Err:
|
||||
vtMemFree(version);
|
||||
vtMemFree(uid);
|
||||
vtMemFree(crypto);
|
||||
vtMemFree(codec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dispatchRead(VtSession *z, Packet **pkt)
|
||||
{
|
||||
Packet *p;
|
||||
int type, n;
|
||||
uchar score[VtScoreSize], buf[4];
|
||||
|
||||
p = *pkt;
|
||||
if(!packetConsume(p, score, VtScoreSize))
|
||||
return 0;
|
||||
if(!packetConsume(p, buf, 4))
|
||||
return 0;
|
||||
type = buf[0];
|
||||
n = (buf[2]<<8) | buf[3];
|
||||
if(packetSize(p) != 0) {
|
||||
vtSetError(EProtocolBotch);
|
||||
return 0;
|
||||
}
|
||||
packetFree(p);
|
||||
*pkt = (*z->vtbl->read)(z, score, type, n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
dispatchWrite(VtSession *z, Packet **pkt)
|
||||
{
|
||||
Packet *p;
|
||||
int type;
|
||||
uchar score[VtScoreSize], buf[4];
|
||||
|
||||
p = *pkt;
|
||||
if(!packetConsume(p, buf, 4))
|
||||
return 0;
|
||||
type = buf[0];
|
||||
if(!(z->vtbl->write)(z, score, type, p)) {
|
||||
*pkt = 0;
|
||||
} else {
|
||||
*pkt = packetAlloc();
|
||||
packetAppend(*pkt, score, VtScoreSize);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
dispatchSync(VtSession *z, Packet **pkt)
|
||||
{
|
||||
(z->vtbl->sync)(z);
|
||||
if(packetSize(*pkt) != 0) {
|
||||
vtSetError(EProtocolBotch);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
vtExport(VtSession *z)
|
||||
{
|
||||
Packet *p;
|
||||
uchar buf[10], *hdr;
|
||||
int op, tid, clean;
|
||||
|
||||
if(z->vtbl == nil) {
|
||||
vtSetError(ENotServer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fork off slave */
|
||||
switch(rfork(RFNOWAIT|RFMEM|RFPROC)){
|
||||
case -1:
|
||||
vtOSError();
|
||||
return 0;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
p = nil;
|
||||
clean = 0;
|
||||
vtAttach();
|
||||
if(!vtConnect(z, nil))
|
||||
goto Exit;
|
||||
|
||||
vtDebug(z, "server connected!\n");
|
||||
if(0) vtSetDebug(z, 1);
|
||||
|
||||
for(;;) {
|
||||
p = vtRecvPacket(z);
|
||||
if(p == nil) {
|
||||
break;
|
||||
}
|
||||
vtDebug(z, "server recv: ");
|
||||
vtDebugMesg(z, p, "\n");
|
||||
|
||||
if(!packetConsume(p, buf, 2)) {
|
||||
vtSetError(EProtocolBotch);
|
||||
break;
|
||||
}
|
||||
op = buf[0];
|
||||
tid = buf[1];
|
||||
switch(op) {
|
||||
default:
|
||||
vtSetError(EProtocolBotch);
|
||||
goto Exit;
|
||||
case VtQPing:
|
||||
break;
|
||||
case VtQGoodbye:
|
||||
clean = 1;
|
||||
goto Exit;
|
||||
case VtQHello:
|
||||
if(!dispatchHello(z, &p))
|
||||
goto Exit;
|
||||
break;
|
||||
case VtQRead:
|
||||
if(!dispatchRead(z, &p))
|
||||
goto Exit;
|
||||
break;
|
||||
case VtQWrite:
|
||||
if(!dispatchWrite(z, &p))
|
||||
goto Exit;
|
||||
break;
|
||||
case VtQSync:
|
||||
if(!dispatchSync(z, &p))
|
||||
goto Exit;
|
||||
break;
|
||||
}
|
||||
if(p != nil) {
|
||||
hdr = packetHeader(p, 2);
|
||||
hdr[0] = op+1;
|
||||
hdr[1] = tid;
|
||||
} else {
|
||||
p = packetAlloc();
|
||||
hdr = packetHeader(p, 2);
|
||||
hdr[0] = VtRError;
|
||||
hdr[1] = tid;
|
||||
if(!vtAddString(p, vtGetError()))
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
vtDebug(z, "server send: ");
|
||||
vtDebugMesg(z, p, "\n");
|
||||
|
||||
if(!vtSendPacket(z, p)) {
|
||||
p = nil;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
Exit:
|
||||
if(p != nil)
|
||||
packetFree(p);
|
||||
if(z->vtbl->closing)
|
||||
z->vtbl->closing(z, clean);
|
||||
vtClose(z);
|
||||
vtFree(z);
|
||||
vtDetach();
|
||||
|
||||
exits(0);
|
||||
return 0; /* never gets here */
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
typedef struct VtAuth VtAuth;
|
||||
|
||||
/* op codes */
|
||||
enum {
|
||||
VtRError = 1,
|
||||
VtQPing,
|
||||
VtRPing,
|
||||
VtQHello,
|
||||
VtRHello,
|
||||
VtQGoodbye,
|
||||
VtRGoodbye, /* not used */
|
||||
VtQAuth0,
|
||||
VtRAuth0,
|
||||
VtQAuth1,
|
||||
VtRAuth1,
|
||||
VtQRead,
|
||||
VtRRead,
|
||||
VtQWrite,
|
||||
VtRWrite,
|
||||
VtQSync,
|
||||
VtRSync,
|
||||
|
||||
VtMaxOp
|
||||
};
|
||||
|
||||
/* connection state */
|
||||
enum {
|
||||
VtStateAlloc,
|
||||
VtStateConnected,
|
||||
VtStateClosed,
|
||||
};
|
||||
|
||||
/* auth state */
|
||||
enum {
|
||||
VtAuthHello,
|
||||
VtAuth0,
|
||||
VtAuth1,
|
||||
VtAuthOK,
|
||||
VtAuthFailed,
|
||||
};
|
||||
|
||||
struct VtAuth {
|
||||
int state;
|
||||
uchar client[VtScoreSize];
|
||||
uchar sever[VtScoreSize];
|
||||
};
|
||||
|
||||
struct VtSession {
|
||||
VtLock *lk;
|
||||
VtServerVtbl *vtbl; /* == nil means client side */
|
||||
int cstate; /* connection state */
|
||||
int fd;
|
||||
char fderror[ERRMAX];
|
||||
|
||||
VtAuth auth;
|
||||
|
||||
VtSha1 *inHash;
|
||||
VtLock *inLock;
|
||||
Packet *part; /* partial packet */
|
||||
|
||||
VtSha1 *outHash;
|
||||
VtLock *outLock;
|
||||
|
||||
int debug;
|
||||
int version;
|
||||
int ref;
|
||||
char *uid;
|
||||
char *sid;
|
||||
int cryptoStrength;
|
||||
int compression;
|
||||
int crypto;
|
||||
int codec;
|
||||
};
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
|
||||
char*
|
||||
vtStrDup(char *s)
|
||||
{
|
||||
int n;
|
||||
char *ss;
|
||||
|
||||
if(s == nil)
|
||||
return nil;
|
||||
n = strlen(s) + 1;
|
||||
ss = vtMemAlloc(n);
|
||||
memmove(ss, s, n);
|
||||
setmalloctag(ss, getcallerpc(&s));
|
||||
return ss;
|
||||
}
|
||||
|
|
@ -1,267 +0,0 @@
|
|||
|
||||
protocol version id
|
||||
|
||||
both client and server send '\n' terminated ascii of the form
|
||||
|
||||
venti-<versions>-<software>
|
||||
|
||||
|
||||
<software> = is a software id which is ignored but may be useful for debugging
|
||||
|
||||
If the server and client have the same version number then this
|
||||
version is used. Otherwise backup to the greatest common
|
||||
major version number, e.g. 1.00 2.00 etc. If no version in
|
||||
common then abort. The idea is both client and server should
|
||||
support a continusous range of major versions. The minor version
|
||||
numbers are used for development purposes.
|
||||
|
||||
After protocol negotiation switch to binary format
|
||||
|
||||
all numbers sent big endian
|
||||
|
||||
strings are sent with 2 byte length without nulls and in utf-8 max size of 1K
|
||||
|
||||
RPC protocol
|
||||
|
||||
header
|
||||
op[1] byte op
|
||||
tid[2] transation id
|
||||
|
||||
client manages the tid space. Until session is established tid must equal 0.
|
||||
i.e. only one outstanding op.
|
||||
|
||||
CipherStrength
|
||||
None,
|
||||
Auth,
|
||||
Weak,
|
||||
Strong
|
||||
CipherAlgorithms
|
||||
None
|
||||
SSL3
|
||||
TLS1
|
||||
CompressionAlgorithms
|
||||
None
|
||||
Deflate
|
||||
Thwack?
|
||||
|
||||
BlockTypes
|
||||
Root
|
||||
Pointer
|
||||
Data
|
||||
|
||||
==============================================
|
||||
|
||||
TPing
|
||||
RPing
|
||||
|
||||
RError
|
||||
error: string
|
||||
|
||||
THello
|
||||
version:string; know to be supported by both
|
||||
uid: string
|
||||
uhash[20] use for cipher boot strapping
|
||||
cipherstrength[1]
|
||||
ncipher[1];
|
||||
cipher[ncipher];
|
||||
ncompressor[1];
|
||||
compressor[ncompressor];
|
||||
RHello
|
||||
sid: string
|
||||
shash[20]; use for cipher bott strapping
|
||||
cipher[1];
|
||||
compressor[1];
|
||||
|
||||
use srp style authentication
|
||||
g=2
|
||||
N is safe prime 1024 bits - find a good prime!
|
||||
|
||||
x = H("venti" H(sid) H(uid) H(password))
|
||||
v = g^x
|
||||
a = random
|
||||
b = random
|
||||
B = (v + g^b)
|
||||
A = g^a
|
||||
u = first four bytes of H(B)
|
||||
S = (B - g^x) ^ (a + u*x) = (A * v^u) ^ b
|
||||
K = H(S)
|
||||
M1 = H(H(versions) H(THello) H(RHello) A B K)
|
||||
M2 = H(A M1 K)
|
||||
|
||||
TAuth0
|
||||
A[128]
|
||||
RAuth0
|
||||
B[128]
|
||||
TAuth1
|
||||
M1[20]
|
||||
RAuth1
|
||||
M2[20]
|
||||
|
||||
push cipher
|
||||
push compression
|
||||
|
||||
TWrite
|
||||
length[2] max 56*1024
|
||||
type[1]
|
||||
data[length]
|
||||
RWrite
|
||||
hash[20]
|
||||
|
||||
TRead
|
||||
hash[20]
|
||||
type[1]
|
||||
length[2]
|
||||
RRead
|
||||
length[2]
|
||||
data[length]
|
||||
|
||||
============================================================
|
||||
|
||||
simplified access when trusting the server
|
||||
reduces network bandwidth since pointer blocks are not
|
||||
sent to the client - can also enable permission checking
|
||||
|
||||
RReadRoot
|
||||
root[20]
|
||||
TReadRoot
|
||||
name: string
|
||||
type: string
|
||||
blocksize[2]
|
||||
nblock[8]
|
||||
time[4]
|
||||
uid: string;
|
||||
gid: string
|
||||
|
||||
RReadData
|
||||
root[20]
|
||||
block[8]
|
||||
length[2]
|
||||
TReadData
|
||||
length[2]
|
||||
collision[1]
|
||||
data[length]
|
||||
|
||||
==============================================
|
||||
|
||||
maybe some clients should be required to navigate to block via root nodes.
|
||||
This would enable permission checking via access to the root node.
|
||||
|
||||
RTagOpen
|
||||
tag[2]
|
||||
root[20]
|
||||
TTagOpen
|
||||
|
||||
QTagRead
|
||||
tag[2]
|
||||
type[1]
|
||||
length[2]
|
||||
RTagRead
|
||||
length[2]
|
||||
data[length]
|
||||
|
||||
QTagWalkRead
|
||||
tag[2]
|
||||
ntag[2] can reuse a tag to do an implict clunk
|
||||
index[2]
|
||||
type[1]
|
||||
length[2]
|
||||
RTagWalkRead
|
||||
length[2]
|
||||
data[length]
|
||||
|
||||
RTagClunk
|
||||
tag[2]
|
||||
TTagClunk
|
||||
|
||||
============================
|
||||
|
||||
Types of blocks
|
||||
|
||||
Data
|
||||
|
||||
Root
|
||||
name[128]
|
||||
type[128]
|
||||
score[20] - DirBlock
|
||||
|
||||
Pointer
|
||||
score[20]* the number of hashes can be less than fanout when the
|
||||
tree is not full
|
||||
DirBlock
|
||||
DirEntry[32]*
|
||||
|
||||
DirEntry
|
||||
pointersize[2] - pointer block size
|
||||
datasize[2] - data blocks size
|
||||
flag[1] directory
|
||||
size[7] in bytes - determines pointer depth - intermidate truncated block count as full
|
||||
score[20] root of pointer blocks or data block
|
||||
|
||||
============================
|
||||
|
||||
mode flags
|
||||
(1<<0) ModeOtherExec
|
||||
(1<<1) ModeOtherWrite
|
||||
(1<<2) ModeOtherRead
|
||||
(1<<3) ModeGroupExec
|
||||
(1<<4) ModeGroupWrite
|
||||
(1<<5) ModeGroupRead
|
||||
(1<<6) ModeOwnerExec
|
||||
(1<<7) ModeOwnerWrite
|
||||
(1<<8) ModeOwnerRead
|
||||
(1<<9) ModeSticky
|
||||
(1<<10) ModeSetUid
|
||||
(1<<11) ModeSetGid
|
||||
(1<<12) ModeAppend
|
||||
(1<<13) ModeExclusive
|
||||
(1<<14) ModeLink
|
||||
(1<<15) ModeDir - duplicates dir entry
|
||||
(1<<16) ModeHidden
|
||||
(1<<17) ModeSystem
|
||||
(1<<18) ModeArchive
|
||||
(1<<19) ModeTemporary
|
||||
(1<<18) ModeCompressed
|
||||
(1<<19) ModeEncrypted
|
||||
|
||||
extraType
|
||||
2 Plan9
|
||||
version[4]
|
||||
muid: string
|
||||
|
||||
3 NT Time
|
||||
createTime[8];
|
||||
modifyTime[8];
|
||||
accessTime[8]
|
||||
|
||||
|
||||
MetaEntry
|
||||
name: string /* must be first */
|
||||
direntry[4]
|
||||
|
||||
id[8]
|
||||
|
||||
uid: string
|
||||
gui: string
|
||||
mtime[4]
|
||||
ctime[4]
|
||||
atime[4]
|
||||
|
||||
mode[4]
|
||||
|
||||
extratype;
|
||||
extrasize[2]
|
||||
extra:[nextra]
|
||||
|
||||
MetaEntry Block
|
||||
magic[4]
|
||||
size[2]
|
||||
free[2] - used to determine if work compacting
|
||||
maxindex[2] - size of index table in bytes
|
||||
nindex[2]
|
||||
index[2*nindex]
|
||||
|
||||
per OS directory entries?
|
||||
|
||||
inode...
|
||||
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <oventi.h>
|
||||
|
||||
/* score of a zero length block */
|
||||
uchar vtZeroScore[VtScoreSize] = {
|
||||
0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
|
||||
0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
vtZeroExtend(int type, uchar *buf, int n, int nn)
|
||||
{
|
||||
uchar *p, *ep;
|
||||
|
||||
switch(type) {
|
||||
default:
|
||||
memset(buf+n, 0, nn-n);
|
||||
break;
|
||||
case VtPointerType0:
|
||||
case VtPointerType1:
|
||||
case VtPointerType2:
|
||||
case VtPointerType3:
|
||||
case VtPointerType4:
|
||||
case VtPointerType5:
|
||||
case VtPointerType6:
|
||||
case VtPointerType7:
|
||||
case VtPointerType8:
|
||||
case VtPointerType9:
|
||||
p = buf + (n/VtScoreSize)*VtScoreSize;
|
||||
ep = buf + (nn/VtScoreSize)*VtScoreSize;
|
||||
while(p < ep) {
|
||||
memmove(p, vtZeroScore, VtScoreSize);
|
||||
p += VtScoreSize;
|
||||
}
|
||||
memset(p, 0, buf+nn-p);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
vtZeroTruncate(int type, uchar *buf, int n)
|
||||
{
|
||||
uchar *p;
|
||||
|
||||
switch(type) {
|
||||
default:
|
||||
for(p = buf + n; p > buf; p--) {
|
||||
if(p[-1] != 0)
|
||||
break;
|
||||
}
|
||||
return p - buf;
|
||||
case VtRootType:
|
||||
if(n < VtRootSize)
|
||||
return n;
|
||||
return VtRootSize;
|
||||
case VtPointerType0:
|
||||
case VtPointerType1:
|
||||
case VtPointerType2:
|
||||
case VtPointerType3:
|
||||
case VtPointerType4:
|
||||
case VtPointerType5:
|
||||
case VtPointerType6:
|
||||
case VtPointerType7:
|
||||
case VtPointerType8:
|
||||
case VtPointerType9:
|
||||
/* ignore slop at end of block */
|
||||
p = buf + (n/VtScoreSize)*VtScoreSize;
|
||||
|
||||
while(p > buf) {
|
||||
if(memcmp(p - VtScoreSize, vtZeroScore, VtScoreSize) != 0)
|
||||
break;
|
||||
p -= VtScoreSize;
|
||||
}
|
||||
return p - buf;
|
||||
}
|
||||
}
|
|
@ -28,7 +28,6 @@ LIBS=\
|
|||
libmemlayer\
|
||||
libmp\
|
||||
libndb\
|
||||
liboventi\
|
||||
libplumb\
|
||||
libregexp\
|
||||
libscribble\
|
||||
|
|
Loading…
Reference in a new issue