Main Page | Modules | Class Hierarchy | Class List | Directories | Class Members | Related Pages | Examples

profile_streams_thesis.cc

The program used to generate flow attributes for my thesis, "Tools, Data, and Flow Attributes for Understanding Network Traffic without Payload".


// test harness for protocol parsing

#include <iostream>             // cout, cerr
#include <string>

#include "data_structures/basic_types.h"        // Timeval
#include "data_structures/PacketFilter.h"
#include "data_structures/Aggregate.h"          // Trace
#include "protocols/parsers/QcapAdaptor.h"
#include "data_structures/Packet.h"
#include "data_structures/Clock.h"
#include "data_structures/StreamListener.h"
#include "protocols/parsers/IPv4Sessionizer.h"  // for TCP and UDP

#include "attributes/ByteCountAttribute.h"
#include "attributes/DurationAttribute.h"
#include "attributes/ArithmeticAttribute.h"
#include "attributes/HistogramAttribute.h"
#include "attributes/PacketCountAttribute.h"
#include "attributes/ConversationTrackerAttribute.h"
#include "attributes/MemoryAttribute.h"

#include <sys/times.h>          // CPU times for profiling

using namespace std; 

int lengthBounds[23] = {
           0,    1,    2,    4,    5, 
           9,   19,   39,   49,   99, 
         179,  235,  268,  349,  449, 
         515,  548,  649,  999, 1379, 
        1380, 1431, 1472 
    };

Timeval delayBounds[8] = { 
        Timeval( 0.000001 ), Timeval( 0.0001 ), Timeval( 0.001 ), Timeval( 0.01 ), Timeval( 0.1 ),
             Timeval( 1.0 ),   Timeval( 10.0 ),  Timeval( 64.0 )
    };

int usage( void ) {
    cerr << "Usage:  profile_streams_thesis [-l] <pcap>" << endl;
    cerr << endl;
    cerr << "\t"    "-l : list packets - time, delay, and payload length" << endl;
    return 0;
}

void initStreamAttributes( Decomposition& templ, Clock& clock ) {
    PacketFilter *nonemptyPacketFilter = new SimplePacketFilter( 
                    PacketAttribute("transport.len"), 
                    ConcretePacketAttributeValue<int>(0),
                    SimplePacketFilter::GREATER );

    // begin time
    templ.addAttrib( "start_time", PacketDrivenMemoryAttribute<Timeval>(
                "frame.time",
                MemoryAttribute<Timeval>::ATTRIB_TYPE_PACKET,
                1,
                false ) );
    
    // duration
    templ.addAttrib( "duration", DurationAttribute() );

    // packet counts
    // packet count pkt_count is implicit
    templ.addAttrib( "nonempty_count", PacketCountAttribute( *nonemptyPacketFilter ) );
    
    // byte counts
    templ.addAttrib( "pkt_byte_count", ByteCountAttribute(true) );
    templ.addAttrib( "payload_byte_count", ByteCountAttribute(false) );

    // mean inter-packet delay
    templ.addAttrib( "mean_delay", 
            ArithmeticAttribute<Timeval,int,double>( "duration", "pkt_count",
                ArithmeticAttribute<Timeval,int,double>::OP_DIVIDE ), 1 );
    
    // mean packet lengths
    templ.addAttrib( "mean_pkt_len",
            ArithmeticAttribute<int,int,double>( "pkt_byte_count", "pkt_count",
                ArithmeticAttribute<Timeval,int,double>::OP_DIVIDE ), 1 );
    templ.addAttrib( "mean_payload_len",
            ArithmeticAttribute<int,int,double>( "payload_byte_count", "pkt_count",
                ArithmeticAttribute<Timeval,int,double>::OP_DIVIDE ), 1 );
    templ.addAttrib( "mean_nonempty_payload_len", 
            ArithmeticAttribute<int,int,double>( "payload_byte_count", "nonempty_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );
    
    // databyte ratio originator to responder 
    templ.addAttrib( "payload_byte_count_fwd_plus1", 
            ArithmeticAttribute<int,int,int>( "payload_byte_count.forward", 1, 
                ArithmeticAttribute<int,int,int>::OP_ADD ), 1 );
    templ.addAttrib( "payload_byte_count_rev_plus1", 
            ArithmeticAttribute<int,int,int>( "payload_byte_count.reverse", 1, 
                ArithmeticAttribute<int,int,int>::OP_ADD ), 1 );
    templ.addAttrib( "dir_data", 
            ArithmeticAttribute<int,int,double>( "payload_byte_count_fwd_plus1", "payload_byte_count_rev_plus1", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 2 );

    templ.addAttrib( "mean_pkt_datarate",
            ArithmeticAttribute<int,Timeval,double>( "pkt_byte_count", "duration",
                ArithmeticAttribute<int,Timeval,double>::OP_DIVIDE ), 1 );
    templ.addAttrib( "mean_payload_datarate",
            ArithmeticAttribute<int,Timeval,double>( "payload_byte_count", "duration",
                ArithmeticAttribute<int,Timeval,double>::OP_DIVIDE ), 1 );

    // max datarate attributes
    // 1s 
    templ.addAttrib( "1s_payload_len_window",
            PacketDrivenMemoryAttribute<int>(
                "transport.len",
                MemoryAttribute<int>::ATTRIB_TYPE_PACKET,
                Timeval(1.0) ) );

    templ.addAttrib( "1s_datarate",
            ArithmeticAttribute<int,double,double>(
                "1s_payload_len_window.sum",
                1.0,
                ArithmeticAttribute<int,double,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "1s_datarate_window",
            SampledMemoryAttribute<double>(
                "1s_datarate",
                SampledMemoryAttribute<double>::ATTRIB_TYPE_AGGREGATE,
                0,
                Timeval(0.2) ) );

    // 5s 
    templ.addAttrib( "5s_payload_len_window",
            PacketDrivenMemoryAttribute<int>(
                "transport.len",
                MemoryAttribute<int>::ATTRIB_TYPE_PACKET,
                Timeval(5.0) ) );

    templ.addAttrib( "5s_datarate",
            ArithmeticAttribute<int,double,double>(
                "5s_payload_len_window.sum",
                5.0,
                ArithmeticAttribute<int,double,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "5s_datarate_window",
            SampledMemoryAttribute<double>(
                "5s_datarate",
                SampledMemoryAttribute<double>::ATTRIB_TYPE_AGGREGATE,
                0,
                Timeval(1.0) ) );

    // 30s 
    templ.addAttrib( "30s_payload_len_window",
            PacketDrivenMemoryAttribute<int>(
                "transport.len",
                MemoryAttribute<int>::ATTRIB_TYPE_PACKET,
                Timeval(30.0) ) );

    templ.addAttrib( "30s_datarate",
            ArithmeticAttribute<int,double,double>(
                "30s_payload_len_window.sum",
                30.0,
                ArithmeticAttribute<int,double,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "30s_datarate_window",
            SampledMemoryAttribute<double>(
                "30s_datarate",
                SampledMemoryAttribute<double>::ATTRIB_TYPE_AGGREGATE,
                0,
                Timeval(6.0) ) );

    // packet flag heuristics
    templ.addAttrib( "urg_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.urg"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_urg",
            ArithmeticAttribute<int,int,double>( "urg_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "ack_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.ack"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_ack",
            ArithmeticAttribute<int,int,double>( "ack_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "psh_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.psh"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_psh",
            ArithmeticAttribute<int,int,double>( "psh_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "rst_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.rst"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_rst",
            ArithmeticAttribute<int,int,double>( "rst_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "syn_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.syn"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_syn",
            ArithmeticAttribute<int,int,double>( "syn_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "fin_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.fin"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_fin",
            ArithmeticAttribute<int,int,double>( "fin_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );
    
    
    /*
    // tracker for conversations
    templ.addAttrib( "conv_tracker", 
            ConversationTrackerAttribute( 
                *nonemptyPacketFilter,
                2,                              // minimum 2 datagrams per exchange
                2 ) );                          // minimum 2 exchanges per conversation
    // tracker for sustained conversations
    templ.addAttrib( "sust_conv_tracker",
            ConversationTrackerAttribute( 
                *nonemptyPacketFilter,
                2,                              // minimum 2 datagrams per exchange
                3 ) );                          // minimum 3 exchanges per sustained conversation

    // conversation indicator alpha
    templ.addAttrib( "conv_alpha", 
            ArithmeticAttribute<int,int,double>( "conv_tracker.datagram_count", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );

    // conversation indicator beta
    templ.addAttrib( "conv_beta", 
            ArithmeticAttribute<int,int,double>( "sust_conv_tracker.datagram_count", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );

    // conversation indicator gamma
    templ.addAttrib( "conv_gamma", 
            ArithmeticAttribute<int,int,double>( "conv_tracker.forward_datagram_count", "conv_tracker.datagram_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );

    // the transaction indicator is a sum of the number of changes in direction, so first we need to
    // track everything as a conversation
    templ.addAttrib( "trans_tracker",
            ConversationTrackerAttribute( 
                *nonemptyPacketFilter,
                1,
                1 ) );

    // transaction indicator
    templ.addAttrib( "trans_ind",
            ArithmeticAttribute<int,int,double>( 
                "trans_tracker.dir_change_count", 
                "trans_tracker.max_dir_change_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    */
    
    delete nonemptyPacketFilter;

}

void initHalfstreamAttributes( Trace& templ, Clock& clock ) {
    templ.addAttrib( "duration", DurationAttribute() );
    
    templ.addAttrib( "pkt_byte_count", ByteCountAttribute(true) );
    templ.addAttrib( "payload_byte_count", ByteCountAttribute(false) );

    // mean inter-packet delay
    templ.addAttrib( "mean_delay", 
            ArithmeticAttribute<Timeval,int,double>( "duration", "pkt_count",
                ArithmeticAttribute<Timeval,int,double>::OP_DIVIDE ), 1 );
    
    // empty and nonempty packet counts
    PacketFilter *nonemptyPacketFilter = new SimplePacketFilter( 
                    PacketAttribute("transport.len"), 
                    ConcretePacketAttributeValue<int>(0),
                    SimplePacketFilter::GREATER );
    templ.addAttrib( "nonempty_count", PacketCountAttribute( *nonemptyPacketFilter ) );
    templ.addAttrib( "empty_count", 
            ArithmeticAttribute<int,int,int>( "pkt_count", "nonempty_count", 
                ArithmeticAttribute<int,int,int>::OP_SUBTRACT ), 1 );

    // mean packet lengths
    templ.addAttrib( "mean_pkt_len", 
            ArithmeticAttribute<int,int,double>( "pkt_byte_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );
    templ.addAttrib( "mean_payload_len", 
            ArithmeticAttribute<int,int,double>( "payload_byte_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );
    templ.addAttrib( "mean_nonempty_payload_len", 
            ArithmeticAttribute<int,int,double>( "payload_byte_count", "nonempty_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    // max datarate attributes
    // 1s 
    templ.addAttrib( "1s_payload_len_window",
            PacketDrivenMemoryAttribute<int>(
                "transport.len",
                MemoryAttribute<int>::ATTRIB_TYPE_PACKET,
                Timeval(1.0) ) );

    templ.addAttrib( "1s_datarate",
            ArithmeticAttribute<int,double,double>(
                "1s_payload_len_window.sum",
                1.0,
                ArithmeticAttribute<int,double,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "1s_datarate_window",
            SampledMemoryAttribute<double>(
                "1s_datarate",
                SampledMemoryAttribute<double>::ATTRIB_TYPE_AGGREGATE,
                0,
                Timeval(0.2) ) );

    // 5s 
    templ.addAttrib( "5s_payload_len_window",
            PacketDrivenMemoryAttribute<int>(
                "transport.len",
                MemoryAttribute<int>::ATTRIB_TYPE_PACKET,
                Timeval(5.0) ) );

    templ.addAttrib( "5s_datarate",
            ArithmeticAttribute<int,double,double>(
                "5s_payload_len_window.sum",
                5.0,
                ArithmeticAttribute<int,double,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "5s_datarate_window",
            SampledMemoryAttribute<double>(
                "5s_datarate",
                SampledMemoryAttribute<double>::ATTRIB_TYPE_AGGREGATE,
                0,
                Timeval(1.0) ) );

    // 30s 
    templ.addAttrib( "30s_payload_len_window",
            PacketDrivenMemoryAttribute<int>(
                "transport.len",
                MemoryAttribute<int>::ATTRIB_TYPE_PACKET,
                Timeval(30.0) ) );

    templ.addAttrib( "30s_datarate",
            ArithmeticAttribute<int,double,double>(
                "30s_payload_len_window.sum",
                30.0,
                ArithmeticAttribute<int,double,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "30s_datarate_window",
            SampledMemoryAttribute<double>(
                "30s_datarate",
                SampledMemoryAttribute<double>::ATTRIB_TYPE_AGGREGATE,
                0,
                Timeval(6.0) ) );

    // small packet filters - parameter set 1 (20bytes, 10ms, 2000ms)
    PacketFilter *sp_filter_1 = new CompoundPacketFilter(
            SimplePacketFilter(
                PacketAttribute( "transport.len" ),
                ConcretePacketAttributeValue<int>(20),
                SimplePacketFilter::LESS_OR_EQUAL ),
            *nonemptyPacketFilter,
            CompoundPacketFilter::AND );
    templ.addAttrib( "sp_count_1", PacketCountAttribute( *sp_filter_1 ) );
    // small and empty packets : sp_count + empty_count
    templ.addAttrib( "sep_count_1", 
            ArithmeticAttribute<int,int,int>( "sp_count_1", "empty_count", ArithmeticAttribute<int,int,int>::OP_ADD ), 2 );
    // consecutive small packets
    PacketFilter *csp_filter_1 = new CompoundPacketFilter( 
            *sp_filter_1,
            ConsecutivePacketFilter(),
            CompoundPacketFilter::AND ); 
    templ.addAttrib( "csp_count_1", PacketCountAttribute( *csp_filter_1 ) );
    PacketFilter *sp_delay_filter_1 = new CompoundPacketFilter( /* 10ms <= frame.time_delta <= 2000ms */
            SimplePacketFilter(
                PacketAttribute( "frame.time_delta" ),
                ConcretePacketAttributeValue<Timeval>(Timeval(0.010)),
                SimplePacketFilter::GREATER_OR_EQUAL ),
            SimplePacketFilter(
                PacketAttribute( "frame.time_delta" ),
                ConcretePacketAttributeValue<Timeval>(Timeval(2.000)),
                SimplePacketFilter::LESS_OR_EQUAL ),
            CompoundPacketFilter::AND );
    templ.addAttrib( "csp_delay_count_1", PacketCountAttribute(
                CompoundPacketFilter( 
                    *csp_filter_1,
                    *sp_delay_filter_1,
                    CompoundPacketFilter::AND ) ) );
    templ.addAttrib( "sp_alpha_1", 
            ArithmeticAttribute<int,int,double>( "csp_delay_count_1", "csp_count_1", ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 
            1 );
    templ.addAttrib( "sp_beta_1",
            ArithmeticAttribute<int,int,double>( "sp_count_1", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "sp_gamma_1", 
            ArithmeticAttribute<int,int,double>( "csp_count_1", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "sp_delta_1",
            ArithmeticAttribute<int,int,double>( "csp_count_1", "sep_count_1", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            3 /*sep_count_1 is tier 2*/ );
    
    // small packet filters - parameter set 2 (60bytes, 25ms, 3000ms)
    PacketFilter *sp_filter_2 = new CompoundPacketFilter(
            SimplePacketFilter(
                PacketAttribute( "transport.len" ),
                ConcretePacketAttributeValue<int>(60),
                SimplePacketFilter::LESS_OR_EQUAL ),
            *nonemptyPacketFilter,
            CompoundPacketFilter::AND );
    templ.addAttrib( "sp_count_2", PacketCountAttribute( *sp_filter_2 ) );
    // small and empty packets : sp_count + empty_count
    templ.addAttrib( "sep_count_2", 
            ArithmeticAttribute<int,int,int>( "sp_count_2", "empty_count", ArithmeticAttribute<int,int,int>::OP_ADD ), 2 );
    // consecutive small packets
    PacketFilter *csp_filter_2 = new CompoundPacketFilter( 
            *sp_filter_2,
            ConsecutivePacketFilter(),
            CompoundPacketFilter::AND ); 
    templ.addAttrib( "csp_count_2", PacketCountAttribute( *csp_filter_2 ) );
    PacketFilter *sp_delay_filter_2 = new CompoundPacketFilter( /* 25ms <= frame.time_delta <= 3000ms */
            SimplePacketFilter(
                PacketAttribute( "frame.time_delta" ),
                ConcretePacketAttributeValue<Timeval>(Timeval(0.025)),
                SimplePacketFilter::GREATER_OR_EQUAL ),
            SimplePacketFilter(
                PacketAttribute( "frame.time_delta" ),
                ConcretePacketAttributeValue<Timeval>(Timeval(3.000)),
                SimplePacketFilter::LESS_OR_EQUAL ),
            CompoundPacketFilter::AND );
    templ.addAttrib( "csp_delay_count_2", PacketCountAttribute(
                CompoundPacketFilter( 
                    *csp_filter_2,
                    *sp_delay_filter_2,
                    CompoundPacketFilter::AND ) ) );
    templ.addAttrib( "sp_alpha_2", 
            ArithmeticAttribute<int,int,double>( "csp_delay_count_2", "csp_count_2", ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 
            1 );
    templ.addAttrib( "sp_beta_2",
            ArithmeticAttribute<int,int,double>( "sp_count_2", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "sp_gamma_2", 
            ArithmeticAttribute<int,int,double>( "csp_count_2", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "sp_delta_2",
            ArithmeticAttribute<int,int,double>( "csp_count_2", "sep_count_2", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            3 /*sep_count_2 is tier 2*/ );
    
    // small packet filters - parameter set 3 (200bytes, 250ms, 30000ms)
    PacketFilter *sp_filter_3 = new CompoundPacketFilter(
            SimplePacketFilter(
                PacketAttribute( "transport.len" ),
                ConcretePacketAttributeValue<int>(200),
                SimplePacketFilter::LESS_OR_EQUAL ),
            *nonemptyPacketFilter,
            CompoundPacketFilter::AND );
    templ.addAttrib( "sp_count_3", PacketCountAttribute( *sp_filter_3 ) );
    // small and empty packets : sp_count + empty_count
    templ.addAttrib( "sep_count_3", 
            ArithmeticAttribute<int,int,int>( "sp_count_3", "empty_count", ArithmeticAttribute<int,int,int>::OP_ADD ), 2 );
    // consecutive small packets
    PacketFilter *csp_filter_3 = new CompoundPacketFilter( 
            *sp_filter_3,
            ConsecutivePacketFilter(),
            CompoundPacketFilter::AND ); 
    templ.addAttrib( "csp_count_3", PacketCountAttribute( *csp_filter_3 ) );
    PacketFilter *sp_delay_filter_3 = new CompoundPacketFilter( /* 250ms <= frame.time_delta <= 30000ms */
            SimplePacketFilter(
                PacketAttribute( "frame.time_delta" ),
                ConcretePacketAttributeValue<Timeval>(Timeval(0.250)),
                SimplePacketFilter::GREATER_OR_EQUAL ),
            SimplePacketFilter(
                PacketAttribute( "frame.time_delta" ),
                ConcretePacketAttributeValue<Timeval>(Timeval(30.000)),
                SimplePacketFilter::LESS_OR_EQUAL ),
            CompoundPacketFilter::AND );
    templ.addAttrib( "csp_delay_count_3", PacketCountAttribute(
                CompoundPacketFilter( 
                    *csp_filter_3,
                    *sp_delay_filter_3,
                    CompoundPacketFilter::AND ) ) );
    templ.addAttrib( "sp_alpha_3", 
            ArithmeticAttribute<int,int,double>( "csp_delay_count_3", "csp_count_3", ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 
            1 );
    templ.addAttrib( "sp_beta_3",
            ArithmeticAttribute<int,int,double>( "sp_count_3", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "sp_gamma_3", 
            ArithmeticAttribute<int,int,double>( "csp_count_3", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "sp_delta_3",
            ArithmeticAttribute<int,int,double>( "csp_count_3", "sep_count_3", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            3 /*sep_count_2 is tier 2*/ );
    
    
    // large packet heuristics - parameter set 1 ( 225 bytes, 50ms )
    PacketFilter *lp_filter_1 = new SimplePacketFilter(
            PacketAttribute( "transport.len" ),
            ConcretePacketAttributeValue<int>(225),
            SimplePacketFilter::GREATER_OR_EQUAL );
    PacketFilter *clp_filter_1 = new CompoundPacketFilter(
            *lp_filter_1,
            ConsecutivePacketFilter(),
            CompoundPacketFilter::AND );
    // file transfer - 50ms delay or less
    PacketFilter *lp_delay_filter_1 = new SimplePacketFilter(
            PacketAttribute( "frame.time_delta" ),
            ConcretePacketAttributeValue<Timeval>(Timeval(0.050)),
            SimplePacketFilter::LESS_OR_EQUAL );
    PacketFilter *clp_delay_filter_1 = new CompoundPacketFilter(
            *clp_filter_1,
            *lp_delay_filter_1,
            CompoundPacketFilter::AND );
    templ.addAttrib( "lp_count_1", PacketCountAttribute( *lp_filter_1 ) );
    // consecutive big packets
    templ.addAttrib( "clp_count_1", PacketCountAttribute( *clp_filter_1 ) );
    // consecutive big packets with file-transfer-range delay
    templ.addAttrib( "clp_delay_count_1", PacketCountAttribute( *clp_delay_filter_1 ) );
    templ.addAttrib( "lp_alpha_1", 
            ArithmeticAttribute<int,int,double>( "clp_delay_count_1", "clp_count_1", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_beta_1",
            ArithmeticAttribute<int,int,double>( "lp_count_1", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_gamma_1",
            ArithmeticAttribute<int,int,double>( "clp_count_1", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    
    // large packet heuristics - parameter set 2 ( 1000 bytes, 50ms )
    PacketFilter *lp_filter_2 = new SimplePacketFilter(
            PacketAttribute( "transport.len" ),
            ConcretePacketAttributeValue<int>(1000),
            SimplePacketFilter::GREATER_OR_EQUAL );
    PacketFilter *clp_filter_2 = new CompoundPacketFilter(
            *lp_filter_2,
            ConsecutivePacketFilter(),
            CompoundPacketFilter::AND );
    // file transfer - 50ms delay or less
    PacketFilter *lp_delay_filter_2 = new SimplePacketFilter(
            PacketAttribute( "frame.time_delta" ),
            ConcretePacketAttributeValue<Timeval>(Timeval(0.050)),
            SimplePacketFilter::LESS_OR_EQUAL );
    PacketFilter *clp_delay_filter_2 = new CompoundPacketFilter(
            *clp_filter_2,
            *lp_delay_filter_2,
            CompoundPacketFilter::AND );
    templ.addAttrib( "lp_count_2", PacketCountAttribute( *lp_filter_2 ) );
    // consecutive big packets
    templ.addAttrib( "clp_count_2", PacketCountAttribute( *clp_filter_2 ) );
    // consecutive big packets with file-transfer-range delay
    templ.addAttrib( "clp_delay_count_2", PacketCountAttribute( *clp_delay_filter_2 ) );
    templ.addAttrib( "lp_alpha_2", 
            ArithmeticAttribute<int,int,double>( "clp_delay_count_2", "clp_count_2", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_beta_2",
            ArithmeticAttribute<int,int,double>( "lp_count_2", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_gamma_2",
            ArithmeticAttribute<int,int,double>( "clp_count_2", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    
    // large packet heuristics - parameter set 3 ( 1460 bytes, 50ms )
    PacketFilter *lp_filter_3 = new SimplePacketFilter(
            PacketAttribute( "transport.len" ),
            ConcretePacketAttributeValue<int>(1460),
            SimplePacketFilter::GREATER_OR_EQUAL );
    PacketFilter *clp_filter_3 = new CompoundPacketFilter(
            *lp_filter_3,
            ConsecutivePacketFilter(),
            CompoundPacketFilter::AND );
    // file transfer - 50ms delay or less
    PacketFilter *lp_delay_filter_3 = new SimplePacketFilter(
            PacketAttribute( "frame.time_delta" ),
            ConcretePacketAttributeValue<Timeval>(Timeval(0.050)),
            SimplePacketFilter::LESS_OR_EQUAL );
    PacketFilter *clp_delay_filter_3 = new CompoundPacketFilter(
            *clp_filter_3,
            *lp_delay_filter_3,
            CompoundPacketFilter::AND );
    templ.addAttrib( "lp_count_3", PacketCountAttribute( *lp_filter_3 ) );
    // consecutive big packets
    templ.addAttrib( "clp_count_3", PacketCountAttribute( *clp_filter_3 ) );
    // consecutive big packets with file-transfer-range delay
    templ.addAttrib( "clp_delay_count_3", PacketCountAttribute( *clp_delay_filter_3 ) );
    templ.addAttrib( "lp_alpha_3", 
            ArithmeticAttribute<int,int,double>( "clp_delay_count_3", "clp_count_3", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_beta_3",
            ArithmeticAttribute<int,int,double>( "lp_count_3", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_gamma_3",
            ArithmeticAttribute<int,int,double>( "clp_count_3", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    
    // large packet heuristics - parameter set 4 ( 225 bytes, 250ms )
    PacketFilter *lp_filter_4 = new SimplePacketFilter(
            PacketAttribute( "transport.len" ),
            ConcretePacketAttributeValue<int>(225),
            SimplePacketFilter::GREATER_OR_EQUAL );
    PacketFilter *clp_filter_4 = new CompoundPacketFilter(
            *lp_filter_4,
            ConsecutivePacketFilter(),
            CompoundPacketFilter::AND );
    // file transfer - 250ms delay or less
    PacketFilter *lp_delay_filter_4 = new SimplePacketFilter(
            PacketAttribute( "frame.time_delta" ),
            ConcretePacketAttributeValue<Timeval>(Timeval(0.250)),
            SimplePacketFilter::LESS_OR_EQUAL );
    PacketFilter *clp_delay_filter_4 = new CompoundPacketFilter(
            *clp_filter_4,
            *lp_delay_filter_4,
            CompoundPacketFilter::AND );
    templ.addAttrib( "lp_count_4", PacketCountAttribute( *lp_filter_4 ) );
    // consecutive big packets
    templ.addAttrib( "clp_count_4", PacketCountAttribute( *clp_filter_4 ) );
    // consecutive big packets with file-transfer-range delay
    templ.addAttrib( "clp_delay_count_4", PacketCountAttribute( *clp_delay_filter_4 ) );
    templ.addAttrib( "lp_alpha_4", 
            ArithmeticAttribute<int,int,double>( "clp_delay_count_4", "clp_count_4", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_beta_4",
            ArithmeticAttribute<int,int,double>( "lp_count_4", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_gamma_4",
            ArithmeticAttribute<int,int,double>( "clp_count_4", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    
    // large packet heuristics - parameter set 5 ( 1000 bytes, 250ms )
    PacketFilter *lp_filter_5 = new SimplePacketFilter(
            PacketAttribute( "transport.len" ),
            ConcretePacketAttributeValue<int>(1000),
            SimplePacketFilter::GREATER_OR_EQUAL );
    PacketFilter *clp_filter_5 = new CompoundPacketFilter(
            *lp_filter_5,
            ConsecutivePacketFilter(),
            CompoundPacketFilter::AND );
    // file transfer - 250ms delay or less
    PacketFilter *lp_delay_filter_5 = new SimplePacketFilter(
            PacketAttribute( "frame.time_delta" ),
            ConcretePacketAttributeValue<Timeval>(Timeval(0.250)),
            SimplePacketFilter::LESS_OR_EQUAL );
    PacketFilter *clp_delay_filter_5 = new CompoundPacketFilter(
            *clp_filter_5,
            *lp_delay_filter_5,
            CompoundPacketFilter::AND );
    templ.addAttrib( "lp_count_5", PacketCountAttribute( *lp_filter_5 ) );
    // consecutive big packets
    templ.addAttrib( "clp_count_5", PacketCountAttribute( *clp_filter_5 ) );
    // consecutive big packets with file-transfer-range delay
    templ.addAttrib( "clp_delay_count_5", PacketCountAttribute( *clp_delay_filter_5 ) );
    templ.addAttrib( "lp_alpha_5", 
            ArithmeticAttribute<int,int,double>( "clp_delay_count_5", "clp_count_5", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_beta_5",
            ArithmeticAttribute<int,int,double>( "lp_count_5", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_gamma_5",
            ArithmeticAttribute<int,int,double>( "clp_count_5", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    
    // large packet heuristics - parameter set 6 ( 1460 bytes, 250ms )
    PacketFilter *lp_filter_6 = new SimplePacketFilter(
            PacketAttribute( "transport.len" ),
            ConcretePacketAttributeValue<int>(1460),
            SimplePacketFilter::GREATER_OR_EQUAL );
    PacketFilter *clp_filter_6 = new CompoundPacketFilter(
            *lp_filter_6,
            ConsecutivePacketFilter(),
            CompoundPacketFilter::AND );
    // file transfer - 250ms delay or less
    PacketFilter *lp_delay_filter_6 = new SimplePacketFilter(
            PacketAttribute( "frame.time_delta" ),
            ConcretePacketAttributeValue<Timeval>(Timeval(0.250)),
            SimplePacketFilter::LESS_OR_EQUAL );
    PacketFilter *clp_delay_filter_6 = new CompoundPacketFilter(
            *clp_filter_6,
            *lp_delay_filter_6,
            CompoundPacketFilter::AND );
    templ.addAttrib( "lp_count_6", PacketCountAttribute( *lp_filter_6 ) );
    // consecutive big packets
    templ.addAttrib( "clp_count_6", PacketCountAttribute( *clp_filter_6 ) );
    // consecutive big packets with file-transfer-range delay
    templ.addAttrib( "clp_delay_count_6", PacketCountAttribute( *clp_delay_filter_6 ) );
    templ.addAttrib( "lp_alpha_6", 
            ArithmeticAttribute<int,int,double>( "clp_delay_count_6", "clp_count_6", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_beta_6",
            ArithmeticAttribute<int,int,double>( "lp_count_6", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    templ.addAttrib( "lp_gamma_6",
            ArithmeticAttribute<int,int,double>( "clp_count_6", "nonempty_count", ArithmeticAttribute<int,int,double>::OP_DIVIDE ),
            1 );
    
    // packet flag heuristics
    templ.addAttrib( "urg_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.urg"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_urg",
            ArithmeticAttribute<int,int,double>( "urg_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "ack_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.ack"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_ack",
            ArithmeticAttribute<int,int,double>( "ack_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "psh_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.psh"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_psh",
            ArithmeticAttribute<int,int,double>( "psh_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "rst_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.rst"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_rst",
            ArithmeticAttribute<int,int,double>( "rst_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "syn_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.syn"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_syn",
            ArithmeticAttribute<int,int,double>( "syn_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );

    templ.addAttrib( "fin_count", 
            PacketCountAttribute( 
                SimplePacketFilter( 
                    PacketAttribute("tcp.flags.fin"),
                    ConcretePacketAttributeValue<int>(1),
                    SimplePacketFilter::EQUAL ) ) );

    templ.addAttrib( "flag_fin",
            ArithmeticAttribute<int,int,double>( "fin_count", "pkt_count", 
                ArithmeticAttribute<int,int,double>::OP_DIVIDE ), 1 );
    
    delete nonemptyPacketFilter;

    delete sp_filter_1;
    delete csp_filter_1;
    delete sp_delay_filter_1;
    delete sp_filter_2;
    delete csp_filter_2;
    delete sp_delay_filter_2;
    delete sp_filter_3;
    delete csp_filter_3;
    delete sp_delay_filter_3;

    delete lp_filter_1;
    delete clp_filter_1;
    delete lp_delay_filter_1;
    delete clp_delay_filter_1;
    delete lp_filter_2;
    delete clp_filter_2;
    delete lp_delay_filter_2;
    delete clp_delay_filter_2;
    delete lp_filter_3;
    delete clp_filter_3;
    delete lp_delay_filter_3;
    delete clp_delay_filter_3;
    delete lp_filter_4;
    delete clp_filter_4;
    delete lp_delay_filter_4;
    delete clp_delay_filter_4;
    delete lp_filter_5;
    delete clp_filter_5;
    delete lp_delay_filter_5;
    delete clp_delay_filter_5;
    delete lp_filter_6;
    delete clp_filter_6;
    delete lp_delay_filter_6;
    delete clp_delay_filter_6;

}

class StatsPrinter : public FilteredStreamListener {
private:
    ostream& output;
public:
    static const StreamEvent EXPIRING_STREAM_FILTER;
    
public:
    StatsPrinter(void);
    StatsPrinter( ostream& out );
    void printStream( const Decomposition& stream, bool csv_output = true, bool printout_packets = false );
    virtual uint32_t handlePassedStreamEvent( const StreamEvent& e );

};

const StreamEvent
StatsPrinter::EXPIRING_STREAM_FILTER( StreamEvent::STREAM_EXPIRING );

StatsPrinter::StatsPrinter(void) : FilteredStreamListener( EXPIRING_STREAM_FILTER ), output( cout ) {
}

StatsPrinter::StatsPrinter( ostream& out ) : FilteredStreamListener( EXPIRING_STREAM_FILTER ), output( out ) {
}

void 
StatsPrinter::printStream( const Decomposition& stream, bool csv_output, bool printout_packets ) {
    PacketAttribute pkttime( "frame.time" );
    PacketAttribute timeDelta( "frame.time_delta" );

    // output per-stream attributes
    if( csv_output ) {
        output << "\"s\"";

        try {
            const PacketDrivenMemoryAttribute<Timeval>& startTimeAttrib = 
                dynamic_cast<const PacketDrivenMemoryAttribute<Timeval>&>(stream.getAttrib("start_time"));
            output << ", " << *(startTimeAttrib.begin());
        } catch( bad_cast bce ) {
            output << ", \"error reading start_time\"";
        }

        output << ", \"" << stream.getStreamKey().toString() << "\"";
        output << ", " << stream.getAttrib("pkt_count");
        output << ", " << dynamic_cast<const ScalarAttribute<Timeval>&>(stream.getAttrib("duration")).getValue().getDoubleValue();
        output << ", " << stream.getAttrib("nonempty_count");
        output << ", " << stream.getAttrib("pkt_byte_count");
        output << ", " << stream.getAttrib("payload_byte_count");
        output << ", " << stream.getAttrib("mean_delay");
        output << ", " << stream.getAttrib("mean_pkt_len");
        output << ", " << stream.getAttrib("mean_payload_len");
        output << ", " << stream.getAttrib("mean_nonempty_payload_len");
        output << ", " << stream.getAttrib("dir_data");
        output << ", " << stream.getAttrib("mean_pkt_datarate");
        output << ", " << stream.getAttrib("mean_payload_datarate");
        output << ", " << stream.getAttrib("1s_datarate_window.max");
        output << ", " << stream.getAttrib("5s_datarate_window.max");
        output << ", " << stream.getAttrib("30s_datarate_window.max");
        output << ", " << stream.getAttrib("flag_urg");
        output << ", " << stream.getAttrib("flag_ack");
        output << ", " << stream.getAttrib("flag_psh");
        output << ", " << stream.getAttrib("flag_rst");
        output << ", " << stream.getAttrib("flag_syn");
        output << ", " << stream.getAttrib("flag_fin");
        output << endl;
    }

    // could add an 'if proto is TCP or UDP' check here
    Decomposition::const_iterator halfstreamIt = stream.activeSubstreamsBegin();
    while( halfstreamIt != stream.activeSubstreamsEnd() ) {
        const Trace& halfstream = dynamic_cast<const Trace&>(*(halfstreamIt->second));
        output << "\"h\", \"" << halfstream.getStreamKey().toString() << "\"";
        output << ", " << halfstream.getAttrib("pkt_count");
        output << ", " << halfstream.getAttrib("pkt_byte_count");
        output << ", " << halfstream.getAttrib("payload_byte_count");
        output << ", " << halfstream.getAttrib("nonempty_count");
        output << ", " << halfstream.getAttrib("mean_delay");
        output << ", " << halfstream.getAttrib("mean_pkt_len");
        output << ", " << halfstream.getAttrib("mean_payload_len");
        output << ", " << halfstream.getAttrib("mean_nonempty_payload_len");
        output << ", " << halfstream.getAttrib("1s_datarate_window.max");
        output << ", " << halfstream.getAttrib("5s_datarate_window.max");
        output << ", " << halfstream.getAttrib("30s_datarate_window.max");
        output << ", " << halfstream.getAttrib("sp_alpha_1");
        output << ", " << halfstream.getAttrib("sp_beta_1");
        output << ", " << halfstream.getAttrib("sp_gamma_1");
        output << ", " << halfstream.getAttrib("sp_delta_1");
        output << ", " << halfstream.getAttrib("sp_alpha_2");
        output << ", " << halfstream.getAttrib("sp_beta_2");
        output << ", " << halfstream.getAttrib("sp_gamma_2");
        output << ", " << halfstream.getAttrib("sp_delta_2");
        output << ", " << halfstream.getAttrib("sp_alpha_3");
        output << ", " << halfstream.getAttrib("sp_beta_3");
        output << ", " << halfstream.getAttrib("sp_gamma_3");
        output << ", " << halfstream.getAttrib("sp_delta_3");
        output << ", " << halfstream.getAttrib("lp_alpha_1");
        output << ", " << halfstream.getAttrib("lp_beta_1");
        output << ", " << halfstream.getAttrib("lp_gamma_1");
        output << ", " << halfstream.getAttrib("lp_alpha_2");
        output << ", " << halfstream.getAttrib("lp_beta_2");
        output << ", " << halfstream.getAttrib("lp_gamma_2");
        output << ", " << halfstream.getAttrib("lp_alpha_3");
        output << ", " << halfstream.getAttrib("lp_beta_3");
        output << ", " << halfstream.getAttrib("lp_gamma_3");
        output << ", " << halfstream.getAttrib("lp_alpha_4");
        output << ", " << halfstream.getAttrib("lp_beta_4");
        output << ", " << halfstream.getAttrib("lp_gamma_4");
        output << ", " << halfstream.getAttrib("lp_alpha_5");
        output << ", " << halfstream.getAttrib("lp_beta_5");
        output << ", " << halfstream.getAttrib("lp_gamma_5");
        output << ", " << halfstream.getAttrib("lp_alpha_6");
        output << ", " << halfstream.getAttrib("lp_beta_6");
        output << ", " << halfstream.getAttrib("lp_gamma_6");
        output << ", " << halfstream.getAttrib("flag_urg");
        output << ", " << halfstream.getAttrib("flag_ack");
        output << ", " << halfstream.getAttrib("flag_psh");
        output << ", " << halfstream.getAttrib("flag_rst");
        output << ", " << halfstream.getAttrib("flag_syn");
        output << ", " << halfstream.getAttrib("flag_fin");
        output << endl;

        // output per-halfstream attributes

        if( printout_packets ) {
            TraceIterator it = halfstream.begin();

            while( ! ( it == halfstream.end() ) ) {
                output << it->getAttrib(pkttime);
                try {
                    output << "," << it->getAttrib(timeDelta);
                } catch( UnknownAttributeException unk ) {
                    // expected for first one
                    output << ",         0.000000000";
                } catch( ... ) {
                    cerr << "blech" << endl;
                }
                output << ", " << it->getAttrib(PacketAttribute("transport.len"));
                output << endl;
                ++it;
            }
        }

        ++halfstreamIt;
    }
}

uint32_t
StatsPrinter::handlePassedStreamEvent( const StreamEvent& e ) {
    const Decomposition* decomp = dynamic_cast<const Decomposition*>(e.getStream());

    if( NULL != decomp ) {
        printStream( *(decomp) );
    } else {
        return StreamEvent::STREAM_OK;
    }

    return StreamEvent::STREAM_ERASE;
}


int main( int argc, char **argv ) {
    try {
        bool profile = true;
        bool printout_conversations = true;
        bool printout_packets = false;
        bool csv_output = true;

        StatsPrinter printer;

        struct tms checkpoint;
        struct tms tms;

        if( profile ) {
            times(&checkpoint);
            cerr << "Profiling started" << endl;
        }

        if( argc < 2 ) {
            usage();
            exit(1);
        }

        int i = 1;

        while( ( argc > i ) && ( argv[i][0] == '-' ) ) {
            switch( argv[i][1] ) {
            case 'l':
                printout_packets = true;
                break;
            case '\0':
                usage();
                cerr << "Illegal null option" << endl;
                exit(1);
            default:
                usage();
                cerr << "Unknown option " << argv[i][1] << endl;
                exit(1);
            }
            i++;
        }

        Trace ethTrace(100);
        Trace ipFragTrace(100);
        Trace ipTrace(100);

        // sessions contains streams keyed by ( src addr, dst addr, proto, src port, dst port )
        // bidirectionally; these streams are Decompositions of half-streams, keyed by the same keys,
        // but unidirectional.
        Decomposition sessions; 

        Clock clock;
        // ipTrace.addListener(clock);

        // stream template - attributes and listeners
        //   - this section defines what attributes will be computed for each stream
        Decomposition *streamTempl = new Decomposition();
        initStreamAttributes( *streamTempl, clock );

        // half-stream template - attributes and listeners
        //   - this section defines what attributes will be computed for each half-stream
        Trace *halfstreamTempl = new Trace(2);
        initHalfstreamAttributes( *halfstreamTempl, clock );

        // create a sessionizer for TCP and UDP
        //   - the sessionizer will take responsibility for the templates; we NULL them out here so that
        //   we don't mistakenly try to free them twice 
        IPv4Sessionizer sessionizer( sessions, streamTempl, halfstreamTempl );
        streamTempl = NULL;
        halfstreamTempl = NULL;

        ipTrace.addListener( sessionizer );             // IPv4Sessionizer implicitly filters down to TCP/UDP

        // StatsPrinter will print out the stats for a stream and erase it rather than letting it
        // expire
        sessions.addStreamListener( printer );

        string filename( argv[i] );

        QcapAdaptor qcap(filename);

        if( profile ) {
            times(&tms);
            cerr << "Initialization : " 
                << ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
                << ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
            checkpoint = tms;
        }

        qcap.getIPTrace( ethTrace, ipFragTrace, ipTrace );

        if( profile ) {
            times(&tms);
            cerr << "Built IPv4 trace : " 
                << ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
                << ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
            checkpoint = tms;
        }

        if( printout_conversations ) {

            cout << "\"== Expired TCP and UDP Streams ==\"" << endl;
            vector<Aggregate*>::const_iterator expiredStreamIt = sessions.expiredSubstreamsBegin();
            while( expiredStreamIt != sessions.expiredSubstreamsEnd() ) {
                printer.printStream( dynamic_cast<const Decomposition&>(**expiredStreamIt), csv_output, printout_packets );
                ++expiredStreamIt;
            }

            cout << "\"== Active TCP and UDP Streams ==\"" << endl;
            Decomposition::const_iterator activeStreamIt = sessions.activeSubstreamsBegin();
            while( activeStreamIt != sessions.activeSubstreamsEnd() ) {
                printer.printStream( dynamic_cast<const Decomposition&>(*(activeStreamIt->second)), csv_output, printout_packets );
                ++activeStreamIt;
            }

            if( profile ) {
                times(&tms);
                cerr << "Iterated through streams : " 
                    << ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
                    << ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
                checkpoint = tms;
            }
        }
    } catch( runtime_error err ) {
        cerr << "Runtime error occurred, message: " << err.what() << endl;
    }

    return 0;
}

Generated on Thu Apr 5 01:02:35 2007 for ANTARES by  doxygen 1.4.2