void ccnl_core_RX(struct ccnl_relay_s *relay, int ifndx, unsigned char *data, int datalen, struct sockaddr *sa, int addrlen) { unsigned char *base = data; struct ccnl_face_s *from; int enc, suite = -1, skip; dispatchFct dispatch; (void) base; // silence compiler warning (if USE_DEBUG is not set) DEBUGMSG_CORE(DEBUG, "ccnl_core_RX ifndx=%d, %d bytes\n", ifndx, datalen); // DEBUGMSG_ON(DEBUG, "ccnl_core_RX ifndx=%d, %d bytes\n", ifndx, datalen); #ifdef USE_STATS if (ifndx >= 0) relay->ifs[ifndx].rx_cnt++; #endif from = ccnl_get_face_or_create(relay, ifndx, sa, addrlen); if (!from) { DEBUGMSG_CORE(DEBUG, " no face\n"); return; } else { DEBUGMSG_CORE(DEBUG, " face %d, peer=%s\n", from->faceid, ccnl_addr2ascii(&from->peer)); } // loop through all packets in the received frame (UDP, Ethernet etc) while (datalen > 0) { // work through explicit code switching while (!ccnl_switch_dehead(&data, &datalen, &enc)) suite = ccnl_enc2suite(enc); if (suite == -1) suite = ccnl_pkt2suite(data, datalen, &skip); if (!ccnl_isSuite(suite)) { DEBUGMSG_CORE(WARNING, "?unknown packet format? ccnl_core_RX ifndx=%d, %d bytes starting with 0x%02x at offset %zd\n", ifndx, datalen, *data, data - base); return; } // dispatch = ccnl_core_RX_dispatch[suite]; dispatch = ccnl_core_suites[suite].RX; if (!dispatch) { DEBUGMSG_CORE(ERROR, "Forwarder not initialized or dispatcher " "for suite %s does not exist.\n", ccnl_suite2str(suite)); return; } if (dispatch(relay, from, &data, &datalen) < 0) break; if (datalen > 0) { DEBUGMSG_CORE(WARNING, "ccnl_core_RX: %d bytes left\n", datalen); } } }
int main(int argc, char *argv[]) { // char *private_key_path = 0; // char *witness = 0; unsigned char out[65*1024]; char *publisher = 0; char *infname = 0, *outdirname = 0, *outfname; int f, fout, contentlen = 0, opt, plen; // int suite = CCNL_SUITE_DEFAULT; int suite = CCNL_SUITE_CCNTLV; int chunk_size = CCNL_MAX_CHUNK_SIZE; struct ccnl_prefix_s *name; while ((opt = getopt(argc, argv, "hc:f:i:o:p:k:w:s:v:")) != -1) { switch (opt) { case 'c': chunk_size = atoi(optarg); if (chunk_size > CCNL_MAX_CHUNK_SIZE) { DEBUGMSG(WARNING, "max chunk size is %d (%d is to large), using max chunk size\n", CCNL_MAX_CHUNK_SIZE, chunk_size); chunk_size = CCNL_MAX_CHUNK_SIZE; } break; case 'f': outfname = optarg; break; case 'i': infname = optarg; break; case 'o': outdirname = optarg; break; /* case 'k': private_key_path = optarg; break; case 'w': witness = optarg; break; */ case 'p': publisher = optarg; plen = unescape_component(publisher); if (plen != 32) { DEBUGMSG(ERROR, "publisher key digest has wrong length (%d instead of 32)\n", plen); exit(-1); } break; case 's': suite = ccnl_str2suite(optarg); break; case 'v': #ifdef USE_LOGGING if (isdigit(optarg[0])) debug_level = atoi(optarg); else debug_level = ccnl_debug_str2level(optarg); #endif break; case 'h': default: Usage: fprintf(stderr, "Creates a chunked content object stream for the input data and writes them to stdout.\n" "usage: %s [options] URL\n" " -c SIZE size for each chunk (max %d)\n" " -f FNAME filename of the chunks when using -o\n" " -i FNAME input file (instead of stdin)\n" " -o DIR output dir (instead of stdout), filename default is cN, otherwise specify -f\n" " -p DIGEST publisher fingerprint\n" " -s SUITE (ccnb, ccnx2015, cisco2015, iot2014, ndn2013)\n" #ifdef USE_LOGGING " -v DEBUG_LEVEL (fatal, error, warning, info, debug, verbose, trace)\n" #endif , argv[0], CCNL_MAX_CHUNK_SIZE); exit(1); } } if (!ccnl_isSuite(suite)) goto Usage; // mandatory url if (!argv[optind]) goto Usage; char *url_orig = argv[optind]; char url[strlen(url_orig)]; optind++; // optional nfn char *nfnexpr = argv[optind]; int status; struct stat st_buf; if(outdirname) { // Check if outdirname is a directory and open it as a file status = stat(outdirname, &st_buf); if (status != 0) { // DEBUGMSG (ERROR, "Error (%d) when opening file %s\n", errno, outdirname); DEBUGMSG(ERROR, "Error (%d) when opening output dir %s (probaby does not exist)\n", errno, outdirname); goto Usage; } if (S_ISREG (st_buf.st_mode)) { // DEBUGMSG (ERROR, "Error: %s is a file and not a directory.\n", argv[optind]); DEBUGMSG(ERROR, "Error: output dir %s is a file and not a directory.\n", outdirname); goto Usage; } } if(infname) { // Check if outdirname is a directory and open it as a file status = stat(infname, &st_buf); if (status != 0) { // DEBUGMSG (ERROR, "Error (%d) when opening file %s\n", errno, outdirname); DEBUGMSG(ERROR, "Error (%d) when opening input file %s (probaby does not exist)\n", errno, infname); goto Usage; } if (S_ISDIR (st_buf.st_mode)) { // DEBUGMSG (ERROR, "Error: %s is a file and not a directory.\n", argv[optind]); DEBUGMSG(ERROR, "Error: input file %s is a directory and not a file.\n", infname); goto Usage; } f = open(infname, O_RDONLY); if (f < 0) { perror("file open:"); } } else { f = 0; } char default_file_name[2] = "c"; if (!outfname) { outfname = default_file_name; } else if(!outdirname) { DEBUGMSG(WARNING, "filename -f without -o output dir does nothing\n"); } char *chunk_buf; chunk_buf = ccnl_malloc(chunk_size * sizeof(unsigned char)); int chunk_len, is_last = 0, offs = -1; unsigned int chunknum = 0; char outpathname[255]; char fileext[10]; switch (suite) { case CCNL_SUITE_CCNB: strcpy(fileext, "ccnb"); break; case CCNL_SUITE_CCNTLV: strcpy(fileext, "ccntlv"); break; case CCNL_SUITE_CISTLV: strcpy(fileext, "cistlv"); break; case CCNL_SUITE_IOTTLV: strcpy(fileext, "iottlv"); break; case CCNL_SUITE_NDNTLV: strcpy(fileext, "ndntlv"); break; default: DEBUGMSG(ERROR, "fileext for suite %d not implemented\n", suite); } chunk_len = 1; chunk_len = read(f, chunk_buf, chunk_size); while (!is_last && chunk_len > 0) { if (chunk_len < chunk_size) { is_last = 1; } strcpy(url, url_orig); offs = CCNL_MAX_PACKET_SIZE; name = ccnl_URItoPrefix(url, suite, nfnexpr, &chunknum); switch (suite) { case CCNL_SUITE_CCNTLV: contentlen = ccnl_ccntlv_prependContentWithHdr(name, (unsigned char *)chunk_buf, chunk_len, is_last ? &chunknum : NULL, NULL, // int *contentpos &offs, out); break; case CCNL_SUITE_CISTLV: contentlen = ccnl_cistlv_prependContentWithHdr(name, (unsigned char *)chunk_buf, chunk_len, is_last ? &chunknum : NULL, &offs, NULL, // int *contentpos out); break; case CCNL_SUITE_IOTTLV: ccnl_iottlv_prependReply(name, (unsigned char *) chunk_buf, chunk_len, &offs, NULL, is_last ? &chunknum : NULL, out); ccnl_switch_prependCoding(CCNL_ENC_IOT2014, &offs, out); contentlen = CCNL_MAX_PACKET_SIZE - offs; break; case CCNL_SUITE_NDNTLV: contentlen = ccnl_ndntlv_prependContent(name, (unsigned char *) chunk_buf, chunk_len, NULL, is_last ? &chunknum : NULL, &offs, out); break; default: DEBUGMSG(ERROR, "produce for suite %i is not implemented\n", suite); goto Error; break; } if (outdirname) { sprintf(outpathname, "%s/%s%d.%s", outdirname, outfname, chunknum, fileext); // DEBUGMSG(INFO, "%s/%s%d.%s\n", outdirname, outfname, chunknum, fileext); DEBUGMSG(INFO, "writing chunk %d to file %s\n", chunknum, outpathname); fout = creat(outpathname, 0666); write(fout, out + offs, contentlen); close(fout); } else { DEBUGMSG(INFO, "writing chunk %d\n", chunknum); fwrite(out + offs, sizeof(unsigned char),contentlen, stdout); } chunknum++; if (!is_last) { chunk_len = read(f, chunk_buf, chunk_size); } } close(f); ccnl_free(chunk_buf); return 0; Error: close(f); ccnl_free(chunk_buf); return -1; }
int main(int argc, char *argv[]) { // char *private_key_path = 0; // char *witness = 0; uint8_t out[65*1024]; char *publisher = 0; char *infname = 0, *outdirname = 0, *outfname = 0; size_t contentlen = 0, plen; int f, fout, opt; // int suite = CCNL_SUITE_DEFAULT; int suite = CCNL_SUITE_CCNTLV; size_t chunk_size = CCNL_MAX_CHUNK_SIZE; struct ccnl_prefix_s *name; ccnl_data_opts_u data_opts; while ((opt = getopt(argc, argv, "hc:f:i:o:p:k:w:s:v:")) != -1) { switch (opt) { case 'c': chunk_size = (size_t) strtol(optarg, (char **) NULL, 10); if (chunk_size > CCNL_MAX_CHUNK_SIZE) { DEBUGMSG(WARNING, "max chunk size is %d (%zu is to large), using max chunk size\n", CCNL_MAX_CHUNK_SIZE, chunk_size); chunk_size = CCNL_MAX_CHUNK_SIZE; } break; case 'f': outfname = optarg; break; case 'i': infname = optarg; break; case 'o': outdirname = optarg; break; /* case 'k': private_key_path = optarg; break; case 'w': witness = optarg; break; */ case 'p': publisher = optarg; plen = unescape_component(publisher); if (plen != 32) { DEBUGMSG(ERROR, "publisher key digest has wrong length (%zu instead of 32)\n", plen); exit(-1); } break; case 's': suite = ccnl_str2suite(optarg); break; case 'v': #ifdef USE_LOGGING if (isdigit(optarg[0])) debug_level = (int)strtol(optarg, (char **)NULL, 10); else debug_level = ccnl_debug_str2level(optarg); #endif break; case 'h': default: Usage: fprintf(stderr, "Creates a chunked content object stream for the input data and writes them to stdout.\n" "usage: %s [options] URL\n" " -c SIZE size for each chunk (max %d)\n" " -f FNAME filename of the chunks when using -o\n" " -i FNAME input file (instead of stdin)\n" " -o DIR output dir (instead of stdout), filename default is cN, otherwise specify -f\n" " -p DIGEST publisher fingerprint\n" " -s SUITE (ccnb, ccnx2015, ndn2013)\n" #ifdef USE_LOGGING " -v DEBUG_LEVEL (fatal, error, warning, info, debug, verbose, trace)\n" #endif , argv[0], CCNL_MAX_CHUNK_SIZE); exit(1); } } if (!ccnl_isSuite(suite)) { goto Usage; } // mandatory url if (!argv[optind]) { goto Usage; } char *url_orig = argv[optind]; char url[strlen(url_orig)]; optind++; int status; struct stat st_buf; if (outdirname) { // Check if outdirname is a directory and open it as a file status = stat(outdirname, &st_buf); if (status != 0) { // DEBUGMSG (ERROR, "Error (%d) when opening file %s\n", errno, outdirname); DEBUGMSG(ERROR, "Error (%d) when opening output dir %s (probaby does not exist)\n", errno, outdirname); goto Usage; } if (S_ISREG (st_buf.st_mode)) { // DEBUGMSG (ERROR, "Error: %s is a file and not a directory.\n", argv[optind]); DEBUGMSG(ERROR, "Error: output dir %s is a file and not a directory.\n", outdirname); goto Usage; } } if (infname) { // Check if outdirname is a directory and open it as a file status = stat(infname, &st_buf); if (status != 0) { // DEBUGMSG (ERROR, "Error (%d) when opening file %s\n", errno, outdirname); DEBUGMSG(ERROR, "Error (%d) when opening input file %s (probaby does not exist)\n", errno, infname); goto Usage; } if (S_ISDIR (st_buf.st_mode)) { // DEBUGMSG (ERROR, "Error: %s is a file and not a directory.\n", argv[optind]); DEBUGMSG(ERROR, "Error: input file %s is a directory and not a file.\n", infname); goto Usage; } f = open(infname, O_RDONLY); if (f < 0) { perror("file open:"); } } else { f = 0; } char default_file_name[2] = "c"; if (!outfname) { outfname = default_file_name; } else if(!outdirname) { DEBUGMSG(WARNING, "filename -f without -o output dir does nothing\n"); } uint8_t *chunk_buf; chunk_buf = ccnl_malloc(chunk_size * sizeof(uint8_t)); if (!chunk_buf) { DEBUGMSG(ERROR, "Error: Failed to allocate memory\n"); exit(1); } size_t chunk_len; ssize_t s_chunk_len; int8_t is_last = 0; size_t offs; uint32_t chunknum = 0; char outpathname[255]; char fileext[10]; switch (suite) { case CCNL_SUITE_CCNB: strcpy(fileext, "ccnb"); break; case CCNL_SUITE_CCNTLV: strcpy(fileext, "ccntlv"); break; case CCNL_SUITE_NDNTLV: strcpy(fileext, "ndntlv"); break; default: DEBUGMSG(ERROR, "fileext for suite %d not implemented\n", suite); } FILE *fp = fopen(infname, "r"); fseek(fp, 0L, SEEK_END); long sz = ftell(fp); size_t isz; if (sz < 0) { DEBUGMSG(ERROR, "Error reading input file offset; error: %d\n", errno); exit(1); } if ((unsigned long) sz > SIZE_MAX) { DEBUGMSG(ERROR, "Input file offset exceeds bounds: %ld", sz); exit(1); } isz = (size_t) sz; rewind(fp); fclose(fp); size_t lastchunknum_s = (isz / chunk_size); if (lastchunknum_s > UINT32_MAX) { DEBUGMSG(ERROR, "lastchunknum exceeds bounds: %zu", lastchunknum_s); exit(1); } uint32_t lastchunknum = (uint32_t) lastchunknum_s; if (sz % chunk_size == 0) { --lastchunknum; } s_chunk_len = read(f, chunk_buf, chunk_size); if (s_chunk_len < 0) { DEBUGMSG(ERROR, "Error reading input file; error: %d\n", errno); exit(1); } chunk_len = (size_t) s_chunk_len; while (!is_last && chunk_len > 0) { if (chunk_len < chunk_size) { is_last = 1; } strcpy(url, url_orig); offs = CCNL_MAX_PACKET_SIZE; name = ccnl_URItoPrefix(url, suite, &chunknum); switch (suite) { case CCNL_SUITE_CCNTLV: if (ccnl_ccntlv_prependContentWithHdr(name, chunk_buf, chunk_len, &lastchunknum, //is_last ? &chunknum : NULL, NULL, // int *contentpos &offs, out, &contentlen)) { goto Error; } break; case CCNL_SUITE_NDNTLV: data_opts.ndntlv.finalblockid = lastchunknum; if (ccnl_ndntlv_prependContent(name, chunk_buf, chunk_len, NULL, &(data_opts.ndntlv),// is_last ? &chunknum : NULL, &offs, out, &contentlen)) { goto Error; } break; default: DEBUGMSG(ERROR, "produce for suite %i is not implemented\n", suite); goto Error; break; } if (outdirname) { sprintf(outpathname, "%s/%s%d.%s", outdirname, outfname, chunknum, fileext); DEBUGMSG(INFO, "writing chunk %d to file %s\n", chunknum, outpathname); fout = creat(outpathname, 0666); write(fout, out + offs, contentlen); close(fout); } else { DEBUGMSG(INFO, "writing chunk %d\n", chunknum); fwrite(out + offs, sizeof(unsigned char),contentlen, stdout); } chunknum++; if (!is_last) { s_chunk_len = read(f, chunk_buf, chunk_size); if (s_chunk_len < 0) { DEBUGMSG(ERROR, "Error reading input file; error: %d\n", errno); exit(1); } chunk_len = (size_t) s_chunk_len; } } close(f); ccnl_free(chunk_buf); return 0; Error: close(f); ccnl_free(chunk_buf); return -1; }
int main(int argc, char **argv) { int opt, max_cache_entries = -1, httpport = -1; int udpport1 = -1, udpport2 = -1; char *datadir = NULL, *ethdev = NULL, *crypto_sock_path = NULL; #ifdef USE_UNIXSOCKET char *uxpath = CCNL_DEFAULT_UNIXSOCKNAME; #else char *uxpath = NULL; #endif #ifdef USE_ECHO char *echopfx = NULL; #endif time(&theRelay.startup_time); srandom(time(NULL)); while ((opt = getopt(argc, argv, "hc:d:e:g:i:o:p:s:t:u:v:x:")) != -1) { switch (opt) { case 'c': max_cache_entries = atoi(optarg); break; case 'd': datadir = optarg; break; case 'e': ethdev = optarg; break; case 'g': inter_pkt_interval = atoi(optarg); break; case 'i': inter_ccn_interval = atoi(optarg); break; #ifdef USE_ECHO case 'o': echopfx = optarg; break; #endif case 'p': crypto_sock_path = optarg; break; case 's': suite = ccnl_str2suite(optarg); if (!ccnl_isSuite(suite)) goto usage; break; case 't': httpport = atoi(optarg); break; case 'u': if (udpport1 == -1) udpport1 = atoi(optarg); else udpport2 = atoi(optarg); break; case 'v': #ifdef USE_LOGGING if (isdigit(optarg[0])) debug_level = atoi(optarg); else debug_level = ccnl_debug_str2level(optarg); #endif break; case 'x': uxpath = optarg; break; case 'h': default: usage: fprintf(stderr, "usage: %s [options]\n" " -c MAX_CONTENT_ENTRIES\n" " -d databasedir\n" " -e ethdev\n" " -g MIN_INTER_PACKET_INTERVAL\n" " -h\n" " -i MIN_INTER_CCNMSG_INTERVAL\n" #ifdef USE_ECHO " -o echo_prefix\n" #endif " -p crypto_face_ux_socket\n" " -s SUITE (ccnb, ccnx2015, cisco2015, iot2014, ndn2013)\n" " -t tcpport (for HTML status page)\n" " -u udpport (can be specified twice)\n" #ifdef USE_LOGGING " -v DEBUG_LEVEL (fatal, error, warning, info, debug, verbose, trace)\n" #endif #ifdef USE_UNIXSOCKET " -x unixpath\n" #endif , argv[0]); exit(EXIT_FAILURE); } } opt = ccnl_suite2defaultPort(suite); if (udpport1 < 0) udpport1 = opt; if (httpport < 0) httpport = opt; ccnl_core_init(); DEBUGMSG(INFO, "This is ccn-lite-relay, starting at %s", ctime(&theRelay.startup_time) + 4); DEBUGMSG(INFO, " ccnl-core: %s\n", CCNL_VERSION); DEBUGMSG(INFO, " compile time: %s %s\n", __DATE__, __TIME__); DEBUGMSG(INFO, " compile options: %s\n", compile_string); DEBUGMSG(INFO, "Abhinav - Modified CCN lite"); // DEBUGMSG(INFO, "using suite %s\n", ccnl_suite2str(suite)); ccnl_relay_config(&theRelay, ethdev, udpport1, udpport2, httpport, uxpath, suite, max_cache_entries, crypto_sock_path); if (datadir) ccnl_populate_cache(&theRelay, datadir); #ifdef USE_ECHO if (echopfx) { struct ccnl_prefix_s *pfx; char *dup = ccnl_strdup(echopfx); pfx = ccnl_URItoPrefix(dup, suite, NULL, NULL); if (pfx) ccnl_echo_add(&theRelay, pfx); ccnl_free(dup); } #endif ccnl_io_loop(&theRelay); while (eventqueue) ccnl_rem_timer(eventqueue); ccnl_core_cleanup(&theRelay); #ifdef USE_HTTP_STATUS theRelay.http = ccnl_http_cleanup(theRelay.http); #endif #ifdef USE_DEBUG_MALLOC debug_memdump(); #endif return 0; }
int main(int argc, char *argv[]) { unsigned char out[64*1024]; int len, opt, port, sock = 0, suite = CCNL_SUITE_DEFAULT; char *addr = NULL, *udp = NULL, *ux = NULL; struct sockaddr sa; float wait = 3.0; while ((opt = getopt(argc, argv, "hs:u:v:w:x:")) != -1) { switch (opt) { case 's': suite = ccnl_str2suite(optarg); if (!ccnl_isSuite(suite)) { DEBUGMSG(ERROR, "Unsupported suite %s\n", optarg); goto usage; } break; case 'u': udp = optarg; break; case 'w': wait = atof(optarg); break; case 'v': #ifdef USE_LOGGING if (isdigit(optarg[0])) debug_level = atoi(optarg); else debug_level = ccnl_debug_str2level(optarg); #endif break; case 'x': ux = optarg; break; case 'h': default: usage: fprintf(stderr, "usage: %s [options] URI [NFNexpr]\n" " -s SUITE (ccnb, ccnx2015, cisco2015, iot2014, ndn2013)\n" " -u a.b.c.d/port UDP destination (default is 127.0.0.1/6363)\n" #ifdef USE_LOGGING " -v DEBUG_LEVEL (fatal, error, warning, info, debug, verbose, trace)\n" #endif " -w timeout in sec (float)\n" " -x ux_path_name UNIX IPC: use this instead of UDP\n" "Examples:\n" "%% peek /ndn/edu/wustl/ping (classic lookup)\n" "%% peek /th/ere \"lambda expr\" (lambda expr, in-net)\n" "%% peek \"\" \"add 1 1\" (lambda expr, local)\n" "%% peek /rpc/site \"call 1 /test/data\" (lambda RPC, directed)\n", argv[0]); exit(1); } } if (!argv[optind]) goto usage; srandom(time(NULL)); if (ccnl_parseUdp(udp, suite, &addr, &port) != 0) { exit(-1); } DEBUGMSG(TRACE, "using suite %d:%s\n", suite, ccnl_suite2str(suite)); DEBUGMSG(TRACE, "using udp address %s/%d\n", addr, port); if (ux) { // use UNIX socket struct sockaddr_un *su = (struct sockaddr_un*) &sa; su->sun_family = AF_UNIX; strcpy(su->sun_path, ux); sock = ux_open(); } else { // UDP struct sockaddr_in *si = (struct sockaddr_in*) &sa; si->sin_family = PF_INET; si->sin_addr.s_addr = inet_addr(addr); si->sin_port = htons(port); sock = udp_open(); } char *url = argv[optind]; char *nfnexpr = 0; if (argv[optind+1]) { nfnexpr = argv[optind+1]; } unsigned char *content = 0; int contlen; unsigned int *curchunknum = NULL; // For CCNTLV always start with the first chunk because of exact content match // This means it can only fetch chunked data and not single content-object data if (suite == CCNL_SUITE_CCNTLV || suite == CCNL_SUITE_CISTLV) { curchunknum = ccnl_malloc(sizeof(unsigned int)); *curchunknum = 0; } struct ccnl_prefix_s *prefix = ccnl_URItoPrefix(url, suite, nfnexpr, curchunknum); const int maxretry = 3; int retry = 0; while (retry < maxretry) { if (curchunknum) { if (!prefix->chunknum) { prefix->chunknum = ccnl_malloc(sizeof(unsigned int)); } *(prefix->chunknum) = *curchunknum; DEBUGMSG(INFO, "fetching chunk %d for prefix '%s'\n", *curchunknum, ccnl_prefix_to_path(prefix)); } else { DEBUGMSG(DEBUG, "fetching first chunk...\n"); DEBUGMSG(INFO, "fetching first chunk for prefix '%s'\n", ccnl_prefix_to_path(prefix)); } // Fetch chunk if (ccnl_fetchContentForChunkName(prefix, nfnexpr, curchunknum, suite, out, sizeof(out), &len, wait, sock, sa) < 0) { retry++; DEBUGMSG(WARNING, "timeout\n");//, retry number %d of %d\n", retry, maxretry); } else { unsigned int lastchunknum; unsigned char *t = &out[0]; struct ccnl_prefix_s *nextprefix = 0; // Parse response if (ccnl_extractDataAndChunkInfo(&t, &len, suite, &nextprefix, &lastchunknum, &content, &contlen) < 0) { retry++; DEBUGMSG(WARNING, "Could not extract response or it was an interest\n"); } else { prefix = nextprefix; // Check if the fetched content is a chunk if (!(prefix->chunknum)) { // Response is not chunked, print content and exit write(1, content, contlen); goto Done; } else { int chunknum = *(prefix->chunknum); // allocate curchunknum because it is the first fetched chunk if(!curchunknum) { curchunknum = ccnl_malloc(sizeof(unsigned int)); *curchunknum = 0; } // Remove chunk component from name if (ccnl_prefix_removeChunkNumComponent(suite, prefix) < 0) { retry++; DEBUGMSG(WARNING, "Could not remove chunknum\n"); } // Check if the chunk is the first chunk or the next valid chunk // otherwise discard content and try again (except if it is the first fetched chunk) if (chunknum == 0 || (curchunknum && *curchunknum == chunknum)) { DEBUGMSG(DEBUG, "Found chunk %d with contlen=%d, lastchunk=%d\n", *curchunknum, contlen, lastchunknum); write(1, content, contlen); if (lastchunknum != -1 && lastchunknum == chunknum) { goto Done; } else { *curchunknum += 1; retry = 0; } } else { // retry if the fetched chunk retry++; DEBUGMSG(WARNING, "Could not find chunk %d, extracted chunknum is %d (lastchunk=%d)\n", *curchunknum, chunknum, lastchunknum); } } } } if(retry > 0) { DEBUGMSG(INFO, "Retry %d of %d\n", retry, maxretry); } } close(sock); return 1; Done: DEBUGMSG(DEBUG, "Sucessfully fetched content\n"); close(sock); return 0; }