|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <venti.h> | 
|  | #include <libsec.h> | 
|  |  | 
|  | #define MAGIC 0x54798314 | 
|  | #define NOTFREE(p)	assert((p)->magic == MAGIC) | 
|  |  | 
|  | struct Packet | 
|  | { | 
|  | char *data; | 
|  | int len; | 
|  | void (*free)(void*); | 
|  | void *arg; | 
|  | int magic; | 
|  | }; | 
|  |  | 
|  | Packet* | 
|  | packetalloc(void) | 
|  | { | 
|  | Packet *p; | 
|  |  | 
|  | p = vtmallocz(sizeof *p); | 
|  | p->free = vtfree; | 
|  | p->arg = nil; | 
|  | p->magic = MAGIC; | 
|  | return p; | 
|  | } | 
|  |  | 
|  | void | 
|  | packetappend(Packet *p, uchar *buf, int n) | 
|  | { | 
|  | NOTFREE(p); | 
|  | if(n < 0) | 
|  | abort(); | 
|  | if(p->free != vtfree) | 
|  | sysfatal("packetappend"); | 
|  | p->data = vtrealloc(p->data, p->len+n); | 
|  | p->arg = p->data; | 
|  | memmove(p->data+p->len, buf, n); | 
|  | p->len += n; | 
|  | } | 
|  |  | 
|  | uint | 
|  | packetasize(Packet *p) | 
|  | { | 
|  | NOTFREE(p); | 
|  | return p->len; | 
|  | } | 
|  |  | 
|  | int | 
|  | packetcmp(Packet *p, Packet *q) | 
|  | { | 
|  | int i, len; | 
|  |  | 
|  | NOTFREE(p); | 
|  | NOTFREE(q); | 
|  | len = p->len; | 
|  | if(len > q->len) | 
|  | len = q->len; | 
|  | if(len && (i=memcmp(p->data, q->data, len)) != 0) | 
|  | return i; | 
|  | if(p->len > len) | 
|  | return 1; | 
|  | if(q->len > len) | 
|  | return -1; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | void | 
|  | packetconcat(Packet *p, Packet *q) | 
|  | { | 
|  | NOTFREE(p); | 
|  | NOTFREE(q); | 
|  | packetappend(p, q->data, q->len); | 
|  | if(q->free == vtfree) | 
|  | memset(q->data, 0xFE, q->len); | 
|  | q->free(q->arg); | 
|  | q->data = nil; | 
|  | q->len = 0; | 
|  | } | 
|  |  | 
|  | int | 
|  | packetconsume(Packet *p, uchar *buf, int n) | 
|  | { | 
|  | NOTFREE(p); | 
|  | if(n < 0) | 
|  | abort(); | 
|  | if(p->len < n) | 
|  | abort(); | 
|  | memmove(buf, p->data, n); | 
|  | p->len -= n; | 
|  | memmove(p->data, p->data+n, p->len); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int | 
|  | packetcopy(Packet *p, uchar *buf, int offset, int n) | 
|  | { | 
|  | NOTFREE(p); | 
|  | if(offset < 0 || n < 0) | 
|  | abort(); | 
|  | if(offset > p->len) | 
|  | abort(); | 
|  | if(offset+n > p->len) | 
|  | n = p->len - offset; | 
|  | memmove(buf, p->data+offset, n); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | Packet* | 
|  | packetdup(Packet *p, int offset, int n) | 
|  | { | 
|  | Packet *q; | 
|  |  | 
|  | NOTFREE(p); | 
|  | if(offset < 0 || n < 0) | 
|  | abort(); | 
|  | if(offset > p->len) | 
|  | abort(); | 
|  | if(offset+n > p->len) | 
|  | n = p->len - offset; | 
|  | q = packetalloc(); | 
|  | packetappend(q, p->data+offset, n); | 
|  | return q; | 
|  | } | 
|  |  | 
|  | Packet* | 
|  | packetforeign(uchar *buf, int n, void (*free)(void*), void *a) | 
|  | { | 
|  | Packet *p; | 
|  |  | 
|  | if(n < 0) | 
|  | abort(); | 
|  | p = packetalloc(); | 
|  | p->data = (char*)buf; | 
|  | p->len = n; | 
|  | p->free = free; | 
|  | p->arg = a; | 
|  | return p; | 
|  | } | 
|  |  | 
|  | int | 
|  | packetfragments(Packet *p, IOchunk *io, int nio, int offset) | 
|  | { | 
|  | NOTFREE(p); | 
|  | if(offset < 0) | 
|  | abort(); | 
|  | if(nio == 0) | 
|  | return 0; | 
|  | memset(io, 0, sizeof(io[0])*nio); | 
|  | if(offset >= p->len) | 
|  | return 0; | 
|  | io[0].addr = p->data + offset; | 
|  | io[0].len = p->len - offset; | 
|  | return p->len; | 
|  | } | 
|  |  | 
|  | void | 
|  | packetfree(Packet *p) | 
|  | { | 
|  | NOTFREE(p); | 
|  | if(p->free == free) | 
|  | memset(p->data, 0xFE, p->len); | 
|  | p->free(p->arg); | 
|  | p->data = nil; | 
|  | p->len = 0; | 
|  | memset(p, 0xFB, sizeof *p); | 
|  | free(p); | 
|  | } | 
|  |  | 
|  | uchar* | 
|  | packetheader(Packet *p, int n) | 
|  | { | 
|  | NOTFREE(p); | 
|  | if(n < 0) | 
|  | abort(); | 
|  | if(n > p->len) | 
|  | abort(); | 
|  | return p->data; | 
|  | } | 
|  |  | 
|  | uchar* | 
|  | packetpeek(Packet *p, uchar *buf, int offset, int n) | 
|  | { | 
|  | NOTFREE(p); | 
|  | if(offset < 0 || n < 0) | 
|  | abort(); | 
|  | if(offset+n > p->len) | 
|  | abort(); | 
|  | return p->data+offset; | 
|  | } | 
|  |  | 
|  | void | 
|  | packetprefix(Packet *p, uchar *buf, int n) | 
|  | { | 
|  | NOTFREE(p); | 
|  | if(n < 0) | 
|  | abort(); | 
|  | if(p->free != free) | 
|  | sysfatal("packetappend"); | 
|  | p->data = vtrealloc(p->data, p->len+n); | 
|  | p->arg = p->data; | 
|  | memmove(p->data+n, p->data, p->len); | 
|  | memmove(p->data, buf, n); | 
|  | p->len += n; | 
|  | } | 
|  |  | 
|  | void | 
|  | packetsha1(Packet *p, uchar d[20]) | 
|  | { | 
|  | NOTFREE(p); | 
|  | sha1((uchar*)p->data, p->len, d, nil); | 
|  | } | 
|  |  | 
|  | uint | 
|  | packetsize(Packet *p) | 
|  | { | 
|  | NOTFREE(p); | 
|  | return p->len; | 
|  | } | 
|  |  | 
|  | Packet* | 
|  | packetsplit(Packet *p, int n) | 
|  | { | 
|  | Packet *q; | 
|  |  | 
|  | NOTFREE(p); | 
|  | q = packetalloc(); | 
|  | q->data = vtmalloc(n); | 
|  | q->arg = q->data; | 
|  | q->free = vtfree; | 
|  | packetconsume(p, q->data, n); | 
|  | return q; | 
|  | } | 
|  |  | 
|  | void | 
|  | packetstats(void) | 
|  | { | 
|  | } | 
|  |  | 
|  | uchar* | 
|  | packettrailer(Packet *p, int n) | 
|  | { | 
|  | NOTFREE(p); | 
|  | if(n < 0) | 
|  | abort(); | 
|  | if(n > p->len) | 
|  | abort(); | 
|  | return p->data + p->len - n; | 
|  | } | 
|  |  | 
|  | int | 
|  | packettrim(Packet *p, int offset, int n) | 
|  | { | 
|  | NOTFREE(p); | 
|  | if(offset < 0 || n < 0) | 
|  | abort(); | 
|  | if(offset+n > p->len) | 
|  | abort(); | 
|  | memmove(p->data+offset, p->data+offset+n, p->len-offset-n); | 
|  | p->len -= n; | 
|  | return 0; | 
|  | } | 
|  |  |