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.<key>, 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
This commit is contained in:
Stig Bjørlykke 2011-10-18 17:46:00 +00:00
parent cc4fe5789b
commit 82e0b65038
4 changed files with 162 additions and 0 deletions

View File

@ -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;

View File

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

View File

@ -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);

View File

@ -5,6 +5,7 @@
*
* (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
* (c) 2008, Balint Reczey <balint.reczey@ericsson.com>
* (c) 2011, Stig Bjorlykke <stig@bjorlykke.org>
*
* $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;
}