/* Complete libtrace skeleton program
 *
 * This libtrace skeleton includes everything you need for a useful libtrace
 * program, including command line parsing, dealing with bpf filters etc.
 *
 */
#include "libtrace.h"
#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <assert.h>

static void per_packet(libtrace_packet_t *packet)
{
    assert(packet);
    /* Your code goes here */
}

static void usage(char *argv0)
{
    fprintf(stderr,
            "usage: %s [ --filter | -f bpfexp ]  [ --snaplen | -s snap "
            "]\n\t\t[ --promisc | -p flag] [ --help | -h ] [ --libtrace-help | "
            "-H ] libtraceuri...\n",
            argv0);
}

int main(int argc, char *argv[])
{
    libtrace_t *trace;
    libtrace_packet_t *packet;
    libtrace_filter_t *filter = NULL;
    int snaplen = -1;
    int promisc = -1;

    while (1) {
        int option_index;
        struct option long_options[] = {
            {"filter", 1, 0, 'f'},        {"snaplen", 1, 0, 's'},
            {"promisc", 1, 0, 'p'},       {"help", 0, 0, 'h'},
            {"libtrace-help", 0, 0, 'H'}, {NULL, 0, 0, 0}};

        int c =
            getopt_long(argc, argv, "f:s:p:hH", long_options, &option_index);

        if (c == -1)
            break;

        switch (c) {
        case 'f':
            filter = trace_create_filter(optarg);
            break;
        case 's':
            snaplen = atoi(optarg);
            break;
        case 'p':
            promisc = atoi(optarg);
            break;
        case 'H':
            trace_help();
            return 1;
        default:
            fprintf(stderr, "Unknown option: %c\n", c);
            /* FALL THRU */
        case 'h':
            usage(argv[0]);
            return 1;
        }
    }

    if (optind >= argc) {
        fprintf(stderr, "Missing input uri\n");
        usage(argv[0]);
        return 1;
    }

    while (optind < argc) {
        trace = trace_create(argv[optind]);
        ++optind;

        if (trace_is_err(trace)) {
            trace_perror(trace, "Opening trace file");
            return 1;
        }

        if (snaplen > 0)
            if (trace_config(trace, TRACE_OPTION_SNAPLEN, &snaplen)) {
                trace_perror(trace, "ignoring: ");
            }
        if (filter)
            if (trace_config(trace, TRACE_OPTION_FILTER, filter)) {
                trace_perror(trace, "ignoring: ");
            }
        if (promisc != -1) {
            if (trace_config(trace, TRACE_OPTION_PROMISC, &promisc)) {
                trace_perror(trace, "ignoring: ");
            }
        }

        if (trace_start(trace)) {
            trace_perror(trace, "Starting trace");
            trace_destroy(trace);
            return 1;
        }

        packet = trace_create_packet();

        while (trace_read_packet(trace, packet) > 0) {
            per_packet(packet);
        }

        trace_destroy_packet(packet);

        if (trace_is_err(trace)) {
            trace_perror(trace, "Reading packets");
        }

        trace_destroy(trace);
    }

    return 0;
}
