tlibventi: protocol support for blocks larger than 64k - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit 33b446b8bbfea80552d462296d27ad4114fbd3fb
parent 9cac97f2c55efc9ffa9b3894127e049cc25852a3
Author: Russ Cox 
Date:   Mon, 25 May 2009 00:30:17 -0700

libventi: protocol support for blocks larger than 64k

Diffstat:
  M include/venti.h                     |       2 +-
  M man/man7/venti.7                    |      15 +++++++++++++++
  M src/libventi/client.c               |       4 ++++
  M src/libventi/fcall.c                |      33 +++++++++++++++++++++++++------
  M src/libventi/send.c                 |      47 ++++++++++++++++++++-----------
  M src/libventi/version.c              |       1 +

6 files changed, 79 insertions(+), 23 deletions(-)
---
diff --git a/include/venti.h b/include/venti.h
t@@ -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 */
 };
 
diff --git a/man/man7/venti.7 b/man/man7/venti.7
t@@ -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),
diff --git a/src/libventi/client.c b/src/libventi/client.c
t@@ -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;
diff --git a/src/libventi/fcall.c b/src/libventi/fcall.c
t@@ -5,7 +5,7 @@
 Packet*
 vtfcallpack(VtFcall *f)
 {
-        uchar buf[4];
+        uchar buf[10];
         Packet *p;
 
         p = packetalloc();
t@@ -60,9 +60,17 @@ vtfcallpack(VtFcall *f)
                 if(~buf[0] == 0)
                         goto Err;
                 buf[1] = 0;
-                buf[2] = f->count >> 8;
-                buf[3] = f->count;
-                packetappend(p, buf, 4);
+                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:
t@@ -163,12 +171,25 @@ 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;
-                f->count = (buf[2] << 8) | buf[3];
+                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:
diff --git a/src/libventi/send.c b/src/libventi/send.c
t@@ -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");
t@@ -20,15 +20,24 @@ _vtsend(VtConn *z, Packet *p)
 
         /* add framing */
         n = packetsize(p);
-        if(n >= (1<<16)) {
-                werrstr("packet too large");
-                packetfree(p);
-                return -1;
+        if(z->version[1] == '2') {
+                if(n >= (1<<16)) {
+                        werrstr("packet too large");
+                        packetfree(p);
+                        return -1;
+                }
+                buf[0] = n>>8;
+                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;
         }
-        buf[0] = n>>8;
-        buf[1] = n;
-        packetprefix(p, buf, 2);
-        ventisendbytes += n+2;
         ventisendpackets++;
 
         tot = 0;
t@@ -63,7 +72,7 @@ static Packet*
 _vtrecv(VtConn *z)
 {
         uchar buf[10], *b;
-        int n;
+        int n, need;
         Packet *p;
         int size, len;
 
t@@ -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;
t@@ -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;
-        len = (buf[0] << 8) | buf[1];
-        size -= 2;
+        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;
diff --git a/src/libventi/version.c b/src/libventi/version.c
t@@ -3,6 +3,7 @@
 #include 
 
 static char *okvers[] = {
+        "04",
         "02",
         nil,
 };