Add a pointer to the start frame of each gop in the gog's tree
[obnox/wireshark/wip.git] / plugins / mate / mate_setup.c
index 93def5120f26908a93cadcff69467b17d86f9299..08e34e14069106e499b9aa0a5f86482682bd90a3 100644 (file)
 
 #include "mate.h"
 
-/* FIXME: config names should be at most 8 chars! */
-
 static int* dbg;
 
-static int dbg_cfg_lvl = 1;
+static int dbg_cfg_lvl = 0;
 static int* dbg_cfg = &dbg_cfg_lvl;
 
 FILE* dbg_facility;
@@ -47,6 +45,23 @@ static GHashTable* actions = NULL;
 /* aestetics: I like keywords separated from user attributes */
 static AVPL* all_keywords = NULL;
 
+/* configuration error */
+GString* config_error;
+
+static void report_error(guint8* fmt, ...) {
+       static guint8 error_buffer[DEBUG_BUFFER_SIZE];
+
+       va_list list;
+       
+       va_start( list, fmt );
+       g_vsnprintf(error_buffer,DEBUG_BUFFER_SIZE,fmt,list);
+       va_end( list );
+       
+       g_string_append(config_error,error_buffer);
+       g_string_append_c(config_error,'\n');
+       
+}
+
 /* use as:  setting = extract_named_xxx(avpl,keyword,default_value); */
 static int extract_named_int(AVPL* avpl, guint8* keyword, int value) {
        AVP* avp = NULL;
@@ -109,36 +124,52 @@ static mate_cfg_item* new_mate_cfg_item(guint8* name) {
        new->type = MATE_UNK_TYPE;
        new->transforms = g_ptr_array_new();
        new->extra = new_avpl(name);
-       new->hfid_proto = -1;
+       new->last_id = 0;
+       new->hfid = -1;
+       new->my_hfids = g_hash_table_new(g_str_hash,g_str_equal);
+       new->items = g_hash_table_new(g_direct_hash,g_direct_equal);
+       new->ett = -1;
+       new->ett_attr = -1;
+       new->ett_times = -1;
+       new->ett_children = -1;
+       
        new->discard_pdu_attributes = matecfg->discard_pdu_attributes;
        new->last_to_be_created = matecfg->last_to_be_created;
-       new->drop_pdu = matecfg->drop_pdu;
-       new->drop_gop = matecfg->drop_gop;
-       new->expiration = matecfg->gog_expiration;
-       new->show_pdu_tree = matecfg->show_pdu_tree;
-       new->show_gop_times = matecfg->show_gop_times;
-       new->last_id = 0;
+       new->hfid_proto = -1;
        new->hfid_ranges = NULL;
        new->hfids_attr = NULL;
+       new->drop_pdu = matecfg->drop_pdu;
+       new->criterium_match_mode = AVPL_NO_MATCH;
        new->criterium = NULL;
+       new->hfid_pdu_rel_time = -1;
+       new->hfid_pdu_time_in_gop = -1;
+
+       new->expiration = -1.0;
+       new->hfid_start_time = -1;
+       new->hfid_stop_time = -1;
+       new->hfid_last_time = -1;
+       
        new->start = NULL;
        new->stop = NULL;
        new->key = NULL;
-       new->keys = NULL;
-
-       new->hfid = -1;
-       new->hfid_pdu_rel_time = -1;
-       new->my_hfids = g_hash_table_new(g_str_hash,g_str_equal);
-
+       new->show_pdu_tree = matecfg->show_pdu_tree;
+       new->show_times = matecfg->show_times;
+       new->drop_gop = matecfg->drop_gop;
+       new->idle_timeout = -1.0;
+       new->lifetime = -1.0;
        new->hfid_gop_pdu = -1;
-       new->hfid_gop_start_time = -1;
-       new->hfid_gop_stop_time = -1;
-       new->hfid_gop_last_time = -1;
        new->hfid_gop_num_pdus = -1;
+       new->ett_gog_gop = -1;
+       new->hfid_gog_gopstart = -1;
+       
+       new->gop_index = NULL;
+       new->gog_index = NULL;
 
+       new->gop_as_subtree = FALSE;
+       new->keys = NULL;
        new->hfid_gog_num_of_gops = -1;
        new->hfid_gog_gop = -1;
-
+       
        return new;
 }
 
@@ -188,10 +219,20 @@ static mate_cfg_pdu* new_pducfg(guint8* name) {
 
 static mate_cfg_gop* new_gopcfg(guint8* name) {
        mate_cfg_gop* new = new_mate_cfg_item(name);
+       
        new->type = MATE_GOP_TYPE;
-
+       new->expiration = matecfg->gop_expiration;
+       new->idle_timeout = matecfg->gop_idle_timeout;
+       new->lifetime = matecfg->gop_lifetime;
+       new->show_pdu_tree = matecfg->show_pdu_tree;
+       new->show_times = matecfg->show_times;
+       new->drop_gop = matecfg->drop_gop;
+       
        g_hash_table_insert(matecfg->gopcfgs,(gpointer) new->name, (gpointer) new);
 
+       new->gop_index = g_hash_table_new(g_str_hash,g_str_equal);
+       new->gog_index = g_hash_table_new(g_str_hash,g_str_equal);
+       
        return new;
 }
 
@@ -201,7 +242,7 @@ static mate_cfg_gog* new_gogcfg(guint8* name) {
 
        new->keys = new_loal(name);
        new->expiration = matecfg->gog_expiration;
-
+       
        g_hash_table_insert(matecfg->gogcfgs,new->name,new);
 
        return new;
@@ -246,55 +287,34 @@ extern void destroy_mate_config(mate_config* mc , gboolean avplib_too) {
 
 }
 
-
-/* a configuration error */
-static void mate_config_error(LoAL* loal _U_ ,guint8* line _U_ , guint8* fmt, ...) {
-       va_list list;
-       guint8* desc;
-
-       va_start( list, fmt );
-       desc = g_strdup_vprintf(fmt, list);
-       va_end( list );
-
-       dbg_print (dbg,0,dbg_facility,"mate_config_error: %s",desc);
-
-       g_warning(desc);
-       g_free(desc);
-
-}
-
-
 static gboolean mate_load_config(guint8* filename) {
        LoAL* loal = loal_from_file(filename);
        AVPL* avpl;
-       guint8* line = NULL;
        config_action* action;
        guint8* name;
-
-       if (loal) {
-       while(( avpl = extract_first_avpl(loal) )) {
-               line = avpl_to_str(avpl);
-
-               dbg_print (dbg_cfg,3,dbg_facility,"mate_make_config: current line: %s",line);
-
-               action = lookup_using_index_avp(avpl, KEYWORD_ACTION, actions,&name);
-
-               if (action) {
-                       if ( ! action(avpl) ) {
-                               mate_config_error(loal,line,"mate: Error on AVPL: '%s'",name);
+       
+       /* FIXME: we are leaking the config avpls to avoid unsubscribed strings left arround */ 
+
+       if (loal->len) {
+               while(( avpl = extract_first_avpl(loal) )) {
+                       dbg_print (dbg_cfg,3,dbg_facility,"mate_make_config: current line: %s",avpl->name);
+                       
+                       action = lookup_using_index_avp(avpl, KEYWORD_ACTION, actions,&name);
+                       
+                       if (action) {
+                               if ( ! action(avpl) ) {
+                                       report_error("MATE: Error on: %s",avpl->name);
+                                       return FALSE;
+                               }
+                       } else {
+                               report_error("MATE: action '%s' unknown in: %s",name,avpl->name);
                                return FALSE;
                        }
-               } else {
-                       mate_config_error(loal,line,"mate: Error: action '%s' unknown",name);
-                       return FALSE;
                }
-
-               g_free(line);
-       }
-
-       return TRUE;
+               
+               return TRUE;
        } else {
-               g_warning("mate: could not load '%s'",filename);
+               report_error("MATE: error reading config file: %s",loal->name);
                return FALSE;
        }
 }
@@ -325,8 +345,8 @@ static gboolean add_hfid(guint8* what, guint8* how, GHashTable* where) {
                if (( as = g_hash_table_lookup(where,ip) )) {
                        g_free(ip);
                        if (! g_str_equal(as,how)) {
-                               g_warning("Error: add_hfid: attempt to add %s(%i) as %s"
-                                                 " failed: hfid already added as '%s'",what,hfi->id,how,as);
+                               report_error("MATE Error: add field to Pdu: attempt to add %s(%i) as %s"
+                                                 " failed: field already added as '%s'",what,hfi->id,how,as);
                                return FALSE;
                        }
                } else {
@@ -342,7 +362,7 @@ static gboolean add_hfid(guint8* what, guint8* how, GHashTable* where) {
        }
 
        if (! exists) {
-               g_warning("Error: add_hfid(%s): cannot find",what);
+               report_error("MATE Error: cannot find field %s",what);
        }
 
        return exists;
@@ -359,11 +379,15 @@ static gboolean config_pdu(AVPL* avpl) {
        guint i;
        AVP* attr_avp;
 
+       if (! name ) {
+               report_error("MATE: PduDef: No Name in: %s",avpl->name);
+               return FALSE;           
+       }
+       
        if (! cfg) {
                cfg = new_pducfg(name);
        } else {
-               g_warning("MATE: PDU Config error: No such PDU: %s",cfg->name);
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: PduDef: No such PDU: '%s' in: %s",cfg->name,avpl->name);
                return FALSE;
        }
 
@@ -376,8 +400,7 @@ static gboolean config_pdu(AVPL* avpl) {
        if (hfi) {
                cfg->hfid_proto = hfi->id;
        } else {
-               g_warning("mate: PDU Config error: no such proto: %s",proto);
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: PduDef: no such proto: '%s' in: %s",proto,avpl->name);
                return FALSE;
        }
 
@@ -396,9 +419,8 @@ static gboolean config_pdu(AVPL* avpl) {
                                        g_ptr_array_add(cfg->hfid_ranges,(gpointer)hfidp);
                                        g_string_sprintfa(matecfg->mate_attrs_filter, "||%s",transports[i]);
                                } else {
-                                       g_warning("mate: PDU Config error: no such proto: %s for Transport",proto);
+                                       report_error("MATE: PduDef: no such proto: '%s' for Transport in: %s",proto,avpl->name);
                                        g_strfreev(transports);
-                                       delete_avpl(avpl,TRUE);
                                        return FALSE;
                                }
                        }
@@ -406,20 +428,18 @@ static gboolean config_pdu(AVPL* avpl) {
                        g_strfreev(transports);
                }
        } else {
-               g_warning("mate: PDU Config error: no Transport for %s",cfg->name);
+               report_error("MATE: PduDef: no Transport for '%s' in: %s",cfg->name,avpl->name);
                return FALSE;
        }
 
        while (( attr_avp = extract_first_avp(avpl) )) {
                if ( ! add_hfid(attr_avp->v,attr_avp->n,cfg->hfids_attr) ) {
-                       g_warning("mate: PDU Config error: failed to set PDU attribute '%s'",attr_avp->n);
-                       delete_avpl(avpl,TRUE);
+                       report_error("MATE: PduDef: failed to set PDU attribute '%s' in: %s",attr_avp->n,avpl->name);
                        return FALSE;
                }
                g_string_sprintfa(matecfg->mate_attrs_filter, "||%s",attr_avp->v);
        }
 
-       delete_avpl(avpl,TRUE);
        return TRUE;
 }
 
@@ -428,9 +448,13 @@ static gboolean config_pduextra(AVPL* avpl) {
        AVP* attr_avp;
        mate_cfg_pdu* cfg = lookup_using_index_avp(avpl,KEYWORD_FOR,matecfg->pducfgs,&name);
 
+       if (! name ) {
+               report_error("MATE: PduExtra: No For in: %s",avpl->name);
+               return FALSE;           
+       }
+
        if (! cfg) {
-               g_warning("mate: PduExtra Config error: no such Pdu %s",name);
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: PduExtra: no such Pdu '%s' in: %s",name,avpl->name);
                return FALSE;
        }
 
@@ -440,9 +464,8 @@ static gboolean config_pduextra(AVPL* avpl) {
 
        while (( attr_avp = extract_first_avp(avpl) )) {
                if ( ! add_hfid(attr_avp->v,attr_avp->n,cfg->hfids_attr) ) {
-                       g_warning("mate: PDU Config error: failed to set attr %s",attr_avp->n);
+                       report_error("MATE: PduExtra: failed to set attr '%s' in: %s",attr_avp->n,avpl->name);
                        delete_avp(attr_avp);
-                       delete_avpl(avpl,TRUE);
                        return FALSE;
                }
                g_string_sprintfa(matecfg->mate_attrs_filter, "||%s",attr_avp->v);
@@ -454,22 +477,93 @@ static gboolean config_pduextra(AVPL* avpl) {
 }
 
 
+static gboolean config_pducriteria(AVPL* avpl) {
+       guint8* name;
+       mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->pducfgs,&name);
+       guint8* match = extract_named_str(avpl, KEYWORD_MATCH, NULL);
+       avpl_match_mode match_mode = AVPL_STRICT;
+       guint8* mode = extract_named_str(avpl, KEYWORD_MODE, NULL);
+
+       if (! name ) {
+               report_error("MATE: PduCriteria: No For in: %s",avpl->name);
+               return FALSE;           
+       }
+       
+       if (!cfg) {
+               report_error("MATE: PduCriteria: Pdu '%s' does not exist in: %s",name,avpl->name);
+               return FALSE;
+       }
+
+       if ( mode ) {
+               if ( g_strcasecmp(mode,KEYWORD_ACCEPT) == 0 ) {
+                       mode = matecfg->accept;
+               } else if ( g_strcasecmp(mode,KEYWORD_REJECT) == 0 ) {
+                       mode = matecfg->reject;
+               } else {
+                       report_error("MATE: PduCriteria: no such criteria mode: '%s' in %s",mode,avpl->name);
+                       return FALSE;
+               }
+       } else {
+               mode = matecfg->accept;
+       }
+
+       rename_avpl(avpl,mode);
+
+       if ( match ) {
+               if ( g_strcasecmp(match,KEYWORD_LOOSE) == 0 ) {
+                       match_mode = AVPL_LOOSE;
+               } else if ( g_strcasecmp(match,KEYWORD_EVERY) == 0 ) {
+                       match_mode = AVPL_EVERY;
+               } else if ( g_strcasecmp(match,KEYWORD_STRICT) == 0 ) {
+                       match_mode = AVPL_STRICT;
+               } else {
+                       report_error("MATE: PduCriteria: Config error: no such match mode '%s' in: %s",match,avpl->name);
+                       return FALSE;
+               }
+       }
+
+       cfg->criterium_match_mode = match_mode;
+
+       if (cfg->criterium) {
+               /* FEATURE: more criteria */
+               report_error("MATE: PduCriteria: PduCriteria alredy exists for '%s' in: %s",name,avpl->name);
+               return FALSE;
+       }
+
+
+       cfg->criterium = avpl;
+
+       return TRUE;
+}
+
 
 static gboolean config_include(AVPL* avpl) {
        guint8* filename = extract_named_str(avpl,KEYWORD_FILENAME,NULL);
+       guint8* lib = extract_named_str(avpl,KEYWORD_LIB,NULL);
 
-       /* TODO: use library path */
-       if( ! filename ) {
-               mate_config_error(NULL,NULL,"mate: Include file error: no filename");
+       if ( ! filename && ! lib ) {
+               report_error("MATE: Include: no Filename or Lib given in: %s",avpl->name);
                return FALSE;
        }
 
+       if ( filename && lib ) {
+               report_error("MATE: Include: use either Filename or Lib, not both. in: %s",avpl->name);
+               return FALSE;
+       }
+
+       if (lib) {
+               filename = g_strdup_printf("%s%s.mate",matecfg->mate_lib_path,lib);
+       }
+
        /* FIXME: stop recursion */
        if ( ! mate_load_config(filename) ) {
-               mate_config_error(NULL,NULL,"mate: Error Loading '%s'",filename);
+               report_error("MATE: Include: Error Loading '%s' in: %s",filename,avpl->name);
+               if (lib) g_free(filename);
                return FALSE;
        }
 
+       if (lib) g_free(filename);
+
        return TRUE;
 }
 
@@ -486,12 +580,15 @@ static gboolean config_settings(AVPL*avpl) {
 #endif
 
 
-       matecfg->gog_expiration = extract_named_bool(avpl, KEYWORD_GOGEXPIRE,matecfg->gog_expiration);
+       matecfg->gog_expiration = extract_named_float(avpl, KEYWORD_GOGEXPIRE,matecfg->gog_expiration);
+       matecfg->gop_expiration = extract_named_float(avpl, KEYWORD_GOPEXPIRATION,matecfg->gop_expiration);
+       matecfg->gop_idle_timeout = extract_named_float(avpl, KEYWORD_GOPIDLETIMEOUT,matecfg->gop_idle_timeout);
+       matecfg->gop_lifetime = extract_named_float(avpl, KEYWORD_GOPLIFETIME,matecfg->gop_lifetime);
        matecfg->discard_pdu_attributes = extract_named_bool(avpl, KEYWORD_DISCARDPDU,matecfg->discard_pdu_attributes);
        matecfg->drop_pdu = extract_named_bool(avpl, KEYWORD_DROPPDU,matecfg->drop_pdu);
        matecfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,matecfg->drop_gop);
-       matecfg->show_pdu_tree = extract_named_bool(avpl, KEYWORD_SHOWPDUTREE,matecfg->show_pdu_tree);
-       matecfg->show_gop_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,matecfg->show_gop_times);
+       matecfg->show_pdu_tree = extract_named_str(avpl, KEYWORD_SHOWPDUTREE,matecfg->show_pdu_tree);
+       matecfg->show_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,matecfg->show_times);
 
        if(( avp = extract_avp_by_name(avpl,KEYWORD_DEBUGFILENAME) )) {
                matecfg->dbg_facility = dbg_facility = fopen(avp->v,"w");
@@ -536,7 +633,7 @@ static gboolean config_transform(AVPL* avpl) {
                } else if ( g_strcasecmp(match,KEYWORD_STRICT) == 0 ) {
                        match_mode = AVPL_STRICT;
                } else {
-                       g_warning("mate: Transform Config error: no such match mode: %s",match);
+                       report_error("MATE: Transform: no such match mode: '%s' in: %s",match,avpl->name);
                        return FALSE;
                }
        } else {
@@ -549,7 +646,7 @@ static gboolean config_transform(AVPL* avpl) {
                } else if ( g_strcasecmp(mode,KEYWORD_REPLACE) == 0 ) {
                        replace_mode = AVPL_REPLACE;
                } else {
-                       g_warning("mate: Transform Config error: no such replace mode: %s",mode);
+                       report_error("MATE: Transform: no such replace mode: '%s' in: %s",mode,avpl->name);
                        return FALSE;
                }
 
@@ -558,7 +655,7 @@ static gboolean config_transform(AVPL* avpl) {
        }
 
        if (! name) {
-               g_warning("mate: Transform Config error: no Name");
+               report_error("MATE: Transform: no Name in: %s",avpl->name);
                return FALSE;
        }
 
@@ -575,28 +672,28 @@ static gboolean config_transform(AVPL* avpl) {
 }
 
 static gboolean config_xxx_transform(AVPL* avpl, GHashTable* hash, guint8* keyword) {
-       guint8* pdu_name;
+       guint8* cfg_name;
        guint8* name;
        AVPL_Transf* transf = lookup_using_index_avp(avpl,KEYWORD_NAME,matecfg->transfs,&name);
-       mate_cfg_pdu* cfg = lookup_using_index_avp(avpl,KEYWORD_FOR,hash,&pdu_name);;
-
+       mate_cfg_pdu* cfg = lookup_using_index_avp(avpl,KEYWORD_FOR,hash,&cfg_name);;
+       
        if (! name ) {
-               g_warning("mate: %s Config error: No Name",keyword);
+               report_error("MATE: %s: no Name in: %s",keyword,avpl->name);
                return FALSE;
        }
 
-       if (! pdu_name ) {
-               g_warning("mate: %s Config error: No For",keyword);
+       if (! cfg_name ) {
+               report_error("MATE: %s: no For in: %s",keyword,avpl->name);
                return FALSE;
        }
 
        if (! cfg ) {
-               g_warning("mate: %s Config error: %s doesn't exist",keyword,pdu_name);
+               report_error("MATE: %s: '%s' doesn't exist in: %s",keyword,cfg_name,avpl->name);
                return FALSE;
        }
 
        if (!transf) {
-               g_warning("mate: %s Config error: Transform %s doesn't exist",keyword,name);
+               report_error("MATE: %s: Transform '%s' doesn't exist in: %s",keyword,name,avpl->name);
                return FALSE;
        }
 
@@ -622,32 +719,42 @@ static gboolean config_gop(AVPL* avpl) {
        mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_NAME,matecfg->gopcfgs,&name);
        guint8* on = extract_named_str(avpl,KEYWORD_ON,NULL);
 
+       if (! name ) {
+               report_error("MATE: GopDef: no Name in: %s",avpl->name);
+               return FALSE;
+       }
+       
        if (!cfg) {
                cfg = new_gopcfg(name);
        } else {
-               g_warning("mate: GopDef Config error: Gop '%s' exists already",name);
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: GopDef: Gop '%s' exists already in: %s",name,avpl->name);
                return FALSE;
        }
 
        if (! on ) {
-               g_warning("mate: GopDef Config error: No 'On' AVP");
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: GopDef: no On in: %s",avpl->name);
                return FALSE;
        }
+       
+       if (g_hash_table_lookup(matecfg->pducfgs,on) == NULL ) {
+               report_error("MATE: GopDef: Pdu '%s' does not exist in: %s",on,avpl->name);
+               return FALSE;           
+       }
 
        if (g_hash_table_lookup(matecfg->gops_by_pduname,on) ) {
-               g_warning("mate: GopDef Config error: Gop for Pdu '%s' exists already",on);
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: GopDef: Gop for Pdu '%s' exists already in: %s",on,avpl->name);
                return FALSE;
        } else {
                g_hash_table_insert(matecfg->gops_by_pduname,on,cfg);
        }
 
        cfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,matecfg->drop_gop);
-       cfg->show_pdu_tree = extract_named_bool(avpl, KEYWORD_SHOWPDUTREE, matecfg->show_pdu_tree);
-       cfg->show_gop_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,matecfg->show_gop_times);
-
+       cfg->show_pdu_tree = extract_named_str(avpl, KEYWORD_SHOWPDUTREE, matecfg->show_pdu_tree);
+       cfg->show_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,matecfg->show_times);
+       cfg->expiration = extract_named_float(avpl, KEYWORD_GOPEXPIRATION,matecfg->gop_expiration);
+       cfg->idle_timeout = extract_named_float(avpl, KEYWORD_GOPIDLETIMEOUT,matecfg->gop_idle_timeout);
+       cfg->lifetime = extract_named_float(avpl, KEYWORD_GOPLIFETIME,matecfg->gop_lifetime);
+       
        cfg->key = avpl;
 
        return TRUE;
@@ -657,16 +764,19 @@ static gboolean config_start(AVPL* avpl) {
        guint8* name;
        mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);;
 
+       if (! name ) {
+               report_error("MATE: GopStart: no For in: %s",avpl->name);
+               return FALSE;
+       }
+       
        if (!cfg) {
-               g_warning("mate: GopStart Config error: Gop %s does not exist",name);
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: GopStart: Gop '%s' doesn't exist in: %s",name,avpl->name);
                return FALSE;
        }
 
        if (cfg->start) {
                /* FEATURE: more start conditions */
-               g_warning("mate: GopStart Config error: GopStart alredy exists for %s",name);
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: GopStart: GopStart for '%s' exists already in: %s",name,avpl->name);
                return FALSE;
        }
 
@@ -678,17 +788,19 @@ static gboolean config_start(AVPL* avpl) {
 static gboolean config_stop(AVPL* avpl) {
        guint8* name;
        mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);;
-
+       
+       if (! name ) {
+               report_error("MATE: GopStop: no For in: %s",avpl->name);
+               return FALSE;
+       }
+       
        if (!cfg) {
-               g_warning("mate: GopStop Config error: Gop %s does not exist",name);
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: GopStop: Gop '%s' doesn't exist in: %s",name,avpl->name);
                return FALSE;
        }
 
        if (cfg->stop) {
-               /* FEATURE: more GopStop conditions */
-               g_warning("mate: GopStart Config error: GopStop alredy exists for %s",name);
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: GopStop: GopStop alredy exists for '%s' in: %s",name,avpl->name);
                return FALSE;
        }
 
@@ -701,19 +813,25 @@ static gboolean config_gopextra(AVPL* avpl) {
        guint8* name;
        mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);;
 
+       if (! name ) {
+               report_error("MATE: GopExtra: no For in: %s",avpl->name);
+               return FALSE;
+       }
+       
        if (!cfg) {
-               g_warning("mate: GopExtra Config error: Gop %s does not exist",name);
-               delete_avpl(avpl,TRUE);
+               report_error("MATE: GopExtra: Gop '%s' does not exist in: %s",name,avpl->name);
                return FALSE;
        }
 
        cfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,cfg->drop_gop);
-       cfg->show_pdu_tree = extract_named_bool(avpl, KEYWORD_SHOWPDUTREE, cfg->show_pdu_tree);
-       cfg->show_gop_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,cfg->show_gop_times);
-
+       cfg->show_pdu_tree = extract_named_str(avpl, KEYWORD_SHOWPDUTREE, cfg->show_pdu_tree);
+       cfg->show_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,cfg->show_times);
+       cfg->expiration = extract_named_float(avpl, KEYWORD_GOPEXPIRATION,cfg->expiration);
+       cfg->idle_timeout = extract_named_float(avpl, KEYWORD_GOPIDLETIMEOUT,cfg->idle_timeout);
+       cfg->lifetime = extract_named_float(avpl, KEYWORD_GOPLIFETIME,cfg->lifetime);
+       
        merge_avpl(cfg->extra,avpl,TRUE);
 
-       delete_avpl(avpl,TRUE);
        return TRUE;
 }
 
@@ -721,20 +839,21 @@ static gboolean config_gog(AVPL* avpl) {
        guint8* name = extract_named_str(avpl, KEYWORD_NAME,NULL);
        mate_cfg_gog* cfg = NULL;
 
-       if (!name) {
-               g_warning("mate: GogDef Config error: no Name");
+       if (! name ) {
+               report_error("MATE: GogDef: no Name in: %s",avpl->name);
                return FALSE;
        }
-
+       
        if ( g_hash_table_lookup(matecfg->gogcfgs,name) ) {
-               g_warning("mate: GogDef Config error: Gog %s exists already", name);
+               report_error("MATE: GogDef: Gog '%s' exists already in: %s",name,avpl->name);
                return FALSE;
        }
 
        cfg = new_gogcfg(name);
 
        cfg->expiration = extract_named_float(avpl, KEYWORD_GOGEXPIRE,matecfg->gog_expiration);
-
+       cfg->gop_as_subtree = extract_named_bool(avpl, KEYWORD_GOPTREE,matecfg->gop_as_subtree);
+       
        return TRUE;
 }
 
@@ -747,15 +866,15 @@ static gboolean config_gogkey(AVPL* avpl) {
 
        if ( ! name || ! cfg ) {
                if ( ! name )
-                       g_warning("mate: GogKey Config error: no Name");
+                       report_error("MATE: GogKey: no For in %s",avpl->name);
                else
-                       g_warning("mate: GogKey Config error: no such Gop %s",name);
+                       report_error("MATE: GogKey: no such Gop '%s' in %s",name,avpl->name);
 
                return FALSE;
        }
 
        if (! on ) {
-               g_warning("mate: GogKey Config error: no " KEYWORD_ON);
+               report_error("MATE: GogKey: no On in %s",avpl->name);
                return FALSE;
        }
 
@@ -783,21 +902,22 @@ static gboolean config_gogextra(AVPL* avpl) {
 
        if ( ! name || ! cfg ) {
                if ( ! name )
-                       g_warning("mate: GogExtra Config error: no Name");
+                       report_error("MATE: GogExtra: no Name in %s",avpl->name);
                else
-                       g_warning("mate: GogExtra Config error: no such Gop %s",name);
+                       report_error("MATE: GogExtra: no such Gop '%s' in %s",name,avpl->name);
 
                return FALSE;
        }
 
        cfg->expiration = extract_named_float(avpl, KEYWORD_GOGEXPIRE,cfg->expiration);
+       cfg->gop_as_subtree = extract_named_bool(avpl, KEYWORD_GOPTREE,cfg->gop_as_subtree);
 
        merge_avpl(cfg->extra,avpl,TRUE);
 
-       delete_avpl(avpl,TRUE);
        return TRUE;
 }
 
+#define true_false_str(v) ((v) ? "TRUE" : "FALSE")
 
 static void print_xxx_transforms(mate_cfg_item* cfg) {
        guint8* tr_name;
@@ -821,7 +941,7 @@ static void print_xxx_transforms(mate_cfg_item* cfg) {
 
        for (i=0; i < cfg->transforms->len; i++) {
                tr_name = ((AVPL_Transf*) g_ptr_array_index(cfg->transforms,i))->name;
-               dbg_print (dbg_cfg,0,dbg_facility,"Action=%s; For=%s; Name=%s;\n",cfg_name,cfg->name,tr_name);
+               dbg_print (dbg_cfg,0,dbg_facility,"Action=%s; For=%s; Name=%s;",cfg_name,cfg->name,tr_name);
        }
 
 }
@@ -832,19 +952,19 @@ static void print_gog_config(gpointer k _U_, gpointer v, gpointer p _U_) {
        void* cookie = NULL;
        AVPL* avpl;
 
-       dbg_print (dbg_cfg,0,dbg_facility,"Action=GogDef; Name=%s; Expiration=%f;\n",cfg->name,cfg->expiration);
+       dbg_print (dbg_cfg,0,dbg_facility,"Action=GogDef; Name=%s; Expiration=%f;",cfg->name,cfg->expiration);
 
        if (cfg->keys) {
                while (( avpl = get_next_avpl(cfg->keys,&cookie) )) {
                        avplstr = avpl_to_str(avpl);
-                       dbg_print (dbg_cfg,0,dbg_facility,"Action=GogKey; For=%s; On=%s; %s\n",cfg->name,avpl->name,avplstr);
+                       dbg_print (dbg_cfg,0,dbg_facility,"Action=GogKey; For=%s; On=%s; %s",cfg->name,avpl->name,avplstr);
                        g_free(avplstr);
                }
        }
 
        if (cfg->extra) {
                avplstr = avpl_to_str(cfg->extra);
-               dbg_print (dbg_cfg,0,dbg_facility,"Action=GogExtra; For=%s; %s\n",cfg->name,avplstr);
+               dbg_print (dbg_cfg,0,dbg_facility,"Action=GogExtra; For=%s; %s",cfg->name,avplstr);
                g_free(avplstr);
        }
 
@@ -863,7 +983,10 @@ static void print_gop_config(gpointer k _U_ , gpointer v, gpointer p _U_) {
        gopdef = g_string_new("Action=GopDef; ");
 
        show_pdu_tree = cfg->show_pdu_tree ? "TRUE" : "FALSE";
-       g_string_sprintfa(gopdef,"Name=%s; ShowPduTree=%s;",cfg->name,show_pdu_tree);
+       g_string_sprintfa(gopdef,"Name=%s; ShowPduTree=%s; ShowGopTimes=%s; "
+                                         "GopExpiration=%f; GopIdleTimeout=%f GopLifetime=%f;",
+                                         cfg->name,show_pdu_tree,true_false_str(cfg->show_times),
+                                         cfg->expiration,cfg->idle_timeout,cfg->lifetime);
 
        if (cfg->key) {
                avplstr = avpl_to_str(cfg->key);
@@ -871,24 +994,24 @@ static void print_gop_config(gpointer k _U_ , gpointer v, gpointer p _U_) {
                g_free(avplstr);
        }
 
-       dbg_print (dbg_cfg,0,dbg_facility,"%s\n",gopdef->str);
+       dbg_print (dbg_cfg,0,dbg_facility,"%s",gopdef->str);
 
 
        if (cfg->start) {
                avplstr = avpl_to_str(cfg->start);
-               dbg_print (dbg_cfg,0,dbg_facility,"Action=GopStart; For=%s; %s\n",cfg->name,avplstr);
+               dbg_print (dbg_cfg,0,dbg_facility,"Action=GopStart; For=%s; %s",cfg->name,avplstr);
                g_free(avplstr);
        }
 
        if (cfg->stop) {
                avplstr = avpl_to_str(cfg->stop);
-               dbg_print (dbg_cfg,0,dbg_facility,"Action=GopStop; For=%s; %s\n",cfg->name,avplstr);
+               dbg_print (dbg_cfg,0,dbg_facility,"Action=GopStop; For=%s; %s",cfg->name,avplstr);
                g_free(avplstr);
        }
 
        if (cfg->extra) {
                avplstr = avpl_to_str(cfg->extra);
-               dbg_print (dbg_cfg,0,dbg_facility,"Action=GopExtra; For=%s;  %s\n",cfg->name,avplstr);
+               dbg_print (dbg_cfg,0,dbg_facility,"Action=GopExtra; For=%s;  %s",cfg->name,avplstr);
                g_free(avplstr);
        }
 
@@ -949,7 +1072,7 @@ static void print_transforms(gpointer k, gpointer v, gpointer p _U_) {
                                break;
                }
 
-               dbg_print (dbg,0,dbg_facility,"\tAction=Transform; Name=%s; Match=%s; Mode=%s; %s %s\n",(guint8*) k,match,mode,match_s,replace_s);
+               dbg_print (dbg,0,dbg_facility,"\tAction=Transform; Name=%s; Match=%s; Mode=%s; %s %s",(guint8*) k,match,mode,match_s,replace_s);
 
                g_free(match_s);
                g_free(replace_s);
@@ -961,6 +1084,8 @@ static void print_pdu_config(mate_cfg_pdu* cfg) {
        int hfid;
        guint8* discard;
        guint8* stop;
+       guint8* criterium_match = NULL;
+       guint8* criterium;
        GString* s = g_string_new("Action=PduDef; ");
 
        discard = cfg->discard_pdu_attributes ? "TRUE": "FALSE";
@@ -980,6 +1105,31 @@ static void print_pdu_config(mate_cfg_pdu* cfg) {
 
        dbg_print(dbg_cfg,0,dbg_facility,"%s",s->str);
 
+       if (cfg->criterium) {
+               switch(cfg->criterium_match_mode) {
+                       case AVPL_NO_MATCH:
+                               criterium_match = "None";
+                               break;
+                       case AVPL_STRICT:
+                               criterium_match = "Strict";
+                               break;
+                       case AVPL_LOOSE:
+                               criterium_match = "Loose";
+                               break;
+                       case AVPL_EVERY:
+                               criterium_match = "Every";
+                               break;
+               }
+
+               criterium = avpl_to_str(cfg->criterium);
+
+               dbg_print(dbg_cfg,0,dbg_facility,
+                                 "Action=PduCriteria; For=%s; Match=%s; Mode=%s;  %s",
+                                 cfg->name,criterium_match,cfg->criterium->name,criterium);
+
+               g_free(criterium);
+       }
+
        print_xxx_transforms(cfg);
 
        g_string_free(s,TRUE);
@@ -994,7 +1144,7 @@ static void print_gogs_by_gopname(gpointer k, gpointer v, gpointer p _U_) {
 
        while(( avpl = get_next_avpl((LoAL*)v,&cookie) )) {
                str = avpl_to_str(avpl);
-               dbg_print(dbg_cfg,0,dbg_facility,"Gop=%s; Gog=%s; --> %s\n",(guint8*)k,avpl->name,str);
+               dbg_print(dbg_cfg,0,dbg_facility,"Gop=%s; Gog=%s; --> %s",(guint8*)k,avpl->name,str);
                g_free(str);
        }
 
@@ -1002,10 +1152,10 @@ static void print_gogs_by_gopname(gpointer k, gpointer v, gpointer p _U_) {
 
 static void print_gops_by_pduname(gpointer k, gpointer v, gpointer p _U_) {
        dbg_print(dbg_cfg,0,dbg_facility,
-                         "PduName=%s; GopName=%s;\n", (guint8*)k,((mate_cfg_gop*)v)->name);
+                         "PduName=%s; GopName=%s;", (guint8*)k,((mate_cfg_gop*)v)->name);
 }
 
-static void print_config() {
+static void print_config(void) {
        guint i;
 
        /* FIXME: print the settings */
@@ -1038,14 +1188,17 @@ static void print_config() {
 static void new_attr_hfri(mate_cfg_item* cfg, guint8* name) {
        int* p_id = g_malloc(sizeof(int));
 
-       hf_register_info hfri = {
-               p_id,
-       {
-               g_strdup_printf("%s",name),
-               g_strdup_printf("mate.%s.%s",cfg->name,name),
-               FT_STRING,BASE_NONE,NULL,0,
-               g_strdup_printf("%s attribute of %s",name,cfg->name),HFILL
-       }};
+       hf_register_info hfri;
+
+       memset(&hfri, 0, sizeof hfri);
+       hfri.p_id = p_id;
+       hfri.hfinfo.name = g_strdup_printf("%s",name);
+       hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.%s",cfg->name,name);
+       hfri.hfinfo.type = FT_STRING;
+       hfri.hfinfo.display = BASE_NONE;
+       hfri.hfinfo.strings = NULL;
+       hfri.hfinfo.bitmask = 0;
+       hfri.hfinfo.blurb = g_strdup_printf("%s attribute of %s",name,cfg->name);
 
        *p_id = -1;
        g_hash_table_insert(cfg->my_hfids,name,p_id);
@@ -1053,7 +1206,7 @@ static void new_attr_hfri(mate_cfg_item* cfg, guint8* name) {
 
 }
 
-static void analyze_pdu_hfids(gpointer k, gpointer v, gpointer p) {
+static void analyze_pdu_hfids(gpointer k _U_, gpointer v, gpointer p) {
        new_attr_hfri((mate_cfg_pdu*) p,(guint8*) v);
 }
 
@@ -1077,25 +1230,43 @@ static void analyze_transform_hfrs(mate_cfg_item* cfg) {
 
 static void analyze_pdu_config(mate_cfg_pdu* cfg) {
        hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}};
+       gint* ett;
 
        hfri.p_id = &(cfg->hfid);
        hfri.hfinfo.name = g_strdup_printf("%s",cfg->name);
        hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name);
-       hfri.hfinfo.blurb = g_strdup_printf("PDU of type %s",cfg->name);
+       hfri.hfinfo.blurb = g_strdup_printf("%s id",cfg->name);
+       hfri.hfinfo.type = FT_UINT32;
+       hfri.hfinfo.display = BASE_DEC;
 
        g_array_append_val(matecfg->hfrs,hfri);
-
+       
        hfri.p_id = &(cfg->hfid_pdu_rel_time);
        hfri.hfinfo.name = g_strdup_printf("%s time",cfg->name);
        hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.RelativeTime",cfg->name);
        hfri.hfinfo.type = FT_FLOAT;
        hfri.hfinfo.display = BASE_DEC;
-       hfri.hfinfo.blurb = "Seconds passed since the start of the GOP or capture if the PDU is unnassigned";
-
+       hfri.hfinfo.blurb = "Seconds passed since the start of capture";
+       
        g_array_append_val(matecfg->hfrs,hfri);
-
+       
+       hfri.p_id = &(cfg->hfid_pdu_time_in_gop);
+       hfri.hfinfo.name = g_strdup_printf("%s time since begining of Gop",cfg->name);
+       hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.TimeInGop",cfg->name);
+       hfri.hfinfo.type = FT_FLOAT;
+       hfri.hfinfo.display = BASE_DEC;
+       hfri.hfinfo.blurb = "Seconds passed since the start of the GOP";
+       
+       g_array_append_val(matecfg->hfrs,hfri);
+       
        g_hash_table_foreach(cfg->hfids_attr,analyze_pdu_hfids,cfg);
 
+       ett = &cfg->ett;
+       g_array_append_val(matecfg->ett,ett);
+
+       ett = &cfg->ett_attr;
+       g_array_append_val(matecfg->ett,ett);
+
        analyze_transform_hfrs(cfg);
 }
 
@@ -1103,16 +1274,19 @@ static void analyze_gop_config(gpointer k _U_, gpointer v, gpointer p _U_) {
        mate_cfg_gop* cfg = v;
        void* cookie = NULL;
        AVP* avp;
+       gint* ett;
        hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}};
 
        hfri.p_id = &(cfg->hfid);
        hfri.hfinfo.name = g_strdup_printf("%s",cfg->name);
        hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name);
-       hfri.hfinfo.blurb = g_strdup_printf("GOP of type %s",cfg->name);
+       hfri.hfinfo.blurb = g_strdup_printf("%s id",cfg->name);
+       hfri.hfinfo.type = FT_UINT32;
+       hfri.hfinfo.display = BASE_DEC;
 
        g_array_append_val(matecfg->hfrs,hfri);
 
-       hfri.p_id = &(cfg->hfid_gop_start_time);
+       hfri.p_id = &(cfg->hfid_start_time);
        hfri.hfinfo.name = g_strdup_printf("%s start time",cfg->name);
        hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.StartTime",cfg->name);
        hfri.hfinfo.type = FT_FLOAT;
@@ -1121,15 +1295,15 @@ static void analyze_gop_config(gpointer k _U_, gpointer v, gpointer p _U_) {
 
        g_array_append_val(matecfg->hfrs,hfri);
 
-       hfri.p_id = &(cfg->hfid_gop_stop_time);
+       hfri.p_id = &(cfg->hfid_stop_time);
        hfri.hfinfo.name = g_strdup_printf("%s hold time",cfg->name);
        hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Time",cfg->name);
        hfri.hfinfo.blurb = g_strdup_printf("Duration in seconds from start to stop of this %s",cfg->name);
 
        g_array_append_val(matecfg->hfrs,hfri);
 
-       hfri.p_id = &(cfg->hfid_gop_last_time);
-       hfri.hfinfo.name = g_strdup_printf("%s current time",cfg->name);
+       hfri.p_id = &(cfg->hfid_last_time);
+       hfri.hfinfo.name = g_strdup_printf("%s duration",cfg->name);
        hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Duration",cfg->name);
        hfri.hfinfo.blurb = g_strdup_printf("Time passed between the start of this %s and the last pdu assigned to it",cfg->name);
 
@@ -1147,9 +1321,16 @@ static void analyze_gop_config(gpointer k _U_, gpointer v, gpointer p _U_) {
        hfri.hfinfo.name = g_strdup_printf("A PDU of %s",cfg->name);
        hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Pdu",cfg->name);
        hfri.hfinfo.blurb = g_strdup_printf("A PDU assigned to this %s",cfg->name);
-       hfri.hfinfo.type = FT_FRAMENUM;
 
-       g_array_append_val(matecfg->hfrs,hfri);
+       if (cfg->show_pdu_tree == matecfg->frame_tree) {
+               hfri.hfinfo.type = FT_FRAMENUM;
+               g_array_append_val(matecfg->hfrs,hfri);
+       } else  if (cfg->show_pdu_tree == matecfg->pdu_tree) {
+               hfri.hfinfo.type = FT_UINT32;
+               g_array_append_val(matecfg->hfrs,hfri);
+       } else {
+               cfg->show_pdu_tree = matecfg->no_tree;
+       }
 
        while(( avp = get_next_avp(cfg->key,&cookie) )) {
                if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
@@ -1157,20 +1338,24 @@ static void analyze_gop_config(gpointer k _U_, gpointer v, gpointer p _U_) {
                }
        }
 
-       cookie = NULL;
-       while(( avp = get_next_avp(cfg->start,&cookie) )) {
-               if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
-                       new_attr_hfri(cfg,avp->n);
+       if(cfg->start) {
+               cookie = NULL;
+               while(( avp = get_next_avp(cfg->start,&cookie) )) {
+                       if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
+                               new_attr_hfri(cfg,avp->n);
+                       }
                }
        }
-
-       cookie = NULL;
-       while(( avp = get_next_avp(cfg->stop,&cookie) )) {
-               if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
-                       new_attr_hfri(cfg,avp->n);
+       
+       if (cfg->stop) {
+               cookie = NULL;
+               while(( avp = get_next_avp(cfg->stop,&cookie) )) {
+                       if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
+                               new_attr_hfri(cfg,avp->n);
+                       }
                }
        }
-
+       
        cookie = NULL;
        while(( avp = get_next_avp(cfg->extra,&cookie) )) {
                if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
@@ -1179,6 +1364,19 @@ static void analyze_gop_config(gpointer k _U_, gpointer v, gpointer p _U_) {
        }
 
        analyze_transform_hfrs(cfg);
+
+       ett = &cfg->ett;
+       g_array_append_val(matecfg->ett,ett);
+
+       ett = &cfg->ett_attr;
+       g_array_append_val(matecfg->ett,ett);
+
+       ett = &cfg->ett_times;
+       g_array_append_val(matecfg->ett,ett);
+
+       ett = &cfg->ett_children;
+       g_array_append_val(matecfg->ett,ett);
+
 }
 
 
@@ -1188,24 +1386,53 @@ static void analyze_gog_config(gpointer k _U_, gpointer v, gpointer p _U_) {
        void* avpl_cookie;
        AVP* avp;
        AVPL* avpl;
+       AVPL* key_avps;
        hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}};
+       gint* ett;
 
        hfri.p_id = &(cfg->hfid);
        hfri.hfinfo.name = g_strdup_printf("%s",cfg->name);
        hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name);
-       hfri.hfinfo.blurb = g_strdup_printf("GOG of type %s",cfg->name);
+       hfri.hfinfo.blurb = g_strdup_printf("%s Id",cfg->name);
+       hfri.hfinfo.type = FT_UINT32;
+       hfri.hfinfo.display = BASE_DEC;
 
        g_array_append_val(matecfg->hfrs,hfri);
-
+       
        hfri.p_id = &(cfg->hfid_gog_num_of_gops);
        hfri.hfinfo.name = "number of GOPs";
        hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.NumOfGops",cfg->name);
        hfri.hfinfo.type = FT_UINT32;
        hfri.hfinfo.display = BASE_DEC;
        hfri.hfinfo.blurb = g_strdup_printf("Number of GOPs assigned to this %s",cfg->name);
-
+       
        g_array_append_val(matecfg->hfrs,hfri);
-
+       
+       hfri.p_id = &(cfg->hfid_gog_gopstart);
+       hfri.hfinfo.name = "GopStart frame";
+       hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.GopStart",cfg->name);
+       hfri.hfinfo.type = FT_FRAMENUM;
+       hfri.hfinfo.display = BASE_DEC;
+       hfri.hfinfo.blurb = g_strdup("The start frame of a GOP");
+       
+       g_array_append_val(matecfg->hfrs,hfri);
+       
+       hfri.p_id = &(cfg->hfid_start_time);
+       hfri.hfinfo.name = g_strdup_printf("%s start time",cfg->name);
+       hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.StartTime",cfg->name);
+       hfri.hfinfo.type = FT_FLOAT;
+       hfri.hfinfo.blurb = g_strdup_printf("Seconds passed since the begining of caputre to the start of this %s",cfg->name);
+       
+       g_array_append_val(matecfg->hfrs,hfri);
+               
+       hfri.p_id = &(cfg->hfid_last_time);
+       hfri.hfinfo.name = g_strdup_printf("%s duration",cfg->name);
+       hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Duration",cfg->name);
+       hfri.hfinfo.blurb = g_strdup_printf("Time passed between the start of this %s and the last pdu assigned to it",cfg->name);
+       
+       g_array_append_val(matecfg->hfrs,hfri);
+       
+       /* this might become mate.gogname.gopname */
        hfri.p_id = &(cfg->hfid_gog_gop);
        hfri.hfinfo.name = "a GOP";
        hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Gop",cfg->name);
@@ -1215,12 +1442,15 @@ static void analyze_gog_config(gpointer k _U_, gpointer v, gpointer p _U_) {
 
        g_array_append_val(matecfg->hfrs,hfri);
 
+       key_avps = new_avpl("");
+       
        avpl_cookie = NULL;
        while (( avpl = get_next_avpl(cfg->keys,&avpl_cookie) )) {
                avp_cookie = NULL;
                while (( avp = get_next_avp(avpl,&avp_cookie) )) {
                        if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
                                new_attr_hfri(cfg,avp->n);
+                               insert_avp(key_avps,avp);
                        }
                }
        }
@@ -1231,11 +1461,29 @@ static void analyze_gog_config(gpointer k _U_, gpointer v, gpointer p _U_) {
                        new_attr_hfri(cfg,avp->n);
                }
        }
-
+       
+       merge_avpl(cfg->extra,key_avps,TRUE);
+       
        analyze_transform_hfrs(cfg);
+
+       ett = &cfg->ett;
+       g_array_append_val(matecfg->ett,ett);
+
+       ett = &cfg->ett_attr;
+       g_array_append_val(matecfg->ett,ett);
+
+       ett = &cfg->ett_children;
+       g_array_append_val(matecfg->ett,ett);
+
+       ett = &cfg->ett_times;
+       g_array_append_val(matecfg->ett,ett);
+       
+       ett = &cfg->ett_gog_gop;        
+       g_array_append_val(matecfg->ett,ett);
+       
 }
 
-static size_t analyze_config() {
+static void analyze_config(void) {
        guint i;
 
        for (i=0; i<matecfg->pducfglist->len; i++) {
@@ -1252,9 +1500,11 @@ static void new_action(guint8* name, config_action* action) {
 
 }
 
-static void init_actions() {
+static void init_actions(void) {
+       AVP* avp;
 
        all_keywords = new_avpl("all_keywords");
+
        insert_avp(all_keywords,new_avp(KEYWORD_ACTION,"",'='));
        insert_avp(all_keywords,new_avp(KEYWORD_SETTINGS,"",'='));
        insert_avp(all_keywords,new_avp(KEYWORD_INCLUDE,"",'='));
@@ -1298,6 +1548,7 @@ static void init_actions() {
        insert_avp(all_keywords,new_avp(KEYWORD_STOP,"",'='));
        insert_avp(all_keywords,new_avp(KEYWORD_DROPPDU,"",'='));
        insert_avp(all_keywords,new_avp(KEYWORD_DROPGOP,"",'='));
+       insert_avp(all_keywords,new_avp(KEYWORD_LIB,"",'='));
 
        insert_avp(all_keywords,new_avp(KEYWORD_DBG_GENERAL,"",'='));
        insert_avp(all_keywords,new_avp(KEYWORD_DBG_CFG,"",'='));
@@ -1313,6 +1564,26 @@ static void init_actions() {
        insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVPL_OP,"",'='));
 #endif
 
+       avp = new_avp(KEYWORD_ACCEPT,"",'=');
+       matecfg->accept = avp->n;
+       insert_avp(all_keywords,avp);
+
+       avp = new_avp(KEYWORD_REJECT,"",'=');
+       matecfg->reject = avp->n;
+       insert_avp(all_keywords,avp);
+
+       avp = new_avp(KEYWORD_NOTREE,"",'=');
+       matecfg->no_tree = avp->n;
+       insert_avp(all_keywords,avp);
+
+       avp = new_avp(KEYWORD_FRAMETREE,"",'=');
+       matecfg->frame_tree = avp->n;
+       insert_avp(all_keywords,avp);
+
+       avp = new_avp(KEYWORD_PDUTREE,"",'=');
+       matecfg->pdu_tree = avp->n;
+       insert_avp(all_keywords,avp);
+       
        if (actions) {
                g_hash_table_destroy(actions);
        }
@@ -1322,7 +1593,7 @@ static void init_actions() {
        new_action(KEYWORD_SETTINGS,config_settings);
        new_action(KEYWORD_PDU,config_pdu);
        new_action(KEYWORD_PDUEXTRA,config_pduextra);
-       /* new_action(KEYWORD_PDUCRITERIA,config_pdu); */
+       new_action(KEYWORD_PDUCRITERIA,config_pducriteria);
        new_action(KEYWORD_GOP,config_gop);
        new_action(KEYWORD_GOGDEF,config_gog);
        new_action(KEYWORD_GOGKEY,config_gogkey);
@@ -1338,24 +1609,14 @@ static void init_actions() {
 
 }
 
-void reset_cfg(gpointer k _U_, gpointer v, gpointer p _U_) {
-       mate_cfg_item* c = v;
-       c->last_id = 0;
-}
-
 extern mate_config* mate_cfg() {
-
-       g_hash_table_foreach(matecfg->pducfgs,reset_cfg,NULL);
-       g_hash_table_foreach(matecfg->gopcfgs,reset_cfg,NULL);
-       g_hash_table_foreach(matecfg->gogcfgs,reset_cfg,NULL);
-
        return matecfg;
 }
 
-extern mate_config* mate_make_config(guint8* filename) {
+extern mate_config* mate_make_config(guint8* filename, int mate_hfid) {
+       gint* ett;
 
        avp_init();
-       init_actions();
 
        matecfg = g_malloc(sizeof(mate_config));
 
@@ -1363,12 +1624,11 @@ extern mate_config* mate_make_config(guint8* filename) {
        matecfg->discard_pdu_attributes = FALSE;
        matecfg->drop_pdu = FALSE;
        matecfg->drop_gop = FALSE;
-       matecfg->show_pdu_tree = TRUE;
-       matecfg->show_gop_times = TRUE;
+       matecfg->show_times = TRUE;
        matecfg->last_to_be_created = FALSE;
        matecfg->match_mode = AVPL_STRICT;
        matecfg->replace_mode = AVPL_INSERT;
-       matecfg->mate_lib_path = g_strdup_printf("%s%c%s",get_datafile_dir(),DIR_SEP,DEFAULT_MATE_LIB_PATH);
+       matecfg->mate_lib_path = g_strdup_printf("%s%c%s%c",get_datafile_dir(),DIR_SEP,DEFAULT_MATE_LIB_PATH,DIR_SEP);
        matecfg->mate_config_file = g_strdup(filename);
        matecfg->mate_attrs_filter = g_string_new("");
        matecfg->mate_protos_filter = g_string_new("");
@@ -1387,14 +1647,28 @@ extern mate_config* mate_make_config(guint8* filename) {
        matecfg->gogs_by_gopname = g_hash_table_new(g_str_hash,g_str_equal);
 
        matecfg->hfrs = g_array_new(FALSE,TRUE,sizeof(hf_register_info));
+       matecfg->ett = g_array_new(FALSE,TRUE,sizeof(gint*));
+       matecfg->ett_root = -1;
+       matecfg->hfid_mate = mate_hfid;
+       
+       ett = &matecfg->ett_root;
+       g_array_append_val(matecfg->ett,ett);
 
        dbg = &matecfg->dbg_lvl;
 
+       init_actions();
+
+       matecfg->show_pdu_tree = matecfg->frame_tree;
+
+       config_error = g_string_new("");
+       
        if ( mate_load_config(filename) ) {
                analyze_config();
                dbg_print (dbg_cfg,3,dbg_facility,"mate_make_config: OK");
                if (dbg_cfg_lvl > 0) print_config();
        } else {
+               report_failure("%s",config_error->str);
+               g_string_free(config_error,TRUE);
                if (matecfg) destroy_mate_config(matecfg,FALSE);
                matecfg = NULL;
                return NULL;
@@ -1404,8 +1678,7 @@ extern mate_config* mate_make_config(guint8* filename) {
                g_string_erase(matecfg->mate_attrs_filter,0,2);
                g_string_erase(matecfg->mate_protos_filter,0,2);
        } else {
-               mate_config_error(NULL,NULL,"mate: Failed: nothing left to tap on");
-               if (matecfg) destroy_mate_config(matecfg,FALSE);
+               destroy_mate_config(matecfg,FALSE);
                matecfg = NULL;
                return NULL;
        }