| #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; |
| } |
| |