int
main(int argc, char *argv[])
{
    unsigned char out[64*1024];
    int cnt, len, opt, sock = 0, socksize, suite = CCNL_SUITE_DEFAULT, port;
    char *addr = NULL, *udp = NULL, *ux = NULL;
    char *defaultNFNpath = "";//strdup("/ndn/ch/unibas/nfn");
    struct sockaddr sa;
    struct ccnl_prefix_s *prefix;
    float wait = 3.0;
    ccnl_mkInterestFunc mkInterest;
    ccnl_isContentFunc isContent;

    while ((opt = getopt(argc, argv, "hn:s:u:v:w:x:")) != -1) {
        switch (opt) {
        case 'n':
            defaultNFNpath = optarg;
            break;
        case 's':
            opt = ccnl_str2suite(optarg);
            if (opt < 0 || opt >= CCNL_SUITE_LAST)
                goto usage;
            suite = opt;
            break;
        case 'u':
            udp = 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 'w':
            wait = atof(optarg);
            break;
        case 'x':
            ux = optarg;
            break;
        case 'h':
        default:
usage:
            fprintf(stderr, "usage: %s [options] NFNexpr\n"
            "  -n NFNPATH       default prefix towards some NFN node(s)\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"
            "%% simplenfn /ndn/edu/wustl/ping\n"
            "%% simplenfn \"echo hello world\"\n"
            "%% simplenfn \"translate 'ccnx2014 /ccnx/parc/info.txt\"\n"
            "%% simplenfn \"add 1 1\"\n",
            argv[0]);
            exit(1);
        }
    }

    if (!argv[optind] || argv[optind+1])
        goto usage;

    srandom(time(NULL));

    if (ccnl_parseUdp(udp, suite, &addr, &port) != 0) {
        exit(-1);
    }
    DEBUGMSG(TRACE, "using udp address %s/%d\n", addr, port);

    mkInterest = ccnl_suite2mkInterestFunc(suite);
    isContent = ccnl_suite2isContentFunc(suite);
    if (!mkInterest || !isContent) {
        exit(-1);
    }

    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();
    }

    prefix = exprToNfnPrefix(defaultNFNpath, suite, argv[optind]);
    if (!prefix)
        goto done;
    for (cnt = 0; cnt < 3; cnt++) {
        int nonce = random();

        len = mkInterest(prefix,
                         &nonce,
                         out, sizeof(out));

        DEBUGMSG(TRACE,
                 "sending interest(prefix=%s, suite=%s)\n",
                 ccnl_prefix_to_path(prefix),
                 ccnl_suite2str(suite));

        if(ux) {
            socksize = sizeof(struct sockaddr_un);
        } else {
            socksize = sizeof(struct sockaddr_in);
        }
        if (sendto(sock, out, len, 0,(struct sockaddr *) &sa, socksize) < 0) {
            perror("sendto");
            myexit(1);
        }

        for (;;) { // wait for a content pkt (ignore interests)
            int rc;

            if (block_on_read(sock, wait) <= 0) // timeout
                break;
            len = recv(sock, out, sizeof(out), 0);
/*
            fprintf(stderr, "received %d bytes\n", len);
            if (len > 0)
                fprintf(stderr, "  suite=%d\n", ccnl_pkt2suite(out, len));
*/
            rc = isContent(out, len);
            if (rc < 0)
                goto done;
            if (rc == 0) { // it's an interest, ignore it
                DEBUGMSG(WARNING, "skipping non-data packet\n");
                continue;
            }
            write(1, out, len);
            myexit(0);
        }
        if (cnt < 2)
            DEBUGMSG(INFO, "re-sending interest\n");
    }
    DEBUGMSG(ERROR, "timeout\n");

done:
    close(sock);
    myexit(-1);
    return 0; // avoid a compiler warning
}
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;
}
Exemple #3
0
int
main(int argc, char **argv)
{
    int opt;
    int max_cache_entries = CCNL_DEFAULT_MAX_CACHE_ENTRIES;

    //    srand(time(NULL));
    srandom(time(NULL));

    while ((opt = getopt(argc, argv, "hc:g:i:s:v:")) != -1) {
        switch (opt) {
        case 'c':
            max_cache_entries = atoi(optarg);
            break;
        case 'g':
            inter_packet_interval = atoi(optarg);
            break;
        case 'i':
            inter_ccn_interval = atoi(optarg);
            break;
        case 'v':
            if (isdigit(optarg[0]))
                debug_level = atoi(optarg);
            else
                debug_level = ccnl_debug_str2level(optarg);
            break;
        case 's':
            theSuite = ccnl_str2suite(optarg);
            if (theSuite >= 0 && theSuite < CCNL_SUITE_LAST)
                break;
        case 'h':
        default:
            fprintf(stderr, "Xusage: %s [-h] [-c MAX_CONTENT_ENTRIES] "
                    "[-g MIN_INTER_PACKET_INTERVAL] "
                    "[-i MIN_INTER_CCNMSG_INTERVAL] "
                    "[-s SUITE (ccnb, ccnx2014, iot2014, ndn2013)] "
                    "[-v DEBUG_LEVEL]\n",
                    argv[0]);
            exit(EXIT_FAILURE);
        }
    }

    time(&relays[0].startup_time);

    ccnl_core_init();

    DEBUGMSG(INFO, "This is ccn-lite-simu, starting at %s",
             ctime(&relays[0].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, "using suite %s\n", ccnl_suite2str(theSuite));

    ccnl_simu_init(max_cache_entries);

    DEBUGMSG(INFO, "simulation starts\n");
    simu_eventloop();
    DEBUGMSG(INFO, "simulation ends\n");

    return -1;
}
Exemple #4
0
int
main(int argc, char *argv[])
{
    unsigned char out[CCNL_MAX_PACKET_SIZE];
    char *minSuffix = 0, *maxSuffix = 0, *scope = 0;
    char *digest = 0, *publisher = 0;
    char *fname = 0;
    int f, len=0, opt;
    int dlen = 0, plen = 0;
    int packettype = CCNL_SUITE_NDNTLV;
    struct ccnl_prefix_s *prefix;
    time_t curtime;
    uint32_t nonce;
    int isLambda = 0;
    unsigned int chunknum = UINT_MAX;

    time(&curtime);
    // Get current time in double to avoid dealing with time_t
    nonce = (uint32_t) difftime(curtime, 0);

    while ((opt = getopt(argc, argv, "ha:c:d:e:i:ln:o:p:s:v:x:")) != -1) {
        switch (opt) {
        case 'a':
            minSuffix = optarg;
            break;
        case 'c':
            scope = optarg;
            break;
        case 'd':
            digest = optarg;
            dlen = unescape_component(digest);
            if (dlen != 32) {
                DEBUGMSG(ERROR, "digest has wrong length (%d instead of 32)\n",
                        dlen);
                exit(-1);
            }
            break;
        case 'e':
            nonce = atoi(optarg);
            break;
        case 'l':
            isLambda = 1 - isLambda;
            break;
        case 'n':
            chunknum = atoi(optarg);
            break;
        case 'o':
            fname = 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 'v':
#ifdef USE_LOGGING
            if (isdigit(optarg[0]))
                debug_level = atoi(optarg);
            else
                debug_level = ccnl_debug_str2level(optarg);
#endif
            break;
        case 'x':
            maxSuffix = optarg;
            break;
        case 's':
            packettype = ccnl_str2suite(optarg);
            if (packettype >= 0 && packettype < CCNL_SUITE_LAST)
                break;
        case 'h':
        default:
Usage:
            fprintf(stderr, "usage: %s [options] URI [NFNexpr]\n"
            "  -a LEN     miN additional components\n"
            "  -c SCOPE\n"

            "  -d DIGEST  content digest (sets -x to 0)\n"
            "  -e NONCE   random 4 bytes\n"
            "  -l         URI is a Lambda expression\n"
            "  -n CHUNKNUM positive integer for chunk interest\n"
            "  -o FNAME   output file (instead of stdout)\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
            "  -x LEN     maX additional components\n",
            argv[0]);
            exit(1);
        }
    }

    if (!argv[optind])
        goto Usage;

    /*
    if (isLambda)
        i = ccnl_lambdaStrToComponents(prefix, argv[optind]);
    else
    */
    prefix = ccnl_URItoPrefix(argv[optind],
                              packettype,
                              argv[optind+1],
                              chunknum == UINT_MAX ? NULL : &chunknum);
    if (!prefix) {
        DEBUGMSG(ERROR, "no URI found, aborting\n");
        return -1;
    }

    switch (packettype) {
    case CCNL_SUITE_CCNB:
        len = ccnl_ccnb_mkInterest(prefix, minSuffix, maxSuffix,
                                   (unsigned char*) digest, dlen,
                                   (unsigned char*) publisher, plen,
                                   scope, &nonce, out);
        break;
    case CCNL_SUITE_CCNTLV:
        len = ccntlv_mkInterest(prefix,
                                (int*)&nonce,
                                out, CCNL_MAX_PACKET_SIZE);
	break;
    case CCNL_SUITE_CISTLV:
        len = cistlv_mkInterest(prefix,
                                (int*)&nonce,
                                out, CCNL_MAX_PACKET_SIZE);
	break;
    case CCNL_SUITE_IOTTLV:
        len = iottlv_mkRequest(prefix, NULL, out, CCNL_MAX_PACKET_SIZE);
        break;
    case CCNL_SUITE_NDNTLV:
        len = ndntlv_mkInterest(prefix,
                                (int*)&nonce,
                                out,
                                CCNL_MAX_PACKET_SIZE);
        break;
    default:
        DEBUGMSG(ERROR, "Not Implemented (yet)\n");
        return -1;
    }

    if (len <= 0) {
        DEBUGMSG(ERROR, "internal error: empty packet\n");
        return -1;
    }

    if (fname) {
        f = creat(fname, 0666);
        if (f < 0) {
            perror("file open:");
            return -1;
        }
    } else
        f = 1;

    write(f, out, len);
    close(f);

    return 0;
}
int
main(int argc, char **argv)
{
    int opt;
    int udpport = 0;
    char *prefix, *defaultgw;
    struct ccnl_if_s *i;
    struct ccnl_forward_s *fwd;
    sockunion sun;

    srandom(time(NULL));

    int suite = CCNL_SUITE_NDNTLV;

    while ((opt = getopt(argc, argv, "hs:u:v:")) != -1) {
        switch (opt) {
        case 's':
            opt = ccnl_str2suite(optarg);
            if (opt >= 0 && opt < CCNL_SUITE_LAST)
                suite = opt;
            else
                fprintf(stderr, "Suite parameter <%s> ignored.\n", optarg);
            break;
        case 'u':
            udpport = atoi(optarg);
            break;
        case 'v':
            debug_level = atoi(optarg);
            break;
        case 'h':
        default:
usage:
            fprintf(stderr,
                    "usage:    %s [options] PREFIX DGWIP/DGWUDPPORT\n"
                    "options:  [-h] [-s SUITE] [-u udpport] [-v debuglevel]\n"
                    "example:  %s /ndn 128.252.153.194/6363\n",
                    argv[0], argv[0]);
            exit(EXIT_FAILURE);
        }
    }

    if ((optind+1) >= argc)
        goto usage;
    prefix = argv[optind];
    defaultgw = argv[optind+1];

    ccnl_core_init();

//    if (theRelay.suite == CCNL_SUITE_NDNTLV && !udpport)
        udpport = NDN_UDP_PORT;

    i = &theRelay.ifs[0];
    i->mtu = NDN_DEFAULT_MTU;
    i->fwdalli = 1;
    i->sock = ccnl_open_udpdev(udpport);
    if (i->sock < 0)
        exit(-1);
    theRelay.ifcount++;
    fprintf(stderr, "NDN minimalrelay started, listening on UDP port %d\n",
            udpport);

    inet_aton(strtok(defaultgw,"/"), &sun.ip4.sin_addr);
    sun.ip4.sin_port = atoi(strtok(NULL, ""));
    fwd = (struct ccnl_forward_s *) ccnl_calloc(1, sizeof(*fwd));
    fwd->prefix = ccnl_URItoPrefix(prefix, suite, NULL, NULL);
    fwd->suite = suite;
    fwd->face = ccnl_get_face_or_create(&theRelay, 0, &sun.sa, sizeof(sun.ip4));
    fwd->face->flags |= CCNL_FACE_FLAGS_STATIC;
    theRelay.fib = fwd;

    ccnl_set_timer(1000000, ccnl_minimalrelay_ageing, &theRelay, 0);
    ccnl_io_loop(&theRelay);

    return 0;
}
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[])
{
    // 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[])
{
    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;
}