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 */ uint nauth; /* TauthX, RauthX */
uchar score[VtScoreSize]; /* Tread, Rwrite */ uchar score[VtScoreSize]; /* Tread, Rwrite */
uchar blocktype; /* Tread, Twrite */ uchar blocktype; /* Tread, Twrite */
ushort count; /* Tread */ uint count; /* Tread */
Packet *data; /* Rread, Twrite */ Packet *data; /* Rread, Twrite */
}; };

View file

@ -441,6 +441,21 @@ message ends a session. There is no
upon receiving the upon receiving the
.BR VtTgoodbye .BR VtTgoodbye
message, the server terminates up the connection. 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 .SH SEE ALSO
.IR venti (1), .IR venti (1),
.IR venti (3), .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) if(memcmp(score, vtzeroscore, VtScoreSize) == 0)
return packetalloc(); return packetalloc();
if(z->version[1] == '2' && n >= (1<<16)) {
werrstr("read count too large for protocol");
return nil;
}
memset(&tx, 0, sizeof tx); memset(&tx, 0, sizeof tx);
tx.msgtype = VtTread; tx.msgtype = VtTread;
tx.blocktype = type; tx.blocktype = type;

View file

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

View file

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

View file

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