diff --git a/lib/c/experimental/labcomm_parser.c b/lib/c/experimental/labcomm_parser.c new file mode 100644 index 0000000000000000000000000000000000000000..77a7a22e1c6f0a53ac0668a0b8e190f3f4bbe2a3 --- /dev/null +++ b/lib/c/experimental/labcomm_parser.c @@ -0,0 +1,585 @@ +/* labcomm_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. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define FALSE 0 +#define TRUE 1 + +void error(char *s) { + fprintf(stderr, "%s\n", s); + exit(1); +} +#define BUF_SIZE 1024 +#define STACK_SIZE 16 + +typedef struct { + unsigned char* c; + unsigned int size; + unsigned int capacity; + unsigned int idx; + unsigned int* stack; + unsigned int top; +} buffer; + + +void dumpStack(buffer *b) { +#ifdef DEBUG + int i; + printf("=== stack: "); + for(i=0; i<STACK_SIZE; i++) { //HERE BE DRAGONS + printf("%2.2x ", b->stack[i]); + } + printf(" top==%d\n", b->top); +#endif +} + +void push(buffer *b, unsigned int e) { + b->stack[b->top]=e; + b->top=b->top-1; + dumpStack(b); +} +unsigned int pop(buffer *b) { + b->top=b->top+1; + return b->stack[b->top]; +} + +int init_buffer(buffer *b, size_t size, size_t stacksize) { + b->c = malloc(size); + b->capacity = size; + b->idx = 0; + + b->stack = calloc(stacksize, sizeof(b->stack)); + b->top = stacksize-1; + + return b->c == NULL || b->stack == NULL; +} + +int more(buffer *b) +{ + return b->idx < b->size; +} + +unsigned char get(buffer *b) { + return b->c[b->idx++]; +} + +unsigned char peek(buffer *b) { + return b->c[b->idx]; +} + +void advance(buffer *b) { + b->idx++; +} + +void advancen(buffer *b, size_t n) { + b->idx+=n; +} + +static int unpack32(unsigned char *c, unsigned int idx) { + unsigned int b0=(c[idx]) << 3 ; + unsigned int b1=(c[idx+1]) << 2 ; + unsigned int b2=(c[idx+2]) << 1 ; + unsigned int b3=c[idx+3]; + + return b0 | b1 | b2 | b3; +} + + +unsigned int peek32(buffer *b) { +#if 0 + unsigned int b0=(b->c[b->idx]) << 3 ; + unsigned int b1=(b->c[b->idx+1]) << 2 ; + unsigned int b2=(b->c[b->idx+2]) << 1 ; + unsigned int b3=b->c[b->idx+3]; + + return b0 | b1 | b2 | b3; +#else + return unpack32(b->c, b->idx); +#endif +} +void advance32(buffer *b) { + b->idx+=4; +} + +unsigned int get32(buffer *b) { + unsigned int res = peek32(b); + advance32(b); + return res; +} + +void getStr(buffer *b, char *dest, size_t size) { + int rem = b->size - b->idx; + if( size > rem ) + size = rem; + strncpy(dest, &b->c[b->idx], size); + b->idx += size; +} + +#define TYPE_DECL 0x00000001 +#define SAMPLE_DECL 0x00000002 +#define USER_ID_BASE 0x00000080 + +#define ARRAY_DECL 0x00000010 +#define STRUCT_DECL 0x00000011 + +#define TYPE_BOOLEAN 0x00000020 +#define TYPE_BYTE 0x00000021 +#define TYPE_SHORT 0x00000022 +#define TYPE_INTEGER 0x00000023 +#define TYPE_LONG 0x00000024 +#define TYPE_FLOAT 0x00000025 +#define TYPE_DOUBLE 0x00000026 +#define TYPE_STRING 0x00000027 + +//XXX experimental +unsigned int signatures_length[10]; +unsigned char signatures_name[10][64]; //HERE BE DRAGONS: add range checks +unsigned char signatures[10][128]; + +unsigned int get_signature_len(unsigned int uid){ + return signatures_length[uid-USER_ID_BASE]; +} +unsigned char* get_signature_name(unsigned int uid){ + return &signatures_name[uid-USER_ID_BASE][1]; +} +unsigned char* get_signature(unsigned int uid){ + return signatures[uid-USER_ID_BASE]; +} + +void dump_signature(unsigned int uid){ + int i; + unsigned int len = get_signature_len(uid); + printf("sig %x : %s (len=%d):\n", uid, get_signature_name(uid), len); + unsigned char* sig = get_signature(uid); + for(i=0; i<len; i++) { + printf("%2.2x ",sig[i]); + if( (i+1)%8==0 ) printf("\n"); + } + printf("\n"); +} + +int accept_packet(buffer *d); +int accept_type_decl(buffer *d); +int accept_sample_decl(buffer *d); +int accept_user_id(buffer *d); +int accept_string(buffer *d); +int accept_string_length(buffer *d); +int accept_char(buffer *d); +int accept_type(buffer *d); +int accept_basic_type(buffer *d); +int accept_boolean_type(buffer *d); +int accept_byte_type(buffer *d); +int accept_short_type(buffer *d); +int accept_integer_type(buffer *d); +int accept_long_type(buffer *d); +int accept_float_type(buffer *d); +int accept_long_type(buffer *d); +int accept_string_type(buffer *d); +int accept_array_decl(buffer *d); +int accept_number_of_indices(buffer *d); +int accept_indices(buffer *d); +int accept_variable_index(buffer *d); +int accept_fixed_index(buffer *d); +int accept_struct_decl(buffer *d); +int accept_number_of_fields(buffer *d); +int accept_field(buffer *d); +int accept_sample_data(buffer *d); +int accept_packed_sample_data(buffer *d); + +int read_file(FILE *f, buffer *b) { + int s = fread(b->c, sizeof(char), b->capacity, f); + b->size = s; + b->idx=0; + return s; +} + +void test_read(buffer *buf) { + int r = read_file(stdin, buf); + printf("read %d bytes:\n\n", r); + int i; + for(i=0; i<r; i++) { + printf("%x ", buf->c[i]); + if(i%8 == 7) printf("\n"); + } + printf("\n"); +} +int main() { + buffer buf; + + if( init_buffer(&buf, BUF_SIZE, STACK_SIZE) ) { + printf("failed to init buffer\n"); + exit(1); + } + test_read(&buf); + do{ + printf("trying to read another packet\n"); + } while(more(&buf) && accept_packet(&buf)); + printf("done\n"); +} + + +int accept_packet(buffer *d) { + if(accept_type_decl(d)) { + printf("*** got type decl\n"); + } else if(accept_sample_decl(d)) { + printf("*** got sample decl\n"); + } else if(accept_sample_data(d)) { + printf("*** got sample data\n"); + } else { +// error("unexpected %x, expecting packet", d->c[d->idx]); + error("packet"); + } +} +int accept_type_decl(buffer *d){ + unsigned int type = peek32(d) ; + if(type == TYPE_DECL ) { + advance32(d); + accept_user_id(d); + unsigned int uid = pop(d); + accept_string(d); + // ignore, for now + accept_type(d); + unsigned int type = pop(d); + + push(d, type); + return TRUE; + }else { + return FALSE; + } +} + +int accept_sample_decl(buffer *d){ + unsigned int type = peek32(d) ; + if (type == SAMPLE_DECL) { + advance32(d); + accept_user_id(d); + unsigned int nstart = d->idx; + unsigned int uid = pop(d); + accept_string(d); + unsigned int start = d->idx; + unsigned int nlen = pop(d); + accept_type(d); + unsigned int end = d->idx; + unsigned int len = end-start; + printf("signature for uid %x (start=%x,end=%x, nlen=%d,len=%d)\n", uid, start,end, nlen, len); + signatures_length[uid-USER_ID_BASE] = len; + memcpy(signatures_name[uid-USER_ID_BASE], &d->c[nstart+3], nlen+1); + signatures_name[uid-USER_ID_BASE][nlen+1]=0; + memcpy(signatures[uid-USER_ID_BASE], &d->c[start], len); + return TRUE; + } else { + return FALSE; + } +} + +int accept_user_id(buffer *d){ + unsigned int uid = peek32(d); + if(uid >= USER_ID_BASE) { + push(d, uid); + advance32(d); + //printf("uid = %x\n", uid); + return TRUE; + } else { + return FALSE; + } +} + +int accept_string(buffer *d){ + unsigned int len = get32(d); + push(d, len); + char *str=malloc(len); + getStr(d, str, len); + //printf("%s\n", str); + free(str); + return TRUE; +} +// included above +// int accept_string_length(buffer *d){ +// unsigned int uid = get32(d); +// return TRUE; +//} +//int accept_char(buffer *d){ +//} + +int accept_type(buffer *d){ + if(accept_basic_type(d)) { + } else if(accept_user_id(d)) { + //printf("user_id \n"); + } else if(accept_array_decl(d)) { + //printf("array_decl \n"); + } else if(accept_struct_decl(d)) { + //printf("struct_decl \n"); + } else { + return FALSE; + } +} +int accept_basic_type(buffer *d){ + unsigned int type = peek32(d); + switch(type) { + case TYPE_BOOLEAN : + //printf("boolean \n"); + break; + case TYPE_BYTE : + //printf("byte \n"); + break; + case TYPE_SHORT : + //printf("short \n"); + break; + case TYPE_INTEGER : + //printf("integer \n"); + break; + case TYPE_LONG : + //printf("long \n"); + break; + case TYPE_FLOAT : + //printf("float \n"); + break; + case TYPE_DOUBLE : + //printf("double \n"); + break; + case TYPE_STRING : + //printf("string \n"); + break; + default : + return FALSE; + } + advance32(d); + push(d,type); + return TRUE; +} +#if 0 // handle all basic types above +int accept_boolean_type(buffer *d){ +} +int accept_byte_type(buffer *d){ +} +int accept_short_type(buffer *d){ +} +int accept_integer_type(buffer *d){ +} +int accept_long_type(buffer *d){ +} +int accept_float_type(buffer *d){ +} +int accept_string_type(buffer *d){ +} +#endif +int accept_array_decl(buffer *d){ + unsigned int tid = peek32(d); + if(tid == ARRAY_DECL) { + advance32(d); + unsigned int nidx = get32(d); + printf("%d dim array: ", nidx); + int i; + unsigned int numVar=0; + unsigned int size=1; + for(i=0; i<nidx; i++) { + unsigned int idx = get32(d); + if(idx == 0) { + printf("variable index,"); + numVar++; + } else { + printf("fixed index: %d,", idx); + size*=idx; + } + printf("\n"); + } + accept_type(d); + return TRUE; + } else { + return FALSE; + } +} +#if 0 +int accept_number_of_indices(buffer *d){ +} +int accept_indices(buffer *d){ +} +int accept_variable_index(buffer *d){ +} +int accept_fixed_index(buffer *d){ +} +#endif +int accept_struct_decl(buffer *d){ + unsigned int tid = peek32(d); + if(tid == STRUCT_DECL) { + advance32(d); + unsigned int nf = get32(d); + printf("%d field struct: ", nf); + int i; + int numVar=0; + int size=0; + for(i=0; i<nf; i++) { + accept_field(d); + } + return TRUE; + } else { + return FALSE; + } +} +#if 0 +int accept_number_of_fields(buffer *d){ +} +#endif +int accept_field(buffer *d){ + accept_string(d); + // ignore, for now + accept_type(d); + unsigned int type = pop(d); + printf("field: %x \n", type); +} +int accept_sample_data(buffer *d){ + accept_user_id(d); + unsigned int uid = pop(d); + printf("sample data... %x\n", uid); + dump_signature(uid); + unsigned int siglen = get_signature_len(uid); + unsigned char *sig = get_signature(uid); + skip_packed_sample_data(d, sig, siglen); + return TRUE; +} +//int accept_packed_sample_data(buffer *d){ + +int skip_type(unsigned int,buffer*,unsigned char*,unsigned int,unsigned int*) ; + +int skip_struct(buffer *d, unsigned char *sig, unsigned int len, unsigned int *pos) { + unsigned int nFields = unpack32(sig,*pos); + *pos += 4; + unsigned int i; + unsigned int skipped=0; + printf("skip_struct (%d fields)\n", nFields); + for(i=0; i<nFields; i++) { + //skip name + unsigned int namelen = unpack32(sig, *pos); + *pos += (4+namelen); // 32bit len + actual string + printf("namelen==%d \n",namelen); + unsigned int type = unpack32(sig, *pos); + *pos += 4; + printf("type == %x\n", type); + skipped += skip_type(type, d, sig, len, pos); + } + return skipped; +} +#ifndef QUIET +/* print and skip */ +int skip_type(unsigned int type, buffer *d, + unsigned char *sig, unsigned int len, unsigned int *pos) +{ + int skipped=0; + printf("skip_type %x\n", 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 : + {unsigned int len = get32(d); + //advancen(d,len); + int i; + printf("string "); + for(i=0; i<len; i++) + printf("%c", get(d)); + printf("\n "); + skipped+=len+4; + break;} + case ARRAY_DECL : + printf("array not implemented\n"); + exit(1); + 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, buffer *d, + unsigned char *sig, unsigned int len, unsigned int *pos) +{ + int skipped=0; + 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 : + {unsigned int len = get32(d); + advancen(d,len); + skipped+=len+4; + break;} + case ARRAY_DECL : + printf("array not implemented\n"); + exit(1); + 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 buffer + */ +int skip_packed_sample_data(buffer *d, unsigned char *sig, unsigned int siglen) { + unsigned int pos = 0; //current position in signature + unsigned int skipped = 0; //skipped byte counter + while(pos < siglen) { + unsigned int type = unpack32(sig,pos); + pos+=4; + skipped += skip_type(type, d, sig, siglen, &pos); + } + printf("skipped %d bytes\n", skipped); + return TRUE; +} diff --git a/lib/c/experimental/throttlenet/throttlenet.lc b/lib/c/experimental/throttlenet/throttlenet.lc index 5c1a09e14e67f177915a5850144d03a3e38383f3..e747d074120dabb29379b8e5d734a939df8d2923 100644 --- a/lib/c/experimental/throttlenet/throttlenet.lc +++ b/lib/c/experimental/throttlenet/throttlenet.lc @@ -1,5 +1,5 @@ -typedef short number_t; // placeholder for protocol buffers like encoding -typedef byte[6] eth_addr; +typedef long number_t; // placeholder for protocol buffers like encoding +typedef byte eth_addr[6]; // *** Service registration, lookup, and channel allocation @@ -12,25 +12,25 @@ typedef struct { typedef struct { string key; - byte value[[_]]; + byte value[_]; } property_t; // used for type info, grounding, etc. typedef struct { string name; - property_t properties[[_]]; - param_t params[[_]]; -} command_t; + property_t properties[_]; +} param_t; typedef struct { string name; - property_t properties[[_]]; -} param_t; + property_t properties[_]; + param_t params[_]; +} command_t; typedef struct { - servicID svcID; + serviceID svcID; string name; - command_t commands[[_]]; - byte data_description[[_]]; + command_t commands[_]; + byte data_description[_]; } serviceDescription; // d:o PalCom typedef struct { @@ -48,38 +48,28 @@ sample struct { sample boolean ack; sample struct { + short dummy; } services_query; sample struct { - service_instance svcs[[_]] + service_instance svcs[_]; } services_list; sample struct { service_instance svc; number_t bytes_per_period; - float periodtime; // in seconds // or number_t microseconds? + number_t period_time; //microseconds // importance? } service_allocate_channel; // client [_]> GlobeThrottle to request connection sample struct { - // requesting service instance? - number_t chnId; // the channel to send the connect message on -} service_channel_ACK; + 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 { - float max_utilization; + short max_utilization; // in percent // min period? } service_channel_NACK; - -// *** service to service connection negotiation - -typedef struct { - number_t sender_chnId; // The chnID at the sender's side that will receive the response, and subsequent traffic; -} connect_t; - - -sample connect_t connect_request; -sample connect_t connect_response; - -