blob: 4c13bc87ee866701a2e8c9b90a28925cb50b696f [file] [log] [blame]
#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;
}