From 82e0b650388aa4f89c4fc371eab057b278b59f92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stig=20Bj=C3=B8rlykke?= Date: Tue, 18 Oct 2011 17:46:00 +0000 Subject: Added a private hash table to transport string values between dissectors. This works between C and Lua. In C the pinfo.private_table pointer must be initialized using g_hash_table_new (g_str_hash, g_str_equal); In Lua the values are available using pinfo.private., and the table is created automatically on first usage. It's possible to use this datatypes: nil, boolean, number and string, but every value is converted to string so numbers must be converted using tonumber() on usage. Boolean is either nil or an empty string. svn path=/trunk/; revision=39461 --- epan/packet_info.h | 1 + epan/wslua/init_wslua.c | 1 + epan/wslua/wslua.h | 8 +++ epan/wslua/wslua_pinfo.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+) (limited to 'epan') diff --git a/epan/packet_info.h b/epan/packet_info.h index 646a24a7be..94ee3c1b42 100644 --- a/epan/packet_info.h +++ b/epan/packet_info.h @@ -175,6 +175,7 @@ typedef struct _packet_info { * in the SCTP packet */ void *private_data; /* pointer to data passed from one dissector to another */ + GHashTable *private_table; /* a hash table passed from one dissector to another */ /* TODO: Use emem_strbuf_t instead */ GString *layer_names; /* layers of each protocol */ guint16 link_number; diff --git a/epan/wslua/init_wslua.c b/epan/wslua/init_wslua.c index ede501fd38..a49204f7e0 100644 --- a/epan/wslua/init_wslua.c +++ b/epan/wslua/init_wslua.c @@ -56,6 +56,7 @@ static void lua_frame_end(void) clear_outstanding_Pinfo(); clear_outstanding_Column(); clear_outstanding_Columns(); + clear_outstanding_PrivateTable(); clear_outstanding_TreeItem(); } diff --git a/epan/wslua/wslua.h b/epan/wslua/wslua.h index a7a6447354..ffa2a84c37 100644 --- a/epan/wslua/wslua.h +++ b/epan/wslua/wslua.h @@ -165,6 +165,12 @@ struct _wslua_cols { gboolean expired; }; +struct _wslua_private_table { + GHashTable *table; + gboolean is_allocated; + gboolean expired; +}; + struct _wslua_treeitem { proto_item* item; proto_tree* tree; @@ -237,6 +243,7 @@ typedef tvbparse_elem_t* Node; typedef tvbparse_action_t* Shortcut; typedef struct _wslua_main* WireShark; typedef struct _wslua_dir* Dir; +typedef struct _wslua_private_table* PrivateTable; /* * toXxx(L,idx) gets a Xxx from an index (Lua Error if fails) @@ -397,6 +404,7 @@ extern Pinfo* push_Pinfo(lua_State* L, packet_info* p); extern void clear_outstanding_Pinfo(void); extern void clear_outstanding_Column(void); extern void clear_outstanding_Columns(void); +extern void clear_outstanding_PrivateTable(void); extern TreeItem* push_TreeItem(lua_State* L, TreeItem ti); extern void clear_outstanding_TreeItem(void); diff --git a/epan/wslua/wslua_pinfo.c b/epan/wslua/wslua_pinfo.c index b6e87cb404..4b197ae60b 100644 --- a/epan/wslua/wslua_pinfo.c +++ b/epan/wslua/wslua_pinfo.c @@ -5,6 +5,7 @@ * * (c) 2006, Luis E. Garcia Ontanon * (c) 2008, Balint Reczey + * (c) 2011, Stig Bjorlykke * * $Id$ * @@ -48,10 +49,12 @@ static GPtrArray* outstanding_Pinfo = NULL; static GPtrArray* outstanding_Column = NULL; static GPtrArray* outstanding_Columns = NULL; +static GPtrArray* outstanding_PrivateTable = NULL; CLEAR_OUTSTANDING(Pinfo,expired, TRUE) CLEAR_OUTSTANDING(Column,expired, TRUE) CLEAR_OUTSTANDING(Columns,expired, TRUE) +CLEAR_OUTSTANDING(PrivateTable,expired, TRUE) Pinfo* push_Pinfo(lua_State* L, packet_info* ws_pinfo) { Pinfo pinfo = NULL; @@ -66,6 +69,7 @@ Pinfo* push_Pinfo(lua_State* L, packet_info* ws_pinfo) { #define PUSH_COLUMN(L,c) {g_ptr_array_add(outstanding_Column,c);pushColumn(L,c);} #define PUSH_COLUMNS(L,c) {g_ptr_array_add(outstanding_Columns,c);pushColumns(L,c);} +#define PUSH_PRIVATE_TABLE(L,c) {g_ptr_array_add(outstanding_PrivateTable,c);pushPrivateTable(L,c);} WSLUA_CLASS_DEFINE(NSTime,NOP,NOP); /* NSTime represents a nstime_t. This is an object with seconds and nano seconds. */ @@ -819,6 +823,117 @@ int Columns_register(lua_State *L) { return 1; } +WSLUA_CLASS_DEFINE(PrivateTable,NOP,NOP); + /* PrivateTable represents the pinfo->private_table. */ + +WSLUA_METAMETHOD PrivateTable__tostring(lua_State* L) { + PrivateTable priv = checkPrivateTable(L,1); + GString *key_string = g_string_new (""); + GList *keys, *key; + + if (!priv) return 0; + + keys = g_hash_table_get_keys (priv->table); + key = g_list_first (keys); + while (key) { + key_string = g_string_append (key_string, key->data); + key = g_list_next (key); + if (key) { + key_string = g_string_append_c (key_string, ','); + } + } + + lua_pushstring(L,ep_strdup(key_string->str)); + + g_string_free (key_string, TRUE); + g_list_free (keys); + + WSLUA_RETURN(1); /* A string with all keys in the table, mostly for debugging. */ +} + +static int PrivateTable__index(lua_State* L) { + /* Gets the text of a specific entry */ + PrivateTable priv = checkPrivateTable(L,1); + const gchar* name = luaL_checkstring(L,2); + const gchar* string; + + if (! (priv && name) ) return 0; + + if (priv->expired) { + luaL_error(L,"expired private_table"); + return 0; + } + + string = g_hash_table_lookup (priv->table, (gpointer) name); + + if (string) { + lua_pushstring(L, string); + } else { + lua_pushnil(L); + } + + return 1; +} + +static int PrivateTable__newindex(lua_State* L) { + /* Sets the text of a specific entry */ + PrivateTable priv = checkPrivateTable(L,1); + const gchar* name = luaL_checkstring(L,2); + const gchar* string = NULL; + + if (! (priv && name) ) return 0; + + if (priv->expired) { + luaL_error(L,"expired private_table"); + return 0; + } + + if (lua_isstring(L,3)) { + /* This also catches numbers, which is converted to string */ + string = luaL_checkstring(L,3); + } else if (lua_isboolean(L,3)) { + /* We support boolean by setting a empty string if true and NULL if false */ + string = lua_toboolean(L,3) ? "" : NULL; + } else if (!lua_isnil(L,3)) { + luaL_error(L,"unsupported type: %s", lua_typename(L,3)); + return 0; + } + + g_hash_table_replace (priv->table, (gpointer) name, (gpointer) string); + + return 1; +} + +static int PrivateTable__gc(lua_State* L) { + PrivateTable priv = checkPrivateTable(L,1); + + if (!priv) return 0; + + if (!priv->expired) { + priv->expired = TRUE; + } else { + if (priv->is_allocated) { + g_hash_table_destroy (priv->table); + } + g_free(priv); + } + + return 0; +} + +WSLUA_META PrivateTable_meta[] = { + {"__index", PrivateTable__index}, + {"__newindex", PrivateTable__newindex}, + {"__tostring", PrivateTable__tostring}, + {"__gc", PrivateTable__gc}, + { NULL, NULL} +}; + +int PrivateTable_register(lua_State* L) { + WSLUA_REGISTER_META(PrivateTable); + return 1; +} + WSLUA_CLASS_DEFINE(Pinfo,FAIL_ON_NULL("expired pinfo"),NOP); /* Packet information */ @@ -960,6 +1075,39 @@ static int Pinfo_columns(lua_State *L) { return 1; } +static int Pinfo_private(lua_State *L) { + PrivateTable priv = NULL; + Pinfo pinfo = checkPinfo(L,1); + const gchar* privname = luaL_optstring(L,2,NULL); + gboolean is_allocated = FALSE; + + if (!pinfo) return 0; + + if (pinfo->expired) { + luaL_error(L,"expired private_table"); + return 0; + } + + if (!pinfo->ws_pinfo->private_table) { + pinfo->ws_pinfo->private_table = g_hash_table_new(g_str_hash,g_str_equal); + is_allocated = TRUE; + } + + priv = g_malloc(sizeof(struct _wslua_private_table)); + priv->table = pinfo->ws_pinfo->private_table; + priv->is_allocated = is_allocated; + priv->expired = FALSE; + + if (!privname) { + PUSH_PRIVATE_TABLE(L,priv); + } else { + lua_settop(L,0); + PUSH_PRIVATE_TABLE(L,priv); + lua_pushstring(L,privname); + return PrivateTable__index(L); + } + return 1; +} typedef enum { PARAM_NONE, @@ -1193,6 +1341,9 @@ static const pinfo_method_t Pinfo_methods[] = { /* WSLUA_ATTRIBUTE Pinfo_private_data RO Access to private data */ {"private_data", Pinfo_private_data, pushnil_param, PARAM_NONE}, + /* WSLUA_ATTRIBUTE Pinfo_private RW Access to the private table entries */ + {"private", Pinfo_private, pushnil_param, PARAM_NONE}, + /* WSLUA_ATTRIBUTE Pinfo_ethertype RW Ethernet Type Code, if this is an Ethernet packet */ {"ethertype", Pinfo_ethertype, Pinfo_set_int, PARAM_ETHERTYPE}, @@ -1298,5 +1449,6 @@ int Pinfo_register(lua_State* L) { outstanding_Pinfo = g_ptr_array_new(); outstanding_Column = g_ptr_array_new(); outstanding_Columns = g_ptr_array_new(); + outstanding_PrivateTable = g_ptr_array_new(); return 1; } -- cgit v1.2.3