diff --git a/sys/Makefile b/sys/Makefile index 85e4e9e1e..d350ade17 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -88,6 +88,12 @@ endif ifneq (,$(findstring semaphore,$(USEMODULE))) DIRS += semaphore endif +ifneq (,$(findstring ccn_lite,$(USEMODULE))) + DIRS += net/ccn_lite +endif +ifneq (,$(findstring ccn_lite_client,$(USEMODULE))) + DIRS += net/ccn_lite/util +endif all: $(BINDIR)$(MODULE).a @for i in $(DIRS) ; do "$(MAKE)" -C $$i ; done ; diff --git a/sys/net/ccn_lite/Makefile b/sys/net/ccn_lite/Makefile new file mode 100644 index 000000000..a4516ae26 --- /dev/null +++ b/sys/net/ccn_lite/Makefile @@ -0,0 +1,4 @@ +MODULE := ccn_lite +INCLUDES = -I$(RIOTBASE) -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/sys/net -I$(RIOTBASE)/cpu/arm_common/include/ -I$(RIOTBASE)/drivers/cc110x_ng/include/ -I$(RIOTBASE)/sys/net/ccn_lite/include/ + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/ccn_lite/README.md b/sys/net/ccn_lite/README.md new file mode 100644 index 000000000..38284ae61 --- /dev/null +++ b/sys/net/ccn_lite/README.md @@ -0,0 +1,50 @@ +CCN lite port of RIOT +===================== + +RIOT's support for CCN messages is based on the work of [Christian Tschudin from University of Basel](http://cn.cs.unibas.ch/people/cft/) [(CCN-lite code available here)](https://github.com/cn-uofbasel/ccn-lite). + +The network stack can handle multiple faces based on the transceiver or from the local device via RIOT's message system. +To communicate with the stack, one can send messages via RIOTs message system to the CCN-lite relay thread or via a physical network transceiver. + +All incoming messages get processed in the main io loop which you can find [here](ccn-lite-relay.c#L283). + +The public api on the ccn network stack one can find in ccn_lite/include (see in file "ccnl-riot.h"). +Client related functions are located in ccn_lite/include/util (see in file "ccn-riot-client.h"). + +To deal with the ccn lite network stack one only needs these two api declarations. + + +Running Test Application +------------------------ + +A test applications are provided in the projects repository. + +### ccn-lite-client + +It uses RIOTs shell for user interaction. +The network stack is started on demand in it's own thread. You have to enter "ccn" in the shell. + +A bunch of ccn user land code is provide to construct interests and content objects. +To request a file e.g. */riot/text*, the user land code request the first segment (chunk): */riot/text/0* and stalls until its received. +If this chunk has the default chunk size the next chunk is requested, ... +If a smaller chunk arrives the user land code prints out the complete file which was requested. + +You can test this functionality by typing "interest /riot/test" in the shell. *See HOWTO.md in the projects directory*. + +### ccn-lite-relay + +It's a stand alone ccn relay without interactive user control +The network stack is started on boot up and is configured set the device address and to serve requests for "/riot/test". +The ccn stack is ready to server requests coming over the transceiver. + +Hardware support +---------------- + +The CCN-lite stack is currently tested and proved to run on the native port of RIOT and the MSBA2 embedded hardware. +On the MSBA2 platform (32 Bit) CCN-lite only needs a stack of 800 bytes. +It uses the heap for the CS, FIB and PIT. + +More +---- + +This README is still under construction. diff --git a/sys/net/ccn_lite/ccn-lite-relay.c b/sys/net/ccn_lite/ccn-lite-relay.c new file mode 100644 index 000000000..eef9f2825 --- /dev/null +++ b/sys/net/ccn_lite/ccn-lite-relay.c @@ -0,0 +1,397 @@ +/* + * @f ccn-lite-relay.c + * @b CCN relay + * + * Copyright (C) 2011-13, Christian Tschudin, University of Basel + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2011-11-22 created + */ + +#include + +#define CCNL_RIOT + +#define USE_CCNxDIGEST +#define USE_RIOT_MSG +#define USE_RIOT_TRANS +#define USE_APPSERVER +#define USE_MGMT +#define RIOT_CCNL_POPULATE (1) + +#include "ccnl-includes.h" + +#include "ccnx.h" +#include "ccnl.h" +#include "ccnl-core.h" + +#include "ccnl-ext.h" +#include "ccnl-platform.h" + +#include "ccnl-core.h" + +#include "ccnl-pdu.h" + +#include "msg.h" +#include "thread.h" +#include "transceiver.h" + +#include "ccnl-riot-compat.h" +#include "test_data/text.txt.ccnb.h" + +/** The size of the message queue between router daemon and transceiver AND clients */ +#define RELAY_MSG_BUFFER_SIZE (64) + +/** message buffer */ +msg_t msg_buffer_relay[RELAY_MSG_BUFFER_SIZE]; + +uint8_t packet_out[PAYLOAD_SIZE]; + +// ---------------------------------------------------------------------- + +struct ccnl_relay_s theRelay; + +struct timeval * +ccnl_run_events(void) +{ + static struct timeval now; + long usec; + + rtc_time(&now); + + while (eventqueue) { + struct ccnl_timer_s *t = eventqueue; + usec = timevaldelta(&(t->timeout), &now); + + if (usec >= 0) { + now.tv_sec = usec / 1000000; + now.tv_usec = usec % 1000000; + return &now; + } + + if (t->fct) { + (t->fct)(t->node, t->intarg); + } + else if (t->fct2) { + (t->fct2)(t->aux1, t->aux2); + } + + eventqueue = t->next; + ccnl_free(t); + } + + return NULL; +} + +// ---------------------------------------------------------------------- + +int ccnl_open_riotmsgdev(void) +{ + /* + * nothing to do here, msg system just needs a buffer, and this is + * generated staticly + */ + return RIOT_MSG_DEV; /* sock id */ +} + +int ccnl_open_riottransdev(void) +{ + + transceiver_init(transceiver_ids); + transceiver_start(); + + /** register for transceiver events */ + transceiver_register(transceiver_ids, thread_getpid()); + + return RIOT_TRANS_DEV; /* sock id */ +} + +void ccnl_ll_TX(struct ccnl_relay_s *ccnl, struct ccnl_if_s *ifc, + sockunion *dest, struct ccnl_buf_s *buf) +{ + (void) ccnl; /* unused */ + + memcpy(&packet_out, &buf->data, buf->datalen); + ifc->sendfunc(packet_out, (uint16_t) buf->datalen, (uint16_t) dest->id); +} + +// ---------------------------------------------------------------------- + +void ccnl_ageing(void *relay, void *aux) +{ + ccnl_do_ageing(relay, aux); + ccnl_set_timer(1000000, ccnl_ageing, relay, 0); +} + +// ---------------------------------------------------------------------- + +void ccnl_relay_config(struct ccnl_relay_s *relay, int max_cache_entries) +{ + struct ccnl_if_s *i; + + DEBUGMSG(99, "ccnl_relay_config\n"); + + relay->max_cache_entries = max_cache_entries; + + if (RIOT_MSG_IDX != relay->ifcount) { + DEBUGMSG(1, "sorry, idx did not match: riot msg device\n"); + } + + i = &relay->ifs[relay->ifcount]; + i->sock = ccnl_open_riotmsgdev(); + i->sendfunc = &riot_send_msg; + i->mtu = 4000; + i->reflect = 0; + i->fwdalli = 0; + + if (i->sock >= 0) { + relay->ifcount++; + + if (relay->defaultInterfaceScheduler) { + i->sched = relay->defaultInterfaceScheduler(relay, + ccnl_interface_CTS); + } + } + else { + DEBUGMSG(1, "sorry, could not open riot msg device\n"); + } + + if (RIOT_TRANS_IDX != relay->ifcount) { + DEBUGMSG(1, "sorry, idx did not match: riot trans device\n"); + } + + i = &relay->ifs[relay->ifcount]; + i->sock = ccnl_open_riottransdev(); + i->sendfunc = &riot_send_transceiver; +#ifdef USE_FRAG + i->mtu = 120; +#else + i->mtu = 1500; +#endif + i->reflect = 0; + i->fwdalli = 0; + + if (i->sock >= 0) { + relay->ifcount++; + + if (relay->defaultInterfaceScheduler) { + i->sched = relay->defaultInterfaceScheduler(relay, + ccnl_interface_CTS); + } + } + else { + DEBUGMSG(1, "sorry, could not open riot trans device\n"); + } +} + +#if RIOT_CCNL_POPULATE + +void ccnl_populate_cache(struct ccnl_relay_s *ccnl, unsigned char *buf, int datalen) +{ + if (buf[0] == 0x04 && buf[1] == 0x82) { + struct ccnl_prefix_s *prefix = 0; + struct ccnl_content_s *c = 0; + struct ccnl_buf_s *nonce = 0, *ppkd = 0, *pkt = 0; + unsigned char *content, *data = buf + 2; + int contlen; + + datalen -= 2; + + pkt = ccnl_extract_prefix_nonce_ppkd(&data, &datalen, 0, 0, + 0, 0, &prefix, &nonce, &ppkd, &content, &contlen); + + if (!pkt) { + DEBUGMSG(6, " parsing error\n"); + goto Done; + } + + if (!prefix) { + DEBUGMSG(6, " no prefix error\n"); + goto Done; + } + + printf("populating: %s\n", ccnl_prefix_to_path(prefix)); + + c = ccnl_content_new(ccnl, &pkt, &prefix, &ppkd, content, + contlen); + + if (!c) { + goto Done; + } + + ccnl_content_add2cache(ccnl, c); + c->flags |= CCNL_CONTENT_FLAGS_STATIC; + Done: + free_prefix(prefix); + ccnl_free(pkt); + ccnl_free(nonce); + ccnl_free(ppkd); + } + else { + DEBUGMSG(6, " not a content object\n"); + } +} + +void handle_populate_cache() +{ + DEBUGMSG(1, "ccnl_populate_cache with: text_txt_ccnb\n"); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_0, (int) text_txt_ccnb_0_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_1, (int) text_txt_ccnb_1_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_2, (int) text_txt_ccnb_2_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_3, (int) text_txt_ccnb_3_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_4, (int) text_txt_ccnb_4_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_5, (int) text_txt_ccnb_5_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_6, (int) text_txt_ccnb_6_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_7, (int) text_txt_ccnb_7_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_8, (int) text_txt_ccnb_8_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_9, (int) text_txt_ccnb_9_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_10, (int) text_txt_ccnb_10_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_11, (int) text_txt_ccnb_11_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_12, (int) text_txt_ccnb_12_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_13, (int) text_txt_ccnb_13_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_14, (int) text_txt_ccnb_14_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_15, (int) text_txt_ccnb_15_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_16, (int) text_txt_ccnb_16_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_17, (int) text_txt_ccnb_17_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_18, (int) text_txt_ccnb_18_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_19, (int) text_txt_ccnb_19_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_20, (int) text_txt_ccnb_20_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_21, (int) text_txt_ccnb_21_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_22, (int) text_txt_ccnb_22_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_23, (int) text_txt_ccnb_23_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_24, (int) text_txt_ccnb_24_len); + ccnl_populate_cache(&theRelay, (unsigned char *) text_txt_ccnb_25, (int) text_txt_ccnb_25_len); +} + +#endif + +// ---------------------------------------------------------------------- + +int ccnl_io_loop(struct ccnl_relay_s *ccnl) +{ + int i, maxfd = -1; + + if (ccnl->ifcount == 0) { + DEBUGMSG(1, "no socket to work with, not good, quitting\n"); + return -1; + } + + for (i = 0; i < ccnl->ifcount; i++) + if (ccnl->ifs[i].sock > maxfd) { + maxfd = ccnl->ifs[i].sock; + } + + maxfd++; + + DEBUGMSG(1, "starting main event and IO loop\n"); + + if (msg_init_queue(msg_buffer_relay, RELAY_MSG_BUFFER_SIZE) != 0) { + DEBUGMSG(1, "msg init queue failed...abording\n"); + return -1; + } + + msg_t in; + radio_packet_t *p; + riot_ccnl_msg_t *m; + + while (!ccnl->halt_flag) { + // struct timeval *timeout = ccnl_run_events(); + DEBUGMSG(1, "waiting for incomming msg\n"); + msg_receive(&in); + + switch (in.type) { + case PKT_PENDING: + p = (radio_packet_t *) in.content.ptr; + DEBUGMSG(1, "%s Packet waiting\n", riot_ccnl_event_to_string(in.type)); + DEBUGMSG(1, "\tLength:\t%u\n", p->length); + DEBUGMSG(1, "\tSrc:\t%u\n", p->src); + DEBUGMSG(1, "\tDst:\t%u\n", p->dst); + + // p->src must be > 0 + if (!p->src) { + p->src = RIOT_BROADCAST; + } + + ccnl_core_RX(ccnl, RIOT_TRANS_IDX, (unsigned char *) p->data, (int) p->length, p->src); + p->processing--; + break; + + case (CCNL_RIOT_MSG): + m = (riot_ccnl_msg_t *) in.content.ptr; + DEBUGMSG(1, "%s Packet waiting\n", riot_ccnl_event_to_string(in.type)); + DEBUGMSG(1, "\tLength:\t%u\n", m->size); + DEBUGMSG(1, "\tSrc:\t%u\n", in.sender_pid); + + ccnl_core_RX(ccnl, RIOT_MSG_IDX, (unsigned char *) m->payload, m->size, + in.sender_pid); + break; + + case (CCNL_RIOT_HALT): + DEBUGMSG(1, "%s Packet waiting\n", riot_ccnl_event_to_string(in.type)); + DEBUGMSG(1, "\tSrc:\t%u\n", in.sender_pid); + DEBUGMSG(1, "\tNumb:\t%" PRIu32 "\n", in.content.value); + + ccnl->halt_flag = 1; + break; +#if RIOT_CCNL_POPULATE + case (CCNL_RIOT_POPULATE): + DEBUGMSG(1, "%s Packet waiting\n", riot_ccnl_event_to_string(in.type)); + DEBUGMSG(1, "\tSrc:\t%u\n", in.sender_pid); + DEBUGMSG(1, "\tNumb:\t%" PRIu32 "\n", in.content.value); + + handle_populate_cache(); + break; +#endif + default: + DEBUGMSG(1, "%s Packet waiting\n", riot_ccnl_event_to_string(in.type)); + DEBUGMSG(1, "\tSrc:\t%u\n", in.sender_pid); + DEBUGMSG(1, "\tdropping it...\n"); + break; + } + } + + return 0; +} + +/** + * @brief initializing routing system + * @param pointer to count transceiver pids + * + */ +void ccnl_riot_relay_start(void) +{ + int max_cache_entries = 20; + + struct timeval now; + theRelay.startup_time = rtc_time(&now); + + DEBUGMSG(1, "This is ccn-lite-relay, starting at %lu:%lu\n", now.tv_sec, now.tv_usec); + DEBUGMSG(1, " compile time: %s %s\n", __DATE__, __TIME__); + DEBUGMSG(1, " compile options: %s\n", compile_string()); + + ccnl_relay_config(&theRelay, max_cache_entries); + + ccnl_io_loop(&theRelay); + DEBUGMSG(1, "ioloop stopped\n"); + + while (eventqueue) { + ccnl_rem_timer(eventqueue); + } + + ccnl_core_cleanup(&theRelay); +} + +// eof diff --git a/sys/net/ccn_lite/ccnl-core.c b/sys/net/ccn_lite/ccnl-core.c new file mode 100644 index 000000000..34f1cf942 --- /dev/null +++ b/sys/net/ccn_lite/ccnl-core.c @@ -0,0 +1,1306 @@ +/* + * @f ccnl-core.c + * @b CCN lite, core CCNx protocol logic + * + * Copyright (C) 2011-13, Christian Tschudin, University of Basel + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2011-04-09 created + */ + +#define CCNL_VERSION "2013-07-27" + +#include +#include + +#include "ccnl.h" +#include "ccnl-core.h" +#include "ccnl-pdu.h" +#include "ccnx.h" +#include "ccnl-ext.h" +#include "ccnl-platform.h" + +#include "ccnl-includes.h" + +#include "ccnl-riot-compat.h" + +#define USE_RIOT_MSG + +static struct ccnl_interest_s *ccnl_interest_remove(struct ccnl_relay_s *ccnl, + struct ccnl_interest_s *i); + +void ccnl_ll_TX(struct ccnl_relay_s *ccnl, struct ccnl_if_s *ifc, + sockunion *dest, struct ccnl_buf_s *buf); + +void free_2ptr_list(void *a, void *b) +{ + ccnl_free(a); + ccnl_free(b); +} +void free_3ptr_list(void *a, void *b, void *c) +{ + ccnl_free(a); + ccnl_free(b); + ccnl_free(c); +} +void free_4ptr_list(void *a, void *b, void *c, void *d) +{ + ccnl_free(a); + ccnl_free(b); + ccnl_free(c); + ccnl_free(d); +} + +void free_prefix(struct ccnl_prefix_s *p) +{ + if (p) { + free_4ptr_list(p->path, p->comp, p->complen, p); + } +} + +void free_content(struct ccnl_content_s *c) +{ + free_prefix(c->name); + free_2ptr_list(c->pkt, c); +} + +// ---------------------------------------------------------------------- +// datastructure support functions + +struct ccnl_buf_s * +ccnl_buf_new(void *data, int len) +{ + struct ccnl_buf_s *b = (struct ccnl_buf_s *) ccnl_malloc(sizeof(*b) + len); + + if (!b) { + return NULL; + } + + b->next = NULL; + b->datalen = len; + + if (data) { + memcpy(b->data, data, len); + } + + return b; +} + +struct ccnl_buf_s *buf_dup(struct ccnl_buf_s *B) +{ + return (B) ? ccnl_buf_new(B->data, B->datalen) : NULL; +} + +int buf_equal(struct ccnl_buf_s *X, struct ccnl_buf_s *Y) +{ + return ((X) && (Y) && (X->datalen == Y->datalen) && !memcmp(X->data, Y->data, X->datalen)); +} + +int ccnl_prefix_cmp(struct ccnl_prefix_s *name, unsigned char *md, + struct ccnl_prefix_s *p, int mode) +/* returns -1 if no match at all (all modes) or exact match failed + returns 0 if full match (CMP_EXACT) + returns n>0 for matched components (CMP_MATCH, CMP_LONGEST) */ +{ + int i, clen, nlen = name->compcnt + (md ? 1 : 0), rc = -1; + unsigned char *comp; + + if (mode == CMP_EXACT && nlen != p->compcnt) { + goto done; + } + + for (i = 0; i < nlen && i < p->compcnt; i++) { + comp = i < name->compcnt ? name->comp[i] : md; + clen = i < name->compcnt ? name->complen[i] : 32; // SHA256_DIGEST_LEN + + if (clen != p->complen[i] || memcmp(comp, p->comp[i], p->complen[i])) { + rc = mode == CMP_EXACT ? -1 : i; + goto done; + } + } + + rc = (mode == CMP_EXACT) ? 0 : i; +done: + DEBUGMSG(49, + "ccnl_prefix_cmp (mode=%d, nlen=%d, plen=%d, %d), name=%s: %d (%p)\n", + mode, nlen, p->compcnt, name->compcnt, ccnl_prefix_to_path(name), + rc, md); + return rc; +} + +// ---------------------------------------------------------------------- +// ccnb parsing support + +static int hunt_for_end(unsigned char **buf, int *len, unsigned char **valptr, + int *vallen) +{ + int typ, num; + + while (dehead(buf, len, &num, &typ) == 0) { + if (num == 0 && typ == 0) { + return 0; + } + + if (consume(typ, num, buf, len, valptr, vallen) < 0) { + return -1; + } + } + + return -1; +} + +int consume(int typ, int num, unsigned char **buf, int *len, + unsigned char **valptr, int *vallen) +{ + if (typ == CCN_TT_BLOB || typ == CCN_TT_UDATA) { + if (valptr) { + *valptr = *buf; + } + + if (vallen) { + *vallen = num; + } + + *buf += num, *len -= num; + return 0; + } + + if (typ == CCN_TT_DTAG || typ == CCN_TT_DATTR) { + return hunt_for_end(buf, len, valptr, vallen); + } + + // case CCN_TT_TAG, CCN_TT_ATTR: + // case DTAG, DATTR: + return -1; +} + +static int data2uint(unsigned char *cp, int len) +{ + int i, val; + + for (i = 0, val = 0; i < len; i++) + if (isdigit(cp[i])) { + val = 10 * val + cp[i] - '0'; + } + else { + return -1; + } + + return val; +} + +struct ccnl_buf_s * +ccnl_extract_prefix_nonce_ppkd(unsigned char **data, int *datalen, int *scope, + int *aok, int *min, int *max, struct ccnl_prefix_s **prefix, + struct ccnl_buf_s **nonce, struct ccnl_buf_s **ppkd, + unsigned char **content, int *contlen) +{ + unsigned char *start = *data - 2, *cp; + int num, typ, len; + struct ccnl_prefix_s *p; + struct ccnl_buf_s *buf, *n = 0, *pub = 0; + DEBUGMSG(99, "ccnl_extract_prefix\n"); + + p = (struct ccnl_prefix_s *) ccnl_calloc(1, sizeof(struct ccnl_prefix_s)); + + if (!p) { + puts("can't get more memory from malloc, dropping ccn msg..."); + return NULL; + } + + p->comp = (unsigned char **) ccnl_malloc( + CCNL_MAX_NAME_COMP * sizeof(unsigned char **)); + p->complen = (int *) ccnl_malloc(CCNL_MAX_NAME_COMP * sizeof(int)); + + if (!p->comp || !p->complen) { + puts("can't get more memory from malloc, dropping ccn msg..."); + goto Bail; + } + + while (dehead(data, datalen, &num, &typ) == 0) { + if (num == 0 && typ == 0) { + break; // end + } + + if (typ == CCN_TT_DTAG) { + if (num == CCN_DTAG_NAME) { + for (;;) { + if (dehead(data, datalen, &num, &typ) != 0) { + goto Bail; + } + + if (num == 0 && typ == 0) { + break; + } + + if (typ == CCN_TT_DTAG && num == CCN_DTAG_COMPONENT + && p->compcnt < CCNL_MAX_NAME_COMP) { + if (hunt_for_end(data, datalen, p->comp + p->compcnt, + p->complen + p->compcnt) < 0) { + goto Bail; + } + + p->compcnt++; + } + else { + if (consume(typ, num, data, datalen, 0, 0) < 0) { + goto Bail; + } + } + } + + continue; + } + + if (num == CCN_DTAG_SCOPE || num == CCN_DTAG_NONCE + || num == CCN_DTAG_MINSUFFCOMP + || num == CCN_DTAG_MAXSUFFCOMP + || num == CCN_DTAG_PUBPUBKDIGEST) { + if (hunt_for_end(data, datalen, &cp, &len) < 0) { + goto Bail; + } + + if (num == CCN_DTAG_SCOPE && len == 1 && scope) { + *scope = isdigit(*cp) && (*cp < '3') ? *cp - '0' : -1; + } + + if (num == CCN_DTAG_ANSWERORIGKIND && aok) { + *aok = data2uint(cp, len); + } + + if (num == CCN_DTAG_MINSUFFCOMP && min) { + *min = data2uint(cp, len); + } + + if (num == CCN_DTAG_MAXSUFFCOMP && max) { + *max = data2uint(cp, len); + } + + if (num == CCN_DTAG_NONCE && !n) { + n = ccnl_buf_new(cp, len); + } + + if (num == CCN_DTAG_PUBPUBKDIGEST && !pub) { + pub = ccnl_buf_new(cp, len); + } + + if (num == CCN_DTAG_EXCLUDE) { + DEBUGMSG(49, "warning: 'exclude' field ignored\n"); + } + else { + continue; + } + } + + if (num == CCN_DTAG_CONTENT || num == CCN_DTAG_CONTENTOBJ) { + if (consume(typ, num, data, datalen, content, contlen) < 0) { + goto Bail; + } + + continue; + } + } + + if (consume(typ, num, data, datalen, 0, 0) < 0) { + goto Bail; + } + } + + if (prefix) { + p->comp[p->compcnt] = NULL; + *prefix = p; + } + else { + free_prefix(p); + } + + if (nonce) { + *nonce = n; + } + else { + ccnl_free(n); + } + + if (ppkd) { + *ppkd = pub; + } + else { + ccnl_free(pub); + } + + buf = ccnl_buf_new(start, *data - start); + + if (!buf) { + puts("can't get more memory from malloc, dropping ccn msg..."); + } + + // carefully rebase ptrs to new buf because of 64bit pointers: + if (content) { + *content = buf->data + (*content - start); + } + + for (num = 0; num < p->compcnt; num++) { + p->comp[num] = buf->data + (p->comp[num] - start); + } + + return buf; +Bail: + free_prefix(p); + free_2ptr_list(n, pub); + return NULL; +} + +// ---------------------------------------------------------------------- +// addresses, interfaces and faces + +static void ccnl_face_CTS(struct ccnl_relay_s *ccnl, struct ccnl_face_s *f); + +int ccnl_addr_cmp(sockunion *s1, sockunion *s2) +{ + return (s1->id == s2->id); +} + +struct ccnl_face_s * +ccnl_get_face_or_create(struct ccnl_relay_s *ccnl, int ifndx, uint16_t sender_id) +{ + DEBUGMSG(1, "ifndx=%d sender_id=%d\n", ifndx, sender_id); + + static int i; + + struct ccnl_face_s *f; + + for (f = ccnl->faces; f; f = f->next) { + DEBUGMSG(1, "f=%p\n", (void *) f); + + if (ifndx == f->ifndx && (f->faceid == sender_id)) { + DEBUGMSG(1, "face found! ifidx=%d sender_id=%d faceid=%d\n", ifndx, sender_id, f->faceid); + f->last_used = CCNL_NOW(); + return f; + } + } + + if (ifndx == -1) { + for (i = 0; i < ccnl->ifcount; i++) { + ifndx = i; + break; + } + + if (ifndx == -1) { // no suitable interface found + return NULL; + } + } + + f = (struct ccnl_face_s *) ccnl_calloc(1, sizeof(struct ccnl_face_s)); + + if (!f) { + return NULL; + } + + f->faceid = sender_id; // ++seqno; + DEBUGMSG(1, "faceid=%d\n", f->faceid); + f->ifndx = ifndx; + + if (ifndx >= 0) { + if (ccnl->defaultFaceScheduler) + f->sched = ccnl->defaultFaceScheduler(ccnl, + (void ( *)(void *, void *)) ccnl_face_CTS); + + if (ccnl->ifs[ifndx].reflect) { + f->flags |= CCNL_FACE_FLAGS_REFLECT; + } + + if (ccnl->ifs[ifndx].fwdalli) { + f->flags |= CCNL_FACE_FLAGS_FWDALLI; + } + } + + f->peer.id = sender_id; + +#ifdef USE_FRAG + + if (ifndx == RIOT_TRANS_IDX) { + // if newly created face, no fragment policy is defined yet + // turning on fragmentation for riot trans dev based faces + int flagval = CCNL_FACE_FLAGS_STATIC; + f->flags = flagval & + (CCNL_FACE_FLAGS_STATIC | CCNL_FACE_FLAGS_REFLECT); + + if (f->frag) { + ccnl_frag_destroy(f->frag); + f->frag = NULL; + } + + int mtu = ccnl->ifs[f->ifndx].mtu; + f->frag = ccnl_frag_new(CCNL_FRAG_CCNx2013, mtu); //TODO + } + +#endif + + f->last_used = CCNL_NOW(); + DBL_LINKED_LIST_ADD(ccnl->faces, f); + + return f; +} + +struct ccnl_face_s * +ccnl_face_remove(struct ccnl_relay_s *ccnl, struct ccnl_face_s *f) +{ + struct ccnl_face_s *f2; + struct ccnl_interest_s *pit; + struct ccnl_forward_s **ppfwd; + DEBUGMSG(1, "ccnl_face_remove relay=%p face=%p\n", (void *) ccnl, (void *) f); + + ccnl_sched_destroy(f->sched); + ccnl_frag_destroy(f->frag); + + for (pit = ccnl->pit; pit;) { + struct ccnl_pendint_s **ppend, *pend; + + if (pit->from == f) { + pit->from = NULL; + } + + for (ppend = &pit->pending; *ppend;) { + if ((*ppend)->face == f) { + pend = *ppend; + *ppend = pend->next; + ccnl_free(pend); + } + else { + ppend = &(*ppend)->next; + } + } + + if (pit->pending) { + pit = pit->next; + } + else { + pit = ccnl_interest_remove(ccnl, pit); + } + } + + for (ppfwd = &ccnl->fib; *ppfwd;) { + if ((*ppfwd)->face == f) { + struct ccnl_forward_s *pfwd = *ppfwd; + free_prefix(pfwd->prefix); + *ppfwd = pfwd->next; + ccnl_free(pfwd); + } + else { + ppfwd = &(*ppfwd)->next; + } + } + + while (f->outq) { + struct ccnl_buf_s *tmp = f->outq->next; + ccnl_free(f->outq); + f->outq = tmp; + } + + f2 = f->next; + DBL_LINKED_LIST_REMOVE(ccnl->faces, f); + ccnl_free(f); + return f2; +} + +void ccnl_interface_cleanup(struct ccnl_if_s *i) +{ + int j; + DEBUGMSG(99, "ccnl_interface_cleanup\n"); + + ccnl_sched_destroy(i->sched); + + for (j = 0; j < i->qlen; j++) { + struct ccnl_txrequest_s *r = i->queue + + (i->qfront + j) % CCNL_MAX_IF_QLEN; + ccnl_free(r->buf); + } +} + +// ---------------------------------------------------------------------- +// face and interface queues, scheduling + +void ccnl_interface_CTS(void *aux1, void *aux2) +{ + struct ccnl_relay_s *ccnl = (struct ccnl_relay_s *) aux1; + struct ccnl_if_s *ifc = (struct ccnl_if_s *) aux2; + struct ccnl_txrequest_s *r, req; + DEBUGMSG(25, "ccnl_interface_CTS interface=%p, qlen=%d, sched=%p\n", + (void *) ifc, ifc->qlen, (void *) ifc->sched); + + if (ifc->qlen <= 0) { + return; + } + + r = ifc->queue + ifc->qfront; + memcpy(&req, r, sizeof(req)); + ifc->qfront = (ifc->qfront + 1) % CCNL_MAX_IF_QLEN; + ifc->qlen--; + + ccnl_ll_TX(ccnl, ifc, &req.dst, req.buf); + ccnl_free(req.buf); +} + +void ccnl_interface_enqueue(void (tx_done)(void *, int, int), + struct ccnl_face_s *f, struct ccnl_relay_s *ccnl, struct ccnl_if_s *ifc, + struct ccnl_buf_s *buf, sockunion *dest) +{ + struct ccnl_txrequest_s *r; + DEBUGMSG(25, "ccnl_interface_enqueue interface=%p buf=%p (qlen=%d)\n", + (void *) ifc, (void *) buf, ifc->qlen); + + if (ifc->qlen >= CCNL_MAX_IF_QLEN) { + DEBUGMSG(2, " DROPPING buf=%p\n", (void *) buf); + ccnl_free(buf); + return; + } + + r = ifc->queue + ((ifc->qfront + ifc->qlen) % CCNL_MAX_IF_QLEN); + r->buf = buf; + memcpy(&r->dst, dest, sizeof(sockunion)); + r->txdone = tx_done; + r->txdone_face = f; + ifc->qlen++; + + ccnl_interface_CTS(ccnl, ifc); +} + +struct ccnl_buf_s * +ccnl_face_dequeue(struct ccnl_relay_s *ccnl, struct ccnl_face_s *f) +{ + (void) ccnl; /* unused */ + + struct ccnl_buf_s *pkt; + DEBUGMSG(20, "ccnl_face_dequeue face=%p (id=%d.%d)\n", (void *) f, ccnl->id, + f->faceid); + + if (!f->outq) { + return NULL; + } + + pkt = f->outq; + f->outq = pkt->next; + + if (!pkt->next) { + f->outqend = NULL; + } + + pkt->next = NULL; + return pkt; +} + +void ccnl_face_CTS_done(void *ptr, int cnt, int len) +{ + DEBUGMSG(99, "ccnl_face_CTS_done face=%p cnt=%d len=%d\n", ptr, cnt, len); +} + +void ccnl_face_CTS(struct ccnl_relay_s *ccnl, struct ccnl_face_s *f) +{ + struct ccnl_buf_s *buf; + DEBUGMSG(99, "ccnl_face_CTS face=%p sched=%p\n", (void *) f, + (void *) f->sched); + + if (!f->frag || f->frag->protocol == CCNL_FRAG_NONE) { + buf = ccnl_face_dequeue(ccnl, f); + + if (buf) + ccnl_interface_enqueue(ccnl_face_CTS_done, f, ccnl, + ccnl->ifs + f->ifndx, buf, &f->peer); + } + +#ifdef USE_FRAG + else { + sockunion dst; + int ifndx = f->ifndx; + buf = ccnl_frag_getnext(f->frag, &ifndx, &dst); + + if (!buf) { + buf = ccnl_face_dequeue(ccnl, f); + ccnl_frag_reset(f->frag, buf, f->ifndx, &f->peer); + buf = ccnl_frag_getnext(f->frag, &ifndx, &dst); + } + + if (buf) { + ccnl_interface_enqueue(ccnl_face_CTS_done, f, + ccnl, ccnl->ifs + ifndx, buf, &dst); + } + } + +#endif +} + +int ccnl_face_enqueue(struct ccnl_relay_s *ccnl, struct ccnl_face_s *to, + struct ccnl_buf_s *buf) +{ + struct ccnl_buf_s *msg; + DEBUGMSG(20, "ccnl_face_enqueue face=%p (id=%d.%d) buf=%p len=%d\n", + (void *) to, ccnl->id, to->faceid, (void *) buf, buf->datalen); + + for (msg = to->outq; msg; msg = msg->next) // already in the queue? + if (buf_equal(msg, buf)) { + DEBUGMSG(31, " not enqueued because already there\n"); + ccnl_free(buf); + return -1; + } + + buf->next = NULL; + + if (to->outqend) { + to->outqend->next = buf; + } + else { + to->outq = buf; + } + + to->outqend = buf; + ccnl_face_CTS(ccnl, to); + return 0; +} + +// ---------------------------------------------------------------------- +// handling of interest messages + +int ccnl_nonce_find_or_append(struct ccnl_relay_s *ccnl, + struct ccnl_buf_s *nonce) +{ + struct ccnl_buf_s *n, *n2 = 0; + int i; + DEBUGMSG(99, "ccnl_nonce_find_or_append\n"); + + for (n = ccnl->nonces, i = 0; n; n = n->next, i++) { + if (buf_equal(n, nonce)) { + return -1; + } + + if (n->next) { + n2 = n; + } + } + + n = ccnl_buf_new(nonce->data, nonce->datalen); + + if (n) { + n->next = ccnl->nonces; + ccnl->nonces = n; + + if (i >= CCNL_MAX_NONCES && n2) { + ccnl_free(n2->next); + n2->next = 0; + } + } + + return 0; +} + +struct ccnl_interest_s * +ccnl_interest_new(struct ccnl_relay_s *ccnl, struct ccnl_face_s *from, + struct ccnl_buf_s **pkt, struct ccnl_prefix_s **prefix, int minsuffix, + int maxsuffix, struct ccnl_buf_s **ppkd) +{ + struct ccnl_interest_s *i = (struct ccnl_interest_s *) ccnl_calloc(1, + sizeof(struct ccnl_interest_s)); + DEBUGMSG(99, "ccnl_new_interest\n"); + + if (!i) { + puts("can't get more memory from malloc, dropping ccn msg..."); + return NULL; + } + + i->from = from; + i->prefix = *prefix; + *prefix = 0; + i->pkt = *pkt; + *pkt = 0; + i->ppkd = *ppkd; + *ppkd = 0; + i->minsuffix = minsuffix; + i->maxsuffix = maxsuffix; + i->last_used = CCNL_NOW(); + DBL_LINKED_LIST_ADD(ccnl->pit, i); + return i; +} + +int ccnl_interest_append_pending(struct ccnl_interest_s *i, + struct ccnl_face_s *from) +{ + struct ccnl_pendint_s *pi, *last = NULL; + DEBUGMSG(99, "ccnl_append_pending\n"); + + for (pi = i->pending; pi; pi = pi->next) { // check whether already listed + if (pi->face == from) { + DEBUGMSG(40, " we found a matching interest, updating time\n"); + pi->last_used = CCNL_NOW(); + return 0; + } + + last = pi; + } + + pi = (struct ccnl_pendint_s *) ccnl_calloc(1, + sizeof(struct ccnl_pendint_s)); + DEBUGMSG(40, " appending a new pendint entry %p\n", (void *) pi); + + if (!pi) { + return -1; + } + + pi->face = from; + pi->last_used = CCNL_NOW(); + + if (last) { + last->next = pi; + } + else { + i->pending = pi; + } + + return 0; +} + +void ccnl_interest_propagate(struct ccnl_relay_s *ccnl, + struct ccnl_interest_s *i) +{ + struct ccnl_forward_s *fwd; + DEBUGMSG(99, "ccnl_interest_propagate\n"); + + ccnl_print_stats(ccnl, STAT_SND_I); // log_send_i + + int hits = 0; + + // CONFORM: "A node MUST implement some strategy rule, even if it is only to + // transmit an Interest Message on all listed dest faces in sequence." + // CCNL strategy: we forward on all FWD entries with a prefix match + for (fwd = ccnl->fib; fwd; fwd = fwd->next) { + int rc = ccnl_prefix_cmp(fwd->prefix, NULL, i->prefix, CMP_LONGEST); + DEBUGMSG(40, " ccnl_interest_propagate, rc=%d/%d\n", rc, + fwd->prefix->compcnt); + + if (rc < fwd->prefix->compcnt) { + continue; + } + + DEBUGMSG(40, " ccnl_interest_propagate, fwd==%p\n", (void *) fwd); + + // suppress forwarding to origin of interest, except wireless + if (!i->from || fwd->face != i->from + || (i->from->flags & CCNL_FACE_FLAGS_REFLECT)) { + ccnl_face_enqueue(ccnl, fwd->face, buf_dup(i->pkt)); + hits++; + } + } + + if (hits == 0) { + DEBUGMSG(1, "no hits in the fib...find riot transceiver face\n"); + struct ccnl_face_s *face = ccnl_get_face_or_create(ccnl, RIOT_TRANS_IDX, 0 /* broadcast */); + ccnl_face_enqueue(ccnl, face, buf_dup(i->pkt)); + } + + return; +} + +struct ccnl_interest_s * +ccnl_interest_remove(struct ccnl_relay_s *ccnl, struct ccnl_interest_s *i) +{ + struct ccnl_interest_s *i2; + DEBUGMSG(40, "ccnl_interest_remove %p\n", (void *) i); + + while (i->pending) { + struct ccnl_pendint_s *tmp = i->pending->next; + ccnl_free(i->pending); + i->pending = tmp; + } + + i2 = i->next; + DBL_LINKED_LIST_REMOVE(ccnl->pit, i); + free_prefix(i->prefix); + free_3ptr_list(i->ppkd, i->pkt, i); + return i2; +} + +// ---------------------------------------------------------------------- +// handling of content messages + +int ccnl_i_prefixof_c(struct ccnl_prefix_s *prefix, struct ccnl_buf_s *ppkd, + int minsuffix, int maxsuffix, struct ccnl_content_s *c) +{ + unsigned char *md; + DEBUGMSG(99, "ccnl_i_prefixof_c prefix=%s min=%d max=%d\n", + ccnl_prefix_to_path(prefix), minsuffix, maxsuffix); + + // CONFORM: we do prefix match, honour min. and maxsuffix, + // and check the PublisherPublicKeyDigest if present + + // NON-CONFORM: "Note that to match a ContentObject must satisfy + // all of the specifications given in the Interest Message." + // >> CCNL does not honour the exclusion filtering + + if ((ppkd && !buf_equal(ppkd, c->ppkd)) + || (prefix->compcnt + minsuffix) > (c->name->compcnt + 1) + || (prefix->compcnt + maxsuffix) < (c->name->compcnt + 1)) { + return 0; + } + + md = NULL; + + if ((prefix->compcnt - c->name->compcnt) == 1) { + md = compute_ccnx_digest(c->pkt); + } + + return ccnl_prefix_cmp(c->name, md, prefix, CMP_MATCH) == prefix->compcnt; +} + +struct ccnl_content_s * +ccnl_content_new(struct ccnl_relay_s *ccnl, struct ccnl_buf_s **pkt, + struct ccnl_prefix_s **prefix, struct ccnl_buf_s **ppkd, + unsigned char *content, int contlen) +{ + + (void) ccnl; /* unused */ + + struct ccnl_content_s *c; + // DEBUGMSG(99, "ccnl_content_new <%s>\n", + // prefix == NULL ? NULL : ccnl_prefix_to_path(*prefix)); + + c = (struct ccnl_content_s *) ccnl_calloc(1, sizeof(struct ccnl_content_s)); + + if (!c) { + return NULL; + } + + c->last_used = CCNL_NOW(); + c->content = content; + c->contentlen = contlen; + c->pkt = *pkt; + *pkt = NULL; + c->name = *prefix; + *prefix = NULL; + + if (ppkd) { + c->ppkd = *ppkd; + *ppkd = NULL; + } + + return c; +} + +struct ccnl_content_s * +ccnl_content_remove(struct ccnl_relay_s *ccnl, struct ccnl_content_s *c) +{ + struct ccnl_content_s *c2; + DEBUGMSG(99, "ccnl_content_remove\n"); + + c2 = c->next; + DBL_LINKED_LIST_REMOVE(ccnl->contents, c); + free_content(c); + ccnl->contentcnt--; + return c2; +} + +struct ccnl_content_s * +ccnl_content_add2cache(struct ccnl_relay_s *ccnl, struct ccnl_content_s *c) +{ + DEBUGMSG(99, "ccnl_content_add2cache (%d/%d)\n", ccnl->contentcnt, + ccnl->max_cache_entries); + + if (ccnl->max_cache_entries > 0 + && ccnl->contentcnt >= ccnl->max_cache_entries) { // remove oldest content + struct ccnl_content_s *c2; + int age = 0; + + for (c2 = ccnl->contents; c2; c2 = c2->next) + if (!(c2->flags & CCNL_CONTENT_FLAGS_STATIC) + && ((age == 0) || c2->last_used < age)) { + age = c2->last_used; + } + + if (c2) { + ccnl_content_remove(ccnl, c2); + } + } + + DBL_LINKED_LIST_ADD(ccnl->contents, c); + ccnl->contentcnt++; + return c; +} + +// deliver new content c to all clients with (loosely) matching interest, +// but only one copy per face +// returns: number of forwards +int ccnl_content_serve_pending(struct ccnl_relay_s *ccnl, + struct ccnl_content_s *c) +{ + struct ccnl_interest_s *i; + struct ccnl_face_s *f; + int cnt = 0; + DEBUGMSG(99, "ccnl_content_serve_pending\n"); + + for (f = ccnl->faces; f; f = f->next) { + f->flags &= ~CCNL_FACE_FLAGS_SERVED; // reply on a face only once + } + + for (i = ccnl->pit; i;) { + struct ccnl_pendint_s *pi; + + if (!ccnl_i_prefixof_c(i->prefix, i->ppkd, i->minsuffix, i->maxsuffix, + c)) { + i = i->next; + continue; + } + + // CONFORM: "Data MUST only be transmitted in response to + // an Interest that matches the Data." + for (pi = i->pending; pi; pi = pi->next) { + if (pi->face->flags & CCNL_FACE_FLAGS_SERVED) { + continue; + } + + pi->face->flags |= CCNL_FACE_FLAGS_SERVED; + + if (pi->face->ifndx >= 0) { + DEBUGMSG(6, " forwarding content <%s>\n", + ccnl_prefix_to_path(c->name)); + ccnl_print_stats(ccnl, STAT_SND_C); //log sent c + ccnl_face_enqueue(ccnl, pi->face, buf_dup(c->pkt)); + } + else + // upcall to deliver content to local client + { + ccnl_app_RX(ccnl, c); + } + + c->served_cnt++; + cnt++; + } + + i = ccnl_interest_remove(ccnl, i); + } + + return cnt; +} + +void ccnl_do_ageing(void *ptr, void *dummy) +{ + + (void) dummy; /* unused */ + + struct ccnl_relay_s *relay = (struct ccnl_relay_s *) ptr; + struct ccnl_content_s *c = relay->contents; + struct ccnl_interest_s *i = relay->pit; + struct ccnl_face_s *f = relay->faces; + time_t t = CCNL_NOW(); + DEBUGMSG(999, "ccnl_do_ageing %d\n", (int) t); + + while (c) { + if ((c->last_used + CCNL_CONTENT_TIMEOUT) <= t + && !(c->flags & CCNL_CONTENT_FLAGS_STATIC)) { + c = ccnl_content_remove(relay, c); + } + else { + c = c->next; + } + } + + while (i) { // CONFORM: "Entries in the PIT MUST timeout rather + // than being held indefinitely." + if ((i->last_used + CCNL_INTEREST_TIMEOUT) <= t || + i->retries > CCNL_MAX_INTEREST_RETRANSMIT) { + i = ccnl_interest_remove(relay, i); + } + else { + // CONFORM: "A node MUST retransmit Interest Messages + // periodically for pending PIT entries." + DEBUGMSG(7, " retransmit %d <%s>\n", i->retries, + ccnl_prefix_to_path(i->prefix)); + ccnl_interest_propagate(relay, i); + i->retries++; + i = i->next; + } + } + + while (f) { + if (!(f->flags & CCNL_FACE_FLAGS_STATIC) + && (f->last_used + CCNL_FACE_TIMEOUT) <= t) { + f = ccnl_face_remove(relay, f); + } + else { + f = f->next; + } + } +} + +void ccnl_core_cleanup(struct ccnl_relay_s *ccnl) +{ + int k; + DEBUGMSG(99, "ccnl_core_cleanup %p\n", (void *) ccnl); + + while (ccnl->pit) { + ccnl_interest_remove(ccnl, ccnl->pit); + } + + while (ccnl->faces) { + ccnl_face_remove(ccnl, ccnl->faces); // also removes all FWD entries + } + + while (ccnl->contents) { + ccnl_content_remove(ccnl, ccnl->contents); + } + + while (ccnl->nonces) { + struct ccnl_buf_s *tmp = ccnl->nonces->next; + ccnl_free(ccnl->nonces); + ccnl->nonces = tmp; + } + + for (k = 0; k < ccnl->ifcount; k++) { + ccnl_interface_cleanup(ccnl->ifs + k); + } +} + +// ---------------------------------------------------------------------- +// the core logic of CCN: + +int ccnl_core_RX_i_or_c(struct ccnl_relay_s *relay, struct ccnl_face_s *from, + unsigned char **data, int *datalen) +{ + int rc = -1, scope = 3, aok = 3, minsfx = 0, maxsfx = CCNL_MAX_NAME_COMP, + contlen; + struct ccnl_buf_s *buf = 0, *nonce = 0, *ppkd = 0; + struct ccnl_interest_s *i = 0; + struct ccnl_content_s *c = 0; + struct ccnl_prefix_s *p = 0; + unsigned char *content = 0; + DEBUGMSG(1, "ccnl_core_RX_i_or_c: (%d bytes left)\n", *datalen); + + buf = ccnl_extract_prefix_nonce_ppkd(data, datalen, &scope, &aok, &minsfx, + &maxsfx, &p, &nonce, &ppkd, &content, &contlen); + + if (!buf) { + DEBUGMSG(6, " parsing error or no prefix\n"); + goto Done; + } + + if (nonce && ccnl_nonce_find_or_append(relay, nonce)) { + DEBUGMSG(6, " dropped because of duplicate nonce\n"); + goto Skip; + } + + if (buf->data[0] == 0x01 && buf->data[1] == 0xd2) { // interest + DEBUGMSG(1, "ccnl_core_RX_i_or_c: interest=<%s>\n", ccnl_prefix_to_path(p)); + ccnl_print_stats(relay, STAT_RCV_I); //log count recv_interest + + if (p->compcnt > 0 && p->comp[0][0] == (unsigned char) 0xc1) { + goto Skip; + } + + if (p->compcnt == 4 && !memcmp(p->comp[0], "ccnx", 4)) { + DEBUGMSG(1, "it's a mgnt msg!\n"); + rc = ccnl_mgmt(relay, buf, p, from); + DEBUGMSG(1, "mgnt processing done!\n"); + goto Done; + } + + // CONFORM: Step 1: + if (aok & 0x01) { // honor "answer-from-existing-content-store" flag + for (c = relay->contents; c; c = c->next) { + if (!ccnl_i_prefixof_c(p, ppkd, minsfx, maxsfx, c)) { + continue; + } + + // FIXME: should check stale bit in aok here + DEBUGMSG(7, " matching content for interest, content %p\n", + (void *) c); + ccnl_print_stats(relay, STAT_SND_C); //log sent_c + + if (from->ifndx >= 0) { + ccnl_face_enqueue(relay, from, buf_dup(c->pkt)); + } + else { + ccnl_app_RX(relay, c); + } + + goto Skip; + } + } + + // CONFORM: Step 2: check whether interest is already known + for (i = relay->pit; i; i = i->next) { + if (!ccnl_prefix_cmp(i->prefix, NULL, p, CMP_EXACT) + && i->minsuffix == minsfx && i->maxsuffix == maxsfx + && ((!ppkd && !i->ppkd) || buf_equal(ppkd, i->ppkd))) { + break; + } + } + + if (!i) { // this is a new/unknown I request: create and propagate + i = ccnl_interest_new(relay, from, &buf, &p, minsfx, maxsfx, &ppkd); + + if (i) { // CONFORM: Step 3 (and 4) + DEBUGMSG(7, " created new interest entry %p\n", (void *) i); + + if (scope > 2) { + ccnl_interest_propagate(relay, i); + } + } + } + else if (scope > 2 && (from->flags & CCNL_FACE_FLAGS_FWDALLI)) { + DEBUGMSG(7, " old interest, nevertheless propagated %p\n", + (void *) i); + ccnl_interest_propagate(relay, i); + } + + if (i) { // store the I request, for the incoming face (Step 3) + DEBUGMSG(7, " appending interest entry %p\n", (void *) i); + ccnl_interest_append_pending(i, from); + } + } + else { // content + DEBUGMSG(6, " content=<%s>\n", ccnl_prefix_to_path(p)); + ccnl_print_stats(relay, STAT_RCV_C); //log count recv_content + + // CONFORM: Step 1: + for (c = relay->contents; c; c = c->next) + if (buf_equal(c->pkt, buf)) { + goto Skip; // content is dup + } + + c = ccnl_content_new(relay, &buf, &p, &ppkd, content, contlen); + + if (c) { // CONFORM: Step 2 (and 3) + if (!ccnl_content_serve_pending(relay, c)) { // unsolicited content + // CONFORM: "A node MUST NOT forward unsolicited data [...]" + DEBUGMSG(7, " removed because no matching interest\n"); + free_content(c); + goto Skip; + } + + if (relay->max_cache_entries != 0) { // it's set to -1 or a limit + DEBUGMSG(7, " adding content to cache\n"); + ccnl_content_add2cache(relay, c); + } + else { + DEBUGMSG(7, " content not added to cache\n"); + free_content(c); + } + } + } + +Skip: + rc = 0; +Done: + free_prefix(p); + free_3ptr_list(buf, nonce, ppkd); + DEBUGMSG(1, "leaving\n"); + return rc; +} + +int ccnl_core_RX_datagram(struct ccnl_relay_s *relay, struct ccnl_face_s *from, + unsigned char **data, int *datalen) +{ + int rc = 0, num = 0, typ = 0; + DEBUGMSG(1, "ccnl_core_RX_datagram: %d bytes from face=%p (id=%d.%d)\n", + *datalen, (void *) from, relay->id, from ? from->faceid : -1); + + while (rc >= 0 && *datalen > 0) { + if (dehead(data, datalen, &num, &typ) || typ != CCN_TT_DTAG) { + return -1; + } + + switch (num) { + case CCN_DTAG_INTEREST: + DEBUGMSG(1, "INTEREST\n"); + + case CCN_DTAG_CONTENTOBJ: + rc = ccnl_core_RX_i_or_c(relay, from, data, datalen); + continue; +#ifdef USE_FRAG + + case CCNL_DTAG_FRAGMENT2012: + rc = ccnl_frag_RX_frag2012(ccnl_core_RX_datagram, relay, from, data, datalen); + continue; + + case CCNL_DTAG_FRAGMENT: + rc = ccnl_frag_RX_CCNx2013(ccnl_core_RX_datagram, relay, from, data, datalen); + continue; +#endif + + default: + DEBUGMSG(15, " unknown datagram type %d\n", num); + return -1; + } + } + + return rc; +} + +void +ccnl_core_RX(struct ccnl_relay_s *relay, int ifndx, unsigned char *data, + int datalen, uint16_t sender_id) +{ + struct ccnl_face_s *from; + DEBUGMSG(14, "ccnl_core_RX ifndx=%d, %d bytes\n", ifndx, datalen); + + from = ccnl_get_face_or_create(relay, ifndx, sender_id); + DEBUGMSG(1, "ccnl_core_RX: faceid=%d frag=%p\n", from->faceid, (void *) from->frag); + + if (!from) { + return; + } + + ccnl_core_RX_datagram(relay, from, &data, &datalen); +} + +const char * +compile_string(void) +{ + static const char *cp = "" +#ifdef USE_CCNxDIGEST + "USE_CCNxDIGEST " +#endif +#ifdef USE_DEBUG + "USE_DEBUG " +#endif +#ifdef USE_DEBUG_MALLOC + "USE_DEBUG_MALLOC " +#endif +#ifdef USE_FRAG + "USE_FRAG " +#endif +#ifdef USE_ETHERNET + "USE_ETHERNET " +#endif +#ifdef USE_UDP + "USE_UDP " +#endif +#ifdef USE_HTTP_STATUS + "USE_HTTP_STATUS " +#endif +#ifdef USE_MGMT + "USE_MGMT " +#endif +#ifdef USE_SCHEDULER + "USE_SCHEDULER " +#endif +#ifdef USE_UNIXSOCKET + "USE_UNIXSOCKET " +#endif +#ifdef USE_APPSERVER + "USE_APPSERVER " +#endif + ; + return cp; +} + +// eof diff --git a/sys/net/ccn_lite/ccnl-core.h b/sys/net/ccn_lite/ccnl-core.h new file mode 100644 index 000000000..b69389d37 --- /dev/null +++ b/sys/net/ccn_lite/ccnl-core.h @@ -0,0 +1,260 @@ +/* + * @f ccnl-core.h + * @b CCN lite (CCNL), core header file (internal data structures) + * + * Copyright (C) 2011-13, Christian Tschudin, University of Basel + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2011-04-09 created + * 2013-03-19 updated (ms): modified struct ccnl_relay_s for 'aux' field + */ + +#ifndef CCNL_CORE_H__ +#define CCNL_CORE_H__ + +//#define CCNL_UNIX + +#define EXACT_MATCH 1 +#define PREFIX_MATCH 0 + +#define CMP_EXACT 0 // used to compare interests among themselves +#define CMP_MATCH 1 // used to match interest and content +#define CMP_LONGEST 2 // used to lookup the FIB + +#define CCNL_FACE_FLAGS_STATIC 1 +#define CCNL_FACE_FLAGS_REFLECT 2 +#define CCNL_FACE_FLAGS_SERVED 4 +#define CCNL_FACE_FLAGS_FWDALLI 8 // forward all interests, also known ones + +#define CCNL_FRAG_NONE 0 +#define CCNL_FRAG_SEQUENCED2012 1 +#define CCNL_FRAG_CCNx2013 2 + +#define CCNL_CONTENT_FLAGS_STATIC 0x01 +#define CCNL_CONTENT_FLAGS_STALE 0x02 + +enum {STAT_RCV_I, STAT_RCV_C, STAT_SND_I, STAT_SND_C, STAT_QLEN, STAT_EOP1}; + +#include +#include + +#include "ccnl.h" + +// ---------------------------------------------------------------------- + +typedef union { + uint16_t id; +} sockunion; + +struct ccnl_txrequest_s { + struct ccnl_buf_s *buf; + sockunion dst; + void (*txdone)(void *, int, int); + struct ccnl_face_s *txdone_face; +}; + +struct ccnl_if_s { // interface for packet IO + sockunion addr; + int sock; + int (*sendfunc)(uint8_t *, uint16_t, uint16_t); + int reflect; // whether to reflect I packets on this interface + int fwdalli; // whether to forward all I packets rcvd on this interface + int mtu; + + int qlen; // number of pending sends + int qfront; // index of next packet to send + struct ccnl_txrequest_s queue[CCNL_MAX_IF_QLEN]; + struct ccnl_sched_s *sched; +}; + +struct ccnl_relay_s { + time_t startup_time; + int id; + struct ccnl_face_s *faces; + struct ccnl_forward_s *fib; + struct ccnl_interest_s *pit; + struct ccnl_content_s *contents; //, *contentsend; + struct ccnl_buf_s *nonces; + int contentcnt; // number of cached items + int max_cache_entries; // -1: unlimited + struct ccnl_if_s ifs[CCNL_MAX_INTERFACES]; + int ifcount; // number of active interfaces + char halt_flag; + struct ccnl_sched_s *(*defaultFaceScheduler)(struct ccnl_relay_s *, + void(*cts_done)(void *, void *)); + struct ccnl_sched_s *(*defaultInterfaceScheduler)(struct ccnl_relay_s *, + void(*cts_done)(void *, void *)); + struct ccnl_http_s *http; + struct ccnl_stats_s *stats; + void *aux; +}; + +struct ccnl_buf_s { + struct ccnl_buf_s *next; + unsigned int datalen; + unsigned char data[1]; +}; + +struct ccnl_prefix_s { + unsigned char **comp; + int *complen; + int compcnt; + unsigned char *path; // memory for name component copies +}; + +struct ccnl_frag_s { + int protocol; // (0=plain CCNx) + int mtu; + sockunion dest; + struct ccnl_buf_s *bigpkt; + unsigned int sendoffs; + // transport state, if present: + int ifndx; + + struct ccnl_buf_s *defrag; + + unsigned int sendseq; + unsigned int losscount; + unsigned int recvseq; + unsigned char flagwidth; + unsigned char sendseqwidth; + unsigned char losscountwidth; + unsigned char recvseqwidth; +}; + +struct ccnl_face_s { + struct ccnl_face_s *next, *prev; + int faceid; + int ifndx; + sockunion peer; + int flags; + int last_used; // updated when we receive a packet + struct ccnl_buf_s *outq, *outqend; // queue of packets to send + struct ccnl_frag_s *frag; // which special datagram armoring + struct ccnl_sched_s *sched; +}; + +struct ccnl_forward_s { + struct ccnl_forward_s *next; + struct ccnl_prefix_s *prefix; + struct ccnl_face_s *face; +}; + +struct ccnl_interest_s { + struct ccnl_interest_s *next, *prev; + struct ccnl_face_s *from; + struct ccnl_pendint_s *pending; // linked list of faces wanting that content + struct ccnl_prefix_s *prefix; + int minsuffix, maxsuffix; + struct ccnl_buf_s *ppkd; // publisher public key digest + struct ccnl_buf_s *pkt; // full datagram + int last_used; + int retries; +}; + +struct ccnl_pendint_s { // pending interest + struct ccnl_pendint_s *next; // , *prev; + struct ccnl_face_s *face; + int last_used; +}; + +struct ccnl_content_s { + struct ccnl_content_s *next, *prev; + struct ccnl_prefix_s *name; + struct ccnl_buf_s *ppkd; // publisher public key digest + struct ccnl_buf_s *pkt; // full datagram + int flags; + unsigned char *content; // pointer into the data buffer + int contentlen; + // NON-CONFORM: "The [ContentSTore] MUST also implement the Staleness Bit." + // >> CCNL: currently no stale bit, old content is fully removed << + int last_used; + int served_cnt; +}; + +// ---------------------------------------------------------------------- +// macros for double linked lists (these double linked lists are not rings) + +#define DBL_LINKED_LIST_ADD(l,e) \ + do { if ((l)) (l)->prev = (e); \ + (e)->next = (l); \ + (l) = (e); \ + } while(0) + +#define DBL_LINKED_LIST_REMOVE(l,e) \ + do { if ((l) == (e)) (l) = (e)->next; \ + if ((e)->prev) (e)->prev->next = (e)->next; \ + if ((e)->next) (e)->next->prev = (e)->prev; \ + } while(0) + +// ---------------------------------------------------------------------- +// collect the USE_* macros in a string +const char *compile_string(void); + +int consume(int typ, int num, unsigned char **buf, int *len, + unsigned char **valptr, int *vallen); + +void +ccnl_core_RX(struct ccnl_relay_s *relay, int ifndx, unsigned char *data, + int datalen, uint16_t sender_id); + +void ccnl_core_cleanup(struct ccnl_relay_s *ccnl); + +struct ccnl_buf_s * +ccnl_buf_new(void *data, int len); + +struct ccnl_content_s * +ccnl_content_new(struct ccnl_relay_s *ccnl, struct ccnl_buf_s **pkt, + struct ccnl_prefix_s **prefix, struct ccnl_buf_s **ppkd, + unsigned char *content, int contlen); + +struct ccnl_content_s * +ccnl_content_add2cache(struct ccnl_relay_s *ccnl, struct ccnl_content_s *c); + +struct ccnl_face_s * +ccnl_get_face_or_create(struct ccnl_relay_s *ccnl, int ifndx, uint16_t sender_id); + +int ccnl_face_enqueue(struct ccnl_relay_s *ccnl, struct ccnl_face_s *to, + struct ccnl_buf_s *buf); + +struct ccnl_face_s * +ccnl_face_remove(struct ccnl_relay_s *ccnl, struct ccnl_face_s *f); + +struct ccnl_buf_s * +ccnl_extract_prefix_nonce_ppkd(unsigned char **data, int *datalen, int *scope, + int *aok, int *min, int *max, struct ccnl_prefix_s **prefix, + struct ccnl_buf_s **nonce, struct ccnl_buf_s **ppkd, + unsigned char **content, int *contlen); + +void ccnl_do_ageing(void *ptr, void *dummy); + +void ccnl_interface_CTS(void *aux1, void *aux2); + +#define ccnl_app_RX(x,y) do{}while(0) +#define ccnl_print_stats(x,y) do{}while(0) + +#define ccnl_malloc(s) malloc(s) +#define ccnl_calloc(n,s) calloc(n,s) +#define ccnl_realloc(p,s) realloc(p,s) +#define ccnl_free(p) free(p) + +void free_2ptr_list(void *a, void *b); +void free_3ptr_list(void *a, void *b, void *c); +void free_4ptr_list(void *a, void *b, void *c, void *d); +void free_prefix(struct ccnl_prefix_s *p); +void free_content(struct ccnl_content_s *c); + +#endif /*CCNL_CORE_H__*/ +// eof diff --git a/sys/net/ccn_lite/ccnl-ext-appserver.c b/sys/net/ccn_lite/ccnl-ext-appserver.c new file mode 100644 index 000000000..f39dba09f --- /dev/null +++ b/sys/net/ccn_lite/ccnl-ext-appserver.c @@ -0,0 +1,166 @@ +/* + * @f ccnl-ext-appserver.c + * + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define RIOT_CCN_APPSERVER (1) + +#if RIOT_CCN_APPSERVER + +#include "msg.h" +#include "thread.h" +#include "util/ccnl-riot-client.h" +#include "ccnl-riot-compat.h" + +#include "ccnl-includes.h" +#include "ccnl-core.h" +#include "ccnl-ext.h" +#include "ccnl-pdu.h" +#include "ccnx.h" + +static volatile int halt_flag; + +/** The size of the message queue between router daemon and transceiver AND clients */ +#define APPSERVER_MSG_BUFFER_SIZE (64) + +/** message buffer */ +msg_t msg_buffer_appserver[APPSERVER_MSG_BUFFER_SIZE]; + +unsigned char big_buf[2 * 1024]; + +int relay_pid; +char prefix[] = "/riot/appserver/"; + +static int appserver_sent_content(uint8_t *buf, int len, uint16_t from) +{ + static riot_ccnl_msg_t rmsg; + rmsg.payload = buf; + rmsg.size = len; + DEBUGMSG(1, "datalen=%d\n", rmsg.size); + + msg_t m; + m.type = CCNL_RIOT_MSG; + m.content.ptr = (char *) &rmsg; + uint16_t dest_pid = from; + DEBUGMSG(1, "sending msg to pid=%u\n", dest_pid); + int ret = msg_send(&m, dest_pid, 1); + DEBUGMSG(1, "msg_reply returned: %d\n", ret); + return ret; +} + +static int appserver_create_content(char **prefix, uint8_t *out) +{ + char buf[CCNL_RIOT_CHUNK_SIZE - 1]; + + for (int i = 0; i < CCNL_RIOT_CHUNK_SIZE - 1; i++) { + buf[i] = 'a' + i%26; + } + + int len = mkContent(prefix, buf, CCNL_RIOT_CHUNK_SIZE - 1, out); + return len; +} + +static int appserver_create_prefix(char *name, char **prefix) +{ + int i = 0; + char *cp = strtok(name, "/"); + + while (i < (CCNL_MAX_NAME_COMP - 1) && cp) { + prefix[i++] = cp; + cp = strtok(NULL, "/"); + } + + prefix[i] = NULL; + + return i; +} + +static int appserver_handle_interest(char *data, uint16_t datalen, uint16_t from) +{ + (void) data; + (void) datalen; + + char *prefix[CCNL_MAX_NAME_COMP]; + //struct ccnl_interest_s *i = appserver_parse_interest(data, datalen); + + char name[] = "/riot/appserver/test/0"; + appserver_create_prefix(name, prefix); + + int len = appserver_create_content(prefix, big_buf); + /* + struct ccnl_prefix *myprefix = ccnl_path_to_prefix(name); + + if (ccnl_prefix_cmp(myprefix, 0, i->prefix, CMP_EXACT) != CMP_EXACT) { + DEBUGMSG(1, "APPSERVER: it's a match"); + } + */ + int ret = appserver_sent_content(big_buf, len, from); + + return ret; +} + +static void riot_ccnl_appserver_ioloop(void) +{ + DEBUGMSG(1, "starting appserver main event and IO loop\n"); + + if (msg_init_queue(msg_buffer_appserver, APPSERVER_MSG_BUFFER_SIZE) != 0) { + DEBUGMSG(1, "msg init queue failed...abording\n"); + } + + msg_t in; + riot_ccnl_msg_t *m; + + while (!halt_flag) { + DEBUGMSG(1, "appserver: waiting for incomming msg\n"); + msg_receive(&in); + + switch (in.type) { + case (CCNL_RIOT_MSG): + m = (riot_ccnl_msg_t *) in.content.ptr; + DEBUGMSG(1, "new msg: size=%" PRIu16 " sender_pid=%" PRIu16 "\n", + m->size, in.sender_pid); + appserver_handle_interest(m->payload, m->size, in.sender_pid); + break; + + default: + DEBUGMSG(1, + "received unknown msg type: '%" PRIu16 "' dropping it\n", + in.type); + break; + } + } +} + +static void riot_ccnl_appserver_register(void) +{ + char faceid[10]; + snprintf(faceid, sizeof(faceid), "%d", thread_getpid()); + char *type = "newMSGface"; + + int content_len = ccnl_riot_client_publish(relay_pid, prefix, faceid, type, big_buf); + DEBUG("received %d bytes.\n", content_len); + DEBUG("appserver received: '%s'\n", big_buf); +} + +void ccnl_riot_appserver_start(int _relay_pid) +{ + relay_pid = _relay_pid; + riot_ccnl_appserver_register(); + riot_ccnl_appserver_ioloop(); + DEBUGMSG(1, "appserver terminated\n"); +} + +#endif diff --git a/sys/net/ccn_lite/ccnl-ext-debug.c b/sys/net/ccn_lite/ccnl-ext-debug.c new file mode 100644 index 000000000..646075722 --- /dev/null +++ b/sys/net/ccn_lite/ccnl-ext-debug.c @@ -0,0 +1,67 @@ +/* + * @f ccnl-ext-debug.c + * @b CCNL debugging support, dumping routines, memory tracking, stats + * + * Copyright (C) 2011-13, Christian Tschudin, University of Basel + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2011-04-19 created + * 2013-03-18 updated (ms): removed omnet related code + * 2013-03-31 merged with ccnl-debug.h and ccnl-debug-mem.c + */ + +#ifndef CCNL_EXT_DEBUG_H +#define CCNL_EXT_DEBUG_H + +#include +#include +#include +#include + +#include "ccnl-core.h" + +char * +ccnl_prefix_to_path(struct ccnl_prefix_s *pr) +{ + static char prefix_buf[256]; + int len, i, j; + + if (!pr) { + return NULL; + } + + for (len = 0, i = 0; i < pr->compcnt; i++) { + if ((len + 1 + 3 * pr->complen[i]) >= (int) sizeof(prefix_buf)) { + return (char *) "(...prefix...)"; + } + + prefix_buf[len++] = '/'; + + for (j = 0; j < pr->complen[i]; j++) { + unsigned char c = pr->comp[i][j]; + len += sprintf(prefix_buf + len, + !isprint(c) || isspace(c) || c == '/' ? "%%%02x" : "%c", + c); + } + } + + prefix_buf[len] = '\0'; + return prefix_buf; +} + +#endif + +// eof diff --git a/sys/net/ccn_lite/ccnl-ext-frag.c b/sys/net/ccn_lite/ccnl-ext-frag.c new file mode 100644 index 000000000..0582613e9 --- /dev/null +++ b/sys/net/ccn_lite/ccnl-ext-frag.c @@ -0,0 +1,711 @@ +/* + * @f ccnl-ext-frag.c + * @b CCN lite extension: fragmentation support (including scheduling interface) + * + * Copyright (C) 2011-13, Christian Tschudin, University of Basel + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2011-10-05 created + * 2013-05-02 prototyped a new fragment format CCNL_FRAG_TYPE_CCNx2013 + */ + +// ---------------------------------------------------------------------- +//#define USE_FRAG +#ifdef USE_FRAG + +#include "ccnl-includes.h" +#include "ccnl-core.h" +#include "ccnl-ext.h" +#include "ccnx.h" + + + +/* see ccnl-core.h for available fragmentation protocols. + * + * CCNL_FRAG_NONE + * passthrough, i.e. no header is added at all + * + * CCNL_FRAG_SEQUENCED2012 + * - a ccnb encoded header is prepended, + * - the driver is configurable for arbitrary MTU + * - packets have sequence numbers (can detect lost packets) + * + * CCNL_FRAG_CCNx2013 + * - a ccnb encoded wire format as currently discussed with PARC. + * It serves as a container for various wire format types, + * including carrying fragments of bigger CCNX objects + * - all attributes from SEQUENCED2012 are retained + * + */ + +// ---------------------------------------------------------------------- +struct ccnl_frag_s * +ccnl_frag_new(int protocol, int mtu) +{ + struct ccnl_frag_s *e = NULL; + + DEBUGMSG(8, "ccnl_frag_new proto=%d mtu=%d\n", protocol, mtu); + + switch (protocol) { + case CCNL_FRAG_SEQUENCED2012: + case CCNL_FRAG_CCNx2013: + e = (struct ccnl_frag_s *) ccnl_calloc(1, sizeof(struct ccnl_frag_s)); + + if (e) { + e->protocol = protocol; + e->mtu = mtu; + e->flagwidth = 1; + e->sendseqwidth = 4; + e->losscountwidth = 2; + e->recvseqwidth = 4; + } + + break; + + case CCNL_FRAG_NONE: + default: + break; + } + + return e; +} + +void ccnl_frag_reset(struct ccnl_frag_s *e, struct ccnl_buf_s *buf, int ifndx, + sockunion *dst) +{ + DEBUGMSG(99, "ccnl_frag_reset (%d bytes)\n", buf ? buf->datalen : -1); + + if (!e) { + return; + } + + e->ifndx = ifndx; + memcpy(&e->dest, dst, sizeof(*dst)); + ccnl_free(e->bigpkt); + e->bigpkt = buf; + e->sendoffs = 0; +} + +int ccnl_frag_getfragcount(struct ccnl_frag_s *e, int origlen, int *totallen) +{ + int cnt = 0, len = 0; + unsigned char dummy[256]; + int hdrlen, blobtaglen, datalen; + int offs = 0; + + if (!e) { + cnt = 1; + } + else if (e && e->protocol == CCNL_FRAG_SEQUENCED2012) { + while (offs < origlen) { // we could do better than to simulate this: + hdrlen = mkHeader(dummy, CCNL_DTAG_FRAGMENT2012, CCN_TT_DTAG); + hdrlen += mkBinaryInt(dummy, CCNL_DTAG_FRAG_FLAGS, CCN_TT_DTAG, 0, + e->flagwidth); + hdrlen += mkBinaryInt(dummy, CCNL_DTAG_FRAG_SEQNR, CCN_TT_DTAG, 0, + e->sendseqwidth); + hdrlen += mkBinaryInt(dummy, CCNL_DTAG_FRAG_OLOSS, CCN_TT_DTAG, 0, + e->losscountwidth); + hdrlen += mkBinaryInt(dummy, CCNL_DTAG_FRAG_YSEQN, CCN_TT_DTAG, 0, + e->recvseqwidth); + + hdrlen += mkHeader(dummy, CCN_DTAG_CONTENT, CCN_TT_DTAG); + blobtaglen = mkHeader(dummy, e->mtu - hdrlen - 1, CCN_TT_BLOB); + datalen = e->mtu - hdrlen - blobtaglen - 1; + + if (datalen > (origlen - offs)) { + datalen = origlen - offs; + } + + hdrlen += mkHeader(dummy, datalen, CCN_TT_BLOB); + len += hdrlen + datalen + 1; + offs += datalen; + cnt++; + } + } + else if (e && e->protocol == CCNL_FRAG_CCNx2013) { + while (offs < origlen) { // we could do better than to simulate this: + hdrlen = mkHeader(dummy, CCNL_DTAG_FRAGMENT, CCN_TT_DTAG); + hdrlen += mkHeader(dummy, CCNL_DTAG_FRAG_TYPE, CCN_TT_DTAG); + hdrlen += 4; // three BLOB bytes plus end-of-entry + hdrlen += mkBinaryInt(dummy, CCNL_DTAG_FRAG_SEQNR, CCN_TT_DTAG, 0, + e->sendseqwidth); + hdrlen += mkBinaryInt(dummy, CCNL_DTAG_FRAG_FLAGS, CCN_TT_DTAG, 0, + e->flagwidth); + hdrlen += mkBinaryInt(dummy, CCNL_DTAG_FRAG_OLOSS, CCN_TT_DTAG, 0, + e->losscountwidth); + hdrlen += mkBinaryInt(dummy, CCNL_DTAG_FRAG_YSEQN, CCN_TT_DTAG, 0, + e->recvseqwidth); + + hdrlen += mkHeader(dummy, CCN_DTAG_CONTENT, CCN_TT_DTAG); + blobtaglen = mkHeader(dummy, e->mtu - hdrlen - 1, CCN_TT_BLOB); + datalen = e->mtu - hdrlen - blobtaglen - 1; + + if (datalen > (origlen - offs)) { + datalen = origlen - offs; + } + + hdrlen += mkHeader(dummy, datalen, CCN_TT_BLOB); + len += hdrlen + datalen + 1; + offs += datalen; + cnt++; + } + } + + if (totallen) { + *totallen = len; + } + + return cnt; +} + +struct ccnl_buf_s * +ccnl_frag_getnextSEQD2012(struct ccnl_frag_s *e, int *ifndx, sockunion *su) +{ + struct ccnl_buf_s *buf = 0; + unsigned char header[256]; + int hdrlen = 0, blobtaglen, flagoffs; + unsigned int datalen; + + DEBUGMSG(16, "ccnl_frag_getnextSEQD2012 e=%p, mtu=%d\n", (void *) e, e->mtu); + DEBUGMSG(17, " %d bytes to fragment, offset=%d\n", e->bigpkt->datalen, + e->sendoffs); + + hdrlen = mkHeader(header, CCNL_DTAG_FRAGMENT2012, CCN_TT_DTAG); + hdrlen += mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG_FLAGS, + CCN_TT_DTAG, 0, e->flagwidth); + flagoffs = hdrlen - 2; + hdrlen += mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG_YSEQN, + CCN_TT_DTAG, e->recvseq, e->recvseqwidth); + hdrlen += mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG_OLOSS, CCN_TT_DTAG, + e->losscount, e->losscountwidth); + + hdrlen += mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG_SEQNR, + CCN_TT_DTAG, e->sendseq, e->sendseqwidth); + hdrlen += mkHeader(header + hdrlen, CCN_DTAG_CONTENT, CCN_TT_DTAG); + blobtaglen = mkHeader(header + hdrlen, e->mtu - hdrlen - 2, CCN_TT_BLOB); + + datalen = e->mtu - hdrlen - blobtaglen - 2; + + if (datalen > (e->bigpkt->datalen - e->sendoffs)) { + datalen = e->bigpkt->datalen - e->sendoffs; + } + + hdrlen += mkHeader(header + hdrlen, datalen, CCN_TT_BLOB); + + buf = ccnl_buf_new(NULL, hdrlen + datalen + 2); + + if (!buf) { + return NULL; + } + + memcpy(buf->data, header, hdrlen); + memcpy(buf->data + hdrlen, e->bigpkt->data + e->sendoffs, datalen); + buf->data[hdrlen + datalen] = '\0'; // end of content/any field + buf->data[hdrlen + datalen + 1] = '\0'; // end of fragment/pdu + + if (datalen >= e->bigpkt->datalen) { // fits in a single fragment + buf->data[flagoffs + e->flagwidth - 1] = + CCNL_DTAG_FRAG_FLAG_FIRST | CCNL_DTAG_FRAG_FLAG_LAST; + ccnl_free(e->bigpkt); + e->bigpkt = NULL; + } + else if (e->sendoffs == 0) { // this is the start fragment + buf->data[flagoffs + e->flagwidth - 1] = CCNL_DTAG_FRAG_FLAG_FIRST; + } + else if (datalen >= (e->bigpkt->datalen - e->sendoffs)) { // the end + buf->data[flagoffs + e->flagwidth - 1] = CCNL_DTAG_FRAG_FLAG_LAST; + ccnl_free(e->bigpkt); + e->bigpkt = NULL; + } + else + // in the middle + { + buf->data[flagoffs + e->flagwidth - 1] = 0x00; + } + + e->sendoffs += datalen; + e->sendseq++; + + DEBUGMSG(17, " e->offset now %d\n", e->sendoffs); + + if (ifndx) { + *ifndx = e->ifndx; + } + + if (su) { + memcpy(su, &e->dest, sizeof(*su)); + } + + return buf; +} + +struct ccnl_buf_s * +ccnl_frag_getnextCCNx2013(struct ccnl_frag_s *fr, int *ifndx, sockunion *su) +{ + struct ccnl_buf_s *buf = 0; + unsigned char header[256]; + int hdrlen, blobtaglen, flagoffs; + unsigned int datalen; + + // switch among encodings of fragments here (ccnb, TLV, etc) + + hdrlen = mkHeader(header, CCNL_DTAG_FRAGMENT, CCN_TT_DTAG); // fragment + + hdrlen += mkHeader(header + hdrlen, CCNL_DTAG_FRAG_TYPE, CCN_TT_DTAG); + hdrlen += mkHeader(header + hdrlen, 3, CCN_TT_BLOB); + memcpy(header + hdrlen, CCNL_FRAG_TYPE_CCNx2013_VAL, 3); // "FHBH" + header[hdrlen + 3] = '\0'; + hdrlen += 4; + + hdrlen += mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG_SEQNR, CCN_TT_DTAG, + fr->sendseq, fr->sendseqwidth); + + hdrlen += mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG_FLAGS, CCN_TT_DTAG, 0, + fr->flagwidth); + flagoffs = hdrlen - 2; // most significant byte of flag element + + // other optional fields would go here + + hdrlen += mkHeader(header + hdrlen, CCN_DTAG_CONTENT, CCN_TT_DTAG); + + blobtaglen = mkHeader(header + hdrlen, fr->mtu - hdrlen - 2, CCN_TT_BLOB); + datalen = fr->mtu - hdrlen - blobtaglen - 2; + + if (datalen > (fr->bigpkt->datalen - fr->sendoffs)) { + datalen = fr->bigpkt->datalen - fr->sendoffs; + } + + hdrlen += mkHeader(header + hdrlen, datalen, CCN_TT_BLOB); + + buf = ccnl_buf_new(NULL, hdrlen + datalen + 2); + + if (!buf) { + return NULL; + } + + memcpy(buf->data, header, hdrlen); + memcpy(buf->data + hdrlen, fr->bigpkt->data + fr->sendoffs, datalen); + buf->data[hdrlen + datalen] = '\0'; // end of content field + buf->data[hdrlen + datalen + 1] = '\0'; // end of fragment + + // patch flag field: + if (datalen >= fr->bigpkt->datalen) { // single + buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_SINGLE; + ccnl_free(fr->bigpkt); + fr->bigpkt = NULL; + } + else if (fr->sendoffs == 0) { // start + buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_FIRST; + } + else if (datalen >= (fr->bigpkt->datalen - fr->sendoffs)) { // end + buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_LAST; + ccnl_free(fr->bigpkt); + fr->bigpkt = NULL; + } + else { + buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_MID; + } + + fr->sendoffs += datalen; + fr->sendseq++; + + if (ifndx) { + *ifndx = fr->ifndx; + } + + if (su) { + memcpy(su, &fr->dest, sizeof(*su)); + } + + return buf; +} + +struct ccnl_buf_s * +ccnl_frag_getnext(struct ccnl_frag_s *fr, int *ifndx, sockunion *su) +{ + if (!fr->bigpkt) { + return NULL; + } + + DEBUGMSG(99, "fragmenting %d bytes (@ %d)\n", fr->bigpkt->datalen, + fr->sendoffs); + + switch (fr->protocol) { + case CCNL_FRAG_SEQUENCED2012: + return ccnl_frag_getnextSEQD2012(fr, ifndx, su); + + case CCNL_FRAG_CCNx2013: + return ccnl_frag_getnextCCNx2013(fr, ifndx, su); + + default: + return NULL; + } +} + +int ccnl_frag_nomorefragments(struct ccnl_frag_s *e) +{ + if (!e || !e->bigpkt) { + return 1; + } + + return e->bigpkt->datalen <= e->sendoffs; +} + +void ccnl_frag_destroy(struct ccnl_frag_s *e) +{ + if (e) { + ccnl_free(e->bigpkt); + ccnl_free(e->defrag); + ccnl_free(e); + } +} + +// ---------------------------------------------------------------------- + +struct serialFragPDU_s { // collect all fields of a numbered HBH fragment + int contlen; + unsigned char *content; + unsigned int flags, ourseq, ourloss, yourseq, HAS; + unsigned char flagwidth, ourseqwidth, ourlosswidth, yourseqwidth; +}; + +void serialFragPDU_init(struct serialFragPDU_s *s) +{ + memset(s, 0, sizeof(*s)); + s->contlen = -1; + s->flagwidth = 1; + s->ourseqwidth = s->ourlosswidth = s->yourseqwidth = sizeof(int); +} + +void ccnl_frag_RX_serialfragment(RX_datagram callback, + struct ccnl_relay_s *relay, struct ccnl_face_s *from, + struct serialFragPDU_s *s) +{ + struct ccnl_buf_s *buf = NULL; + struct ccnl_frag_s *e = from->frag; + DEBUGMSG(8, " frag %p protocol=%d, flags=%04x, seq=%d (%d)\n", (void *) e, + e->protocol, s->flags, s->ourseq, e->recvseq); + + if (e->recvseq != s->ourseq) { + // should increase error counter here + if (e->defrag) { + DEBUGMSG(17, " >> seqnum mismatch (%d/%d), dropped defrag buf\n", + s->ourseq, e->recvseq); + ccnl_free(e->defrag); + e->defrag = NULL; + } + } + + switch (s->flags & (CCNL_DTAG_FRAG_FLAG_FIRST | CCNL_DTAG_FRAG_FLAG_LAST)) { + case CCNL_DTAG_FRAG_FLAG_SINGLE: // single packet + DEBUGMSG(17, " >> single fragment\n"); + + if (e->defrag) { + DEBUGMSG(18, " had to drop defrag buf\n"); + ccnl_free(e->defrag); + e->defrag = NULL; + } + + // no need to copy the buffer: + callback(relay, from, &s->content, &s->contlen); + return; + + case CCNL_DTAG_FRAG_FLAG_FIRST: // start of fragment sequence + DEBUGMSG(17, " >> start of fragment series\n"); + + if (e->defrag) { + DEBUGMSG(18, " had to drop defrag buf\n"); + ccnl_free(e->defrag); + } + + e->defrag = ccnl_buf_new(s->content, s->contlen); + break; + + case CCNL_DTAG_FRAG_FLAG_LAST: // end of fragment sequence + DEBUGMSG(17, " >> last fragment of a series\n"); + + if (!e->defrag) { + break; + } + + buf = ccnl_buf_new(NULL, e->defrag->datalen + s->contlen); + + if (buf) { + memcpy(buf->data, e->defrag->data, e->defrag->datalen); + memcpy(buf->data + e->defrag->datalen, s->content, s->contlen); + } + + ccnl_free(e->defrag); + e->defrag = NULL; + break; + + case CCNL_DTAG_FRAG_FLAG_MID: // fragment in the middle of a squence + default: + DEBUGMSG(17, " >> fragment in the middle of a series\n"); + + if (!e->defrag) { + break; + } + + buf = ccnl_buf_new(NULL, e->defrag->datalen + s->contlen); + + if (buf) { + memcpy(buf->data, e->defrag->data, e->defrag->datalen); + memcpy(buf->data + e->defrag->datalen, s->content, s->contlen); + ccnl_free(e->defrag); + e->defrag = buf; + buf = NULL; + } + else { + ccnl_free(e->defrag); + e->defrag = NULL; + } + + break; + } + + // FIXME: we should only bump recvseq if s->ourseq is ahead, or 0 + e->recvseq = s->ourseq + 1; + DEBUGMSG(1, ">>> seq from %d to %d (w=%d)\n", s->ourseq, e->recvseq, + s->ourseqwidth); + + if (buf) { + unsigned char *frag = buf->data; + int fraglen = buf->datalen; + DEBUGMSG(1, " >> reassembled fragment is %d bytes\n", buf->datalen); + callback(relay, from, &frag, &fraglen); + ccnl_free(buf); + } + + DEBUGMSG(1, "leaving function\n"); +} + +// ---------------------------------------------------------------------- + +#define getNumField(var,len,flag,rem) \ + DEBUGMSG(19, " parsing " rem "\n"); \ + if (unmkBinaryInt(data, datalen, &var, &len) != 0) \ + goto Bail; \ + s.HAS |= flag +#define HAS_FLAGS 0x01 +#define HAS_OSEQ 0x02 +#define HAS_OLOS 0x04 +#define HAS_YSEQ 0x08 + +int ccnl_frag_RX_frag2012(RX_datagram callback, struct ccnl_relay_s *relay, + struct ccnl_face_s *from, unsigned char **data, int *datalen) +{ + int num, typ; + struct serialFragPDU_s s; + DEBUGMSG(99, "ccnl_frag_RX_frag2012 (%d bytes)\n", *datalen); + + serialFragPDU_init(&s); + + while (dehead(data, datalen, &num, &typ) == 0) { + if (num == 0 && typ == 0) { + break; // end + } + + if (typ == CCN_TT_DTAG) { + switch (num) { + case CCN_DTAG_CONTENT: + DEBUGMSG(18, " frag content\n"); + + // if (s.content) // error: more than one content entry + if (consume(typ, num, data, datalen, &s.content, &s.contlen) + < 0) { + goto Bail; + } + + continue; + + case CCNL_DTAG_FRAG_FLAGS: + getNumField(s.flags, s.flagwidth, HAS_FLAGS, "flags") + ; + continue; + + case CCNL_DTAG_FRAG_SEQNR: + getNumField(s.ourseq, s.ourseqwidth, HAS_OSEQ, "ourseq") + ; + continue; + + case CCNL_DTAG_FRAG_OLOSS: + getNumField(s.ourloss, s.ourlosswidth, HAS_OLOS, "ourloss") + ; + continue; + + case CCNL_DTAG_FRAG_YSEQN: + getNumField(s.yourseq, s.yourseqwidth, HAS_YSEQ, "yourseq") + ; + continue; + + default: + break; + } + } + + if (consume(typ, num, data, datalen, 0, 0) < 0) { + goto Bail; + } + } + + if (!s.content || s.HAS != 15) { + DEBUGMSG(1, "* incomplete frag\n"); + return 0; + } + + if (from) { + if (!from->frag) + from->frag = ccnl_frag_new(CCNL_FRAG_SEQUENCED2012, + relay->ifs[from->ifndx].mtu); + + if (from->frag && from->frag->protocol == CCNL_FRAG_SEQUENCED2012) { + ccnl_frag_RX_serialfragment(callback, relay, from, &s); + } + else { + DEBUGMSG(1, "WRONG FRAG PROTOCOL\n"); + } + } + else { + ccnl_frag_RX_serialfragment(callback, relay, from, &s); + } + + return 0; +Bail: + DEBUGMSG(1, "* frag bailing\n"); + return -1; +} + +int ccnl_frag_RX_CCNx2013(RX_datagram callback, struct ccnl_relay_s *relay, + struct ccnl_face_s *from, unsigned char **data, int *datalen) +{ + int rc, num, typ, pdutypelen; + unsigned char *pdutype = 0; + struct serialFragPDU_s s; + + DEBUGMSG(99, "ccnl_frag_RX_CCNx2013 (%d bytes)\n", *datalen); + serialFragPDU_init(&s); + + while (dehead(data, datalen, &num, &typ) == 0) { + if (num == 0 && typ == 0) { + break; // end + } + + if (typ == CCN_TT_DTAG) { + switch (num) { + case CCNL_DTAG_FRAG_TYPE: + if (hunt_for_end(data, datalen, &pdutype, &pdutypelen) + || pdutypelen != 3) { + goto Bail; + } + + continue; + + case CCNL_DTAG_FRAG_SEQNR: + getNumField(s.ourseq, s.ourseqwidth, HAS_OSEQ, "ourseq") + ; + continue; + + case CCNL_DTAG_FRAG_FLAGS: + getNumField(s.flags, s.flagwidth, HAS_FLAGS, "flags") + ; + continue; + + case CCN_DTAG_CONTENT: + + // if (frag) // error: more than one content entry + if (consume(typ, num, data, datalen, &s.content, &s.contlen) + < 0) { + goto Bail; + } + + continue; + + // CCNL extensions: + case CCN_DTAG_INTEREST: + case CCN_DTAG_CONTENTOBJ: + rc = ccnl_core_RX_i_or_c(relay, from, data, datalen); + + if (rc < 0) { + return rc; + } + + continue; + + case CCNL_DTAG_FRAG_OLOSS: + getNumField(s.ourloss, s.ourlosswidth, HAS_OLOS, "ourloss") + ; + continue; + + case CCNL_DTAG_FRAG_YSEQN: + getNumField(s.yourseq, s.yourseqwidth, HAS_YSEQ, "yourseq") + ; + continue; + + default: + break; + } + } + + if (consume(typ, num, data, datalen, 0, 0) < 0) { + goto Bail; + } + } + + if (!pdutype || !s.content) { + /* || + (s.HAS&(HAS_FLAGS|HAS_OSEQ)) != (HAS_FLAGS|HAS_OSEQ) ) { + */ + DEBUGMSG(1, "* incomplete frag\n"); + return 0; + } + + DEBUGMSG(1, "hop-by-hop\n"); + + if (memcmp(pdutype, CCNL_FRAG_TYPE_CCNx2013_VAL, 3) == 0) { // hop-by-hop + if (from) { + if (!from->frag) + from->frag = ccnl_frag_new(CCNL_FRAG_CCNx2013, + relay->ifs[from->ifndx].mtu); + + if (from->frag && from->frag->protocol == CCNL_FRAG_CCNx2013) { + ccnl_frag_RX_serialfragment(callback, relay, from, &s); + } + else { + DEBUGMSG(1, "WRONG FRAG PROTOCOL\n"); + } + } + else { + ccnl_frag_RX_serialfragment(callback, relay, from, &s); + } + } + + /* + * echo "FMTE" | base64 -d | hexdump -v -e '/1 "@x%02x"'| tr @ '\\'; echo + */ + if (memcmp(pdutype, "\x14\xc4\xc4", 3) == 0) { // mid-to-end fragment + // not implemented yet + } + + DEBUGMSG(1, "mid-to-end fragment\n"); + + return 0; +Bail: + DEBUGMSG(1, "* frag bailing\n"); + return -1; +} + +#endif // USE_FRAG +// eof diff --git a/sys/net/ccn_lite/ccnl-ext-mgmt.c b/sys/net/ccn_lite/ccnl-ext-mgmt.c new file mode 100644 index 000000000..6610ae868 --- /dev/null +++ b/sys/net/ccn_lite/ccnl-ext-mgmt.c @@ -0,0 +1,643 @@ +/* + * @f ccnl-ext-mgmt.c + * @b CCN lite extension, management logic (face mgmt and registration) + * + * Copyright (C) 2012-13, Christian Tschudin, University of Basel + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2012-05-06 created + */ + +#ifndef USE_MGMT +#define USE_MGMT 1 +#endif + +#ifndef CCNL_RIOT +#define CCNL_RIOT 1 +#endif + +#ifdef USE_MGMT + +#include +#include + +#include "ccnx.h" +#include "ccnl-pdu.h" +#include "ccnl.h" +#include "ccnl-includes.h" +#include "ccnl-core.h" +#include "ccnl-ext.h" + +unsigned char contentobj_buf[500]; +unsigned char faceinst_buf[500]; +unsigned char out_buf[500]; +unsigned char fwdentry_buf[500]; + +char * +ccnl_addr2ascii(sockunion *su) +{ + static char buf[10]; + snprintf(buf, sizeof(buf), "%d", su->id); + return buf; +} + +// ---------------------------------------------------------------------- +int +ccnl_is_local_addr(sockunion *su) +{ + (void) su ; /*unused */ + return 1; +} + +struct ccnl_prefix_s * +ccnl_prefix_clone(struct ccnl_prefix_s *p) +{ + int i, len; + struct ccnl_prefix_s *p2; + + p2 = (struct ccnl_prefix_s *) ccnl_calloc(1, sizeof(struct ccnl_prefix_s)); + + if (!p2) { + return NULL; + } + + for (i = 0, len = 0; i < p->compcnt; len += p->complen[i++]); + + p2->path = (unsigned char *) ccnl_malloc(len); + p2->comp = (unsigned char **) ccnl_malloc(p->compcnt * sizeof(char *)); + p2->complen = (int *) ccnl_malloc(p->compcnt * sizeof(int)); + + if (!p2->comp || !p2->complen || !p2->path) { + goto Bail; + } + + p2->compcnt = p->compcnt; + + for (i = 0, len = 0; i < p->compcnt; len += p2->complen[i++]) { + p2->complen[i] = p->complen[i]; + p2->comp[i] = p2->path + len; + memcpy(p2->comp[i], p->comp[i], p2->complen[i]); + } + + return p2; +Bail: + free_prefix(p2); + return NULL; +} + +// ---------------------------------------------------------------------- +// management protocols + +#define extractStr(VAR,DTAG) \ + if (typ == CCN_TT_DTAG && num == DTAG) { \ + char *s; unsigned char *valptr; int vallen; \ + if (consume(typ, num, &buf, &buflen, &valptr, &vallen) < 0) goto Bail; \ + s = ccnl_malloc(vallen+1); if (!s) goto Bail; \ + memcpy(s, valptr, vallen); s[vallen] = '\0'; \ + ccnl_free(VAR); \ + VAR = (unsigned char*) s; \ + continue; \ + } do {} while(0) + +void +ccnl_mgmt_return_msg(struct ccnl_relay_s *ccnl, struct ccnl_buf_s *orig, + struct ccnl_face_s *from, char *msg) +{ + (void) orig; /* unused */ + + struct ccnl_buf_s *buf; + + // this is a temporary non-solution: a CCN-content reply should + // be returned instead of a string message + + buf = ccnl_buf_new(msg, strlen(msg)); + ccnl_face_enqueue(ccnl, from, buf); +} + +int +ccnl_mgmt_newface(struct ccnl_relay_s *ccnl, struct ccnl_buf_s *orig, + struct ccnl_prefix_s *prefix, struct ccnl_face_s *from) +{ + (void) orig; /* unused */ + + unsigned char *buf; + int buflen, num, typ; + unsigned char *action, *macsrc, *ip4src, *proto, *host, *port, + *path, *frag, *flags; + char *cp = "newface cmd failed"; + int rc = -1; + struct ccnl_face_s *f = NULL; + //varibales for answer + struct ccnl_buf_s *retbuf; + // unsigned char out[2000]; + int len = 0, len2, len3; + // unsigned char contentobj[2000]; + // unsigned char faceinst[2000]; + unsigned char faceidstr[100]; + unsigned char retstr[200]; + + DEBUGMSG(99, "ccnl_mgmt_newface from=%p, ifndx=%d\n", + (void *) from, from->ifndx); + action = macsrc = ip4src = proto = host = port = NULL; + path = frag = flags = NULL; + + buf = prefix->comp[3]; + buflen = prefix->complen[3]; + + if (dehead(&buf, &buflen, &num, &typ) < 0) { + goto Bail; + } + + if (typ != CCN_TT_DTAG || num != CCN_DTAG_CONTENTOBJ) { + goto Bail; + } + + if (dehead(&buf, &buflen, &num, &typ) != 0) { + goto Bail; + } + + if (typ != CCN_TT_DTAG || num != CCN_DTAG_CONTENT) { + goto Bail; + } + + if (dehead(&buf, &buflen, &num, &typ) != 0) { + goto Bail; + } + + if (typ != CCN_TT_BLOB) { + goto Bail; + } + + buflen = num; + + if (dehead(&buf, &buflen, &num, &typ) != 0) { + goto Bail; + } + + if (typ != CCN_TT_DTAG || num != CCN_DTAG_FACEINSTANCE) { + goto Bail; + } + + while (dehead(&buf, &buflen, &num, &typ) == 0) { + if (num == 0 && typ == 0) { + break; // end + } + + extractStr(action, CCN_DTAG_ACTION); + extractStr(macsrc, CCNL_DTAG_MACSRC); + extractStr(ip4src, CCNL_DTAG_IP4SRC); + extractStr(path, CCNL_DTAG_UNIXSRC); + extractStr(proto, CCN_DTAG_IPPROTO); + extractStr(host, CCN_DTAG_HOST); + extractStr(port, CCN_DTAG_PORT); + // extractStr(frag, CCNL_DTAG_FRAG); + extractStr(flags, CCNL_DTAG_FACEFLAGS); + + if (consume(typ, num, &buf, &buflen, 0, 0) < 0) { + goto Bail; + } + } + + // should (re)verify that action=="newface" + + /***************************************************************************/ + + int ifndx = 0; + + if (strcmp((const char *) macsrc, "newTRANSface") == 0) { + ifndx = RIOT_TRANS_IDX; + } + else if (strcmp((const char *) macsrc, "newMSGface") == 0) { + ifndx = RIOT_MSG_IDX; + } + else { + goto Bail; + } + + uint16_t faceid = 0; + + if (port) { + faceid = atoi((const char *) port); + } + else { + goto Bail; + } + + // create face ontop of the traceceiver iface + DEBUGMSG(1, "new %s=%d face gets created - faceid==%s==%d!\n", (const char *) macsrc, ifndx, (const char *) port, faceid); + f = ccnl_get_face_or_create( + ccnl, + ifndx, + faceid + ); + + /***************************************************************************/ + if (f) { + int flagval = flags ? + strtol((const char *)flags, NULL, 0) : CCNL_FACE_FLAGS_STATIC; + // DEBUGMSG(1, " flags=%s %d\n", flags, flagval); + DEBUGMSG(99, " adding a new face (id=%d) worked!\n", f->faceid); + f->flags = flagval & + (CCNL_FACE_FLAGS_STATIC | CCNL_FACE_FLAGS_REFLECT); + +#ifdef USE_FRAG + + if (frag) { + int mtu = 1500; + + if (f->frag) { + ccnl_frag_destroy(f->frag); + f->frag = NULL; + } + + if (f->ifndx >= 0 && ccnl->ifs[f->ifndx].mtu > 0) { + mtu = ccnl->ifs[f->ifndx].mtu; + } + + f->frag = ccnl_frag_new(strtol((const char *)frag, NULL, 0), + mtu); + } + +#endif + cp = "newface cmd worked"; + } + else { + DEBUGMSG(99, " newface request for (macsrc=%s ip4src=%s proto=%s host=%s port=%s frag=%s flags=%s) failed or was ignored\n", + macsrc, ip4src, proto, host, port, frag, flags); + } + + rc = 0; + +Bail: + /*ANSWER*/ + + len = mkHeader(out_buf, CCN_DTAG_CONTENT, CCN_TT_DTAG); // content + len += mkHeader(out_buf + len, CCN_DTAG_NAME, CCN_TT_DTAG); // name + + len += mkStrBlob(out_buf + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "ccnx"); + len += mkStrBlob(out_buf + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, ""); + + len += mkStrBlob(out_buf + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "newface"); + + // prepare FACEINSTANCE + len3 = mkHeader(faceinst_buf, CCN_DTAG_FACEINSTANCE, CCN_TT_DTAG); + sprintf((char *)retstr, "newface: %s", cp); + len3 += mkStrBlob(faceinst_buf + len3, CCN_DTAG_ACTION, CCN_TT_DTAG, (char *) retstr); + + if (macsrc) { + len3 += mkStrBlob(faceinst_buf + len3, CCNL_DTAG_MACSRC, CCN_TT_DTAG, (char *) macsrc); + } + + if (ip4src) { + len3 += mkStrBlob(faceinst_buf + len3, CCNL_DTAG_IP4SRC, CCN_TT_DTAG, (char *) ip4src); + len3 += mkStrBlob(faceinst_buf + len3, CCN_DTAG_IPPROTO, CCN_TT_DTAG, "17"); + } + + if (host) { + len3 += mkStrBlob(faceinst_buf + len3, CCN_DTAG_HOST, CCN_TT_DTAG, (char *) host); + } + + if (port) { + len3 += mkStrBlob(faceinst_buf + len3, CCN_DTAG_PORT, CCN_TT_DTAG, (char *) port); + } + + /* + if (frag) + len3 += mkStrBlob(faceinst+len3, CCNL_DTAG_FRAG, CCN_TT_DTAG, frag); + */ + if (flags) { + len3 += mkStrBlob(faceinst_buf + len3, CCNL_DTAG_FACEFLAGS, CCN_TT_DTAG, (char *) flags); + } + + if (f) { + sprintf((char *)faceidstr, "%i", f->faceid); + len3 += mkStrBlob(faceinst_buf + len3, CCN_DTAG_FACEID, CCN_TT_DTAG, (char *) faceidstr); + } + + faceinst_buf[len3++] = 0; // end-of-faceinst + + // prepare CONTENTOBJ with CONTENT + len2 = mkHeader(contentobj_buf, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG);// contentobj + len2 += mkBlob(contentobj_buf + len2, CCN_DTAG_CONTENT, CCN_TT_DTAG, // content + (char *) faceinst_buf, len3); + contentobj_buf[len2++] = 0;// end-of-contentobj + + // add CONTENTOBJ as the final name component + len += mkBlob(out_buf + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, // comp + (char *) contentobj_buf, len2); + + out_buf[len++] = (unsigned char) 0;// end-of-name + out_buf[len++] = (unsigned char) 0;// end-of-interest + + retbuf = ccnl_buf_new((char *)out_buf, len); + ccnl_face_enqueue(ccnl, from, retbuf); + + /*END ANWER*/ + + ccnl_free(action); + ccnl_free(macsrc); + ccnl_free(ip4src); + ccnl_free(proto); + ccnl_free(host); + ccnl_free(port); + ccnl_free(frag); + ccnl_free(flags); + + //ccnl_mgmt_return_msg(ccnl, orig, from, cp); + return rc; +} + +int +ccnl_mgmt_prefixreg(struct ccnl_relay_s *ccnl, struct ccnl_buf_s *orig, + struct ccnl_prefix_s *prefix, struct ccnl_face_s *from) +{ + unsigned char *buf; + int buflen, num, typ; + struct ccnl_prefix_s *p = NULL; + unsigned char *action, *faceid; + char *cp = "prefixreg cmd failed"; + int rc = -1; + //variables for answer + int len = 0, len2, len3; + + DEBUGMSG(1, "ccnl_mgmt_prefixreg\n"); + action = faceid = NULL; + + buf = prefix->comp[3]; + buflen = prefix->complen[3]; + + if (dehead(&buf, &buflen, &num, &typ) < 0) { + goto Bail; + } + + if (typ != CCN_TT_DTAG || num != CCN_DTAG_CONTENTOBJ) { + goto Bail; + } + + if (dehead(&buf, &buflen, &num, &typ) != 0) { + goto Bail; + } + + if (typ != CCN_TT_DTAG || num != CCN_DTAG_CONTENT) { + goto Bail; + } + + if (dehead(&buf, &buflen, &num, &typ) != 0) { + goto Bail; + } + + if (typ != CCN_TT_BLOB) { + goto Bail; + } + + buflen = num; + + if (dehead(&buf, &buflen, &num, &typ) != 0) { + goto Bail; + } + + if (typ != CCN_TT_DTAG || num != CCN_DTAG_FWDINGENTRY) { + goto Bail; + } + + p = (struct ccnl_prefix_s *) ccnl_calloc(1, sizeof(struct ccnl_prefix_s)); + + if (!p) { + goto Bail; + } + + p->comp = (unsigned char **) ccnl_malloc(CCNL_MAX_NAME_COMP * + sizeof(unsigned char *)); + p->complen = (int *) ccnl_malloc(CCNL_MAX_NAME_COMP * sizeof(int)); + + if (!p->comp || !p->complen) { + goto Bail; + } + + while (dehead(&buf, &buflen, &num, &typ) == 0) { + if (num == 0 && typ == 0) { + break; // end + } + + if (typ == CCN_TT_DTAG && num == CCN_DTAG_NAME) { + for (;;) { + if (dehead(&buf, &buflen, &num, &typ) != 0) { + goto Bail; + } + + if (num == 0 && typ == 0) { + break; + } + + if (typ == CCN_TT_DTAG && num == CCN_DTAG_COMPONENT && + p->compcnt < CCNL_MAX_NAME_COMP) { + // if (ccnl_grow_prefix(p)) goto Bail; + if (consume(typ, num, &buf, &buflen, + p->comp + p->compcnt, + p->complen + p->compcnt) < 0) { + goto Bail; + } + + p->compcnt++; + } + else { + if (consume(typ, num, &buf, &buflen, 0, 0) < 0) { + goto Bail; + } + } + } + + continue; + } + + extractStr(action, CCN_DTAG_ACTION); + extractStr(faceid, CCN_DTAG_FACEID); + + if (consume(typ, num, &buf, &buflen, 0, 0) < 0) { + goto Bail; + } + } + + // should (re)verify that action=="prefixreg" + if (faceid && p->compcnt > 0) { + struct ccnl_face_s *f; + struct ccnl_forward_s *fwd, **fwd2; + int fi = strtol((const char *)faceid, NULL, 0); + + DEBUGMSG(1, "mgmt: adding prefix %s to faceid='%s'='%d'\n", + ccnl_prefix_to_path(p), faceid, fi); + + for (f = ccnl->faces; f && f->faceid != fi; f = f->next) { + DEBUGMSG(1, "faceid=%d\n", f->faceid); + } + + if (!f) { + DEBUGMSG(1, "bail!\n"); + goto Bail; + } + + DEBUGMSG(1, "Face %s found! ifndx=%d\n", faceid, f->ifndx); + fwd = (struct ccnl_forward_s *) ccnl_calloc(1, sizeof(*fwd)); + + if (!fwd) { + goto Bail; + } + + fwd->prefix = ccnl_prefix_clone(p); + fwd->face = f; + fwd2 = &ccnl->fib; + + while (*fwd2) { + fwd2 = &((*fwd2)->next); + } + + *fwd2 = fwd; + + cp = "prefixreg cmd worked"; + } + else { + DEBUGMSG(1, "mgmt: ignored prefixreg faceid=%s\n", faceid); + } + + rc = 0; + +Bail: + /*ANSWER*/ + + len = mkHeader(out_buf, CCN_DTAG_CONTENT, CCN_TT_DTAG); // interest + len += mkHeader(out_buf + len, CCN_DTAG_NAME, CCN_TT_DTAG); // name + + len += mkStrBlob(out_buf + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "ccnx"); + len += mkStrBlob(out_buf + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, ""); + len += mkStrBlob(out_buf + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, (char *) action); + + // prepare FWDENTRY + len3 = mkHeader(fwdentry_buf, CCNL_DTAG_PREFIX, CCN_TT_DTAG); + len3 += mkStrBlob(fwdentry_buf + len3, CCN_DTAG_ACTION, CCN_TT_DTAG, cp); + len3 += mkStrBlob(fwdentry_buf + len3, CCN_DTAG_NAME, CCN_TT_DTAG, ccnl_prefix_to_path(p)); // prefix + + len3 += mkStrBlob(fwdentry_buf + len3, CCN_DTAG_FACEID, CCN_TT_DTAG, (char *) faceid); + fwdentry_buf[len3++] = 0;// end-of-fwdentry + + // prepare CONTENTOBJ with CONTENT + len2 = mkHeader(contentobj_buf, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG);// contentobj + len2 += mkBlob(contentobj_buf + len2, CCN_DTAG_CONTENT, CCN_TT_DTAG, // content + (char *) fwdentry_buf, len3); + contentobj_buf[len2++] = 0;// end-of-contentobj + + // add CONTENTOBJ as the final name component + len += mkBlob(out_buf + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, // comp + (char *) contentobj_buf, len2); + + out_buf[len++] = 0;// end-of-name + out_buf[len++] = 0;// end-of-interest + + /*END ANWER*/ + ccnl_free(faceid); + ccnl_free(action); + free_prefix(p); + + DEBUGMSG(1, "data='%s' faceid=%d cp='%s'\n", orig->data, from->faceid, cp); + ccnl_mgmt_return_msg(ccnl, orig, from, cp); + return rc; +} + +static int ccnl_mgmt_handle(struct ccnl_relay_s *ccnl, struct ccnl_buf_s *orig, + struct ccnl_prefix_s *prefix, struct ccnl_face_s *from, char *cmd, + int verified) +{ + DEBUGMSG(99, "ccnl_mgmt_handle \"%s\"\n", cmd); + if (!verified) { + ccnl_mgmt_return_msg(ccnl, orig, from, + "refused: error signature not verified"); + return -1; + } + + if (!strcmp(cmd, "newface")) { + DEBUGMSG(1, "ccnl_mgmt_newface msg\n"); + ccnl_mgmt_newface(ccnl, orig, prefix, from); + } else if (!strcmp(cmd, "prefixreg")) { + DEBUGMSG(1, "ccnl_mgmt_prefixreg msg\n"); + ccnl_mgmt_prefixreg(ccnl, orig, prefix, from); + } else { + DEBUGMSG(99, "unknown mgmt command %s\n", cmd); + + ccnl_mgmt_return_msg(ccnl, orig, from, "unknown mgmt command"); + return -1; + } + + return 0; +} + +char cmd[500]; +int ccnl_mgmt(struct ccnl_relay_s *ccnl, struct ccnl_buf_s *orig, + struct ccnl_prefix_s *prefix, struct ccnl_face_s *from) +{ + if (prefix->complen[2] < (int) sizeof(cmd)) { + memcpy(cmd, prefix->comp[2], prefix->complen[2]); + cmd[prefix->complen[2]] = '\0'; + } else { + strcpy(cmd, "cmd-is-too-long-to-display"); + } + + DEBUGMSG(99, "ccnl_mgmt request \"%s\"\n", cmd); + + if (ccnl_is_local_addr(&from->peer)) + goto MGMT; + + DEBUGMSG(99, " rejecting because src=%s is not a local addr\n", + ccnl_addr2ascii(&from->peer)); + ccnl_mgmt_return_msg(ccnl, orig, from, + "refused: origin of mgmt cmd is not local"); + return -1; + + MGMT: ccnl_mgmt_handle(ccnl, orig, prefix, from, cmd, 1); + + return 0; +} + +#if 0 + char *cmd = (char *) prefix->comp[2]; + + if (!ccnl_is_local_addr(&from->peer)) { + DEBUGMSG(99, " rejecting because src=%s is not a local addr\n", + ccnl_addr2ascii(&from->peer)); + ccnl_mgmt_return_msg(ccnl, orig, from, + "refused: origin of mgmt cmd is not local"); + return -1; + } + + if (!strcmp(cmd, "newface")) { + DEBUGMSG(1, "ccnl_mgmt_newface msg\n"); + ccnl_mgmt_newface(ccnl, orig, prefix, from); + } + else if (!strcmp(cmd, "prefixreg")) { + DEBUGMSG(1, "ccnl_mgmt_prefixreg msg\n"); + ccnl_mgmt_prefixreg(ccnl, orig, prefix, from); + } + else { + DEBUGMSG(99, "unknown mgmt command %s\n", cmd); + + ccnl_mgmt_return_msg(ccnl, orig, from, "unknown mgmt command"); + return -1; + } + + return 0; +} +#endif + +#endif // USE_MGMT +// eof diff --git a/sys/net/ccn_lite/ccnl-ext.h b/sys/net/ccn_lite/ccnl-ext.h new file mode 100644 index 000000000..2639c849f --- /dev/null +++ b/sys/net/ccn_lite/ccnl-ext.h @@ -0,0 +1,96 @@ +/* + * @f ccnl-ext.h + * @b header file for CCN lite extentions (forward declarations) + * + * Copyright (C) 2011-13, Christian Tschudin, University of Basel + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2013-03-30 created + */ + +// ---------------------------------------------------------------------- + +#ifndef CCNL_EXT_H__ +#define CCNL_EXT_H__ + +#ifdef USE_CCNxDIGEST +# define compute_ccnx_digest(buf) SHA256(buf->data, buf->datalen, NULL) +#else +# define compute_ccnx_digest(b) NULL +#endif + +#ifdef USE_FRAG + +struct ccnl_frag_s *ccnl_frag_new(int protocol, int mtu); + +void ccnl_frag_reset(struct ccnl_frag_s *e, struct ccnl_buf_s *buf, + int ifndx, sockunion *su); + +int ccnl_frag_getfragcount(struct ccnl_frag_s *e, int origlen, + int *totallen); + +struct ccnl_buf_s *ccnl_frag_getnext(struct ccnl_frag_s *e, + int *ifndx, sockunion *su); + +/* +struct ccnl_buf_s* ccnl_frag_handle_fragment(struct ccnl_relay_s *r, + struct ccnl_face_s *f, unsigned char *data, int datalen); +*/ + +void ccnl_frag_destroy(struct ccnl_frag_s *e); + +/* +struct ccnl_buf_s* ccnl_frag_fragment(struct ccnl_relay_s *ccnl, + struct ccnl_frag_s *frag, + struct ccnl_buf_s *buf); +*/ + +typedef int (RX_datagram)(struct ccnl_relay_s *, struct ccnl_face_s *, + unsigned char **, int *); + +int ccnl_frag_RX_frag2012(RX_datagram callback, struct ccnl_relay_s *relay, + struct ccnl_face_s *from, + unsigned char **data, int *datalen); + +int ccnl_frag_RX_CCNx2013(RX_datagram callback, struct ccnl_relay_s *relay, + struct ccnl_face_s *from, + unsigned char **data, int *datalen); + +int ccnl_is_fragment(unsigned char *data, int datalen); +#else +# define ccnl_frag_new(e,u) NULL +# define ccnl_frag_destroy(e) do{}while(0) +# define ccnl_frag_handle_fragment(r,f,data,len) ccnl_buf_new(data,len) +# define ccnl_is_fragment(d,l) 0 +#endif // USE_FRAG + +// ---------------------------------------------------------------------- + +// ---------------------------------------------------------------------- + +int ccnl_mgmt(struct ccnl_relay_s *ccnl, struct ccnl_buf_s *buf, + struct ccnl_prefix_s *prefix, struct ccnl_face_s *from); + +// ---------------------------------------------------------------------- + +# define ccnl_sched_CTS_done(S,C,L) do{}while(0) +# define ccnl_sched_destroy(S) do{}while(0) + +char *ccnl_prefix_to_path(struct ccnl_prefix_s *pr); + +#endif /* CCNL_EXT_H__ */ + +// eof diff --git a/sys/net/ccn_lite/ccnl-includes.h b/sys/net/ccn_lite/ccnl-includes.h new file mode 100644 index 000000000..5cd484c20 --- /dev/null +++ b/sys/net/ccn_lite/ccnl-includes.h @@ -0,0 +1,38 @@ +/* + * @f ccnl-includes.h + * @b does the #include of all (system) header file + * + * Copyright (C) 2011, Christian Tschudin, University of Basel + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2011-03-30 created + */ + +#include +#include +#include +#include +#include + +#include "rtc.h" +#include "sha256.h" + +#define RIOT_MSG_DEV (1) +#define RIOT_TRANS_DEV (2) + +#define RIOT_MSG_IDX (0) +#define RIOT_TRANS_IDX (1) + +// eof diff --git a/sys/net/ccn_lite/ccnl-pdu.c b/sys/net/ccn_lite/ccnl-pdu.c new file mode 100644 index 000000000..96997c383 --- /dev/null +++ b/sys/net/ccn_lite/ccnl-pdu.c @@ -0,0 +1,239 @@ +/* + * @f ccnl-pdu.c + * @b CCN lite - create and manipulate CCN protocol data units + * + * Copyright (C) 2011-13, Christian Tschudin, University of Basel + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2011-03-13 created (cft): orig name ccnl-parse-ccnb.c + * 2013-04-04 modified (ms): #if defined(CCNL_SIMULATION) || defined(CCNL_OMNET) + */ + +#ifndef CCNL_PDU +#define CCNL_PDU + +#include + +#include "ccnl-core.h" +#include "ccnx.h" + +int dehead(unsigned char **buf, int *len, int *num, int *typ) +{ + int i; + int val = 0; + + if (*len > 0 && **buf == 0) { // end + *num = *typ = 0; + *buf += 1; + *len -= 1; + return 0; + } + + for (i = 0; (unsigned int) i < sizeof(i) && i < *len; i++) { + unsigned char c = (*buf)[i]; + + if (c & 0x80) { + *num = (val << 4) | ((c >> 3) & 0xf); + *typ = c & 0x7; + *buf += i + 1; + *len -= i + 1; + return 0; + } + + val = (val << 7) | c; + } + + return -1; +} + +int mkHeader(unsigned char *buf, unsigned int num, unsigned int tt) +{ + unsigned char tmp[100]; + int len = 0, i; + + *tmp = 0x80 | ((num & 0x0f) << 3) | tt; + len = 1; + num = num >> 4; + + while (num > 0) { + tmp[len++] = num & 0x7f; + num = num >> 7; + } + + for (i = len - 1; i >= 0; i--) { + *buf++ = tmp[i]; + } + + return len; +} + +static int addBlob(unsigned char *out, char *cp, int cnt) +{ + int len; + + len = mkHeader(out, cnt, CCN_TT_BLOB); + memcpy(out + len, cp, cnt); + len += cnt; + + return len; +} + +int mkBlob(unsigned char *out, unsigned int num, unsigned int tt, char *cp, + int cnt) +{ + int len; + + len = mkHeader(out, num, tt); + len += addBlob(out + len, cp, cnt); + out[len++] = 0; + + return len; +} + +int mkStrBlob(unsigned char *out, unsigned int num, unsigned int tt, char *str) +{ + return mkBlob(out, num, tt, str, strlen(str)); +} + +int mkBinaryInt(unsigned char *out, unsigned int num, unsigned int tt, + unsigned int val, int bytes) +{ + int len = mkHeader(out, num, tt); + + if (!bytes) { + for (bytes = sizeof(val) - 1; bytes > 0; bytes--) + if (val >> (8 * bytes)) { + break; + } + + bytes++; + } + + len += mkHeader(out + len, bytes, CCN_TT_BLOB); + + while (bytes > 0) { // big endian + bytes--; + out[len++] = 0x0ff & (val >> (8 * bytes)); + } + + out[len++] = 0; // end-of-entry + return len; +} + +int unmkBinaryInt(unsigned char **data, int *datalen, unsigned int *result, + unsigned char *width) +{ + unsigned char *cp = *data; + int len = *datalen, typ, num; + unsigned int val = 0; + + if (dehead(&cp, &len, &num, &typ) != 0 || typ != CCN_TT_BLOB) { + return -1; + } + + if (width) { + if (*width < num) { + num = *width; + } + else { + *width = num; + } + } + + // big endian (network order): + while (num-- > 0 && len > 0) { + val = (val << 8) | *cp++; + len--; + } + + *result = val; + + if (len < 1 || *cp != '\0') { // no end-of-entry + return -1; + } + + *data = cp + 1; + *datalen = len - 1; + return 0; +} + +// ---------------------------------------------------------------------- +// (ms): Brought here the following two. I noticed also that some +// of them are replicated elsewhere in the util/ dir. Should we put them +// in one place only ? + +int mkInterest(char **namecomp, unsigned int *nonce, unsigned char *out) +{ + int len = 0, k; + + len = mkHeader(out, CCN_DTAG_INTEREST, CCN_TT_DTAG); // interest + len += mkHeader(out + len, CCN_DTAG_NAME, CCN_TT_DTAG); // name + + while (*namecomp) { + len += mkHeader(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG); // comp + k = strlen(*namecomp); + len += mkHeader(out + len, k, CCN_TT_BLOB); + memcpy(out + len, *namecomp++, k); + len += k; + out[len++] = 0; // end-of-component + } + + out[len++] = 0; // end-of-name + + if (nonce) { + len += mkHeader(out + len, CCN_DTAG_NONCE, CCN_TT_DTAG); + len += mkHeader(out + len, sizeof(unsigned int), CCN_TT_BLOB); + memcpy(out + len, (void *) nonce, sizeof(unsigned int)); + len += sizeof(unsigned int); + } + + out[len++] = 0; // end-of-interest + + return len; +} + +int +mkContent(char **namecomp, char *data, int datalen, unsigned char *out) +{ + int len = 0, k; + + len = mkHeader(out, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG); // content + len += mkHeader(out + len, CCN_DTAG_NAME, CCN_TT_DTAG); // name + + while (*namecomp) { + len += mkHeader(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG); // comp + k = strlen(*namecomp); + len += mkHeader(out + len, k, CCN_TT_BLOB); + memcpy(out + len, *namecomp++, k); + len += k; + out[len++] = 0;// end-of-component + } + + out[len++] = 0; // end-of-name + + len += mkHeader(out + len, CCN_DTAG_CONTENT, CCN_TT_DTAG); // content obj + len += mkHeader(out + len, datalen, CCN_TT_BLOB); + memcpy(out + len, data, datalen); + len += datalen; + out[len++] = 0;// end-of-content obj + + out[len++] = 0;// end-of-content + + return len; +} + +#endif /*CCNL_PDU*/ +// eof diff --git a/sys/net/ccn_lite/ccnl-pdu.h b/sys/net/ccn_lite/ccnl-pdu.h new file mode 100644 index 000000000..c8e779b2d --- /dev/null +++ b/sys/net/ccn_lite/ccnl-pdu.h @@ -0,0 +1,30 @@ +/* + * @f ccnl-pdu.h + * + * Copyright (C) 2013, Christian Mehlis, Freie University Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ccnl-riot.h" + +int dehead(unsigned char **buf, int *len, int *num, int *typ); +int mkHeader(unsigned char *buf, unsigned int num, unsigned int tt); +int mkBlob(unsigned char *out, unsigned int num, unsigned int tt, char *cp, int cnt); +int mkStrBlob(unsigned char *out, unsigned int num, unsigned int tt, char *str); +int mkBinaryInt(unsigned char *out, unsigned int num, unsigned int tt, + unsigned int val, int bytes); +int unmkBinaryInt(unsigned char **data, int *datalen, unsigned int *result, + unsigned char *width); +int mkInterest(char **namecomp, unsigned int *nonce, unsigned char *out); +int mkContent(char **namecomp, char *data, int datalen, unsigned char *out); diff --git a/sys/net/ccn_lite/ccnl-platform.c b/sys/net/ccn_lite/ccnl-platform.c new file mode 100644 index 000000000..5b746cf33 --- /dev/null +++ b/sys/net/ccn_lite/ccnl-platform.c @@ -0,0 +1,175 @@ +/* + * @f ccnl-platform.c + * @b routines for uniform time handling + * + * Copyright (C) 2011-13, Christian Tschudin, University of Basel + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2012-11 created + * 2013-03-18 updated (ms): removed omnet related code, and moved struct + * ccnl_timer_s to the '#ifndef CCNL_LINUXKERNEL' section + */ + +#include +#include + +#include "rtc.h" + +long +timevaldelta(struct timeval *a, struct timeval *b) +{ + return 1000000 * (a->tv_sec - b->tv_sec) + a->tv_usec - b->tv_usec; +} + +#include "ccnl-ext-debug.c" +#include "ccnl-platform.h" + +// ---------------------------------------------------------------------- + +struct ccnl_timer_s *eventqueue; + +void +ccnl_get_timeval(struct timeval *tv) +{ + //gettimeofday(tv, NULL); + rtc_time(tv); +} + +void * +ccnl_set_timer(int usec, void (*fct)(void *aux1, void *aux2), + void *aux1, void *aux2) +{ + struct ccnl_timer_s *t, **pp; + static int handlercnt; + + t = (struct ccnl_timer_s *) ccnl_calloc(1, sizeof(*t)); + + if (!t) { + return 0; + } + + t->fct2 = fct; + //gettimeofday(&t->timeout, NULL); + rtc_time(&t->timeout); + usec += t->timeout.tv_usec; + t->timeout.tv_sec += usec / 1000000; + t->timeout.tv_usec = usec % 1000000; + t->aux1 = aux1; + t->aux2 = aux2; + + for (pp = &eventqueue; ; pp = &((*pp)->next)) { + if (!*pp || (*pp)->timeout.tv_sec > t->timeout.tv_sec || + ((*pp)->timeout.tv_sec == t->timeout.tv_sec && + (*pp)->timeout.tv_usec > t->timeout.tv_usec)) { + t->next = *pp; + t->handler = handlercnt++; + *pp = t; + return t; + } + } + + return NULL; // ? +} + +void * +ccnl_set_absolute_timer(struct timeval abstime, void (*fct)(void *aux1, void *aux2), + void *aux1, void *aux2) +{ + struct ccnl_timer_s *t, **pp; + static int handlercnt; + + t = (struct ccnl_timer_s *) ccnl_calloc(1, sizeof(*t)); + + if (!t) { + return 0; + } + + t->fct2 = fct; + t->timeout = abstime; + t->aux1 = aux1; + t->aux2 = aux2; + + for (pp = &eventqueue; ; pp = &((*pp)->next)) { + if (!*pp || (*pp)->timeout.tv_sec > t->timeout.tv_sec || + ((*pp)->timeout.tv_sec == t->timeout.tv_sec && + (*pp)->timeout.tv_usec > t->timeout.tv_usec)) { + t->next = *pp; + t->handler = handlercnt++; + *pp = t; + return t; + } + } + + return NULL; // ? +} + +void +ccnl_rem_timer(void *h) +{ + struct ccnl_timer_s **pp; + + DEBUGMSG(99, "removing time handler %p\n", h); + + for (pp = &eventqueue; *pp; pp = &((*pp)->next)) { + if ((void *)*pp == h) { + struct ccnl_timer_s *e = *pp; + *pp = e->next; + ccnl_free(e); + break; + } + } +} + +double +current_time(void) +{ + struct timeval tv; + static time_t start; + static time_t start_usec; + + ccnl_get_timeval(&tv); + + if (!start) { + start = tv.tv_sec; + start_usec = tv.tv_usec; + } + + return (double)(tv.tv_sec) - start + + ((double)(tv.tv_usec) - start_usec) / 1000000; +} + +char * +timestamp(void) +{ + static char ts[30], *cp; + + sprintf(ts, "%.4g", CCNL_NOW()); + cp = strchr(ts, '.'); + + if (!cp) { + strcat(ts, ".0000"); + } + else if (strlen(cp) > 5) { + cp[5] = '\0'; + } + else while (strlen(cp) < 5) { + strcat(cp, "0"); + } + + return ts; +} + +// eof diff --git a/sys/net/ccn_lite/ccnl-platform.h b/sys/net/ccn_lite/ccnl-platform.h new file mode 100644 index 000000000..8e73c4f6d --- /dev/null +++ b/sys/net/ccn_lite/ccnl-platform.h @@ -0,0 +1,50 @@ +/* + * @f ccnl-platform.h + * + * Copyright (C) 2013, Christian Mehlis, Freie University Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +double current_time(void); +#define CCNL_NOW() current_time() + +// (ms) I moved the following struct def here because it is used by all +// containers apart from the kernel (this way I don't need to redefine it +// for omnet. +// +struct ccnl_timer_s { + struct ccnl_timer_s *next; + struct timeval timeout; + void (*fct)(char, int); + void (*fct2)(void *, void *); + char node; + int intarg; + void *aux1; + void *aux2; + int handler; +}; + +long timevaldelta(struct timeval *a, struct timeval *b); + +void *ccnl_set_timer(int usec, void (*fct)(void *aux1, void *aux2), + void *aux1, void *aux2); + +void +ccnl_rem_timer(void *h); + +extern struct ccnl_timer_s *eventqueue; diff --git a/sys/net/ccn_lite/ccnl-riot-compat.c b/sys/net/ccn_lite/ccnl-riot-compat.c new file mode 100644 index 000000000..996873759 --- /dev/null +++ b/sys/net/ccn_lite/ccnl-riot-compat.c @@ -0,0 +1,94 @@ +/* + * @f ccnl-riot-compat.c + * + * Copyright (C) 2013, Christian Mehlis, Freie University Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include "msg.h" + +#include "ccnl.h" +#include "ccnl-core.h" +#include "ccnl-pdu.h" +#include "ccnl-riot-compat.h" + +radio_packet_t p; +transceiver_command_t tcmd; +msg_t mesg, rep; + +int riot_send_transceiver(uint8_t *buf, uint16_t size, uint16_t to) +{ + DEBUGMSG(1, "this is a RIOT TRANSCEIVER based connection\n"); + DEBUGMSG(1, "size=%" PRIu16 " to=%" PRIu16 "\n", size, to); + + if (size > PAYLOAD_SIZE) { + DEBUGMSG(1, "size > PAYLOAD_SIZE\n"); + return 0; + } + + p.length = size; + p.dst = (to == RIOT_BROADCAST) ? 0 : to; + p.data = buf; + + tcmd.transceivers = transceiver_ids; + tcmd.data = &p; + + mesg.type = SND_PKT; + mesg.content.ptr = (char *) &tcmd; + msg_send_receive(&mesg, &rep, transceiver_pid); + + return size; +} + +int riot_send_msg(uint8_t *buf, uint16_t size, uint16_t to) +{ + DEBUGMSG(1, "this is a RIOT MSG based connection\n"); + DEBUGMSG(1, "size=%" PRIu16 " to=%" PRIu16 "\n", size, to); + + static riot_ccnl_msg_t rmsg; + rmsg.payload = buf; + rmsg.size = size; + + msg_t m; + m.type = CCNL_RIOT_MSG; + m.content.ptr = (char *) &rmsg; + DEBUGMSG(1, "sending msg to pid=%u\n", to); + msg_send(&m, to, 1); + + return size; +} + +char *riot_ccnl_event_to_string(ccnl_riot_event_t event) +{ + switch (event) { + case PKT_PENDING: + return "PKT_PENDING"; + + case CCNL_RIOT_MSG: + return "RIOT_MSG"; + + case CCNL_RIOT_HALT: + return "RIOT_HALT"; + + case CCNL_RIOT_POPULATE: + return "RIOT_POPULATE"; + + default: + return "UNKNOWN"; + } +} diff --git a/sys/net/ccn_lite/ccnl-riot-compat.h b/sys/net/ccn_lite/ccnl-riot-compat.h new file mode 100644 index 000000000..614db99df --- /dev/null +++ b/sys/net/ccn_lite/ccnl-riot-compat.h @@ -0,0 +1,32 @@ +/* + * @f ccnl-riot-compat.h + * + * Copyright (C) 2013, Christian Mehlis, Freie University Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ccnl-riot.h" + +#define RIOT_CCN_EVENT_NUMBER_OFFSET (1 << 8) + +#define RIOT_BROADCAST ((1 << sizeof(radio_address_t))-1) + +typedef struct riot_ccnl_msg { + void *payload; + uint16_t size; +} riot_ccnl_msg_t; + +int riot_send_transceiver(uint8_t *buf, uint16_t size, uint16_t to); +int riot_send_msg(uint8_t *buf, uint16_t size, uint16_t to); +char *riot_ccnl_event_to_string(ccnl_riot_event_t event); diff --git a/sys/net/ccn_lite/ccnl.h b/sys/net/ccn_lite/ccnl.h new file mode 100644 index 000000000..5b775e740 --- /dev/null +++ b/sys/net/ccn_lite/ccnl.h @@ -0,0 +1,123 @@ +/* + * @f ccnl.h + * @b header file for CCN lite (CCNL) + * + * Copyright (C) 2011-13, Christian Tschudin, University of Basel + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2011-03-30 created + */ + +#define CCNL_MAX_INTERFACES 10 +#define CCNL_MAX_PACKET_SIZE NATIVE_MAX_DATA_LENGTH + +#define CCNL_CONTENT_TIMEOUT 30 // sec +#define CCNL_INTEREST_TIMEOUT 4 // sec +#define CCNL_MAX_INTEREST_RETRANSMIT 2 + +#define CCNL_FACE_TIMEOUT 15 // sec + +#define CCNL_MAX_NAME_COMP 16 +#define CCNL_MAX_IF_QLEN 64 + +#define CCNL_DEFAULT_MAX_CACHE_ENTRIES 0 // means: no content caching +#define CCNL_MAX_NONCES 256 // for detected dups + + +// ---------------------------------------------------------------------- +// our own CCN-lite extensions for the ccnb encoding: + +// management protocol: (ccnl-ext-mgmt.c) +#define CCNL_DTAG_MACSRC 99001 // newface: which L2 interface +#define CCNL_DTAG_IP4SRC 99002 // newface: which L3 interface +#define CCNL_DTAG_UNIXSRC 99003 // newface: which UNIX path +#define CCNL_DTAG_FRAG 99004 // fragmentation protocol, see core.h +#define CCNL_DTAG_FACEFLAGS 99005 // +#define CCNL_DTAG_DEVINSTANCE 99006 // adding/removing a device/interface +#define CCNL_DTAG_DEVNAME 99007 // name of interface (eth0, wlan0) +#define CCNL_DTAG_DEVFLAGS 99008 // +#define CCNL_DTAG_MTU 99009 // + +#define CCNL_DTAG_DEBUGREQUEST 99100 // +#define CCNL_DTAG_DEBUGACTION 99101 // dump, halt, dump+halt + +//FOR THE DEBUG_REPLY MSG +#define CCNL_DTAG_DEBUGREPLY 99201 // dump reply +#define CCNL_DTAG_INTERFACE 99202 // interface list +#define CCNL_DTAG_NEXT 99203 // next pointer e.g. for faceinstance +#define CCNL_DTAG_PREV 99204 // prev pointer e.g. for faceinstance +#define CCNL_DTAG_IFNDX 99205 +#define CCNL_DTAG_IP 99206 +#define CCNL_DTAG_ETH 99207 +#define CCNL_DTAG_UNIX 99208 +#define CCNL_DTAG_PEER 99209 +#define CCNL_DTAG_FWD 99210 +#define CCNL_DTAG_FACE 99211 +#define CCNL_DTAG_ADDRESS 99212 +#define CCNL_DTAG_SOCK 99213 +#define CCNL_DTAG_REFLECT 99214 +#define CCNL_DTAG_PREFIX 99215 +#define CCNL_DTAG_INTERESTPTR 99216 +#define CCNL_DTAG_LAST 99217 +#define CCNL_DTAG_MIN 99218 +#define CCNL_DTAG_MAX 99219 +#define CCNL_DTAG_RETRIES 99220 +#define CCNL_DTAG_PUBLISHER 99221 +#define CCNL_DTAG_CONTENTPTR 99222 +#define CCNL_DTAG_LASTUSE 99223 +#define CCNL_DTAG_SERVEDCTN 99224 + +// fragmentation protocol: (ccnl-ext-frag.c, FRAG_SEQUENCED2012) +#define CCNL_DTAG_FRAGMENT2012 144144 // http://redmine.ccnx.org/issues/100803 +#define CCNL_DTAG_FRAGMENT 144199 // pending request (2013-07-24) + +#define CCNL_DTAG_FRAG_TYPE (CCNL_DTAG_FRAGMENT+1) +#define CCNL_DTAG_FRAG_FLAGS (CCNL_DTAG_FRAGMENT+2) +#define CCNL_DTAG_FRAG_SEQNR (CCNL_DTAG_FRAGMENT+3) // our seq number + +#define CCNL_DTAG_FRAG_OLOSS (CCNL_DTAG_FRAGMENT+5) // our loss count +#define CCNL_DTAG_FRAG_YSEQN (CCNL_DTAG_FRAGMENT+6) // your (highest) seq no +/* +#define CCNL_DTAG_FRAG_YSEQN16 (CCNL_DTAG_FRAGMENT+4) +#define CCNL_DTAG_FRAG_YSEQN32 (CCNL_DTAG_FRAGMENT+5) +*/ +#define CCNL_DTAG_FRAG_FLAG_MASK 0x03 +#define CCNL_DTAG_FRAG_FLAG_FIRST 0x01 +#define CCNL_DTAG_FRAG_FLAG_MID 0x00 +#define CCNL_DTAG_FRAG_FLAG_LAST 0x02 +#define CCNL_DTAG_FRAG_FLAG_SINGLE 0x03 + +#define CCNL_DTAG_FRAG_FLAG_STATUSREQ 0x04 + +// echo "FHBH" | base64 -d | hexdump -v -e '/1 "@x%02x"'| tr @ '\\'; echo +#define CCNL_FRAG_TYPE_CCNx2013_VAL "\x14\x70\x47" + +// fragmentation protocol: (ccnl-ext-frag.c, FRAG_WIRE2013) +#define CCNL_DTAG_WIRE 333333 +#define CCNL_DTAG_WFRAG_FLAGS (CCNL_DTAG_WIRE+1) +#define CCNL_DTAG_WFRAG_OSEQN (CCNL_DTAG_WIRE+2) // our seq number +#define CCNL_DTAG_WFRAG_OLOSS (CCNL_DTAG_WIRE+3) // our loss count +#define CCNL_DTAG_WFRAG_YSEQN (CCNL_DTAG_WIRE+4) // your (highest) seq no +#define CCNL_DTAG_WFRAG_FLAG_FIRST 0x01 +#define CCNL_DTAG_WFRAG_FLAG_LAST 0x02 + +#define ENABLE_DEBUG (1) +#include "debug.h" + +// function alias for RIOTs debug infrastructure +#define DEBUGMSG(LVL, ...) DEBUG(__VA_ARGS__) + +// eof diff --git a/sys/net/ccn_lite/ccnx.h b/sys/net/ccn_lite/ccnx.h new file mode 100644 index 000000000..fa8472471 --- /dev/null +++ b/sys/net/ccn_lite/ccnx.h @@ -0,0 +1,72 @@ +/* + * @f ccnx.h + * @b CCN constants + * + * Copyright (C) 2011, Christian Tschudin, University of Basel + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2011-03-13 created + */ + +// ---------------------------------------------------------------------- + +#define CCN_DEFAULT_MTU PAYOAD_SIZE + +// ---------------------------------------------------------------------- + +#define CCN_TT_TAG 1 +#define CCN_TT_DTAG 2 +#define CCN_TT_ATTR 3 +#define CCN_TT_DATTR 4 +#define CCN_TT_BLOB 5 +#define CCN_TT_UDATA 6 + +#define CCN_DTAG_ANY 13 +#define CCN_DTAG_NAME 14 +#define CCN_DTAG_COMPONENT 15 +#define CCN_DTAG_CONTENT 19 +#define CCN_DTAG_SIGNEDINFO 20 +#define CCN_DTAG_INTEREST 26 +#define CCN_DTAG_KEY 27 +#define CCN_DTAG_KEYLOCATOR 28 +#define CCN_DTAG_KEYNAME 29 +#define CCN_DTAG_SIGNATURE 37 +#define CCN_DTAG_TIMESTAMP 39 +#define CCN_DTAG_TYPE 40 +#define CCN_DTAG_NONCE 41 +#define CCN_DTAG_SCOPE 42 +#define CCN_DTAG_EXCLUDE 43 +#define CCN_DTAG_ANSWERORIGKIND 47 +#define CCN_DTAG_WITNESS 53 +#define CCN_DTAG_SIGNATUREBITS 54 +#define CCN_DTAG_FRESHNESS 58 +#define CCN_DTAG_FINALBLOCKID 59 +#define CCN_DTAG_PUBPUBKDIGEST 60 +#define CCN_DTAG_PUBCERTDIGEST 61 +#define CCN_DTAG_CONTENTOBJ 64 +#define CCN_DTAG_ACTION 73 +#define CCN_DTAG_FACEID 74 +#define CCN_DTAG_IPPROTO 75 +#define CCN_DTAG_HOST 76 +#define CCN_DTAG_PORT 77 +#define CCN_DTAG_FWDINGFLAGS 79 +#define CCN_DTAG_FACEINSTANCE 80 +#define CCN_DTAG_FWDINGENTRY 81 +#define CCN_DTAG_MINSUFFCOMP 83 +#define CCN_DTAG_MAXSUFFCOMP 84 +#define CCN_DTAG_SEQNO 256 +#define CCN_DTAG_CCNPDU 17702112 + +// eof diff --git a/sys/net/ccn_lite/include/ccnl-riot.h b/sys/net/ccn_lite/include/ccnl-riot.h new file mode 100644 index 000000000..1f2a27fdf --- /dev/null +++ b/sys/net/ccn_lite/include/ccnl-riot.h @@ -0,0 +1,60 @@ +/* + * @f ccnl-riot.h + * + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef RIOT_CCN_COMPAT_H_ +#define RIOT_CCN_COMPAT_H_ + +#include + +#include "transceiver.h" + +#ifdef MODULE_CC110X_NG +# include "cc110x_ng.h" +# define transceiver_ids (TRANSCEIVER_CC1100 | TRANSCEIVER_NONE) +#else +# include "nativenet.h" +# define transceiver_ids (TRANSCEIVER_NATIVE | TRANSCEIVER_NONE) +#endif + +#define CCNL_RIOT_EVENT_NUMBER_OFFSET (1 << 8) +typedef enum ccnl_riot_event { + CCNL_RIOT_MSG = CCNL_RIOT_EVENT_NUMBER_OFFSET + 1, + CCNL_RIOT_HALT, + CCNL_RIOT_POPULATE, + + CCNL_RIOT_RESERVED +} ccnl_riot_event_t; + +#define CCNL_RIOT_CHUNK_SIZE 90 + +/** + * riot_ccnl_relay_start starts the ccnl relay + * + * to stop the relay send msg "RIOT_HALT" to this thread + */ +void ccnl_riot_relay_start(void); + +/** + * riot_ccnl_appserver_start starts an appication server, + * which can repy to ccn interests + * + * @param relay_pid the pid of the relay + */ +void ccnl_riot_appserver_start(int relay_pid); + +#endif /* RIOT_CCN_COMPAT_H_ */ diff --git a/sys/net/ccn_lite/include/test_data/text.txt.ccnb.h b/sys/net/ccn_lite/include/test_data/text.txt.ccnb.h new file mode 100644 index 000000000..f1636a518 --- /dev/null +++ b/sys/net/ccn_lite/include/test_data/text.txt.ccnb.h @@ -0,0 +1,359 @@ +/* + * @f txt.txt.ccnb.h this is a text file encoded as ccnb chunks + * + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define RIOT_CCNL_POPULATE (1) + +#if RIOT_CCNL_POPULATE + +unsigned char text_txt_ccnb_0[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x8d, 0x30, 0x00, 0x00, 0x01, 0x9a, + 0x05, 0xd5, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x0a, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x0a, 0x0a, 0x32, 0x30, 0x30, 0x38, 0x0a, + 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x2e, 0x20, 0x54, 0x68, 0x65, + 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x52, 0x49, + 0x4f, 0x54, 0x20, 0x77, 0x61, 0x73, 0x20, 0x46, 0x65, 0x75, 0x65, 0x72, + 0x57, 0x61, 0x72, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_0_len = 118; +unsigned char text_txt_ccnb_1[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x8d, 0x31, 0x00, 0x00, 0x01, 0x9a, + 0x05, 0xd5, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x57, 0x69, 0x72, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x53, 0x65, 0x6e, + 0x73, 0x6f, 0x72, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, + 0x2e, 0x0a, 0x49, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x70, 0x61, 0x72, + 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x65, 0x75, + 0x65, 0x72, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x66, 0x69, + 0x72, 0x65, 0x66, 0x69, 0x67, 0x68, 0x74, 0x65, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_1_len = 118; +unsigned char text_txt_ccnb_10[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x31, 0x30, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x69, 0x73, 0x73, + 0x21, 0x0a, 0x0a, 0x0a, 0x54, 0x68, 0x72, 0x65, 0x65, 0x20, 0x67, 0x6f, + 0x6f, 0x64, 0x20, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x6b, 0x20, 0x61, 0x62, 0x6f, 0x75, + 0x74, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x4f, 0x53, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x6f, 0x54, 0x2e, 0x0a, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_10_len = 119; +unsigned char text_txt_ccnb_11[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x31, 0x31, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x0a, 0x0a, 0x52, 0x49, 0x4f, 0x54, 0x20, 0x69, 0x73, 0x20, 0x44, + 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x20, 0x46, 0x72, 0x69, + 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_11_len = 119; +unsigned char text_txt_ccnb_12[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x31, 0x32, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x0a, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, + 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x65, + 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x2e, 0x20, 0x44, 0x6f, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x77, 0x61, 0x73, 0x74, 0x65, 0x20, 0x74, + 0x69, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x78, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x65, 0x77, 0x20, + 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x2e, 0x0a, 0x0a, 0x2d, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_12_len = 119; +unsigned char text_txt_ccnb_13[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x31, 0x33, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x64, 0x61, 0x72, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x67, + 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x20, 0x43, + 0x20, 0x6f, 0x72, 0x20, 0x43, 0x2b, 0x2b, 0x0a, 0x2d, 0x20, 0x53, 0x74, + 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x64, 0x65, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x73, + 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x67, 0x63, 0x63, + 0x2c, 0x20, 0x67, 0x64, 0x62, 0x0a, 0x2d, 0x20, 0x4d, 0x69, 0x6e, 0x69, + 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x68, 0x61, 0x72, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_13_len = 119; +unsigned char text_txt_ccnb_14[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x31, 0x34, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x64, 0x77, 0x61, 0x72, 0x65, 0x20, 0x64, 0x65, 0x70, + 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a, + 0x2d, 0x20, 0x5a, 0x65, 0x72, 0x6f, 0x20, 0x6c, 0x65, 0x61, 0x72, 0x6e, + 0x69, 0x6e, 0x67, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x20, 0x70, + 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x0a, 0x2d, + 0x20, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x2c, 0x20, + 0x72, 0x75, 0x6e, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_14_len = 119; +unsigned char text_txt_ccnb_15[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x31, 0x35, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x6f, 0x6e, 0x20, 0x31, 0x36, 0x2d, 0x62, 0x69, 0x74, + 0x20, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x20, 0x28, + 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x4d, 0x53, 0x50, 0x34, 0x33, 0x30, 0x29, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x33, 0x32, 0x2d, 0x62, + 0x69, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, + 0x20, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x41, 0x52, 0x4d, 0x29, 0x0a, + 0x2d, 0x20, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x50, 0x4f, + 0x53, 0x49, 0x58, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_15_len = 119; +unsigned char text_txt_ccnb_16[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x31, 0x36, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x20, 0x54, 0x6f, + 0x77, 0x61, 0x72, 0x64, 0x73, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x50, + 0x4f, 0x53, 0x49, 0x58, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, + 0x6e, 0x63, 0x65, 0x2e, 0x0a, 0x0a, 0x52, 0x49, 0x4f, 0x54, 0x20, 0x69, + 0x73, 0x20, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x46, + 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_16_len = 119; +unsigned char text_txt_ccnb_17[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x31, 0x37, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x0a, 0x0a, 0x42, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, + 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x6d, 0x69, 0x63, 0x72, + 0x6f, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x20, 0x61, 0x72, 0x63, 0x68, + 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x61, 0x20, 0x74, 0x69, 0x63, 0x6b, 0x6c, 0x65, 0x73, 0x73, 0x20, + 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x20, 0x6f, 0x6e, + 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x77, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x64, 0x65, 0x76, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_17_len = 119; +unsigned char text_txt_ccnb_18[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x31, 0x38, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x2d, 0x20, + 0x52, 0x6f, 0x62, 0x75, 0x73, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x26, + 0x20, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x66, 0x6f, 0x6f, 0x74, 0x70, 0x72, + 0x69, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x65, 0x78, 0x69, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x0a, 0x2d, 0x20, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x69, + 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x65, + 0x6e, 0x65, 0x72, 0x67, 0x79, 0x2d, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, + 0x65, 0x6e, 0x63, 0x79, 0x0a, 0x2d, 0x20, 0x52, 0x65, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_18_len = 119; +unsigned char text_txt_ccnb_19[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x31, 0x39, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x61, 0x6c, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x63, + 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x64, 0x75, + 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x6c, 0x74, 0x72, 0x61, 0x2d, 0x6c, + 0x6f, 0x77, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, + 0x20, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x20, 0x28, 0x7e, 0x35, + 0x30, 0x20, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x63, 0x79, 0x63, 0x6c, + 0x65, 0x73, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x69, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_19_len = 119; +unsigned char text_txt_ccnb_2[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x8d, 0x32, 0x00, 0x00, 0x01, 0x9a, + 0x05, 0xd5, 0x72, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, + 0x62, 0x65, 0x0a, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x65, 0x64, + 0x2e, 0x20, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x73, 0x69, + 0x67, 0x6e, 0x20, 0x67, 0x6f, 0x61, 0x6c, 0x73, 0x20, 0x77, 0x65, 0x72, + 0x65, 0x20, 0x72, 0x65, 0x6c, 0x69, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x2d, 0x74, + 0x69, 0x6d, 0x65, 0x20, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, + 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x32, 0x30, 0x31, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_2_len = 118; +unsigned char text_txt_ccnb_20[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x32, 0x30, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x64, 0x20, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x69, 0x6e, 0x67, 0x0a, 0x2d, 0x20, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x2d, + 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x75, 0x6c, 0x74, 0x72, 0x61, 0x2d, 0x6c, 0x6f, 0x77, + 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, + 0x76, 0x65, 0x72, 0x68, 0x65, 0x61, 0x64, 0x20, 0x28, 0x3c, 0x32, 0x35, + 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x74, + 0x68, 0x72, 0x65, 0x61, 0x64, 0x29, 0x0a, 0x0a, 0x52, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_20_len = 119; +unsigned char text_txt_ccnb_21[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x32, 0x31, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x49, 0x4f, 0x54, 0x20, 0x69, 0x73, 0x20, 0x49, 0x6f, + 0x54, 0x20, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x0a, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x4d, 0x61, 0x6b, + 0x65, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, + 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_21_len = 119; +unsigned char text_txt_ccnb_22[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x32, 0x32, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x6e, 0x67, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x0a, 0x0a, 0x2d, 0x20, 0x36, 0x4c, 0x6f, 0x57, 0x50, 0x41, + 0x4e, 0x2c, 0x20, 0x49, 0x50, 0x76, 0x36, 0x2c, 0x20, 0x52, 0x50, 0x4c, + 0x2c, 0x20, 0x54, 0x43, 0x50, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x55, + 0x44, 0x50, 0x0a, 0x2d, 0x20, 0x53, 0x74, 0x61, 0x74, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_22_len = 119; +unsigned char text_txt_ccnb_23[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x32, 0x33, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x69, 0x63, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x79, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, + 0x2d, 0x20, 0x46, 0x41, 0x54, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x2d, 0x20, 0x4c, 0x6f, 0x67, 0x67, + 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x2d, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_23_len = 119; +unsigned char text_txt_ccnb_24[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x32, 0x34, 0x00, 0x00, 0x01, + 0x9a, 0x05, 0xd5, 0x6c, 0x6f, 0x6e, 0x67, 0x2d, 0x74, 0x65, 0x72, 0x6d, + 0x20, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x73, 0x0a, 0x2d, 0x20, 0x57, 0x69, + 0x73, 0x65, 0x6c, 0x69, 0x62, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x20, 0x28, 0x43, 0x2b, 0x2b, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, + 0x69, 0x74, 0x68, 0x6d, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, + 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, + 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_24_len = 119; +unsigned char text_txt_ccnb_25[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x95, 0x32, 0x35, 0x00, 0x00, 0x01, + 0x9a, 0x03, 0xb5, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x2c, + 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2c, 0x20, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x67, + 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x29, 0x0a, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_25_len = 83; +unsigned char text_txt_ccnb_3[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x8d, 0x33, 0x00, 0x00, 0x01, 0x9a, + 0x05, 0xd5, 0x30, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x54, 0x6f, + 0x77, 0x61, 0x72, 0x64, 0x73, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, + 0x65, 0x2e, 0x20, 0x54, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61, + 0x73, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x61, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x49, 0x45, 0x54, 0x46, 0x0a, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_3_len = 118; +unsigned char text_txt_ccnb_4[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x8d, 0x34, 0x00, 0x00, 0x01, 0x9a, + 0x05, 0xd5, 0x2c, 0x20, 0x26, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x3b, 0x6b, + 0x6c, 0x65, 0x6f, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x6f, 0x72, + 0x6b, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x6f, 0x72, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x0a, 0x46, 0x65, 0x75, + 0x65, 0x72, 0x57, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x20, 0x53, 0x75, 0x70, 0x70, 0x6f, + 0x72, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x36, 0x4c, 0x6f, 0x57, 0x50, + 0x41, 0x4e, 0x2c, 0x20, 0x52, 0x50, 0x4c, 0x2c, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_4_len = 118; +unsigned char text_txt_ccnb_5[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x8d, 0x35, 0x00, 0x00, 0x01, 0x9a, + 0x05, 0xd5, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x43, 0x50, 0x20, 0x77, + 0x61, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x66, + 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x79, 0x65, 0x61, + 0x72, 0x73, 0x2e, 0x0a, 0x0a, 0x32, 0x30, 0x31, 0x33, 0x0a, 0x2d, 0x2d, + 0x2d, 0x2d, 0x0a, 0x0a, 0x52, 0x49, 0x4f, 0x54, 0x20, 0x67, 0x6f, 0x65, + 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2e, 0x20, 0x52, 0x49, + 0x4f, 0x54, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_5_len = 118; +unsigned char text_txt_ccnb_6[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x8d, 0x36, 0x00, 0x00, 0x01, 0x9a, + 0x05, 0xd5, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x73, + 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, + 0x26, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x3b, 0x6b, 0x6c, 0x65, 0x6f, 0x73, + 0x2e, 0x20, 0x57, 0x65, 0x20, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x64, + 0x20, 0x6f, 0x6e, 0x0a, 0x72, 0x65, 0x2d, 0x62, 0x72, 0x61, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x76, 0x6f, 0x69, 0x64, + 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x73, 0x70, 0x65, 0x6c, 0x6c, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_6_len = 118; +unsigned char text_txt_ccnb_7[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x8d, 0x37, 0x00, 0x00, 0x01, 0x9a, + 0x05, 0xd5, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x72, + 0x6f, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, + 0x65, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x20, 0x57, 0x65, 0x20, 0x65, + 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x6c, 0x79, 0x20, 0x70, 0x72, + 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x52, 0x49, 0x4f, 0x54, 0x20, 0x74, + 0x6f, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_7_len = 118; +unsigned char text_txt_ccnb_8[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x8d, 0x38, 0x00, 0x00, 0x01, 0x9a, + 0x05, 0xd5, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x74, 0x79, 0x2e, 0x0a, 0x0a, 0x46, 0x75, 0x74, 0x75, 0x72, 0x65, 0x0a, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x42, 0x65, 0x20, 0x70, + 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x57, 0x65, + 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x61, 0x62, 0x6f, 0x75, + 0x74, 0x20, 0x6f, 0x6e, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, + 0x68, 0x61, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_8_len = 118; +unsigned char text_txt_ccnb_9[] = { + 0x04, 0x82, 0xf2, 0xfa, 0xa5, 0x72, 0x69, 0x6f, 0x74, 0x00, 0xfa, 0xa5, + 0x74, 0x65, 0x78, 0x74, 0x00, 0xfa, 0x8d, 0x39, 0x00, 0x00, 0x01, 0x9a, + 0x05, 0xd5, 0x74, 0x73, 0x0a, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x72, 0x20, + 0x69, 0x73, 0x73, 0x75, 0x65, 0x20, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x65, + 0x72, 0x2e, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x77, 0x6f, 0x72, + 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x6e, 0x65, 0x77, 0x20, + 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x20, 0x6f, 0x72, 0x20, + 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x49, 0x4f, 0x54, + 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x20, 0x6b, + 0x6e, 0x6f, 0x77, 0x20, 0x77, 0x68, 0x61, 0x74, 0x00, 0x00 +}; +unsigned int text_txt_ccnb_9_len = 118; + +#endif diff --git a/sys/net/ccn_lite/include/util/ccnl-riot-client.h b/sys/net/ccn_lite/include/util/ccnl-riot-client.h new file mode 100644 index 000000000..dd470070d --- /dev/null +++ b/sys/net/ccn_lite/include/util/ccnl-riot-client.h @@ -0,0 +1,93 @@ +/* + * @f ccnl-riot-client.h client side api for ccnl on RIOT + * + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * riot_get high level function to fetch a file (all chunks of a file) + * + * @param relay_pid pid of the relay thread + * + * @param name c string represenation of the name to fetch e.g. "/riot/test" + * + * @param reply_buf buffer for the aswer message from the relay + * + * @return the length of the reply message stored in reply_buf + */ +int ccnl_riot_client_get(unsigned int relay_pid, char *name, char *reply_buf); + +/** + * riot_publish high level function to publish a name, e.g. "/riot/test" + * all interest with "prefix" as prefix received by the rely + * are forwarded to this thread + * + * this function uses riot_new_face and riot_register_prefix + * + * @param relay_pid pid of the relay thread + * + * @param prefix c string representation of the name to publish + * + * @param faceid in case of "newMSGface" this is the pid to connect the face to + * in case of "newTRANSface" this is the network address to + * connect the face to + * + * @param type a c string may "newMSGface" for a RIOT message based face or + * "newTRANSface" for a network face + * + * @param reply_buf buffer for the aswer message from the relay + * + * @return the length of the reply message stored in reply_buf + */ +int ccnl_riot_client_publish(unsigned int relay_pid, char *prefix, char *faceid, + char *type, unsigned char *reply_buf); + +/** + * riot_new_face lower layer function to register a new face in the relay + * + * @param relay_pid pid of the relay + * + * @param type a c string may "newMSGface" for a RIOT message based face or + * "newTRANSface" for a network face + * + * @param faceid in case of "newMSGface" this is the pid to connect the face to + * in case of "newTRANSface" this is the network address to + * connect the face to + * + * @param reply_buf buffer for the aswer message from the relay + * + * @return the length of the reply message stored in reply_buf + */ +int ccnl_riot_client_new_face(unsigned int relay_pid, char *type, char *faceid, + unsigned char *reply_buf); + +/** + * riot_register_prefix lower layer function to register a new prefix + * in the relay + * + * @param relay_pid pid of the relay + * + * @param prefix c string representation of the name to publish + * + * @param faceid in case of "newMSGface" this is the pid to connect the face to + * in case of "newTRANSface" this is the network address to + * connect the face to + * + * @param reply_buf buffer for the aswer message from the relay + * + * @return the length of the reply message stored in reply_buf + */ +int ccnl_riot_client_register_prefix(unsigned int relay_pid, char *prefix, + char *faceid, unsigned char *reply_buf); diff --git a/sys/net/ccn_lite/util/Makefile b/sys/net/ccn_lite/util/Makefile new file mode 100644 index 000000000..878aaa02f --- /dev/null +++ b/sys/net/ccn_lite/util/Makefile @@ -0,0 +1,4 @@ +MODULE := ccn_lite_client +INCLUDES = -I$(RIOTBASE) -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/sys/net -I$(RIOTBASE)/cpu/arm_common/include/ -I$(RIOTBASE)/drivers/cc110x_ng/include/ -I$(RIOTBASE)/sys/net/ccn_lite/ -I$(RIOTBASE)/sys/net/ccn_lite/include + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/ccn_lite/util/ccn-lite-ctrl.c b/sys/net/ccn_lite/util/ccn-lite-ctrl.c new file mode 100644 index 000000000..84c94cfd3 --- /dev/null +++ b/sys/net/ccn_lite/util/ccn-lite-ctrl.c @@ -0,0 +1,151 @@ +/* + * @f util/ccn-lite-ctrl.c + * @b control utility to steer a ccn-lite relay + * + * Copyright (C) 2012-13, Christian Tschudin, University of Basel + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2012-06-01 created + * 2013-07 heavy reworking and parsing + * of return message + */ + +#include +#include +#include + +#include "ccnx.h" +#include "ccnl.h" +#include "ccnl-pdu.h" + +// ---------------------------------------------------------------------- + +static unsigned char contentobj[2000]; +static unsigned char faceinst[2000]; +static unsigned char fwdentry[2000]; + +int +mkNewFaceRequest(unsigned char *out, char *macsrc, char *ip4src, + char *host, char *port, char *flags) +{ + int len = 0, len2, len3; + + len = mkHeader(out, CCN_DTAG_INTEREST, CCN_TT_DTAG); // interest + len += mkHeader(out + len, CCN_DTAG_NAME, CCN_TT_DTAG); // name + + len += mkStrBlob(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "ccnx"); + len += mkStrBlob(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, ""); + len += mkStrBlob(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "newface"); + + // prepare FACEINSTANCE + len3 = mkHeader(faceinst, CCN_DTAG_FACEINSTANCE, CCN_TT_DTAG); + len3 += mkStrBlob(faceinst + len3, CCN_DTAG_ACTION, CCN_TT_DTAG, "newface"); + + if (macsrc) { + len3 += mkStrBlob(faceinst + len3, CCNL_DTAG_MACSRC, CCN_TT_DTAG, macsrc); + } + + if (ip4src) { + len3 += mkStrBlob(faceinst + len3, CCNL_DTAG_IP4SRC, CCN_TT_DTAG, ip4src); + len3 += mkStrBlob(faceinst + len3, CCN_DTAG_IPPROTO, CCN_TT_DTAG, "17"); + } + + if (host) { + len3 += mkStrBlob(faceinst + len3, CCN_DTAG_HOST, CCN_TT_DTAG, host); + } + + if (port) { + len3 += mkStrBlob(faceinst + len3, CCN_DTAG_PORT, CCN_TT_DTAG, port); + } + + /* + if (frag) + len3 += mkStrBlob(faceinst+len3, CCNL_DTAG_FRAG, CCN_TT_DTAG, frag); + */ + if (flags) { + len3 += mkStrBlob(faceinst + len3, CCNL_DTAG_FACEFLAGS, CCN_TT_DTAG, flags); + } + + faceinst[len3++] = 0; // end-of-faceinst + + // prepare CONTENTOBJ with CONTENT + len2 = mkHeader(contentobj, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG); // contentobj + len2 += mkBlob(contentobj + len2, CCN_DTAG_CONTENT, CCN_TT_DTAG, // content + (char *) faceinst, len3); + contentobj[len2++] = 0; // end-of-contentobj + + // add CONTENTOBJ as the final name component + len += mkBlob(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, // comp + (char *) contentobj, len2); + + out[len++] = 0; // end-of-name + out[len++] = 0; // end-of-interest + + return len; +} + +// ---------------------------------------------------------------------- + +int +mkPrefixregRequest(unsigned char *out, char reg, char *path, char *faceid) +{ + int len = 0, len2, len3; + char *cp; + + len = mkHeader(out, CCN_DTAG_INTEREST, CCN_TT_DTAG); // interest + len += mkHeader(out + len, CCN_DTAG_NAME, CCN_TT_DTAG); // name + + len += mkStrBlob(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "ccnx"); + len += mkStrBlob(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, ""); + len += mkStrBlob(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, + reg ? "prefixreg" : "prefixunreg"); + + // prepare FWDENTRY + len3 = mkHeader(fwdentry, CCN_DTAG_FWDINGENTRY, CCN_TT_DTAG); + len3 += mkStrBlob(fwdentry + len3, CCN_DTAG_ACTION, CCN_TT_DTAG, + reg ? "prefixreg" : "prefixunreg"); + len3 += mkHeader(fwdentry + len3, CCN_DTAG_NAME, CCN_TT_DTAG); // prefix + + cp = strtok(path, "/"); + + while (cp) { + len3 += mkBlob(fwdentry + len3, CCN_DTAG_COMPONENT, CCN_TT_DTAG, + cp, strlen(cp)); + cp = strtok(NULL, "/"); + } + + fwdentry[len3++] = 0; // end-of-prefix + len3 += mkStrBlob(fwdentry + len3, CCN_DTAG_FACEID, CCN_TT_DTAG, faceid); + fwdentry[len3++] = 0; // end-of-fwdentry + + // prepare CONTENTOBJ with CONTENT + len2 = mkHeader(contentobj, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG); // contentobj + len2 += mkBlob(contentobj + len2, CCN_DTAG_CONTENT, CCN_TT_DTAG, // content + (char *) fwdentry, len3); + contentobj[len2++] = 0; // end-of-contentobj + + // add CONTENTOBJ as the final name component + len += mkBlob(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, // comp + (char *) contentobj, len2); + + out[len++] = 0; // end-of-name + out[len++] = 0; // end-of-interest + + // ccnl_prefix_free(p); + return len; +} + +// ---------------------------------------------------------------------- diff --git a/sys/net/ccn_lite/util/ccn-lite-ctrl.h b/sys/net/ccn_lite/util/ccn-lite-ctrl.h new file mode 100644 index 000000000..c85cf79ce --- /dev/null +++ b/sys/net/ccn_lite/util/ccn-lite-ctrl.h @@ -0,0 +1,22 @@ +/* + * @f ccn-lite-ctrl.h + * + * Copyright (C) 2011-13, Christian Tschudin, University of Basel + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +int mkNewFaceRequest(unsigned char *out, char *macsrc, char *ip4src, + char *host, char *port, char *flags); + +int mkPrefixregRequest(unsigned char *out, char reg, char *path, char *faceid); diff --git a/sys/net/ccn_lite/util/ccnl-riot-client.c b/sys/net/ccn_lite/util/ccnl-riot-client.c new file mode 100644 index 000000000..4e924e3d9 --- /dev/null +++ b/sys/net/ccn_lite/util/ccnl-riot-client.c @@ -0,0 +1,166 @@ +/* + * @f ccnl-riot-client.c client side api for ccnl on RIOT + * + * Copyright (C) 2013, Christian Mehlis, Freie Universität Berlin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include "msg.h" + +#include "ccnl.h" +#include "ccnl-core.h" +#include "ccnl-riot-compat.h" +#include "ccn-lite-ctrl.h" +#include "ccnl-pdu.h" + +msg_t mesg, rep; + +unsigned char compat_small_buf[PAYLOAD_SIZE]; + +int ccnl_riot_client_get(unsigned int relay_pid, char *name, char *reply_buf) +{ + char *prefix[CCNL_MAX_NAME_COMP]; + char *cp = strtok(name, "/"); + int i = 0; + + while (i < (CCNL_MAX_NAME_COMP - 1) && cp) { + prefix[i++] = cp; + cp = strtok(NULL, "/"); + } + + //prefix[i] = 0; //segment to request + prefix[i + 1] = 0; + + int content_len = 0; + + for (int segment = 0; ; segment++) { + char segment_string[16]; //max=999\0 + memset(segment_string, 0, 16); + snprintf(segment_string, 16, "%d", segment); + prefix[i] = segment_string; + int interest_len = mkInterest(prefix, NULL, compat_small_buf); + DEBUGMSG(1, "relay_pid=%u interest_len=%d\n", relay_pid, interest_len); + + riot_ccnl_msg_t rmsg; + rmsg.payload = &compat_small_buf; + rmsg.size = interest_len; + + msg_t m, rep; + m.content.ptr = (char *) &rmsg; + m.type = CCNL_RIOT_MSG; + msg_send(&m, relay_pid, 1); + + /* ######################################################################### */ + + msg_receive(&rep); + riot_ccnl_msg_t *rmsg_reply = (riot_ccnl_msg_t *) rep.content.ptr; + memcpy(&compat_small_buf, rmsg_reply->payload, rmsg_reply->size); + unsigned char *data = compat_small_buf; + int datalen = (int) rmsg_reply->size; + DEBUGMSG(1, "%d bytes left; msg from=%u '%s'\n", datalen, rep.sender_pid, compat_small_buf); + + + int scope = 3, aok = 3, minsfx = 0, maxsfx = CCNL_MAX_NAME_COMP, + contlen = 0; + struct ccnl_buf_s *buf = 0, *nonce = 0, *ppkd = 0; + struct ccnl_prefix_s *p = 0; + unsigned char *content = 0; + + buf = ccnl_extract_prefix_nonce_ppkd(&data, &datalen, &scope, &aok, &minsfx, + &maxsfx, &p, &nonce, &ppkd, &content, &contlen); + + if (!buf) { + DEBUGMSG(6, " parsing error or no prefix\n"); + return 0; + } + + DEBUGMSG(1, "content_len=%d contlen=%d\n", content_len, contlen); + memcpy(reply_buf + content_len, content, contlen); + content_len += contlen; + + free_prefix(p); + free_3ptr_list(buf, nonce, ppkd); + + if (contlen < CCNL_RIOT_CHUNK_SIZE || CCNL_RIOT_CHUNK_SIZE < contlen) { + /* last chunk */ + break; + } + } + + return content_len; +} + +int ccnl_riot_client_new_face(unsigned int relay_pid, char *type, char *faceid, + unsigned char *reply_buf) +{ + DEBUGMSG(1, "riot_new_face: mkNewFaceRquest\n"); + int len = mkNewFaceRequest(reply_buf, type, NULL, NULL, faceid, NULL); + + riot_ccnl_msg_t rmsg; + rmsg.payload = reply_buf; + rmsg.size = len; + + msg_t m, rep; + m.content.ptr = (char *) &rmsg; + m.type = CCNL_RIOT_MSG; + DEBUGMSG(1, " sending face req to relay\n"); + msg_send(&m, relay_pid, 1); + + /* ######################################################################### */ + + msg_receive(&rep); + DEBUGMSG(1, " received reply from relay\n"); + riot_ccnl_msg_t *rmsg_reply = (riot_ccnl_msg_t *) rep.content.ptr; + memcpy(reply_buf, rmsg_reply->payload, rmsg_reply->size); + return rmsg_reply->size; +} + +int ccnl_riot_client_register_prefix(unsigned int relay_pid, char *prefix, char *faceid, + unsigned char *reply_buf) +{ + DEBUGMSG(1, "riot_register_prefix: mkPrefixregRequest\n"); + int len = mkPrefixregRequest(reply_buf, 1, prefix, faceid); + + riot_ccnl_msg_t rmsg; + rmsg.payload = reply_buf; + rmsg.size = len; + + msg_t m, rep; + m.content.ptr = (char *) &rmsg; + m.type = CCNL_RIOT_MSG; + DEBUGMSG(1, " sending prefix req to relay\n"); + msg_send(&m, relay_pid, 1); + + /* ######################################################################### */ + + msg_receive(&rep); + DEBUGMSG(1, " received reply from relay\n"); + riot_ccnl_msg_t *rmsg_reply = (riot_ccnl_msg_t *) rep.content.ptr; + memcpy(reply_buf, rmsg_reply->payload, rmsg_reply->size); + reply_buf[rmsg_reply->size] = '\0'; + + return rmsg_reply->size; +} + +int ccnl_riot_client_publish(unsigned int relay_pid, char *prefix, char *faceid, char *type, unsigned char *reply_buf) +{ + ccnl_riot_client_new_face(relay_pid, type, faceid, reply_buf); + int content_len = ccnl_riot_client_register_prefix(relay_pid, prefix, faceid, reply_buf); + return content_len; +}