Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • anders_blomdell/labcomm
  • klaren/labcomm
  • tommyo/labcomm
  • erikj/labcomm
  • sven/labcomm
5 results
Show changes
Showing
with 3031 additions and 0 deletions
#include "ethaddr.h"
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
#if ETH_ALEN != 6
#warning "Assumption that ETH_ALEN == 6 appears false. Here be dragons."
#endif
/* parse a string on the format 00:01:02:0d:0e:0f into a char array
* the mac_addr argument must be at least six bytes.
* returns 0 on success, or -1 on error
*/
int parse_MAC_address(const char *str, struct ether_addr *mac_addr)
{
int res = sscanf(str, "%x:%x:%x:%x:%x:%x", &mac_addr->ether_addr_octet[0],
&mac_addr->ether_addr_octet[1],
&mac_addr->ether_addr_octet[2],
&mac_addr->ether_addr_octet[3],
&mac_addr->ether_addr_octet[4],
&mac_addr->ether_addr_octet[5]);
return (res == 6? 0 : -1);
}
#if 0
/* test program */
int main(int argc, char *argv[])
{
int i;
unsigned char a[6];
int res = parse_MAC_address(argv[1], a);
if(res) {
perror("Failed to parse MAC address");
}
printf("%x.%x.%x.%x.%x.%x\n", a[0], a[1], a[2], a[3], a[4], a[5]);
return 0;
}
#endif
#ifndef ETHADDR_H
#define ETHADDR_H
#include <net/ethernet.h>
/* parse a string on the format 00:01:02:0d:0e:0f into a char array
* the mac_addr argument must be at least six bytes.
* returns 0 on success, or -1 on error
*/
int parse_MAC_address(const char *str, struct ether_addr *mac_addr);
#endif
/* labcomm2014_sig_parser.c:
* an example parser for labcomm signatures, illustrating how to skip samples
* based on their signature. Intended as an embryo for introducing this
* functionality into the lib to allow a channel to survive types with no
* registered handler.
*/
/* TODO, and notes about strange quirks
*
* - the return values for the accept_ functions are not really used anymore
* as the parser "peeks" and calls the correct accept function instead.
* This should be refactored
*
* - The RETURN_STRINGS and where/if to allocate strings is to be decided, it
* is currently not used
*
* - The dynamic allocation of the parser is not quite dynamic, the sizes are
* set through the init function, and are then static.
* This should be adapted when allocation is parameterized/user-definable
* for the entire lib.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "labcomm2014_sig_parser.h"
static void error(char *s) {
fprintf(stderr, "ERROR: %s", s);
fprintf(stderr, "\nexiting\n");
exit(1);
}
/* aux method for reading a big endian uint32 from a char* (i.e. ntohl but for explicit char*) */
static int unpack32(unsigned char *c, int idx) {
int b0=(c[idx]) << 3 ;
int b1=(c[idx+1]) << 2 ;
int b2=(c[idx+2]) << 1 ;
int b3=c[idx+3];
return b0 | b1 | b2 | b3;
}
static inline int get32(labcomm2014_sig_parser_t *b) {
int res = unpack32(b->c, b->idx);
b->idx+=4;
return res;
}
/* aux method for reading labcomm varint from a char*
size is an out parameter: if not NULL the number of bytes read will be written here
*/
static int unpack_varint(unsigned char *buf,
int idx,
size_t *size)
{
int res = 0;
unsigned int i=0;
unsigned char cont = LABCOMM2014_TRUE;
do {
unsigned char c = buf[idx+i];
res = (res << 7) | (c & 0x7f);
cont = c & 0x80;
i++;
} while(cont);
if(size != NULL)
*size = i;
return res;
}
void dumpValStack(labcomm2014_sig_parser_t *b) {
printf("=== value stack: ");
#ifdef DEBUG_STACK_VERBOSE
int i;
for(i=0; i<STACK_SIZE; i++) { //HERE BE DRAGONS
printf("%2.2x ", b->val_stack[i]);
}
#endif
printf(" top==%d\n", b->val_top);
}
void dumpPtrStack(labcomm2014_sig_parser_t *b) {
printf("=== pointer stack: ");
#ifdef DEBUG_STACK_VERBOSE
int i;
for(i=0; i<STACK_SIZE; i++) { //HERE BE DRAGONS
printf("%2.2x ", b->ptr_stack[i]);
}
#endif
printf(" top==%d\n", b->ptr_top);
}
void push_val(labcomm2014_sig_parser_t *b, unsigned int e) {
b->val_stack[b->val_top]=e;
b->val_top=b->val_top-1;
if(b->val_top<0) error("value stack overrun");
#if defined DEBUG && !defined QUIET_STACK
dumpValStack(b);
#endif
}
unsigned int pop_val(labcomm2014_sig_parser_t *b) {
b->val_top=b->val_top+1;
if(b->val_top>b->stacksize) error("value stack underrun");
#if defined DEBUG && !defined QUIET_STACK
dumpValStack(b);
#endif
return b->val_stack[b->val_top];
}
void push_ptr(labcomm2014_sig_parser_t *b, void* e) {
b->ptr_stack[b->ptr_top]=e;
b->ptr_top=b->ptr_top-1;
if(b->ptr_top<0) error("pointer stack overrun");
#ifdef DEBUG
dumpPtrStack(b);
#endif
}
void* pop_ptr(labcomm2014_sig_parser_t *b) {
b->ptr_top=b->ptr_top+1;
if(b->ptr_top>b->stacksize) error("pointer stack underrun");
#ifdef DEBUG
dumpPtrStack(b);
#endif
return b->ptr_stack[b->ptr_top];
}
int labcomm2014_sig_parser_init(labcomm2014_sig_parser_t *b, size_t buffer_size,
size_t stacksize, size_t num_signatures,
size_t max_name_len, size_t max_sig_len)
{
b->c = malloc(buffer_size);
b->capacity = buffer_size;
b->size = 0;
b->idx = 0;
b->stacksize = stacksize;
b->val_stack = calloc(stacksize, sizeof(b->val_stack));
b->val_top = stacksize-1;
b->ptr_stack = calloc(stacksize, sizeof(b->ptr_stack));
b->ptr_top = stacksize-1;
b->max_signatures = num_signatures;
b->max_name_len = max_name_len;
b->max_sig_len = max_sig_len;
#ifdef STATIC_ALLOCATION
printf("warning: labcomm2014_sig_parser_t_init: size params ignored, using defaults from .h file \n");
#else
b->sig_ts=calloc(num_signatures, sizeof(struct labcomm2014_signature));
b->signatures_length=calloc(num_signatures, sizeof(int));
b->signatures_name_length=calloc(num_signatures, sizeof(int));
b->signatures_name=calloc(num_signatures, sizeof(void *)); //HERE BE DRAGONS: add range checks
b->signatures=calloc(num_signatures, sizeof(void *));
int i;
for(i = 0; i<num_signatures; i++) {
b->signatures[i] = calloc(b->max_sig_len, sizeof(char));
b->signatures_name[i] = calloc(b->max_name_len, sizeof(char));
}
#endif
return b->c == NULL || b->val_stack == NULL || b->ptr_stack == NULL;
}
/* free the objects allocated by labcomm_sig_parser_init(b)
* NB! does not free b itself */
void labcomm2014_sig_parser_free(labcomm2014_sig_parser_t *b)
{
int i;
free(b->c);
free(b->val_stack);
free(b->ptr_stack);
#ifndef STATIC_ALLOCATION
for(i = 0; i<b->max_signatures; i++) {
free(b->signatures[i]);
free(b->signatures_name[i]);
}
free(b->signatures);
free(b->signatures_name);
free(b->signatures_name_length);
free(b->signatures_length);
free(b->sig_ts);
#endif
}
int labcomm2014_sig_parser_read_file(labcomm2014_sig_parser_t *b, FILE *f) {
int s = fread(b->c, sizeof(char), b->capacity, f);
b->size = s;
b->idx=0;
return s;
}
int more(labcomm2014_sig_parser_t *b)
{
return b->idx < b->size;
}
unsigned char get(labcomm2014_sig_parser_t *b) {
return b->c[b->idx++];
}
unsigned char peek(labcomm2014_sig_parser_t *b) {
return b->c[b->idx];
}
void advance(labcomm2014_sig_parser_t *b) {
b->idx++;
}
void advancen(labcomm2014_sig_parser_t *b, size_t n) {
b->idx+=n;
}
int peek_varint(labcomm2014_sig_parser_t *b, size_t *size) {
return unpack_varint(b->c, b->idx, size);
}
int get_varint(labcomm2014_sig_parser_t *b) {
size_t size;
int res = peek_varint(b, &size);
advancen(b, size);
return res;
}
int get_varint_size(labcomm2014_sig_parser_t *b, size_t *size) {
unsigned int res = peek_varint(b, size);
advancen(b, *size);
return res;
}
void getStr(labcomm2014_sig_parser_t *b, unsigned char *dest, size_t size) {
int rem = b->size - b->idx;
if( size > rem )
size = rem;
strncpy((char *)dest, (char *)&b->c[b->idx], size);
dest[size] = 0;
b->idx += size;
}
struct labcomm2014_signature *get_sig_t(labcomm2014_sig_parser_t *p, unsigned int uid)
{
return &(p->sig_ts[uid-LABCOMM_USER]);
}
unsigned int get_signature_len(labcomm2014_sig_parser_t *p, unsigned int uid){
//return signatures_length[uid-LABCOMM_USER];
return p->sig_ts[uid-LABCOMM_USER].size;
}
unsigned char* get_signature(labcomm2014_sig_parser_t *p, unsigned int uid){
//return signatures[uid-LABCOMM_USER];
return p->sig_ts[uid-LABCOMM_USER].signature;
}
//is this needed?
//unsigned int get_signature_name_len(labcomm2014_sig_parser_t *p, unsigned int uid){
// return signatures_name_length[uid-LABCOMM_USER];
//}
char* get_signature_name(labcomm2014_sig_parser_t *p, unsigned int uid){
//return signatures_name[uid-LABCOMM_USER];
return p->sig_ts[uid-LABCOMM_USER].name;
}
void dump_signature(labcomm2014_sig_parser_t *p, unsigned int uid){
int i;
unsigned int len = get_signature_len(p, uid);
printf("signature for uid %x : %s (len=%d):\n", uid, get_signature_name(p, uid), len);
unsigned char* sig = get_signature(p, uid);
for(i=0; i<len; i++) {
printf("%2.2x ",sig[i]);
if( i < len-1 && (i+1)%8==0 ) printf("\n");
}
printf("\n");
}
static inline void labcomm2014_sig_parser_t_set_varsize(labcomm2014_sig_parser_t *b)
{
b->current_decl_is_varsize = LABCOMM2014_TRUE;
}
static size_t labcomm2014_sizeof_primitive(unsigned int type)
{
switch(type) {
case TYPE_BOOLEAN :
case TYPE_BYTE :
return 1;
case TYPE_SHORT :
return 2;
case TYPE_INTEGER :
case TYPE_FLOAT :
case TYPE_SAMPLE_REF :
return 4;
case TYPE_LONG :
case TYPE_DOUBLE :
return 8;
default:
printf("labcomm2014_sizeof_primitive(%x)\n", type);
error("labcomm2014_sizeof_primitive should only be called for primitive types");
return 0;
}
}
//these are inlined in do_accept_packet
//static int accept_type_decl(labcomm2014_sig_parser_t *d);
//static int accept_sample_decl(labcomm2014_sig_parser_t *d);
static int accept_user_id(labcomm2014_sig_parser_t *d);
static int accept_string(labcomm2014_sig_parser_t *d);
static int accept_type(labcomm2014_sig_parser_t *d);
static int accept_array_decl(labcomm2014_sig_parser_t *d);
static int accept_intentions(labcomm2014_sig_parser_t *d);
#if 0
// UNUSED declarations
static int accept_string_length(labcomm2014_sig_parser_t *d);
static int accept_char(labcomm2014_sig_parser_t *d);
static int accept_number_of_indices(labcomm2014_sig_parser_t *d);
static int accept_indices(labcomm2014_sig_parser_t *d);
static int accept_variable_index(labcomm2014_sig_parser_t *d);
static int accept_fixed_index(labcomm2014_sig_parser_t *d);
static int accept_number_of_fields(labcomm2014_sig_parser_t *d);
#endif
static int accept_struct_decl(labcomm2014_sig_parser_t *d);
static int accept_field(labcomm2014_sig_parser_t *d);
static int accept_sample_data(labcomm2014_sig_parser_t *d);
static unsigned char labcomm2014_varint_sizeof(unsigned int i)
{
if(i < 128) {
return 1;
} else {
unsigned char res = 1;
while (i >>= 7) ++res;
return res;
}
}
int encoded_size_static(struct labcomm2014_signature *sig, void *unused)
{
#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
if(sig->cached_encoded_size == -1) {
error("encoded_size_static called for var_size sample or uninitialized signature");
}
return sig->cached_encoded_size;
#else
printf("Warning: encoded_size_static currently broken\n");
return -1;
#endif
}
/* This function probably never will be implemented, as it would be
similar to skip_packed_sample_data. And if unregistered variable size
samples is to be handled, the proper way is to generate and register
a handler. Thus, the most probable use of the encoded_size function
on the receiver side, is to skip unhandled samples.
*/
int encoded_size_parse_sig(struct labcomm2014_signature *sig, void *sample)
{
printf("Warning: encoded_size_parse_sig not implemented\n");
return -1;
}
static int accept_signature(labcomm2014_sig_parser_t *d,
labcomm2014_type type,
unsigned int start,
unsigned int uid, char *name)
{
get_varint(d); // ignore sig len
VERBOSE_PRINTF("\ntype = ");
accept_type(d);
//printf(" : ");
//unsigned int dt = pop(d);
#ifdef USE_TYPE_AND_SIZE
unsigned int type = pop_val(d);
unsigned int enc_size = pop_val(d);
#else
pop_val(d); // unsigned int type
pop_val(d); // unsigned int enc_size
#endif
if(type != PKG_SAMPLE_DECL) {
if(type == PKG_SAMPLE_REF) {
INFO_PRINTF("accept_signature: ignoring sample ref\n");
return LABCOMM2014_TRUE;
} else if (type == PKG_TYPE_DECL) {
INFO_PRINTF("accept_signature: ignoring typedef\n");
return LABCOMM2014_TRUE;
} else {
error("decl is neither sample, ref, or typedef???");
return LABCOMM2014_FALSE;
}
}
unsigned int end = d->idx;
unsigned int len = end-start;
struct labcomm2014_signature *newsig = get_sig_t(d, uid);
// newsig->type = type;
if(len <= d->max_sig_len) {
d->signatures_length[uid-LABCOMM_USER] = len;
memcpy(d->signatures[uid-LABCOMM_USER], &d->c[start], len);
newsig->size = len;
newsig->signature = d->signatures[uid-LABCOMM_USER];
newsig->name = name;
} else {
error("sig longer than max length (this ought to be dynamic...)");
}
VERBOSE_PRINTF("signature for uid %x: %s (start=%x,end=%x,len=%d)\n", uid, get_signature_name(d, uid), start,end, len);
INFO_PRINTF("accept_signature: %s\n", newsig->name);
#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
if(! d->current_decl_is_varsize) {
newsig->cached_encoded_size = enc_size;
newsig->encoded_size = encoded_size_static;
INFO_PRINTF(".... is static size = %d\n", enc_size);
} else {
newsig->cached_encoded_size = -1;
newsig->encoded_size = encoded_size_parse_sig;
INFO_PRINTF(".... is variable size\n");
}
#endif
return LABCOMM2014_TRUE;
}
static int accept_decl(labcomm2014_sig_parser_t *d, labcomm2014_type type)
{
if(accept_user_id(d)) {
unsigned int uid = pop_val(d);
VERBOSE_PRINTF(", intentions = ");
accept_intentions(d);
unsigned int start = d->idx;
unsigned int nstart = pop_val(d);
unsigned int nlen = pop_val(d);
#ifdef RETURN_STRINGS
char *str = (char *) pop_ptr(d);
free(str);
#endif
unsigned char lenlen = labcomm2014_varint_sizeof(nlen);
if(type != PKG_SAMPLE_DECL) {
// don't record typedefs and samplerefs (for now)
// to avoid number clashes with sample defs
// in the parser struct
return accept_signature(d, type, start, uid, (char *) &d->c[nstart+lenlen]);
}
if(nlen < d->max_name_len) { // leave 1 byte for terminating NULL
char *name;
d->signatures_name_length[uid-LABCOMM_USER] = nlen;
memcpy(d->signatures_name[uid-LABCOMM_USER], &d->c[nstart+lenlen], nlen);
d->signatures_name[uid-LABCOMM_USER][nlen]=0;
name = d->signatures_name[uid-LABCOMM_USER];
return accept_signature(d, type, start, uid, name);
} else {
error("sig name longer than max length (this ought to be dynamic...");
return LABCOMM2014_FALSE;
}
} else {
error("sample_decl with uid < LABCOMM_USER");
return LABCOMM2014_FALSE;
}
}
// HERE BE DRAGONS! what does the return value mean?
int accept_packet(labcomm2014_sig_parser_t *d) {
size_t nbytes;
unsigned int type = peek_varint(d, &nbytes) ;
if(type == PKG_VERSION ) {
advancen(d, nbytes);//consume type field
get_varint(d); //ignore length field
VERBOSE_PRINTF("got version.\n");
accept_string(d);
pop_val(d); // ignore length, for now
#ifdef RETURN_STRINGS
char *str = (char *) pop_ptr(d);
free(str);
#endif
} else if (type == PKG_SAMPLE_DECL) {
d->current_decl_is_varsize = LABCOMM2014_FALSE; // <-- a conveniance flag in labcomm2014_sig_parser_t
advancen(d, nbytes);
VERBOSE_PRINTF("sample_decl ");
get_varint(d); //ignore length field
accept_decl(d, type);
} else if (type == PKG_SAMPLE_REF) {
d->current_decl_is_varsize = LABCOMM2014_FALSE; // <-- a conveniance flag in labcomm2014_sig_parser_t
advancen(d, nbytes);
VERBOSE_PRINTF("sample_ref ");
get_varint(d); //ignore length field
accept_decl(d, type);
}else if(type == PKG_TYPE_DECL ) {
d->current_decl_is_varsize = LABCOMM2014_FALSE; // <-- a conveniance flag in labcomm2014_sig_parser_t
advancen(d, nbytes);//consume type field
VERBOSE_PRINTF("type_decl ");
get_varint(d); //ignore length field
accept_decl(d, type);
} else if (type == PKG_TYPE_BINDING) {
VERBOSE_PRINTF("type_binding ");
advancen(d, nbytes);
get_varint(d); //ignore length field
#ifdef VERBOSE
int sid =
#endif
get_varint(d); //ignore sample id field
#ifdef VERBOSE
int tid =
#endif
get_varint(d); //ignore type id field
VERBOSE_PRINTF("sid=0x%x, tid=0x%x\n ", sid, tid);
} else if(type >= LABCOMM_USER) {
#ifdef EXIT_WHEN_RECEIVING_DATA
printf("*** got sample data, exiting\n");
exit(0);
#else
accept_sample_data(d);
#endif
} else {
#ifdef EXIT_ON_UNKNOWN_TAG
error("got unknown type (<LABCOMM_USER)");
exit(1);
#else
int len = get_varint(d); // length field
printf("got unknown tag: 0x%x, skipping %d bytes\n",type, len);
advancen(d, len);
#endif
}
return LABCOMM2014_TRUE;
}
static int accept_user_id(labcomm2014_sig_parser_t *d){
size_t nbytes;
int uid = peek_varint(d, &nbytes);
if(uid >= LABCOMM_USER) {
advancen(d, nbytes);
VERBOSE_PRINTF("uid = 0x%x ", uid);
push_val(d, uid);
return LABCOMM2014_TRUE;
} else {
error("uid < LABCOMM_USER");
return LABCOMM2014_FALSE;
}
}
/** pushes (index in stream of name) and (length of name) */
static int accept_intentions(labcomm2014_sig_parser_t *d){
unsigned int num = get_varint(d);
int i;
int npos = 0;
int nlen = 0;
for(i=0; i<num; i++) {
int klen, vlen;
printf("( ");
#ifdef RETURN_STRINGS
char *key;
char *val;
#endif
accept_string(d);
klen = pop_val(d);
if(klen==0) {
npos = d->idx;
}
#ifdef RETURN_STRINGS
key = (char *) pop_ptr(d);
if(klen!=0) {
printf("%s] : ",key);
}
free(key);
#else
if(klen!=0) {
printf(": ");
} else {
printf("name: ");
}
#endif
accept_string(d);
printf(" ");
vlen = pop_val(d);
if(klen==0) {
nlen = vlen;
}
#ifdef RETURN_STRINGS
val = (char *) pop_ptr(d);
printf("%s %s",(klen?",val : ":""), val);
free(val);
#endif
printf(") ");
}
push_val(d, nlen);
push_val(d, npos);
return LABCOMM2014_TRUE;
}
static int accept_string(labcomm2014_sig_parser_t *d){
unsigned int len = get_varint(d);
unsigned char *str=malloc(len+1); // len is without terminating null
getStr(d, str, len);
VERBOSE_PRINTF("%s", str);
#ifdef RETURN_STRINGS
push_ptr(d, str);
#else
free(str);
#endif
push_val(d, len);
return LABCOMM2014_TRUE;
}
/* pushes size and type id */
static int accept_type(labcomm2014_sig_parser_t *d){
size_t nbytes;
unsigned int type = peek_varint(d, &nbytes) ;
switch(type) {
case TYPE_BOOLEAN :
VERBOSE_PRINTF("boolean\n");
advancen(d, nbytes);
push_val(d, 1);
break;
case TYPE_BYTE :
VERBOSE_PRINTF("byte\n");
advancen(d, nbytes);
push_val(d, 1);
break;
case TYPE_SHORT :
VERBOSE_PRINTF("short\n");
advancen(d, nbytes);
push_val(d, 2);
break;
case TYPE_INTEGER :
VERBOSE_PRINTF("integer\n");
advancen(d, nbytes);
push_val(d, 4);
break;
case TYPE_LONG :
VERBOSE_PRINTF("long\n");
advancen(d, nbytes);
push_val(d, 8);
break;
case TYPE_FLOAT :
VERBOSE_PRINTF("float\n");
advancen(d, nbytes);
push_val(d, 4);
break;
case TYPE_DOUBLE :
VERBOSE_PRINTF("double\n");
advancen(d, nbytes);
push_val(d, 8);
break;
case TYPE_STRING :
VERBOSE_PRINTF("string\n");
advancen(d, nbytes);
labcomm2014_sig_parser_t_set_varsize(d);
push_val(d, 0);
break;
case TYPE_SAMPLE_REF :
VERBOSE_PRINTF("sample\n");
advancen(d, nbytes);
push_val(d, 4);
break;
case ARRAY_DECL :
accept_array_decl(d);
pop_val(d); // ignore element type
// push(d, pop(d) is a NOP --> leave size on stack
break;
case STRUCT_DECL :
accept_struct_decl(d);
// push(d, pop(d) is a NOP --> leave size on stack
break;
default :
//should we distinguish between SAMPLE_DEF and TYPE_DEF here?
//printf("accept_type default (type==%x) should not happen\n", type);
VERBOSE_PRINTF("user type 0x%x\n",type);
advancen(d, nbytes);
push_val(d, 0);
push_val(d, type);
return LABCOMM2014_FALSE;
}
push_val(d, type);
return LABCOMM2014_TRUE;
}
/* pushes size and element type */
static int accept_array_decl(labcomm2014_sig_parser_t *d){
size_t nbytes;
int tid = peek_varint(d, &nbytes) ;
if(tid == ARRAY_DECL) {
advancen(d, nbytes);
unsigned int nidx = get_varint(d);
VERBOSE_PRINTF("%d dim array", nidx);
int i;
unsigned int numVar=0;
unsigned int size=1;
for(i=0; i<nidx; i++) {
unsigned int idx = get_varint(d);
if(idx == 0) {
numVar++;
VERBOSE_PRINTF("[_] ");
labcomm2014_sig_parser_t_set_varsize(d);
} else {
VERBOSE_PRINTF("[%d] ", idx);
size*=idx;
}
}
VERBOSE_PRINTF(" of ");
accept_type(d);
unsigned int et= pop_val(d); // type
unsigned int es= pop_val(d); // (encoded) size
#ifdef DEBUG
printf("accept_array_decl: et = %x\n", et);
#endif
if(numVar == 0) {
#ifdef DEBUG
printf("size=%d, es=%d\n", size, es);
#endif
push_val(d, (size*es));
} else {
//HERE BE DRAGONS! push a (non-) size for variable size arrays?
push_val(d, 0);
}
push_val(d, et);
return LABCOMM2014_TRUE;
} else {
printf("accept_array_decl: type=%x, should not happen\n",tid);
push_val(d, 0);
push_val(d, tid);
return LABCOMM2014_FALSE;
}
}
/* pushes size */
static int accept_struct_decl(labcomm2014_sig_parser_t *d){
size_t nbytes;
int tid = peek_varint(d, &nbytes) ;
if(tid == STRUCT_DECL) {
advancen(d, nbytes);
unsigned int nf = get_varint(d);
if(nf == 0) {
VERBOSE_PRINTF("void\n");
} else {
VERBOSE_PRINTF("%d field struct:\n", nf);
}
int i;
#ifdef USE_UNUSED_VARS
int numVar=0;
int size=0;
#endif
unsigned int fieldsizes=0;
for(i=0; i<nf; i++) {
accept_field(d);
fieldsizes += pop_val(d);
}
push_val(d, fieldsizes);
return LABCOMM2014_TRUE;
} else {
printf("accept_struct_decl: type=%x, should not happen\n",tid);
push_val(d, 0);
return LABCOMM2014_FALSE;
}
}
/* pushes field size */
static int accept_field(labcomm2014_sig_parser_t *d){
VERBOSE_PRINTF("\tfield: ");
accept_intentions(d);
pop_val(d); // ignore name pos, for now
pop_val(d); // ignore name length, for now
#ifdef RETURN_STRINGS
char *str = (char *) pop_ptr(d);
free(str);
#endif
VERBOSE_PRINTF("\n\ttype: ");
accept_type(d);
pop_val(d); // ignore type, for now
// push(pop() is really a NOP , leave size on the stack when debugging done
VERBOSE_PRINTF("\n");
return LABCOMM2014_TRUE;
}
static int accept_sample_data(labcomm2014_sig_parser_t *d){
accept_user_id(d);
unsigned int uid = pop_val(d);
printf("sample data... uid=0x%x\n", uid);
int len = get_varint(d); //length field
#ifdef DEBUG
dump_signature(d, uid);
#endif
#ifdef SKIP_BY_PARSING
struct labcomm2014_signature *sigt = get_sig_t(d, uid);
int encoded_size = sigt->encoded_size(NULL);
INFO_PRINTF("encoded_size from sig: %d\n", encoded_size);
struct labcomm2014_signature *sig = get_sig_t(d, uid);
skip_packed_sample_data(d, sig);
#else
advancen(d, len);
#endif
return LABCOMM2014_TRUE;
}
static int skip_type(unsigned int,labcomm2014_sig_parser_t*,unsigned char*,unsigned int,int*) ;
static int skip_array(labcomm2014_sig_parser_t *d, unsigned char *sig, int len, int *pos) {
unsigned int skip = 0;
unsigned int tot_nbr_elem_tmp = 1;
size_t nbytes;
unsigned int nIdx = unpack_varint(sig, *pos, &nbytes);
VERBOSE_PRINTF("skip_array: nIdx = %d (from sig)\n", nIdx);
*pos +=nbytes;
unsigned int idx[nIdx];
unsigned int nVar=0;
unsigned int i;
for(i=0; i<nIdx; i++) {
idx[i] = unpack_varint(sig, *pos, &nbytes);
*pos += nbytes;
VERBOSE_PRINTF("skip_array: idx[%d]=%d (from sig)\n", i, idx[i]);
if(idx[i] == 0) {
nVar++;
} else {
tot_nbr_elem_tmp *= idx[i];
}
}
int var[nVar];
unsigned char varSize=0; // total number of bytes required for var size fields
for(i=0; i<nVar; i++) {
var[i] = get_varint_size(d, &nbytes);
varSize += nbytes;
VERBOSE_PRINTF("skip_array: var[%d]=%d (from sample)\n", i, var[i]);
tot_nbr_elem_tmp *= var[i];
}
int type = unpack_varint(sig, *pos, &nbytes);
*pos+=nbytes;
unsigned int elemSize = labcomm2014_sizeof_primitive(type);
skip = elemSize * tot_nbr_elem_tmp;
VERBOSE_PRINTF("skip_array: skip: %d * %d = %d\n", tot_nbr_elem_tmp, elemSize ,skip);
advancen(d, skip);
//return skip + 4*nVar;
return skip + varSize;
}
int skip_struct(labcomm2014_sig_parser_t *d, unsigned char *sig, unsigned int len, int *pos) {
size_t nbytes;
int nFields = unpack_varint(sig,*pos, &nbytes);
*pos += nbytes;
unsigned int i;
unsigned int skipped=0;
VERBOSE_PRINTF("skip_struct (%d fields)\n", nFields);
for(i=0; i<nFields; i++) {
//skip name
unsigned int namelen = unpack_varint(sig, *pos, &nbytes);
#ifdef DEBUG
VERBOSE_PRINTF("field #%d:\n----namelen==%d\n",i,namelen);
char name[namelen+1]; //HERE BE DRAGONS. alloca?
strncpy(name, (const char *)sig+*pos+nbytes, namelen);
name[namelen]=0;
VERBOSE_PRINTF("----name = %s\n",name);
#endif
*pos += (nbytes+namelen); // 32bit len + actual string
unsigned int type = unpack_varint(sig, *pos, &nbytes);
*pos += nbytes;
#ifdef DEBUG
VERBOSE_PRINTF("----type == %x\n", type);
#endif
skipped += skip_type(type, d, sig, len, pos);
}
return skipped;
}
#ifndef QUIET
/* print and skip */
int skip_type(unsigned int type, labcomm2014_sig_parser_t *d,
unsigned char *sig, unsigned int len, int *pos)
{
int skipped=0;
printf("skip_type %x:", type);
switch(type) {
case TYPE_BOOLEAN :
printf("boolean [%d]\n", get(d));
skipped++;
break;
case TYPE_BYTE :
printf("byte [%d]\n", get(d));
skipped++;
break;
case TYPE_SHORT :
//XXX not supported
advancen(d,2);
skipped+=2;
break;
case TYPE_INTEGER :
printf("integer [%d]\n", get32(d));
skipped +=4;
break;
case TYPE_FLOAT :
//XXX not supported
advancen(d,4);
skipped+=4;
break;
case TYPE_LONG :
case TYPE_DOUBLE :
//XXX not supported
advancen(d,8);
skipped+=8;
break;
case TYPE_STRING :
{
size_t nbytes;
int len = get_varint_size(d, &nbytes);
int i;
printf("string [");
for(i=0; i<len; i++)
printf("%c", get(d));
printf("]\n");
skipped+=len+nbytes;
break;}
case ARRAY_DECL :
printf("array\n");
skipped += skip_array(d, sig, len, pos);
break;
case STRUCT_DECL :
printf("struct\n");
skipped += skip_struct(d, sig, len, pos);
break;
default:
printf("ERROR: skip_type: type = %x\n", type);
exit(1);
}
return skipped;
}
#else
int skip_type(unsigned int type, labcomm2014_sig_parser_t *d,
const char *sig, unsigned int len, int *pos)
{
int skipped=0;
VERBOSE_PRINTF("skip_type %x\n", type);
switch(type) {
case TYPE_BOOLEAN :
case TYPE_BYTE :
advancen(d,1);
skipped++;
break;
case TYPE_SHORT :
advancen(d,2);
skipped+=2;
break;
case TYPE_INTEGER :
case TYPE_FLOAT :
advancen(d,4);
skipped+=4;
break;
case TYPE_LONG :
case TYPE_DOUBLE :
advancen(d,8);
skipped+=8;
break;
case TYPE_STRING :
{
size_t nbytes;
int len = get_varint_size(d, &nbytes);
advancen(d,len);
skipped+=len+nbytes;
break;}
case ARRAY_DECL :
skipped += skip_array(d, sig, len, pos);
break;
case STRUCT_DECL :
skipped += skip_struct(d, sig, len, pos);
break;
default:
printf("ERROR: skip_type: type = %x\n", type);
exit(1);
}
return skipped;
}
#endif
/* parse signature and skip the corresponding bytes in the labcomm2014_sig_parser_t
*/
int skip_packed_sample_data(labcomm2014_sig_parser_t *d, struct labcomm2014_signature *sig) {
int pos = 0; //current position in signature
unsigned int skipped = 0; //skipped byte counter
while(pos < sig->size) {
size_t nbytes;
int type = unpack_varint(sig->signature,pos, &nbytes);
pos+=nbytes;
skipped += skip_type(type, d, sig->signature, sig->size, &pos);
}
printf("skipped %d bytes\n", skipped);
return LABCOMM2014_TRUE;
}
/* labcomm2014_sig_parser.h:
* an example parser for labcomm signatures, illustrating how to skip samples
* based on their signature. Intended as an embryo for introducing this
* functionality into the lib to allow a channel to survive types with no
* registered handler.
*/
#ifndef LABCOMM_SIG_PARSER_H
#define LABCOMM_SIG_PARSER_H
#include "labcomm2014.h"
#include "labcomm2014_private.h"
#undef DEBUG
#define QUIET_STACK // don't print anything for push/pop
#undef DEBUG_STACK_VERBOSE // dump stack, otherwise just print value of top
#undef QUIET //just print type and size when skipping data
#define VERBOSE // print in great detail
#undef SKIP_BY_PARSING
#undef STATIC_ALLOCATION //dynamic allocation not completely implemented
#ifdef STATIC_ALLOCATION
#define MAX_SIGNATURES 100
#define MAX_NAME_LEN 32
#define MAX_SIG_LEN 128
#define TYPEDEF_BASE MAX_SIGNATURES
#endif
/* internal type: stack &c. for the parser */
typedef struct {
unsigned char* c;
size_t size;
size_t capacity;
int idx;
int val_top;
int * val_stack;
int ptr_top;
void** ptr_stack;
size_t stacksize;
int current_decl_is_varsize;
size_t max_signatures; // set by init(...)
size_t max_name_len;
size_t max_sig_len;
// arrays for signatures and typedefs
// signatures start at index 0
// typedefs start at index MAX_SIGNATURES
#ifdef STATIC_ALLOCATION
struct labcomm2014_signature sig_ts[2*MAX_SIGNATURES];
unsigned int signatures_length[2*MAX_SIGNATURES];
unsigned int signatures_name_length[2*MAX_SIGNATURES];
unsigned char signatures_name[2*MAX_SIGNATURES][MAX_NAME_LEN];
unsigned char signatures[2*MAX_SIGNATURES][MAX_SIG_LEN];
#else
struct labcomm2014_signature *sig_ts; // [2*MAX_SIGNATURES]
unsigned int *signatures_length; // [2*MAX_SIGNATURES]
unsigned char **signatures; // [2*MAX_SIGNATURES][MAX_SIG_LEN];
unsigned int *signatures_name_length; // [2*MAX_SIGNATURES]
char **signatures_name; // [2*MAX_SIGNATURES][MAX_NAME_LEN];
#endif
} labcomm2014_sig_parser_t;
int labcomm2014_sig_parser_init(labcomm2014_sig_parser_t *p, size_t size,
size_t stacksize, size_t max_num_signatures,
size_t max_name_len, size_t max_sig_len);
void labcomm2014_sig_parser_free(labcomm2014_sig_parser_t *b);
int labcomm2014_sig_parser_read_file(labcomm2014_sig_parser_t *p, FILE *f);
int accept_packet(labcomm2014_sig_parser_t *p);
struct labcomm2014_signature *get_sig_t(labcomm2014_sig_parser_t *p,unsigned int uid);
unsigned int get_signature_len(labcomm2014_sig_parser_t *p,unsigned int uid);
char* get_signature_name(labcomm2014_sig_parser_t *p,unsigned int uid);
unsigned char* get_signature(labcomm2014_sig_parser_t *p,unsigned int uid);
void dump_signature(labcomm2014_sig_parser_t *p,unsigned int uid);
int more(labcomm2014_sig_parser_t *b);
/* parse signature and skip the corresponding bytes in the labcomm2014_sig_parser
*/
int skip_packed_sample_data(labcomm2014_sig_parser_t *p, struct labcomm2014_signature *sig);
#ifdef QUIET
#define INFO_PRINTF(format, args...)
#undef VERBOSE
#else
#define INFO_PRINTF(format, args...) \
printf (format , ## args)
#endif
#ifdef VERBOSE
#define VERBOSE_PRINTF(format, args...) \
printf (format , ## args)
#else
#define VERBOSE_PRINTF(format, args...)
#endif
#undef EXIT_WHEN_RECEIVING_DATA
#undef RETURN_STRINGS // not really tested
typedef enum{
PKG_VERSION = LABCOMM_VERSION,
PKG_SAMPLE_DECL = LABCOMM_SAMPLE_DEF,
PKG_SAMPLE_REF = LABCOMM_SAMPLE_REF,
PKG_TYPE_DECL = LABCOMM_TYPE_DEF,
PKG_TYPE_BINDING = LABCOMM_TYPE_BINDING,
ARRAY_DECL = LABCOMM_ARRAY,
STRUCT_DECL = LABCOMM_STRUCT,
TYPE_BOOLEAN = LABCOMM_BOOLEAN,
TYPE_BYTE = LABCOMM_BYTE,
TYPE_SHORT = LABCOMM_SHORT,
TYPE_INTEGER = LABCOMM_INT,
TYPE_LONG = LABCOMM_LONG,
TYPE_FLOAT = LABCOMM_FLOAT,
TYPE_DOUBLE = LABCOMM_DOUBLE,
TYPE_STRING = LABCOMM_STRING,
TYPE_SAMPLE_REF = LABCOMM_REF
} labcomm2014_type ;
#endif
#include <errno.h>
#include <unistd.h>
#include "labcomm.h"
#include "ThrottleDrv/throttle_drv.h"
#define BUFFER_SIZE 2048
int labcomm_thr_reader(labcomm_reader_t *r, labcomm_reader_action_t action)
{
int result = -EINVAL;
struct thr_chn_t *ctx = r->context;
switch (action)
{
case labcomm_reader_alloc:
{
r->data = malloc(BUFFER_SIZE);
if (r->data)
{
r->data_size = BUFFER_SIZE;
result = r->data_size;
}
else
{
r->data_size = 0;
result = -ENOMEM;
}
r->count = 0;
r->pos = 0;
}
break;
case labcomm_reader_start:
case labcomm_reader_continue:
{
if (r->pos < r->count)
{
result = r->count - r->pos;
}
else
{
int err;
r->pos = 0;
err = thr_read(ctx, r->data, r->data_size);
if (err <= 0)
{
r->count = 0;
result = -1;
} else
{
r->count = err;
result = r->count - r->pos;
}
}
}
break;
case labcomm_reader_end:
{
result = 0;
}
break;
case labcomm_reader_free:
{
free(r->data);
r->data = 0;
r->data_size = 0;
r->count = 0;
r->pos = 0;
result = 0;
}
break;
}
return result;
}
int labcomm_thr_writer(labcomm_writer_t *w, labcomm_writer_action_t action)
{
int result = 0;
struct thr_chn_t *ctx = w->context;
switch (action)
{
case labcomm_writer_alloc:
{
w->data = malloc(BUFFER_SIZE);
if (! w->data)
{
result = -ENOMEM;
w->data_size = 0;
w->count = 0;
w->pos = 0;
}
else
{
w->data_size = BUFFER_SIZE;
w->count = BUFFER_SIZE;
w->pos = 0;
}
} break;
case labcomm_writer_free:
{
free(w->data);
w->data = 0;
w->data_size = 0;
w->count = 0;
w->pos = 0;
}
break;
case labcomm_writer_start:
{
w->pos = 0;
}
break;
case labcomm_writer_continue:
{
result = thr_send(ctx, w->data, w->pos);
w->pos = 0;
}
break;
case labcomm_writer_end:
{
result = thr_send(ctx, w->data, w->pos);
w->pos = 0;
}
break;
case labcomm_writer_available:
{
result = w->count - w->pos;
}
break;
}
return result;
}
#include "labcomm.h"
extern int labcomm_thr_reader(labcomm_reader_t *r, labcomm_reader_action_t action);
extern int labcomm_thr_writer(labcomm_writer_t *r, labcomm_writer_action_t action);
#include <errno.h>
#include <unistd.h>
#include "labcomm.h"
#include "udp_hack.h"
#define BUFFER_SIZE 2048
int labcomm_udp_reader(
labcomm_reader_t *r,
labcomm_reader_action_t action)
{
int result = -EINVAL;
server_context_t *ctx = r->context;
switch (action) {
case labcomm_reader_alloc: {
r->data = malloc(BUFFER_SIZE);
if (r->data) {
r->data_size = BUFFER_SIZE;
result = r->data_size;
} else {
r->data_size = 0;
result = -ENOMEM;
}
r->count = 0;
r->pos = 0;
} break;
case labcomm_reader_start:
case labcomm_reader_continue: {
if (r->pos < r->count) {
result = r->count - r->pos;
} else {
int err;
r->pos = 0;
err=udp_recv(ctx, r->data, r->data_size);
if (err <= 0) {
r->count = 0;
result = -1;
} else {
r->count = err;
result = r->count - r->pos;
}
}
} break;
case labcomm_reader_end: {
result = 0;
} break;
case labcomm_reader_free: {
free(r->data);
r->data = 0;
r->data_size = 0;
r->count = 0;
r->pos = 0;
result = 0;
} break;
}
return result;
}
int labcomm_udp_writer(
labcomm_writer_t *w,
labcomm_writer_action_t action)
{
int result = 0;
//int *fd = w->context;
server_context_t *ctx = w->context;
switch (action) {
case labcomm_writer_alloc: {
w->data = malloc(BUFFER_SIZE);
if (! w->data) {
result = -ENOMEM;
w->data_size = 0;
w->count = 0;
w->pos = 0;
} else {
w->data_size = BUFFER_SIZE;
w->count = BUFFER_SIZE;
w->pos = 0;
}
} break;
case labcomm_writer_free: {
free(w->data);
w->data = 0;
w->data_size = 0;
w->count = 0;
w->pos = 0;
} break;
case labcomm_writer_start: {
w->pos = 0;
} break;
case labcomm_writer_continue: {
result = udp_send(ctx, w->data, w->pos);
w->pos = 0;
} break;
case labcomm_writer_end: {
result = udp_send(ctx, w->data, w->pos);
w->pos = 0;
} break;
case labcomm_writer_available: {
result = w->count - w->pos;
} break;
}
return result;
}
#include "labcomm.h"
extern int labcomm_udp_reader(
labcomm_reader_t *r,
labcomm_reader_action_t action);
extern int labcomm_udp_writer(
labcomm_writer_t *r,
labcomm_writer_action_t action);
#include <stdio.h>
typedef unsigned int number;
unsigned char do_pack(unsigned char *buf, number i)
{
printf("do_pack %lu == %lx\n", i, i);
number tmp = i;
unsigned char res = 0;
while ( tmp >= 0x80 ) {
buf[res] = (tmp & 0x7f) | 0x80;
tmp >>= 7;
res++;
}
buf[res] = tmp;
return res+1;
}
number do_unpack(unsigned char *buf)
{
number res=0;
unsigned char i=0;
unsigned char cont=1;
do {
unsigned char c = buf[i];
res |= (c & 0x7f) << 7*i;
cont = c & 0x80;
i++;
} while(cont);
return res;
}
void print_packed(unsigned char *buf, unsigned char len)
{
int i;
for(i=0; i<len;i++) {
printf("%2x ", buf[i]);
}
printf("\n");
}
int main()
{
unsigned char buf[10];
unsigned char len;
len = do_pack(buf, 10);
print_packed(buf, len);
printf("... unpacks to %u\n\n", do_unpack(buf));
len = do_pack(buf, 100);
print_packed(buf, len);
printf("... unpacks to %u\n\n", do_unpack(buf));
len = do_pack(buf, 1000);
print_packed(buf, len);
printf("... unpacks to %u\n\n", do_unpack(buf));
len = do_pack(buf, 100000);
print_packed(buf, len);
printf("... unpacks to %u\n\n", do_unpack(buf));
len = do_pack(buf, 2345678901);
print_packed(buf, len);
printf("... unpacks to %u\n\n", do_unpack(buf));
len = do_pack(buf, 0xffffffff);
print_packed(buf, len);
printf("... unpacks to %lx\n", do_unpack(buf));
return 0;
}
/* labcomm2014_sig_parser.c:
* a main program for the example labcomm signatures parser
*/
#include <stdio.h>
#include <stdlib.h>
#include "experimental/labcomm2014_sig_parser.h"
#define DEBUG_READ
#define BUF_SIZE 1024
#define STACK_SIZE 16
#define MAX_NUM_SIGNATURES 10
#define MAX_SIGNATURES 100
#define MAX_NAME_LEN 64
#define MAX_SIG_LEN 512
void test_read(labcomm2014_sig_parser_t *p) {
int r = labcomm2014_sig_parser_read_file(p, stdin);
#ifdef DEBUG_READ
printf("read %d bytes:\n\n", r);
int i;
for(i=0; i<r; i++) {
printf("%x ", p->c[i]);
if(i%8 == 7) printf("\n");
}
printf("\n");
#endif
}
int main() {
labcomm2014_sig_parser_t p;
if(labcomm2014_sig_parser_init(&p, BUF_SIZE, STACK_SIZE,
MAX_NUM_SIGNATURES, MAX_NAME_LEN, MAX_SIG_LEN) ) {
printf("failed to init buffer\n");
exit(1);
}
test_read(&p);
do{
printf("--------------------------------------------- new packet: \n");
} while(more(&p) && accept_packet(&p));
printf("EOF\n");
labcomm2014_sig_parser_free(&p);
}
typedef long number_t; // placeholder for protocol buffers like encoding
typedef byte eth_addr[6];
// *** Service registration, lookup, and channel allocation
typedef struct {
string creatorId;
string svcId;
int version; //unique
string versionName; //human readable
} serviceID; // Should probably be a PalCom[_]like struct
typedef struct {
string key;
byte value[_];
} property_t; // used for type info, grounding, etc.
typedef struct {
string name;
property_t properties[_];
} param_t;
typedef struct {
string name;
property_t properties[_];
param_t params[_];
} command_t;
typedef struct {
serviceID svcID;
string name;
command_t commands[_];
byte data_description[_];
} serviceDescription; // d:o PalCom
typedef struct {
eth_addr device; // or more generic, as in PalCom?
serviceID svcID;
number_t instanceID;
string instance_name;
} service_instance;
sample struct {
service_instance svc;
number_t chnID; // the channel to use for connecting to the service
} service_register;
sample boolean ack;
sample struct {
short dummy;
} services_query;
sample struct {
service_instance svcs[_];
} services_list;
sample struct {
service_instance svc;
number_t bytes_per_period;
number_t period_time; //microseconds
// importance?
} service_allocate_channel; // client [_]> GlobeThrottle to request connection
sample struct {
number_t chnId;
eth_addr remote_device;
number_t remote_chnId;
} service_channel_open; // sent as response to service_allocate_channel (sent to both sides)
sample struct {
short max_utilization; // in percent
// min period?
} service_channel_NACK;
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
#define BUFLEN 512
#define NPACK 10
#define PORT 9930
void diep(char *s)
{
perror(s);
exit(1);
}
typedef struct {
struct sockaddr_in si_me, si_other;
int s, i, slen;
char buf[BUFLEN];
} server_context_t;
server_context_t* server_init(void)
{
server_context_t* ctx;
ctx = malloc(sizeof(server_context_t));
if(!ctx)
diep("malloc");
ctx->slen=sizeof(struct sockaddr_in);
if ((ctx->s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &ctx->si_me, 0, sizeof(ctx->si_me));
ctx->si_me.sin_family = AF_INET;
ctx->si_me.sin_port = htons(PORT);
ctx->si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(ctx->s, &ctx->si_me, sizeof(ctx->si_me))==-1)
diep("bind");
return ctx;
}
int udp_recv(server_context_t *ctx, char *buf, int len){
int l;
if ((l=recvfrom(ctx->s, buf, len, 0, &ctx->si_other, &ctx->slen))==-1)
diep("recvfrom()");
return l;
// printf("Received packet from %s:%d\nData: %s\n\n",
// inet_ntoa(ctx->si_other.sin_addr), ntohs(ctx->si_other.sin_port), ctx->buf);
}
int server_run(server_context_t *ctx){
for (ctx->i=0; ctx->i<NPACK; ctx->i++) {
int l = udp_recv(ctx, ctx->buf, BUFLEN);
printf("Received %d bytes\n",l);
printf("Received data: %s\n",
ctx->buf);
}
}
int server_exit(server_context_t *ctx) {
close(ctx->s);
free(ctx);
return 0;
}
#define SRV_IP "127.0.0.1"
server_context_t* client_init(void)
{
server_context_t *ctx = malloc(sizeof(server_context_t));
if(!ctx)
diep("malloc");
ctx->slen=sizeof(struct sockaddr_in);
if ((ctx->s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &ctx->si_other, 0, sizeof(ctx->si_other));
ctx->si_other.sin_family = AF_INET;
ctx->si_other.sin_port = htons(PORT);
if (inet_aton(SRV_IP, &ctx->si_other.sin_addr)==0) {
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
return ctx;
}
int udp_send(server_context_t* ctx, char *s, int len)
{
int result;
if ( (result=sendto(ctx->s, s, len, 0, &(ctx->si_other), ctx->slen))==-1)
diep("sendto()");
return result;
}
int client_run(server_context_t* ctx)
{
for (ctx->i=0; ctx->i<NPACK; ctx->i++) {
printf("Sending packet %d\n", ctx->i);
// sprintf(ctx->buf, "This is packet %d\n", ctx->i);
// udp_send(ctx);
udp_send(ctx, "Hello, world", 12);
}
return 0;
}
int client_exit(server_context_t* ctx)
{
close(ctx->s);
free(ctx);
return 0;
}
struct hidden;
typedef struct hidden server_context_t;
int udp_send(server_context_t*, char*, int);
int udp_recv(server_context_t*, char*, int);
server_context_t* server_init(void);
int server_run(server_context_t *ctx);
int server_exit(server_context_t *ctx);
server_context_t* client_init(void);
//int client_run()server_context_t* ;
//int client_free(vserver_context_t*);
/*
labcomm2014.c -- runtime for handling encoding and decoding of
labcomm2014 samples.
Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LabComm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef LABCOMM_COMPAT
#include LABCOMM_COMPAT
#else
#include <stdio.h>
#include <strings.h>
#endif
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <stddef.h>
#include "labcomm2014.h"
#include "labcomm2014_private.h"
#include "labcomm2014_ioctl.h"
#include "labcomm2014_dynamic_buffer_writer.h"
/* Unwrapping reader/writer functions */
#define UNWRAP_ac(rw, ac, ...) ac
#define UNWRAP(func, ...) \
while (1) { \
if (UNWRAP_ac(__VA_ARGS__)->action->func) { \
return UNWRAP_ac(__VA_ARGS__)->action->func(__VA_ARGS__); } \
if (UNWRAP_ac(__VA_ARGS__)->next == NULL) { return -ENOSYS; } \
UNWRAP_ac( __VA_ARGS__) = UNWRAP_ac(__VA_ARGS__)->next; \
}
int labcomm2014_reader_alloc(struct labcomm2014_reader *r,
struct labcomm2014_reader_action_context *action_context)
{
UNWRAP(alloc, r, action_context);
}
int labcomm2014_reader_free(struct labcomm2014_reader *r,
struct labcomm2014_reader_action_context *action_context)
{
UNWRAP(free, r, action_context);
}
int labcomm2014_reader_start(struct labcomm2014_reader *r,
struct labcomm2014_reader_action_context *action_context,
int local_index, int remote_index,
const struct labcomm2014_signature *signature,
void *value)
{
UNWRAP(start, r, action_context, local_index, remote_index, signature, value);
}
int labcomm2014_reader_end(struct labcomm2014_reader *r,
struct labcomm2014_reader_action_context *action_context)
{
UNWRAP(end, r, action_context);
}
int labcomm2014_reader_fill(struct labcomm2014_reader *r,
struct labcomm2014_reader_action_context *action_context)
{
UNWRAP(fill, r, action_context);
}
int labcomm2014_reader_ioctl(struct labcomm2014_reader *r,
struct labcomm2014_reader_action_context *action_context,
int local_index, int remote_index,
const struct labcomm2014_signature *signature,
uint32_t ioctl_action, va_list args)
{
UNWRAP(ioctl, r, action_context,
local_index, remote_index, signature, ioctl_action, args);
}
int labcomm2014_writer_alloc(struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context)
{
UNWRAP(alloc, w, action_context);
}
int labcomm2014_writer_free(struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context)
{
UNWRAP(free, w, action_context);
}
int labcomm2014_writer_start(struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context,
int index, const struct labcomm2014_signature *signature,
void *value)
{
UNWRAP(start, w, action_context, index, signature, value);
}
int labcomm2014_writer_end(struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context)
{
UNWRAP(end, w, action_context);
}
int labcomm2014_writer_flush(struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context)
{
UNWRAP(flush, w, action_context);
}
int labcomm2014_writer_ioctl(struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context,
int index,
const struct labcomm2014_signature *signature,
uint32_t ioctl_action, va_list args)
{
UNWRAP(ioctl, w, action_context, index, signature, ioctl_action, args);
}
#undef UNWRAP
#undef UNWRAP_ac
static const char *labcomm2014_error_string[] = {
#define LABCOMM2014_ERROR(name, description) description ,
#include "labcomm2014_error.h"
#undef LABCOMM2014_ERROR
};
static const int labcomm2014_error_string_count = (sizeof(labcomm2014_error_string) /
sizeof(labcomm2014_error_string[0]));
const char *labcomm2014_error_get_str(enum labcomm2014_error error_id)
{
const char *error_str = NULL;
// Check if this is a known error ID.
if (error_id < labcomm2014_error_string_count) {
error_str = labcomm2014_error_string[error_id];
}
return error_str;
}
void labcomm20142014_on_error_fprintf(enum labcomm2014_error error_id, size_t nbr_va_args, ...)
{
#ifndef LABCOMM_NO_STDIO
const char *err_msg = labcomm2014_error_get_str(error_id); // The final string to print.
if (err_msg == NULL) {
err_msg = "Error with an unknown error ID occured.";
}
fprintf(stderr, "%s\n", err_msg);
if (nbr_va_args > 0) {
va_list arg_pointer;
va_start(arg_pointer, nbr_va_args);
fprintf(stderr, "%s\n", "Extra info {");
char *print_format = va_arg(arg_pointer, char *);
vfprintf(stderr, print_format, arg_pointer);
fprintf(stderr, "}\n");
va_end(arg_pointer);
}
#else
; // If labcomm2014 can't be compiled with stdio the user will have to make an own error callback functionif he/she needs error reporting.
#endif
}
#if 0
static void dump(void *p, int size, int first, int last)
{
int i, j;
printf("%d %d (%p): ", first, last, p);
for (i = first ; i < last ; i++) {
for (j = 0 ; j < size ; j++) {
printf("%2.2d", ((char*)p)[(i-first)*size + j]);
}
printf(" ");
}
printf("\n");
}
#endif
void *labcomm2014_signature_array_ref(struct labcomm2014_memory *memory,
int *first, int *last, void **data,
int size, int index)
{
if (*first == 0 && *last == 0) {
*first = index;
*last = index + 1;
*data = labcomm2014_memory_alloc(memory, 0, size);
if (*data) {
memset(*data, 0, size);
}
} else if (index < *first || *last <= index) {
void *old_data = *data;
int old_first = *first;
int old_last = *last;
int n;
*first = (index<old_first)?index:old_first;
*last = (old_last<=index)?index+1:old_last;
n = (*last - *first);
*data = labcomm2014_memory_alloc(memory, 0, n * size);
if (*data) {
memset(*data, 0, n * size);
memcpy(*data + (old_first - *first) * size,
old_data,
(old_last - old_first) * size);
}
// dump(old_data, size, old_first, old_last);
labcomm2014_memory_free(memory, 0, old_data);
}
if (*data) {
// dump(*data, size, *first, *last);
return *data + (index - *first) * size;
} else {
return NULL;
}
}
static int local_index = LABCOMM_USER;
void labcomm2014_set_local_index(struct labcomm2014_signature *signature)
{
if (signature->index != 0) {
labcomm2014_error_fatal_global(LABCOMM2014_ERROR_SIGNATURE_ALREADY_SET,
"Signature already set: %s\n", signature->name);
}
signature->index = local_index;
local_index++;
}
int labcomm2014_get_local_index(const struct labcomm2014_signature *signature)
{
int result;
if (! signature) {
result = 0;
} else {
if (signature->index == 0) {
labcomm2014_error_fatal_global(LABCOMM2014_ERROR_SIGNATURE_NOT_SET,
"Signature not set: %s\n",
signature->name);
}
result = signature->index;
}
return result;
}
int labcomm2014_get_local_type_index(const struct labcomm2014_signature *signature)
{
return labcomm2014_get_local_index(signature);
}
int labcomm2014_internal_sizeof(const struct labcomm2014_signature *signature,
void *v)
{
int length = signature->encoded_size(signature, v);
return (labcomm2014_size_packed32(signature->index) +
labcomm2014_size_packed32(length) +
length);
}
/*
labcomm2014.h -- user interface for handling encoding and decoding of
labcomm2014 samples.
Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LabComm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __LABCOMM2014_H__
#define __LABCOMM2014_H__
#include <stdarg.h>
#ifdef LABCOMM_COMPAT
#include LABCOMM_COMPAT
#else
#include <stdint.h>
#include <unistd.h>
#endif
#include "labcomm2014_error.h"
#include "labcomm2014_scheduler.h"
/* Forward declaration */
struct labcomm2014_encoder;
struct labcomm2014_decoder;
#include "labcomm2014_type_signature.h"
/*
* Error handling.
*/
/* The callback prototype for error handling.
* First parameter is the error ID.
* The second paramters is the number of va_args that comes after this
* one. If none it should be 0.
* Optionaly other paramters can be supplied depending on what is needed
* for this error ID.
*/
typedef void (*labcomm2014_error_handler_callback)(enum labcomm2014_error error_id,
size_t nbr_va_args, ...);
/* Default error handler, prints message to stderr.
* Extra info about the error can be supplied as char* as VA-args. Especially user defined errors should supply a describing string. if nbr_va_args > 1 the first variable argument must be a printf format string and the possibly following arguments are passed as va_args to vprintf.
*/
void labcomm20142014_on_error_fprintf(enum labcomm2014_error error_id, size_t nbr_va_args, ...);
/* Register a callback for the error handler for this encoder. */
void labcomm2014_register_error_handler_encoder(struct labcomm2014_encoder *encoder, labcomm2014_error_handler_callback callback);
/* Register a callback for the error handler for this decoder. */
void labcomm2014_register_error_handler_decoder(struct labcomm2014_decoder *decoder, labcomm2014_error_handler_callback callback);
/* Get a string describing the supplied standrad labcomm2014 error. */
const char *labcomm2014_error_get_str(enum labcomm2014_error error_id);
typedef int (*labcomm2014_handle_new_datatype_callback)(
struct labcomm2014_decoder *decoder,
struct labcomm2014_signature *sig);
/*
* Dynamic memory handling
* lifetime == 0 memory that will live for as long as the
* encoder/decoder or that are allocated/deallocated
* during the communication setup phase
* otherwise memory will live for approximately this number of
* sent/received samples
*/
struct labcomm2014_memory;
void *labcomm2014_memory_alloc(struct labcomm2014_memory *m, int lifetime, size_t size);
void *labcomm2014_memory_realloc(struct labcomm2014_memory *m, int lifetime,
void *ptr, size_t size);
void labcomm2014_memory_free(struct labcomm2014_memory *m, int lifetime, void *ptr);
/*
* Decoder
*/
struct labcomm2014_reader;
struct labcomm2014_decoder *labcomm2014_decoder_new(
struct labcomm2014_reader *reader,
struct labcomm2014_error_handler *error,
struct labcomm2014_memory *memory,
struct labcomm2014_scheduler *scheduler);
void labcomm2014_decoder_free(
struct labcomm2014_decoder *decoder);
int labcomm2014_decoder_decode_one(
struct labcomm2014_decoder *decoder);
void labcomm2014_decoder_run(
struct labcomm2014_decoder *decoder);
int labcomm2014_decoder_sample_ref_register(
struct labcomm2014_decoder *decoder,
const struct labcomm2014_signature *signature);
/* See labcomm2014_ioctl.h for predefined ioctl_action values */
int labcomm2014_decoder_ioctl(struct labcomm2014_decoder *decoder,
uint32_t ioctl_action,
...);
const struct labcomm2014_sample_ref *labcomm2014_decoder_get_sample_ref(
struct labcomm2014_decoder *decoder,
const struct labcomm2014_signature *signature);
/*
* Encoder
*/
struct labcomm2014_writer;
struct labcomm2014_encoder *labcomm2014_encoder_new(
struct labcomm2014_writer *writer,
struct labcomm2014_error_handler *error,
struct labcomm2014_memory *memory,
struct labcomm2014_scheduler *scheduler);
void labcomm2014_encoder_free(
struct labcomm2014_encoder *encoder);
int labcomm2014_encoder_sample_ref_register(
struct labcomm2014_encoder *encoder,
const struct labcomm2014_signature *signature);
/* See labcomm2014_ioctl.h for predefined ioctl_action values */
int labcomm2014_encoder_ioctl(struct labcomm2014_encoder *encoder,
uint32_t ioctl_action,
...);
const struct labcomm2014_sample_ref *labcomm2014_encoder_get_sample_ref(
struct labcomm2014_encoder *encoder,
const struct labcomm2014_signature *signature);
#endif
#ifndef ARM_CORTEXM3_CODESOURCERY
#error "ARM_CORTEXM3_CODESOURCERY" not defined
#endif
#include <machine/endian.h>
#ifndef __APPLE__
#error "__APPLE__" not defined
#endif
#ifndef LABCOMM_COMPAT_OSX
#define LABCOMM_COMPAT_OSX
#include <machine/endian.h>
#include <stdio.h>
#include <time.h>
#include <mach/clock.h>
#include <mach/mach.h>
#define CLOCK_REALTIME 0
static inline void clock_gettime(int garbage, struct timespec *ts)
{
(void) garbage;
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts->tv_sec = mts.tv_sec;
ts->tv_nsec = mts.tv_nsec;
}
#endif
#ifndef _LABCOMM_COMPAT_VXWORKS_H_
#define _LABCOMM_COMPAT_VXWORKS_H_
#ifndef __VXWORKS__
#error "__VXWORKS__" not defined
#endif
#include <types/vxTypes.h>
#include <selectLib.h>
#include <types.h>
#include <timers.h>
#include <stdio.h>
#include <private/stdioP.h>
#ifdef __INT64_MAX__
#undef INT64_MAX
#define INT64_MAX __INT64_MAX__
#endif
#if (CPU == PPC603)
#undef _LITTLE_ENDIAN
#endif
#if (CPU == PENTIUM4)
#undef _BIG_ENDIAN
#endif
extern unsigned int cpuFrequency;
#endif
/*
labcomm2014_decoder.c -- runtime for handling decoding of labcomm2014 samples.
Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LabComm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define CURRENT_VERSION "LabComm2014"
#include <errno.h>
#include "labcomm2014.h"
#include "labcomm2014_private.h"
#include "labcomm2014_ioctl.h"
#include "labcomm2014_dynamic_buffer_writer.h"
#ifdef DEBUG
#define DEBUG_FPRINTF(str, ...) fprintf(str, ##__VA_ARGS__)
#else
#define DEBUG_FPRINTF(str, ...)
#endif
#ifdef DECODER_DEBUG
#define DECODER_DEBUG_FPRINTF(str, ...) fprintf(str, ##__VA_ARGS__)
#else
#define DECODER_DEBUG_FPRINTF(str, ...)
#endif
struct sample_entry {
int remote_index;
const struct labcomm2014_signature *signature;
labcomm2014_decoder_function decode;
labcomm2014_handler_function handler;
void *context;
};
struct decoder {
struct labcomm2014_decoder decoder;
LABCOMM_SIGNATURE_ARRAY_DEF(local, struct sample_entry);
LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local, int);
LABCOMM_SIGNATURE_ARRAY_DEF(local_ref, const struct labcomm2014_signature *);
LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local_ref, int);
};
static int handle_sample_def(struct labcomm2014_decoder *d, int remote_index,
const struct labcomm2014_signature *signature)
{
struct decoder *id = d->context;
int result;
int i;
const struct labcomm2014_signature *local_signature = NULL;
int local_index = 0;
labcomm2014_scheduler_data_lock(d->scheduler);
LABCOMM_SIGNATURE_ARRAY_FOREACH(id->local, struct sample_entry, i) {
struct sample_entry *s;
int *remote_to_local;
result = -ENOENT;
s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->local, struct sample_entry, i);
if (s->signature &&
s->signature->size == signature->size &&
strcmp(s->signature->name, signature->name) == 0 &&
memcmp((void*)s->signature->signature, (void*)signature->signature,
signature->size) == 0) {
s->remote_index = remote_index;
local_signature = s->signature;
local_index = i;
remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->remote_to_local, int,
remote_index);
*remote_to_local = i;
result = remote_index;
break;
}
}
labcomm2014_scheduler_data_unlock(d->scheduler);
if (local_signature) {
labcomm2014_reader_start(d->reader, d->reader->action_context,
local_index, remote_index, local_signature,
NULL);
labcomm2014_reader_end(d->reader, d->reader->action_context);
}
return result;
}
static int handle_sample_ref(struct labcomm2014_decoder *d, int remote_index,
const struct labcomm2014_signature *signature)
{
struct decoder *id = d->context;
int result;
int i;
labcomm2014_scheduler_data_lock(d->scheduler);
LABCOMM_SIGNATURE_ARRAY_FOREACH(id->local_ref,
const struct labcomm2014_signature *, i) {
const struct labcomm2014_signature *s;
int *remote_to_local_ref;
result = -ENOENT;
s = LABCOMM_SIGNATURE_ARRAY_GET(id->local_ref, const struct labcomm2014_signature *, i, 0);
if (s &&
s->signature &&
s->size == signature->size &&
strcmp(s->name, signature->name) == 0 &&
memcmp((void*)s->signature, (void*)signature->signature, signature->size) == 0) {
remote_to_local_ref = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->remote_to_local_ref,
int,
remote_index);
*remote_to_local_ref = i;
result = remote_index;
break;
}
}
labcomm2014_scheduler_data_unlock(d->scheduler);
return result;
}
static int reader_skip(struct labcomm2014_reader *r, int len, int tag)
{
int i;
DECODER_DEBUG_FPRINTF(stdout, "got tag 0x%x, skipping %d bytes\n", tag, len);
for(i = 0; i <len; i++){
DECODER_DEBUG_FPRINTF(stderr, ".");
labcomm2014_read_byte(r);
if (r->error < 0) {
DECODER_DEBUG_FPRINTF(stderr, "\nerror while skipping: %d\n", r->error);
return r->error;
}
}
DECODER_DEBUG_FPRINTF(stderr, "\n");
return tag;
}
static char* TODO_read_intentions(struct labcomm2014_reader *r)
{
int numInts = labcomm2014_read_byte(r);
int i;
char *name=NULL;
printf("TODO_read_intentions: numInts=%d\n", numInts);
for(i=0; i <numInts; i++){
int klen = labcomm2014_read_packed32(r);
printf("TODO_read_intentions: klen=%d\n", klen);
if(klen == 0) {
name = labcomm2014_read_string(r);
printf("TODO_read_intentions: name=%s\n", name);
}else{
int vlen;
reader_skip(r, klen, 1);
vlen = labcomm2014_read_packed32(r);
reader_skip(r, vlen, 1);
printf("TODO_read_intentions: skipping value, %d bytes\n", vlen);
}
}
return name;
}
static int decode_sample_def_or_ref(struct labcomm2014_decoder *d, int kind)
{
int result;
struct labcomm2014_signature signature;
int i, remote_index;
remote_index = labcomm2014_read_packed32(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
signature.name = TODO_read_intentions(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto free_signature_name;
}
signature.size = labcomm2014_read_packed32(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto free_signature_name;
}
signature.signature = labcomm2014_memory_alloc(d->memory, 1, signature.size);
if (d->reader->error < 0) {
result = d->reader->error;
goto free_signature_name;
}
for (i = 0 ; i < signature.size ; i++) {
signature.signature[i] = labcomm2014_read_byte(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto free_signature_signature;
}
}
switch (kind) {
case LABCOMM_SAMPLE_DEF: {
result = handle_sample_def(d, remote_index, &signature);
break;
}
case LABCOMM_SAMPLE_REF: {
result = handle_sample_ref(d, remote_index, &signature);
if (result == -ENOENT) {
/* Dummy value to silently continue */
result = LABCOMM_SAMPLE_REF;
}
break;
}
default:
result = -EINVAL;
}
free_signature_signature:
labcomm2014_memory_free(d->memory, 1, signature.signature);
free_signature_name:
if (signature.name) {
if (result == -ENOENT) {
labcomm2014_error_warning(d->error,
LABCOMM2014_ERROR_DEC_NO_REG_SIGNATURE,
"Signature not found: %s\n",
signature.name);
}
labcomm2014_memory_free(d->memory, 0, signature.name);
}
out:
return result;
}
struct call_handler_context {
struct labcomm2014_reader *reader;
int local_index;
int remote_index;
const struct labcomm2014_signature *signature;
labcomm2014_handler_function handler;
void *context;
};
static void call_handler(void *value, void *context)
{
struct call_handler_context *wrap = context;
if (wrap->reader->error >= 0) {
labcomm2014_reader_start(wrap->reader, wrap->reader->action_context,
wrap->local_index, wrap->remote_index, wrap->signature,
value);
wrap->handler(value, wrap->context);
labcomm2014_reader_end(wrap->reader, wrap->reader->action_context);
}
}
static void reader_alloc(struct labcomm2014_decoder *d)
{
if (!d->reader_allocated) {
d->reader_allocated = 1;
labcomm2014_reader_alloc(d->reader, d->reader->action_context);
}
}
/* d - decoder to read from
registry - decoder to lookup signatures (registry != d only if
nesting decoders, e.g., when decoding pragma)
len - length of the labcomm2014 packet )
*/
static int decode_pragma(struct labcomm2014_decoder *d,
struct labcomm2014_decoder *registry,
int len)
{
char *pragma_type;
int result;
pragma_type = labcomm2014_read_string(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
int bytes = labcomm2014_size_string(pragma_type);
int psize = len-bytes;
result = reader_skip(d->reader, psize, LABCOMM_PRAGMA);
out:
return result;
}
static labcomm2014_decoder_function lookup_h(struct labcomm2014_decoder *d,
struct call_handler_context *wrap,
int remote_index,
int *r_local_index)
{
struct decoder *id = d->context;
labcomm2014_decoder_function do_decode = NULL;
int *local_index;
labcomm2014_scheduler_data_lock(d->scheduler);
local_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->remote_to_local, int,
remote_index);
*r_local_index = *local_index;
if (*local_index != 0) {
struct sample_entry *entry;
entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->local, struct sample_entry,
*local_index);
wrap->local_index = *local_index;
wrap->signature = entry->signature;
wrap->handler = entry->handler;
wrap->context = entry->context;
do_decode = entry->decode;
}
labcomm2014_scheduler_data_unlock(d->scheduler);
return do_decode;
}
/* d - decoder to read from
registry - decoder to lookup signatures (registry != d only if
nesting decoders, e.g., when decoding pragma)
remote_index - received type index )
*/
static int decode_and_handle(struct labcomm2014_decoder *d,
struct labcomm2014_decoder *registry,
int remote_index)
{
int result;
int local_index;
struct call_handler_context wrap = {
.reader = d->reader,
.remote_index = remote_index,
.signature = NULL,
.handler = NULL,
.context = NULL,
};
labcomm2014_decoder_function do_decode = lookup_h(registry, &wrap, remote_index, &local_index);
result = local_index;
if (do_decode) {
do_decode(d->reader, call_handler, &wrap);
if (d->reader->error < 0) {
result = d->reader->error;
}
} else {
result = -ENOENT;
}
return result;
}
int labcomm2014_decoder_decode_one(struct labcomm2014_decoder *d)
{
return d->decode_one(d);
}
static int do_decode_one(struct labcomm2014_decoder *d)
{
int result, remote_index, length;
reader_alloc(d);
remote_index = labcomm2014_read_packed32(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
length = labcomm2014_read_packed32(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
if (remote_index == LABCOMM_VERSION) {
char *version = labcomm2014_read_string(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
} else if (strcmp(version, CURRENT_VERSION) == 0) {
result = LABCOMM_VERSION;
d->version_ok = 1;
} else {
result = -ECONNRESET;
}
labcomm2014_memory_free(d->memory, 1, version);
if (result < 0) {
goto out;
}
} else if (! d->version_ok) {
DEBUG_FPRINTF(stderr, "No VERSION %d %d\n", remote_index, length);
result = -ECONNRESET;
} else if (remote_index == LABCOMM_SAMPLE_DEF) {
result = decode_sample_def_or_ref(d, LABCOMM_SAMPLE_DEF);
} else if (remote_index == LABCOMM_SAMPLE_REF) {
result = decode_sample_def_or_ref(d, LABCOMM_SAMPLE_REF);
} else if (remote_index == LABCOMM_TYPE_DEF) {
result = decode_and_handle(d, d, remote_index);
if(result == -ENOENT) {
//No handler for type_defs, skip
result = reader_skip(d->reader, length, remote_index);
}
} else if (remote_index == LABCOMM_TYPE_BINDING) {
result = decode_and_handle(d, d, remote_index);
if(result == -ENOENT) {
//No handler for type_bindings, skip
result = reader_skip(d->reader, length, remote_index);
}
} else if (remote_index == LABCOMM_PRAGMA) {
result = decode_pragma(d, d, length);
} else if (remote_index < LABCOMM_USER) {
DECODER_DEBUG_FPRINTF(stderr, "SKIP %d %d\n", remote_index, length);
result = reader_skip(d->reader, length, remote_index);
} else {
result = decode_and_handle(d, d, remote_index);
}
out:
return result;
}
void labcomm2014_decoder_run(struct labcomm2014_decoder *d)
{
while (labcomm2014_decoder_decode_one(d) > 0) {
}
}
int labcomm2014_decoder_ioctl(struct labcomm2014_decoder *d,
uint32_t action,
...)
{
int result;
va_list va;
va_start(va, action);
result = d->ioctl(d, NULL, action, va);
va_end(va);
return result;
}
int labcomm2014_decoder_sample_ref_register(
struct labcomm2014_decoder *d,
const struct labcomm2014_signature *signature)
{
return d->ref_register(d, signature);
}
static int do_ref_register(
struct labcomm2014_decoder *d,
const struct labcomm2014_signature *signature)
{
struct decoder *id = d->context;
int local_index, *remote_to_local_ref;
const struct labcomm2014_signature **s;
local_index = labcomm2014_get_local_index(signature);
if (local_index <= 0) { goto out; }
labcomm2014_scheduler_data_lock(d->scheduler);
s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->local_ref,
const struct labcomm2014_signature*, local_index);
if (s == NULL) { local_index = -ENOMEM; goto unlock; };
if (*s) { goto unlock; }
*s = signature;
remote_to_local_ref = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->remote_to_local_ref,
int, local_index);
*remote_to_local_ref = 0;
unlock:
labcomm2014_scheduler_data_unlock(d->scheduler);
out:
return local_index;
}
static int do_ioctl(struct labcomm2014_decoder *d,
const struct labcomm2014_signature *signature,
uint32_t action, va_list va)
{
struct decoder *id = d->context;
int result;
int local_index, remote_index;
local_index = labcomm2014_get_local_index(signature);
if (local_index == 0) {
remote_index = 0;
} else {
labcomm2014_scheduler_data_lock(d->scheduler);
remote_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->local,
struct sample_entry,
local_index)->remote_index;
labcomm2014_scheduler_data_unlock(d->scheduler);
}
result = labcomm2014_reader_ioctl(d->reader, d->reader->action_context,
local_index, remote_index,
signature, action, va);
return result;
}
#ifndef LABCOMM_NO_TYPEDECL
//// Code for allowing user code to handle type_defs
//// (should perhaps be moved to another file)
static void decode_raw_type_def(
struct labcomm2014_reader *r,
void (*handle)(
struct labcomm2014_raw_type_def *v,
void *context
),
void *context
)
{
struct labcomm2014_raw_type_def v;
v.index = labcomm2014_read_packed32(r);
if (r->error < 0) { goto out; }
v.name = TODO_read_intentions(r);
if (r->error < 0) { goto free_name; }
v.length = labcomm2014_read_packed32(r);
if (r->error < 0) { goto free_name; }
int i;
v.signature_data = labcomm2014_memory_alloc(r->memory, 1, v.length);
if(v.signature_data) {
for(i=0; i<v.length; i++) {
v.signature_data[i] = labcomm2014_read_byte(r);
if (r->error < 0) { goto free_sig; }
}
handle(&v, context);
}
free_sig:
labcomm2014_memory_free(r->memory, 1, v.signature_data);
free_name:
labcomm2014_memory_free(r->memory, 1, v.name);
out:
return;
}
int labcomm2014_decoder_register_labcomm2014_type_def(
struct labcomm2014_decoder *d,
void (*handler)(
struct labcomm2014_raw_type_def *v,
void *context
),
void *context
)
{
struct decoder *id = d->context;
int tag = LABCOMM_TYPE_DEF;
struct sample_entry *entry;
int *remote_to_local;
labcomm2014_scheduler_data_lock(d->scheduler);
entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->local, struct sample_entry,
tag);
if (entry == NULL) { tag = -ENOMEM; goto unlock; }
entry->remote_index = tag;
entry->signature = NULL;
entry->decode = (labcomm2014_decoder_function) decode_raw_type_def;
entry->handler =(labcomm2014_handler_function) handler;
entry->context = context;
remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->remote_to_local, int,
tag);
*remote_to_local = tag;
unlock:
labcomm2014_scheduler_data_unlock(d->scheduler);
return tag;
}
static void decode_type_binding(
struct labcomm2014_reader *r,
void (*handle)(
struct labcomm2014_type_binding *v,
void *context
),
void *context
)
{
struct labcomm2014_type_binding v;
v.sample_index = labcomm2014_read_packed32(r);
if (r->error < 0) { goto out; }
v.type_index = labcomm2014_read_packed32(r);
if (r->error < 0) { goto out; }
handle(&v, context);
out:
return;
}
int labcomm2014_decoder_register_labcomm2014_type_binding(
struct labcomm2014_decoder *d,
void (*handler)(
struct labcomm2014_type_binding *v,
void *context
),
void *context
)
{
struct decoder *id = d->context;
int tag = LABCOMM_TYPE_BINDING;
struct sample_entry *entry;
int *remote_to_local;
labcomm2014_scheduler_data_lock(d->scheduler);
entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->local, struct sample_entry,
tag);
if (entry == NULL) { tag = -ENOMEM; goto unlock; }
entry->remote_index = tag;
entry->signature = NULL;
entry->decode = (labcomm2014_decoder_function) decode_type_binding;
entry->handler =(labcomm2014_handler_function) handler;
entry->context = context;
remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->remote_to_local, int,
tag);
*remote_to_local = tag;
unlock:
labcomm2014_scheduler_data_unlock(d->scheduler);
return tag;
}
//// End type_def handling
#endif
static int do_register_sample(
struct labcomm2014_decoder *d,
const struct labcomm2014_signature *signature,
labcomm2014_decoder_function decode,
labcomm2014_handler_function handler,
void *context)
{
struct decoder *id = d->context;
int local_index;
struct sample_entry *entry;
reader_alloc(d);
local_index = labcomm2014_get_local_index(signature);
if (local_index <= 0) { goto out; }
labcomm2014_reader_start(d->reader, d->reader->action_context,
local_index, 0, signature,
NULL);
labcomm2014_reader_end(d->reader, d->reader->action_context);
labcomm2014_scheduler_data_lock(d->scheduler);
entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
id->local, struct sample_entry,
local_index);
if (entry == NULL) { local_index = -ENOMEM; goto unlock; }
entry->remote_index = 0;
entry->signature = signature;
entry->decode = decode;
entry->handler = handler;
entry->context = context;
unlock:
labcomm2014_scheduler_data_unlock(d->scheduler);
out:
return local_index;
}
static const struct labcomm2014_sample_ref *do_index_to_sample_ref(
struct labcomm2014_decoder *d, int index)
{
const struct labcomm2014_signature *result = 0;
struct decoder *id = d->context;
int local_index;
labcomm2014_scheduler_data_lock(d->scheduler);
local_index = LABCOMM_SIGNATURE_ARRAY_GET(id->remote_to_local_ref,
int, index, 0);
if (local_index) {
result = LABCOMM_SIGNATURE_ARRAY_GET(id->local_ref,
const struct labcomm2014_signature*,
local_index, 0);
}
labcomm2014_scheduler_data_unlock(d->scheduler);
return labcomm2014_signature_to_sample_ref(result);
}
static const struct labcomm2014_sample_ref *do_ref_get(
struct labcomm2014_decoder *d,
const struct labcomm2014_signature *signature)
{
return (const struct labcomm2014_sample_ref *) signature;
}
static void do_free(struct labcomm2014_decoder* d)
{
struct decoder *id = d->context;
struct labcomm2014_memory *memory = d->memory;
labcomm2014_reader_free(d->reader, d->reader->action_context);
LABCOMM_SIGNATURE_ARRAY_FREE(memory, id->local, struct sample_entry);
LABCOMM_SIGNATURE_ARRAY_FREE(memory, id->remote_to_local, int);
LABCOMM_SIGNATURE_ARRAY_FREE(memory, id->local_ref,
const struct labcomm2014_signature*);
LABCOMM_SIGNATURE_ARRAY_FREE(memory, id->remote_to_local_ref, int);
labcomm2014_memory_free(memory, 0, id);
}
void labcomm2014_decoder_free(struct labcomm2014_decoder* d)
{
d->free(d);
}
struct labcomm2014_decoder *labcomm2014_decoder_new(
struct labcomm2014_reader *reader,
struct labcomm2014_error_handler *error,
struct labcomm2014_memory *memory,
struct labcomm2014_scheduler *scheduler)
{
struct decoder *result;
result = labcomm2014_memory_alloc(memory, 0, sizeof(*result));
if (result) {
result->decoder.context = result;
result->decoder.reader = reader;
result->decoder.reader->decoder = &result->decoder;
result->decoder.reader->data = 0;
result->decoder.reader->data_size = 0;
result->decoder.reader->count = 0;
result->decoder.reader->pos = 0;
result->decoder.reader->error = 0;
result->decoder.reader_allocated = 0;
result->decoder.version_ok = 0;
result->decoder.error = error;
result->decoder.memory = memory;
result->decoder.scheduler = scheduler;
result->decoder.on_error = labcomm20142014_on_error_fprintf;
result->decoder.free = do_free;
result->decoder.decode_one = do_decode_one;
result->decoder.ref_register = do_ref_register;
result->decoder.sample_register = do_register_sample;
result->decoder.ioctl = do_ioctl;
result->decoder.index_to_sample_ref = do_index_to_sample_ref;
result->decoder.ref_get = do_ref_get;
LABCOMM_SIGNATURE_ARRAY_INIT(result->local, struct sample_entry);
LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local, int);
LABCOMM_SIGNATURE_ARRAY_INIT(result->local_ref,
const struct labcomm2014_signature*);
LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local_ref, int);
}
return &(result->decoder);
}
const struct labcomm2014_sample_ref *labcomm2014_decoder_get_sample_ref(
struct labcomm2014_decoder *decoder,
const struct labcomm2014_signature *signature)
{
return decoder->ref_get(decoder, signature);
}
/*
test_default_error_handler.c -- LabComm default error handler
Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LabComm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "labcomm2014.h"
struct labcomm2014_error_handler *labcomm2014_default_error_handler = NULL;