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\
|
libmemlayer\
|
||||||
libmp\
|
libmp\
|
||||||
libndb\
|
libndb\
|
||||||
liboventi\
|
|
||||||
libplumb\
|
libplumb\
|
||||||
libregexp\
|
libregexp\
|
||||||
libscribble\
|
libscribble\
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue