/* @@@HEAD@@@
// Veil packets buffer manipulation module
*/
#include "config.h"
#include "defs.h"
#include "y.tab.h"
#include "cdc_types.h"
#include "operators.h"
#include "execute.h"
#include "memory.h"
extern Ident pabort_id, pclose_id, popen_id;
#define VEIL_P_PUSH 1
#define VEIL_P_ABORT 2
#define VEIL_P_CLOSE 4
#define VEIL_P_OPEN 8
#define VEIL_P_UNDF1 16
#define VEIL_P_UNDF2 32
#define VEIL_P_UNDF3 64
#define VEIL_P_UNDF4 128
#define HEADER_SIZE 5 /* 1 byte bitfield flags
2 bytes session id
2 bytes length */
internal list_t * buffer_to_veil_packets(Buffer * buf) {
int flags,
session,
length,
blen;
Buffer * databuf,
* incomplete;
data_t d,
* list;
list_t * output,
* packet;
char * cbuf;
output = list_new(0);
blen = buf->len;
cbuf = buf->s;
for (;;) {
/* 5 bytes will give us the header, we check length again after
that, because the header gives us the data length */
if (blen < HEADER_SIZE)
break;
flags = (int) cbuf[0];
session = (((int) cbuf[1]) * 256) + (int) cbuf[2];
length = (((int) cbuf[3]) * 256) + cbuf[4];
if (length > (blen - HEADER_SIZE))
break;
/* copy the data segment of the packet to the databuf */
databuf = buffer_new(length);
cbuf += HEADER_SIZE;
MEMCPY(databuf->s, cbuf, length);
cbuf += (length + HEADER_SIZE);
blen -= (length + HEADER_SIZE);
/* create the packet list, add it to the output list */
packet = list_new(4);
list = list_empty_spaces(packet, 4);
list[0].type = INTEGER;
list[0].u.val = (flags & VEIL_P_PUSH);
/* give abort precedence */
if (flags & VEIL_P_ABORT) {
list[1].type = SYMBOL;
list[1].u.symbol = pabort_id;
} else if (flags & VEIL_P_CLOSE) {
list[1].type = SYMBOL;
list[1].u.symbol = pclose_id;
} else if (flags & VEIL_P_OPEN) {
list[1].type = SYMBOL;
list[1].u.symbol = popen_id;
} else {
list[1].type = INTEGER;
list[1].u.val = 0;
}
list[2].type = INTEGER;
list[2].u.val = session;
list[3].type = BUFFER;
list[3].u.buffer = databuf;
/* add it to the list */
d.type = LIST;
d.u.list = packet;
output = list_add(output, &d);
buffer_discard(databuf);
list_discard(packet);
}
/* add the incomplete buffer to the end */
incomplete = buffer_new(blen);
if (blen > 0)
MEMMOVE(incomplete->s, cbuf, blen); \
d.type = BUFFER;
d.u.buffer = incomplete;
output = list_add(output, &d);
buffer_discard(incomplete);
return output;
}
void op_buf_to_veil_packets(void) {
data_t * args;
int numargs;
Buffer * buf;
list_t * packets;
if (!func_init_1_or_2(&args, &numargs, BUFFER, BUFFER))
return;
/* if they sent us a second argument, concatenate it on the end */
buf = buffer_dup(args[0].u.buffer);
if (numargs == 2)
buffer_append(buf, args[1].u.buffer);
packets = buffer_to_veil_packets(buf);
buffer_discard(buf);
pop(numargs);
push_list(packets);
list_discard(packets);
}
void op_buf_from_veil_packets(void) {
if (!func_init_0()) /* &args, LIST)) */
return;
push_int(0);
}