libventi: protocol support for blocks larger than 64k

This commit is contained in:
Russ Cox 2009-05-25 00:30:17 -07:00
parent 9cac97f2c5
commit 33b446b8bb
6 changed files with 79 additions and 23 deletions

View file

@ -292,7 +292,7 @@ struct VtFcall
uint nauth; /* TauthX, RauthX */
uchar score[VtScoreSize]; /* Tread, Rwrite */
uchar blocktype; /* Tread, Twrite */
ushort count; /* Tread */
uint count; /* Tread */
Packet *data; /* Rread, Twrite */
};

View file

@ -441,6 +441,21 @@ message ends a session. There is no
upon receiving the
.BR VtTgoodbye
message, the server terminates up the connection.
.PP
Version
.B 04
of the Venti protocol is similar to version
.B 02
(described above)
but has two changes to accomodates larger payloads.
First, it replaces the leading 2-byte packet size with
a 4-byte size.
Second, the
.I count
in the
.B VtTread
packet may be either 2 or 4 bytes;
the total packet length distinguishes the two cases.
.SH SEE ALSO
.IR venti (1),
.IR venti (3),

View file

@ -65,6 +65,10 @@ vtreadpacket(VtConn *z, uchar score[VtScoreSize], uint type, int n)
if(memcmp(score, vtzeroscore, VtScoreSize) == 0)
return packetalloc();
if(z->version[1] == '2' && n >= (1<<16)) {
werrstr("read count too large for protocol");
return nil;
}
memset(&tx, 0, sizeof tx);
tx.msgtype = VtTread;
tx.blocktype = type;

View file

@ -5,7 +5,7 @@
Packet*
vtfcallpack(VtFcall *f)
{
uchar buf[4];
uchar buf[10];
Packet *p;
p = packetalloc();
@ -60,9 +60,17 @@ vtfcallpack(VtFcall *f)
if(~buf[0] == 0)
goto Err;
buf[1] = 0;
if(f->count >= (1<<16)) {
buf[2] = f->count >> 24;
buf[3] = f->count >> 16;
buf[4] = f->count >> 8;
buf[5] = f->count;
packetappend(p, buf, 6);
} else {
buf[2] = f->count >> 8;
buf[3] = f->count;
packetappend(p, buf, 4);
}
break;
case VtRread:
@ -163,13 +171,26 @@ vtfcallunpack(VtFcall *f, Packet *p)
case VtTread:
if(packetconsume(p, f->score, VtScoreSize) < 0
|| packetconsume(p, buf, 4) < 0)
|| packetconsume(p, buf, 2) < 0)
goto Err;
f->blocktype = vtfromdisktype(buf[0]);
if(~f->blocktype == 0)
goto Err;
switch(packetsize(p)) {
default:
goto Err;
case 2:
if(packetconsume(p, buf, 2) < 0)
goto Err;
f->count = (buf[2] << 8) | buf[3];
break;
case 4:
if(packetconsume(p, buf, 4) < 0)
goto Err;
f->count = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
break;
}
break;
case VtRread:
f->data = packetalloc();

View file

@ -11,7 +11,7 @@ _vtsend(VtConn *z, Packet *p)
{
IOchunk ioc;
int n, tot;
uchar buf[2];
uchar buf[4];
if(z->state != VtStateConnected) {
werrstr("session not connected");
@ -20,6 +20,7 @@ _vtsend(VtConn *z, Packet *p)
/* add framing */
n = packetsize(p);
if(z->version[1] == '2') {
if(n >= (1<<16)) {
werrstr("packet too large");
packetfree(p);
@ -29,6 +30,14 @@ _vtsend(VtConn *z, Packet *p)
buf[1] = n;
packetprefix(p, buf, 2);
ventisendbytes += n+2;
} else {
buf[0] = n>>24;
buf[1] = n>>16;
buf[2] = n>>8;
buf[3] = n;
packetprefix(p, buf, 4);
ventisendbytes += n+4;
}
ventisendpackets++;
tot = 0;
@ -63,7 +72,7 @@ static Packet*
_vtrecv(VtConn *z)
{
uchar buf[10], *b;
int n;
int n, need;
Packet *p;
int size, len;
@ -75,11 +84,12 @@ _vtrecv(VtConn *z)
p = z->part;
/* get enough for head size */
size = packetsize(p);
while(size < 2) {
b = packettrailer(p, 2);
need = z->version[1] - '0'; // 2 or 4
while(size < need) {
b = packettrailer(p, need);
assert(b != nil);
if(0) fprint(2, "%d read hdr\n", getpid());
n = read(z->infd, b, 2);
n = read(z->infd, b, need);
if(0) fprint(2, "%d got %d (%r)\n", getpid(), n);
if(n==0 || (n<0 && !interrupted()))
goto Err;
@ -87,10 +97,15 @@ _vtrecv(VtConn *z)
packettrim(p, 0, size);
}
if(packetconsume(p, buf, 2) < 0)
if(packetconsume(p, buf, need) < 0)
goto Err;
if(z->version[1] == '2') {
len = (buf[0] << 8) | buf[1];
size -= 2;
} else {
len = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
size -= 4;
}
while(size < len) {
n = len - size;

View file

@ -3,6 +3,7 @@
#include <venti.h>
static char *okvers[] = {
"04",
"02",
nil,
};