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 2554 additions and 11 deletions
liblabcomm.a
liblabcomm.so
liblabcomm.so.1
liblabcomm2006.so.1
liblabcomm2006.so
liblabcomm2006.a
liblabcomm2014.so.1
liblabcomm2014.so
liblabcomm2014.a
## Macros
VERSION=2014
LIBVERSION=2014
include ../os_compat.mk
ALL_DEPS=../liblabcomm$(LIBVERSION).a ../liblabcomm$(LIBVERSION).so
# TODO: Support for Codesourcery ARM toolchain.
OBJS=labcomm$(VERSION).o \
labcomm$(VERSION)_memory.o \
labcomm$(VERSION)_error.o \
labcomm$(VERSION)_default_error_handler.o \
labcomm$(VERSION)_default_memory.o \
labcomm$(VERSION)_default_scheduler.o \
labcomm$(VERSION)_time.o \
labcomm$(VERSION)_scheduler.o \
labcomm$(VERSION)_encoder.o \
labcomm$(VERSION)_decoder.o \
labcomm$(VERSION)_dynamic_buffer_writer.o \
labcomm$(VERSION)_fd_reader.o \
labcomm$(VERSION)_type_signature.o \
labcomm$(VERSION)_fd_writer.o \
labcomm$(VERSION)_pthread_scheduler.o \
labcomm$(VERSION)_renaming.o \
labcomm$(VERSION)_renaming_registry.o \
labcomm$(VERSION)_renaming_encoder.o \
labcomm$(VERSION)_renaming_decoder.o
# Enable experimental objects by `make LABCOMM_EXPERIMENTAL=true`
ifeq ($(LABCOMM_EXPERIMENTAL),true)
OBJS += experimental/udp_hack.o experimental/ethaddr.o \
experimental/labcomm_thr_reader_writer.o \
experimental/ThrottleDrv/ethernet_drv.o \
experimental/ThrottleDrv/throttle_drv.o \
experimental/labcomm_udp_reader_writer.o
endif
# Enable experimental objects by `make LABCOMM_SIG_PARSER=true`
ifeq ($(LABCOMM_SIG_PARSER),true)
OBJS += experimental/labcomm2014_sig_parser.o
endif
LABCOMM_JAR=../../../compiler/labcomm$(LIBVERSION)_compiler.jar
LABCOMM=java -jar $(LABCOMM_JAR)
TESTS=test_labcomm_basic_type_encoding \
test_labcomm_generated_encoding \
test_signature_numbers \
test_labcomm \
test_labcomm_pthread_scheduler \
test_labcomm_copy \
test_labcomm_renaming_registry \
test_labcomm_renaming_encoder \
test_labcomm_renaming_decoder
#FIXME: test_labcomm_errors
TEST_DIR=test
## Targets
.PHONY: all
all: $(ALL_DEPS)
.PHONY: test
test: all $(TESTS:%=run-test-%)
.PHONY: clean
clean:
$(RM) *.o
$(RM) experimental/*.o
$(RM) experimental/ThrottleDrv/*.o
$(RM) test/*.o
$(RM) test/*.gch
$(RM) test/test_labcomm_errors
$(RM) test/testdata/gen/*.[cho]
$(RM) test/gen/*.[cho]
$(RM) -rf test/gen
.PHONY: distclean
distclean: clean
$(RM) ../liblabcomm$(LIBVERSION).so.1
$(RM) ../liblabcomm$(LIBVERSION).a
# rules invoked by 'all'
../liblabcomm$(LIBVERSION).so: ../liblabcomm$(LIBVERSION).so.1
if [ -h $@ ] ; then rm $@ ; fi
ln -s $(<:../%=%) $@
../liblabcomm$(LIBVERSION).so.1: $(OBJS:%.o=%.pic.o)
$(call MAKESHARED,$@,$(@:../%=%),$^)
../liblabcomm$(LIBVERSION).a: $(OBJS)
ar -r $@ $^
# Enable sig parser objects by `make labcomm2014_sig_PARSER=true`
ifeq ($(LABCOMM_SIG_PARSER),true)
experimental/test_sig_parser : experimental/labcomm2014_sig_parser.o experimental/test_sig_parser.c
endif
# compilation rules
%.pic.o: %.c
$(CC) -fPIC $(CFLAGS) -c -o $@ $<
%.o: %.c %.h
$(CC) $(CFLAGS) -c -o $@ $<
# rules invoked by 'test'
.PHONY: run-test-%
run-test-%: $(TEST_DIR)/gen/% | $(TEST_DIR)/gen
$(VALGRIND) $<
.PRECIOUS: $(TEST_DIR)/gen/%
$(TEST_DIR)/gen/%: $(TEST_DIR)/gen/%.o | $(TEST_DIR)/gen
$(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(TEST_DIR)/gen/%.o: $(TEST_DIR)/%.c | $(TEST_DIR)/gen
$(CC) $(CFLAGS_TEST) -o $@ -c $<
.PRECIOUS: $(TEST_DIR)/gen/%.c
.PRECIOUS: $(TEST_DIR)/gen/%.h
$(TEST_DIR)/gen/%.c $(TEST_DIR)/gen/%.h: $(TEST_DIR)/%.lc | $(TEST_DIR)/gen
$(LABCOMM) \
--c=$(TEST_DIR)/gen/$*.c \
--h=$(TEST_DIR)/gen/$*.h \
$<
$(LABCOMM_JAR):
@echo "======Building LabComm compiler======"
cd $(shell dirname $(LABCOMM_JAR)); ant jar
@echo "======End building LabComm compiler======"
$(TEST_DIR)/gen:
mkdir -p $@
# Extra compilation dependencies
labcomm$(VERSION).o: \
labcomm$(VERSION).c \
labcomm$(VERSION).h \
labcomm$(VERSION)_private.h
labcomm$(VERSION)_fd_reader.o: \
labcomm$(VERSION)_private.h
labcomm$(VERSION)_fd_writer.o: \
labcomm$(VERSION)_private.h
labcomm$(VERSION)_dynamic_buffer_writer.o: \
labcomm$(VERSION)_private.h
$(TEST_DIR)/gen/test_labcomm_basic_type_encoding.o: \
labcomm$(VERSION)_private.h
$(TEST_DIR)/gen/test_labcomm_generated_encoding.o: \
labcomm$(VERSION)_private.h \
$(TEST_DIR)/gen/generated_encoding.h
$(TEST_DIR)/gen/test_labcomm_generated_encoding: \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_signature_numbers.c: \
$(TEST_DIR)/gen/another_encoding.h \
$(TEST_DIR)/gen/generated_encoding.h
$(TEST_DIR)/gen/test_signature_numbers: \
$(TEST_DIR)/gen/another_encoding.o \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_labcomm: \
$(TEST_DIR)/gen/test_sample.o
$(TEST_DIR)/gen/test_labcomm_copy: \
$(TEST_DIR)/gen/generated_encoding.o \
$(TEST_DIR)/gen/test_sample.o \
$(TEST_DIR)/gen/more_types.o
$(TEST_DIR)/gen/test_labcomm_renaming_registry: \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_labcomm_renaming_encoder: \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_labcomm_renaming_decoder: \
$(TEST_DIR)/gen/generated_encoding.o
#define PC_MODE
#ifdef PC_MODE
#define DISPLAY_ERR(s) perror(s);
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
#else
#define DISPLAY_ERR(s) ;
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
//#include <linux/if_ether.h>
//#include <linux/if_packet.h>
//#include <linux/if_arp.h>
#include <net/if.h>
#include <netpacket/packet.h>
//#include <netinet/in.h>
#include "ethernet_drv.h"
#include "display.h"
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
/** LOCAL FUNCTIONS **/
/* local type for the ethernet interface */
struct eth_int_t
{
struct ether_addr mac_adr; /* MAC address */
int socket_id; /* socket file descriptor */
int index; /* index of the eth interface */
unsigned char validity;
};
/***
Open an Ethernet Raw packet connection
***/
struct eth_int_t* eth_open(const char* eth_int_name)
{
struct eth_int_t* tmp_eth = NULL; /* pointer to ethernet interface struct */
struct ifreq ifr; /* struct used by ioctl function */
/* TO-DO: check if a ethernet socket has already been created for eth_int_name interface */
/* Ethernet interface name pointer valid ? */
if (NULL == eth_int_name)
{
errno = EINVAL;
DISPLAY_ERR("Input parameter NULL");
}
else
{
/* allocate memory for the Ethernet Interface */
tmp_eth = (struct eth_int_t*)malloc(sizeof(struct eth_int_t));
if (NULL == tmp_eth)
{
DISPLAY_ERR("Error allocating memory!");
}
else
{
/* creates a Packet Socket, raw delivery, accept all protocol */
tmp_eth->socket_id = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (-1 == tmp_eth->socket_id) /* error occurred during socket creation ? */
{
free(tmp_eth); /* deallocate the memory */
tmp_eth = NULL;
DISPLAY_ERR("Error in creating socket");
}
else
{
/* retrieve the Ethernet card MAC address */
strcpy(ifr.ifr_name, eth_int_name);
if (ioctl(tmp_eth->socket_id, SIOCGIFHWADDR, &ifr) == -1) /* error during the retrieve of MAC address ? */
{
close(tmp_eth->socket_id); /* close the socket */
free(tmp_eth); /* deallocate the memory */
tmp_eth = NULL;
DISPLAY_ERR("ioctl error SIOCGIFHWADDR");
}
else
{
/* copy the MAC address into the eth interface struct */
memcpy(tmp_eth->mac_adr.ether_addr_octet, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
/*retrieve the Ethernet interface index*/
if (ioctl(tmp_eth->socket_id, SIOCGIFINDEX, &ifr) == -1)/* error during the retrieve of index */
{
close(tmp_eth->socket_id); /* close the socket */
free(tmp_eth); /* deallocate the memory */
tmp_eth = NULL;
DISPLAY_ERR("ioctl error SIOCGIFINDEX");
}
else
{
/* copy the interface index into the eth interface struct */
tmp_eth->index = ifr.ifr_ifindex;
printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
tmp_eth->mac_adr.ether_addr_octet[0],tmp_eth->mac_adr.ether_addr_octet[1],tmp_eth->mac_adr.ether_addr_octet[2],tmp_eth->mac_adr.ether_addr_octet[3],tmp_eth->mac_adr.ether_addr_octet[4],tmp_eth->mac_adr.ether_addr_octet[5]);
printf("Successfully got interface index for %s: %i\n",eth_int_name, tmp_eth->index);
}
}
}
}
}
return(tmp_eth);
}
/***
Close the Ethernet Raw packet connection
***/
int eth_close(struct eth_int_t* eth_int)
{
int ret = 0;
/* Ethernet interface pointer valid ? */
if (NULL == eth_int)
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter NULL");
}
else
{
if (-1 == close(eth_int->socket_id)) /* error during the closure of the socket ? */
{
ret = -1;
DISPLAY_ERR("Socket closure error");
}
else
{
free(eth_int); /* deallocate the memory */
eth_int = NULL;
}
}
return(ret);
}
/***
Returns the MAC address of the Ethernet Interface
***/
int eth_getMACadr(const struct eth_int_t* eth_int, struct ether_addr * mac_adr)
{
int ret = 0;
if ((NULL == eth_int) || (NULL == mac_adr)) /* Input parameters valid ? */
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) NULL");
}
else
{
/* TO-DO: introduce a validity flag to be check before accessing to eth_int (better a crc) */
memcpy(mac_adr, &eth_int->mac_adr, sizeof(mac_adr));
}
return(ret);
}
/***
send a complete Ethernet Raw Packet
***/
int eth_send(const struct eth_int_t* eth_int, const unsigned char* eth_frame, unsigned short length)
{
struct ethhdr *eth_header = NULL; /* Pointer to Ethernet frame header (Dest,Source,Type) */
struct sockaddr_ll socket_address;
int ret;
if ((NULL == eth_int) || (NULL == eth_frame))
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) Null!");
}
else
{
eth_header = (struct ethhdr*)eth_frame;
/*prepare sockaddr_ll (address structure for PACKET_SOCKET) */
socket_address.sll_family = AF_PACKET;
socket_address.sll_addr[0] = eth_header->h_dest[0];
socket_address.sll_addr[1] = eth_header->h_dest[1];
socket_address.sll_addr[2] = eth_header->h_dest[2];
socket_address.sll_addr[3] = eth_header->h_dest[3];
socket_address.sll_addr[4] = eth_header->h_dest[4];
socket_address.sll_addr[5] = eth_header->h_dest[5];
socket_address.sll_addr[6] = 0x00; /* not used */
socket_address.sll_addr[7] = 0x00; /* not used */
socket_address.sll_halen = ETH_ALEN; /* Length of the MAC address */
socket_address.sll_ifindex = eth_int->index; /* Ethernet Interface index */
// The rest should be zero for sending, and are set by the system for receiving.
socket_address.sll_hatype = 0;
socket_address.sll_protocol = 0;
socket_address.sll_pkttype = 0;
//socket_address.sll_protocol = htons(ETH_P_IP); /* Physical layer protocol */
//socket_address.sll_hatype = ARPHRD_ETHER; /* ARP hardware identifier: Ethernet */
//socket_address.sll_pkttype = PACKET_OTHERHOST; /* Packet type: Another host */
/*send the Ethernet frame */
ret = sendto(eth_int->socket_id, eth_frame, length, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
if (ret == -1) /* error during the trasmission of the Ethernet frame ? */
{
DISPLAY_ERR("sendto error!");
}
}
return(ret);
}
/***
receive a complete Ethernet Raw Packet
***/
int eth_receive (const struct eth_int_t* eth_int, unsigned char* eth_frame, unsigned short length)
{
int ret;
if ((NULL == eth_int) || (NULL == eth_frame))
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) Null!");
}
else
{
/*Wait for incoming packet...*/
ret = recvfrom(eth_int->socket_id, (void*)eth_frame, length, 0, NULL, NULL);
if (ret == -1) /* error during the reception of the Ethernet frame ? */
{
DISPLAY_ERR("recvfrom error!");
}
}
return(ret);
}
#ifndef _ETHERNET_DRV_H_
#define _ETHERNET_DRV_H_
#include <net/ethernet.h>
struct eth_int_t;
struct eth_int_t* eth_open(const char* eth_int_name);
int eth_close(struct eth_int_t* eth_int);
int eth_getMACadr(const struct eth_int_t* eth_int, struct ether_addr *mac_adr);
int eth_send(const struct eth_int_t* eth_int, const unsigned char* eth_frame, unsigned short length);
int eth_receive (const struct eth_int_t* eth_int, unsigned char* eth_frame, unsigned short length);
#endif
#include "throttle_drv.h"
#include "ethernet_drv.h"
#include <errno.h>
#include "display.h"
#include "stdlib.h"
#include <string.h>
#include <time.h>
// #include <arpa/inet.h>
#define THROTTLENET_PROTO 0x544e
#define THR_DST_ADR_POS 0
#define THR_SRC_ADR_POS (THR_DST_ADR_POS + sizeof(((thr_header_t*)0)->dst_adr)) //6
#define THR_ETH_TYP_POS (THR_SRC_ADR_POS + sizeof(((thr_header_t*)0)->src_adr)) //12
#define THR_CHN_ID_POS (THR_ETH_TYP_POS + sizeof(((thr_header_t*)0)->eth_type)) //14
#define THR_FRAG_NUM_POS (THR_CHN_ID_POS + sizeof(((thr_header_t*)0)->chn_id)) //15
#define THR_FRAG_TOT_NUM_POS (THR_FRAG_NUM_POS + sizeof(((thr_header_t*)0)->frag_num)) //17
#define THR_FRAG_LEN_POS (THR_FRAG_TOT_NUM_POS + sizeof(((thr_header_t*)0)->frag_num_tot)) //19
#define THR_PAYLOAD_POS (THR_FRAG_LEN_POS + sizeof(((thr_header_t*)0)->frag_len)) //21
#define THR_MSG_HEADER_LEN THR_PAYLOAD_POS
#define THR_MSG_DST_ADR(thr_msg) (struct ether_addr*)(&thr_msg[THR_DST_ADR_POS])
#define THR_MSG_SRC_ADR(thr_msg) (struct ether_addr*)(&thr_msg[THR_SRC_ADR_POS])
#define THR_MSG_ETH_TYP(thr_msg) *(unsigned short*)(&thr_msg[THR_ETH_TYP_POS])
#define THR_MSG_CHN_ID(thr_msg) *(unsigned char*)(&thr_msg[THR_CHN_ID_POS])
#define THR_MSG_FRAG_NUM(thr_msg) *(unsigned short*)(&thr_msg[THR_FRAG_NUM_POS])
#define THR_MSG_FRAG_TOT_NUM(thr_msg) *(unsigned short*)(&thr_msg[THR_FRAG_TOT_NUM_POS])
#define THR_MSG_FRAG_LEN(thr_msg) *(unsigned short*)(&thr_msg[THR_FRAG_LEN_POS])
#define THR_MSG_PAYLOAD(thr_msg) (unsigned char*)(&thr_msg[THR_PAYLOAD_POS])
/* local type for the Throttle Channel structure */
struct thr_chn_t
{
struct ether_addr dst_adr; /* destination MAC address */
unsigned char id; /* Channel id */
unsigned short frag_size; /* Fragment size */
unsigned short freq; /* Message transmission frequency */
thr_msg_handler_t funct; /* Callback function invoked at the reception */
unsigned short msg_length;
unsigned char* p_msg;
struct ether_addr last_sender_adr;/* src MAC address of last message */
};
/* Type for the Throttle message */
typedef struct
{
struct ether_addr dst_adr; /* destination MAC address */
struct ether_addr src_adr; /* source MAC address */
unsigned short eth_type; /* ethernet packet type */
unsigned char chn_id; /* channel identification */
unsigned short frag_num; /* fragment number */
unsigned short frag_num_tot; /* total fragment number */
unsigned short frag_len; /* fragment length */
}thr_header_t;
/* Local functions */
static int thr_msg_check(const unsigned char* thr_msg, unsigned short chn_id, unsigned short length);
static struct eth_int_t* eth_int = NULL;
/**
* @fn int thr_init(const char* eth_int_name)
*
* @brief Initializes the Throttle Net Driver, enabling the Ethernet Raw communication for the eth_int_name interface.
*
* @param [in] eth_int_name: ethernet interface name (e.g. "eth0","eth1")
*
* @retval int: 0 on success; -1 on error and errno is set appropriately
*
*******************************************************************************/
int thr_init(const char* eth_int_name)
{
int ret = 0;
if (NULL == eth_int_name)
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter NULL");
}
else
{
eth_int = eth_open(eth_int_name); /* open the Ethernet socket */
if (NULL == eth_int)
{
ret = -1;
}
}
return(ret);
}
/**
* @fn struct thr_chn_t* thr_open_chn(const char* dst_adr, unsigned char chn_id, unsigned char frag_size, unsigned short freq, const thr_msg_handler_t funct);
*
* @brief Open a logic channel
*
* @param [in] dst_adr: destination MAC address;
* @param [in] chn_id: identification of the channel;
* @param [in] frag_size: fragment size;
* @param [in] freq: frequency of trasmission for each fragment;
* @param [in] msg_handler: callback invoked when a message is completely received;
*
* @retval struct thr_chn_t*: pointer to the Channel structure. NULL on error and errno is set appropriately.
*
*******************************************************************************/
struct thr_chn_t* thr_open_chn(const struct ether_addr* dst_adr, unsigned char chn_id, unsigned char frag_size, unsigned short freq, const thr_msg_handler_t funct)
{
struct thr_chn_t* tmp_chn = NULL; /* pointer to Channel structure */
/* TO-DO: check if a similar channel has already been created */
/* Input parameters not valid ? */
if ((NULL == dst_adr) || (0 == frag_size))
{
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) NULL");
}
else
{
/* allocate memory for the Channel structure */
tmp_chn = (struct thr_chn_t*)malloc(sizeof(struct thr_chn_t));
if (NULL == tmp_chn)
{
DISPLAY_ERR("Error allocating memory!");
}
else
{
/* Update the Channel structure */
memcpy(&tmp_chn->dst_adr, dst_adr, sizeof(tmp_chn->dst_adr));
tmp_chn->id = chn_id;
tmp_chn->frag_size = frag_size;
tmp_chn->freq = freq;
tmp_chn->funct = funct;
}
#ifdef DEBUG
printf("thr_open_chn: callback = %x\n", tmp_chn->funct);
#endif
}
return(tmp_chn);
}
void thr_close_chn(struct thr_chn_t* c){
free(c);
}
/**
* @fn int thr_send(const struct thr_chn_t* thr_chn, const char* data, unsigned int length)
*
* @brief Sends a Throttle message. A channel must be opened first.
*
* @param [in] thr_chn: pointer to the Throttle channel descriptor;
* @param [in] data: data buffer to be sent;
* @param [in] length: length of the data buffer;
*
* @retval int: number of byte sent, on success. -1 on error and errno is set appropriately.
*
*******************************************************************************/
int thr_send(const struct thr_chn_t* thr_chn, const char* data, unsigned int length)
{
unsigned char* thr_msg;
unsigned char i;
int ret = 0;
/* Check the input parameters */
if ((NULL == thr_chn) || (NULL == data) || (0 == length))
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) NULL");
}
else
{
if (0 == thr_chn->frag_size)
{
ret = -1;
errno = ERANGE;
DISPLAY_ERR("Division by zero");
}
else
{
/* allocate memory for the Throttle Message */
thr_msg = (unsigned char*)malloc(THR_MSG_HEADER_LEN + thr_chn->frag_size);
if (NULL == thr_msg)
{
ret = -1;
DISPLAY_ERR("Error allocating memory!");
}
else
{
/* Compose the Ethernet Frame to be sent */
memcpy(THR_MSG_DST_ADR(thr_msg), &thr_chn->dst_adr, sizeof(thr_chn->dst_adr)); /* Destiantion MAC Address */
eth_getMACadr(eth_int, THR_MSG_SRC_ADR(thr_msg)); /* Source MAC Address */
THR_MSG_ETH_TYP(thr_msg) = htons(THROTTLENET_PROTO); /* Ethernet Packet Type */
THR_MSG_CHN_ID(thr_msg) = thr_chn->id; /* Channel identification */
THR_MSG_FRAG_TOT_NUM(thr_msg) = ((length - 1) / thr_chn->frag_size) + 1; /* Total number of fragment */
struct timespec thr_time;
thr_time.tv_sec = thr_chn->freq / 1000;
thr_time.tv_nsec = (thr_chn->freq % 1000) * 1000000;
/* Message is splitted into fragments and they are sent */
for (i = 1; i <= THR_MSG_FRAG_TOT_NUM(thr_msg); i++)
{
THR_MSG_FRAG_NUM(thr_msg) = i; /* fragment number */
/* update the fragment length */
if (length >= thr_chn->frag_size)
{
THR_MSG_FRAG_LEN(thr_msg) = thr_chn->frag_size;
length -= thr_chn->frag_size;
}
else
{
THR_MSG_FRAG_LEN(thr_msg) = length;
}
memcpy ((void*)THR_MSG_PAYLOAD(thr_msg), (void*)data, THR_MSG_FRAG_LEN(thr_msg)); /* update the payload */
ret = eth_send(eth_int, &thr_msg[0], (THR_MSG_HEADER_LEN + THR_MSG_FRAG_LEN(thr_msg))); /* send the message */
if (-1 == ret) /*Error during the Ethernet trasmission ? */
{
DISPLAY_ERR("Error during Throttle msg trasmission!");
break;
}
else
{
data += THR_MSG_FRAG_LEN(thr_msg);
nanosleep(&thr_time, NULL);
}
}
/*deallocate the memory */
free(thr_msg);
thr_msg = NULL;
}
}
}
return(ret);
}
int thr_receive(struct thr_chn_t* thr_chn, unsigned char* data, void* param)
{
unsigned char* thr_msg = NULL;
unsigned char* p_data = NULL;
unsigned short frag_index = 1;
short byte_rec = 0;
unsigned char msg_received = 0;
int ret;
if ((NULL == thr_chn) || (NULL == data) || (NULL == thr_chn->funct) || (NULL == param))
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) NULL");
}
else
{
/* allocate memory for the Throttle Message */
thr_msg = (unsigned char*)malloc(THR_MSG_HEADER_LEN + thr_chn->frag_size);
if (NULL == thr_msg)
{
ret = -1;
DISPLAY_ERR("Error allocating memory!");
}
else
{
p_data = data;
do
{
byte_rec = eth_receive(eth_int, thr_msg, (THR_MSG_HEADER_LEN + thr_chn->frag_size)); /* receive the Ethernet Raw packet */
if (-1 == byte_rec)
{
/* discard the message */
DISPLAY_ERR("Error during Throttle msg reception: Fragment discarded.");
}
else
{
/* check if the Ethernet Raw message is correct (Ethernet protocol, Channel ID, length) */
ret = thr_msg_check(thr_msg, thr_chn->id, byte_rec);
if (ret < 0)
{
//printf("Throttle msg mismatch: Fragment discarded.\n");
}
else
{
#ifdef DEBUG
printf("thr_receive: Message Index %d on %d. Actual Index %d\n", THR_MSG_FRAG_NUM(thr_msg), THR_MSG_FRAG_TOT_NUM(thr_msg), frag_index);
#endif
if (frag_index == THR_MSG_FRAG_NUM(thr_msg)) /* The fragment is the one expected ? */
{
/* Rebuild the original data linking the payloads of each fragment */
memcpy((void*)p_data, (void*)THR_MSG_PAYLOAD(thr_msg), THR_MSG_FRAG_LEN(thr_msg));
p_data += THR_MSG_FRAG_LEN(thr_msg); /* update the pointer to the buffer */
frag_index++; /* update the fragment index */
ret = p_data - data; /* update the number of received byte */
if (frag_index > THR_MSG_FRAG_TOT_NUM(thr_msg))
{
msg_received = 1;
}
}
else
{
printf("thr_receive: Fragment mismatch: Fragment discarded.\n");
frag_index = 1;
p_data = data;
}
}
}
}while (msg_received != 1);
thr_chn->p_msg = (unsigned char*)malloc(ret);
if (NULL == thr_chn->p_msg)
{
ret = -1;
DISPLAY_ERR("Error allocating memory!");
}
else
{
#ifdef DEBUG
printf("thr_receive: Number of byte receive %d\n",ret);
#endif
thr_chn->msg_length = ret;
memcpy(thr_chn->p_msg, data, ret); /* copy the msg into the thr structure */
memcpy(&thr_chn->last_sender_adr, THR_MSG_SRC_ADR(thr_msg), 6); /* ... and the address of the sender */
#ifdef DEBUG
printf("thr_receive: calling %x\n", thr_chn->funct);
#endif
(thr_chn->funct)(param);
free(thr_chn->p_msg);
thr_chn->p_msg = NULL;
}
/* deallocate memory for the Throttle Message */
free(thr_msg);
thr_msg = NULL;
p_data = NULL;
}
}
return(ret);
}
static int thr_msg_check(const unsigned char* thr_msg, unsigned short chn_id, unsigned short length)
{
int ret = 0;
if (length > THR_MSG_HEADER_LEN) /* Ethernet Raw Packet contains a valid Payload ? */
{
if (THROTTLENET_PROTO == ntohs(THR_MSG_ETH_TYP(thr_msg))) /* Is Ethernet Type THROTTLENET Protocol ? */
{
if (THR_MSG_CHN_ID(thr_msg) == chn_id) /* Is Channel identification correct ? */
{
/* throttle message is correct */
}
else
{
ret = -1;
}
}
else
{
/* discard the message */
ret = -2;
}
}
else
{
/* discard the message */
ret = -3;
}
return(ret);
}
int thr_read(struct thr_chn_t* thr_chn, unsigned char* data, int length)
{
int ret = 0;
if ((NULL == thr_chn) || (NULL == data))
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) NULL");
}
else
{
if (length > thr_chn->msg_length)
{
length = thr_chn->msg_length;
#ifdef DEBUG
printf("thr_read: truncating length to %d\n", length);
#endif
}
#ifdef DEBUG
printf("thr_read: calling memcpy(%x, %x, %d\n", data, thr_chn->p_msg, length);
#endif
memcpy(data, thr_chn->p_msg, length); /* copy the msg into the thr structure */
ret = length;
thr_chn->msg_length = 0;
}
return(ret);
}
struct ether_addr* get_sender_addr(struct thr_chn_t* ch) {
return &ch->last_sender_adr;
}
unsigned char get_channel(struct thr_chn_t* ch) {
return ch->id;
}
#ifndef _THROTTLE_DRV_H_
#define _THROTTLE_DRV_H_
//#define ETH_ADR_SIZE 6
#include <net/ethernet.h>
/* typedef of the callback used to manage the received Ethernet Frame (the User Data)*/
typedef int (*thr_msg_handler_t)(void* data);
struct thr_chn_t;
int thr_init(const char* eth_int);
struct thr_chn_t* thr_open_chn(const struct ether_addr* dst_adr, unsigned char chn_id, unsigned char frag_size, unsigned short freq, thr_msg_handler_t funct);
void thr_close_chn(struct thr_chn_t* c);
int thr_receive (struct thr_chn_t* thr_chn, unsigned char* data, void* param);
int thr_send(const struct thr_chn_t* thr_chn, const char* data, unsigned int length);
int thr_read(struct thr_chn_t* thr_chn, unsigned char* data, int length);
struct ether_addr * get_sender_addr(struct thr_chn_t* ch);
unsigned char get_channel(struct thr_chn_t* ch);
#endif
#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_fd_reader(
int labcomm_udp_reader(
labcomm_reader_t *r,
labcomm_reader_action_t action)
{
int result = -EINVAL;
int *fd = r->context;
server_context_t *ctx = r->context;
switch (action) {
case labcomm_reader_alloc: {
......@@ -29,10 +30,9 @@ int labcomm_fd_reader(
if (r->pos < r->count) {
result = r->count - r->pos;
} else {
int err;
int err;
r->pos = 0;
err = read(*fd, r->data, r->data_size);
err=udp_recv(ctx, r->data, r->data_size);
if (err <= 0) {
r->count = 0;
result = -1;
......@@ -57,12 +57,13 @@ int labcomm_fd_reader(
return result;
}
int labcomm_fd_writer(
int labcomm_udp_writer(
labcomm_writer_t *w,
labcomm_writer_action_t action)
{
int result = 0;
int *fd = w->context;
//int *fd = w->context;
server_context_t *ctx = w->context;
switch (action) {
case labcomm_writer_alloc: {
......@@ -89,11 +90,11 @@ int labcomm_fd_writer(
w->pos = 0;
} break;
case labcomm_writer_continue: {
result = write(*fd, w->data, w->pos);
result = udp_send(ctx, w->data, w->pos);
w->pos = 0;
} break;
case labcomm_writer_end: {
result = write(*fd, w->data, w->pos);
result = udp_send(ctx, w->data, w->pos);
w->pos = 0;
} break;
case labcomm_writer_available: {
......
#include "labcomm.h"
extern int labcomm_fd_reader(
extern int labcomm_udp_reader(
labcomm_reader_t *r,
labcomm_reader_action_t action);
extern int labcomm_fd_writer(
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*);