Store pointers to previously displayed and captured packet, not nstime_t deltas.
[metze/wireshark/wip.git] / epan / wslua / wslua_pinfo.c
index a55c64497cc36ce0a342a3674d2ab8233673db39..5fecb5ea85961c7177dc7661b821108e83008cc1 100644 (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$
  *
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
 
 /* WSLUA_MODULE Pinfo Obtaining packet information */
 
 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 +67,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. */
@@ -91,7 +93,7 @@ WSLUA_METAMETHOD NSTime__tostring(lua_State* L) {
 
     if (!nstime) return 0;
 
-    lua_pushstring(L,ep_strdup_printf("%ld.%09d", nstime->secs, nstime->nsecs));
+    lua_pushstring(L,ep_strdup_printf("%ld.%09d", (long)nstime->secs, nstime->nsecs));
 
     WSLUA_RETURN(1); /* The string representing the nstime. */
 }
@@ -297,9 +299,9 @@ WSLUA_META NSTime_meta[] = {
 int NSTime_register(lua_State* L) {
     WSLUA_REGISTER_META(NSTime);
 
-    lua_pushstring(L, "NSTime");
     lua_pushcfunction(L, NSTime_new);
-    lua_settable(L, LUA_GLOBALSINDEX);
+    lua_setglobal(L, "NSTime");
+
     return 1;
 }
 
@@ -805,7 +807,7 @@ static int Columns_gc(lua_State* L) {
 }
 
 
-static const luaL_reg Columns_meta[] = {
+static const luaL_Reg Columns_meta[] = {
     {"__tostring", Columns__tostring },
     {"__newindex", Columns__newindex },
     {"__index",  Columns_index},
@@ -819,67 +821,189 @@ 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;
+    GList *keys, *key;
+
+    if (!priv) return 0;
+
+    key_string = g_string_new ("");
+    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,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;
+    }
+
+    if (string) {
+      g_hash_table_replace (priv->table, (gpointer) ep_strdup(name), (gpointer) ep_strdup(string));
+    } else {
+      g_hash_table_remove (priv->table, (gpointer) name);
+    }
+
+    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 */
 
 static int Pinfo_tostring(lua_State *L) { lua_pushstring(L,"a Pinfo"); return 1; }
 
-#define PINFO_GET_NUMBER(name,val) static int name(lua_State *L) {  \
+#define PINFO_GET(name,block) static int name(lua_State *L) {  \
     Pinfo pinfo = checkPinfo(L,1); \
     if (!pinfo) return 0;\
     if (pinfo->expired) { \
         luaL_error(L,"expired_pinfo"); \
         return 0; \
     } \
-    lua_pushnumber(L,(lua_Number)(val));\
+    block \
     return 1;\
 }
 
-#define PINFO_GET_STRING(name,val) static int name(lua_State *L) { \
-    Pinfo pinfo = checkPinfo(L,1); \
-    const gchar* value; \
-    if (!pinfo) return 0; \
-    if (pinfo->expired) { \
-        luaL_error(L,"expired_pinfo"); \
-        return 0; \
-    } \
-    value = val; \
-    if (value) lua_pushstring(L,(const char*)(value)); else lua_pushnil(L); \
-    return 1; \
-}
+#define PINFO_GET_BOOLEAN(name,val) \
+    PINFO_GET(name,{lua_pushboolean(L,val);})
 
-#define PINFO_GET_ADDRESS(name,role) static int name(lua_State *L) { \
-    Pinfo pinfo = checkPinfo(L,1); \
-    Address addr = g_malloc(sizeof(address)); \
-    if (!pinfo) return 0; \
-    if (pinfo->expired) { \
-        luaL_error(L,"expired_pinfo"); \
-        return 0; \
-    } \
-    COPY_ADDRESS(addr, &(pinfo->ws_pinfo->role)); \
-    pushAddress(L,addr); \
-    return 1; \
+#define PINFO_GET_NUMBER(name,val) \
+    PINFO_GET(name,{lua_pushnumber(L,(lua_Number)(val));})
+
+#define PINFO_GET_STRING(name,val) \
+    PINFO_GET(name, { \
+      const gchar* value; \
+      value = val; \
+      if (value) lua_pushstring(L,(const char*)(value)); else lua_pushnil(L); \
+    })
+
+#define PINFO_GET_ADDRESS(name,role) \
+    PINFO_GET(name, { \
+      Address addr; \
+      addr = g_new(address,1); \
+      COPY_ADDRESS(addr, &(pinfo->ws_pinfo->role)); \
+      pushAddress(L,addr); \
+    })
+
+#define PINFO_GET_LIGHTUSERDATA(name, val) \
+    PINFO_GET(name,{lua_pushlightuserdata(L, (void *) (val));})
+
+static double
+lua_nstime_to_sec(const nstime_t *nstime)
+{
+    return (((double)nstime->secs) + (((double)nstime->nsecs) / 1000000000.0));
 }
 
-#define PINFO_GET_LIGHTUSERDATA(name, val) static int name(lua_State *L) { \
-    Pinfo pinfo = checkPinfo(L, 1); \
-    if (!pinfo) return 0; \
-    if (pinfo->expired) { \
-        luaL_error(L, "expired_pinfo"); \
-        return 0; \
-    } \
-    lua_pushlightuserdata(L, (void *) (val)); \
-    return 1; \
+static double
+lua_delta_nstime_to_sec(const frame_data *fd, const frame_data *prev)
+{
+       nstime_t del;
+
+       frame_delta_abs_time(fd, prev, &del);
+       return lua_nstime_to_sec(&del);
 }
 
+PINFO_GET_BOOLEAN(Pinfo_fragmented,pinfo->ws_pinfo->fragmented)
+PINFO_GET_BOOLEAN(Pinfo_in_error_pkt,pinfo->ws_pinfo->flags.in_error_pkt)
+PINFO_GET_BOOLEAN(Pinfo_visited,pinfo->ws_pinfo->fd->flags.visited)
+
 PINFO_GET_NUMBER(Pinfo_number,pinfo->ws_pinfo->fd->num)
 PINFO_GET_NUMBER(Pinfo_len,pinfo->ws_pinfo->fd->pkt_len)
 PINFO_GET_NUMBER(Pinfo_caplen,pinfo->ws_pinfo->fd->cap_len)
-PINFO_GET_NUMBER(Pinfo_abs_ts,(((double)pinfo->ws_pinfo->fd->abs_ts.secs) + (((double)pinfo->ws_pinfo->fd->abs_ts.nsecs) / 1000000000.0) ))
-PINFO_GET_NUMBER(Pinfo_rel_ts,(((double)pinfo->ws_pinfo->fd->rel_ts.secs) + (((double)pinfo->ws_pinfo->fd->rel_ts.nsecs) / 1000000000.0) ))
-PINFO_GET_NUMBER(Pinfo_delta_ts,(((double)pinfo->ws_pinfo->fd->del_cap_ts.secs) + (((double)pinfo->ws_pinfo->fd->del_cap_ts.nsecs) / 1000000000.0) ))
-PINFO_GET_NUMBER(Pinfo_delta_dis_ts,(((double)pinfo->ws_pinfo->fd->del_dis_ts.secs) + (((double)pinfo->ws_pinfo->fd->del_dis_ts.nsecs) / 1000000000.0) ))
+PINFO_GET_NUMBER(Pinfo_abs_ts,lua_nstime_to_sec(&pinfo->ws_pinfo->fd->abs_ts))
+PINFO_GET_NUMBER(Pinfo_rel_ts,lua_nstime_to_sec(&pinfo->ws_pinfo->fd->rel_ts))
+PINFO_GET_NUMBER(Pinfo_delta_ts,lua_delta_nstime_to_sec(pinfo->ws_pinfo->fd, pinfo->ws_pinfo->fd->prev_cap))
+PINFO_GET_NUMBER(Pinfo_delta_dis_ts,lua_delta_nstime_to_sec(pinfo->ws_pinfo->fd, pinfo->ws_pinfo->fd->prev_dis))
 PINFO_GET_NUMBER(Pinfo_ipproto,pinfo->ws_pinfo->ipproto)
 PINFO_GET_NUMBER(Pinfo_circuit_id,pinfo->ws_pinfo->circuit_id)
 PINFO_GET_NUMBER(Pinfo_desegment_len,pinfo->ws_pinfo->desegment_len)
@@ -887,8 +1011,11 @@ PINFO_GET_NUMBER(Pinfo_desegment_offset,pinfo->ws_pinfo->desegment_offset)
 PINFO_GET_NUMBER(Pinfo_ptype,pinfo->ws_pinfo->ptype)
 PINFO_GET_NUMBER(Pinfo_src_port,pinfo->ws_pinfo->srcport)
 PINFO_GET_NUMBER(Pinfo_dst_port,pinfo->ws_pinfo->destport)
+PINFO_GET_NUMBER(Pinfo_ethertype,pinfo->ws_pinfo->ethertype)
+PINFO_GET_NUMBER(Pinfo_match_uint,pinfo->ws_pinfo->match_uint)
 
 PINFO_GET_STRING(Pinfo_curr_proto,pinfo->ws_pinfo->current_proto)
+PINFO_GET_STRING(Pinfo_match_string,pinfo->ws_pinfo->match_string)
 
 PINFO_GET_ADDRESS(Pinfo_net_src,net_src)
 PINFO_GET_ADDRESS(Pinfo_net_dst,net_dst)
@@ -899,18 +1026,6 @@ PINFO_GET_ADDRESS(Pinfo_dst,dst)
 
 PINFO_GET_LIGHTUSERDATA(Pinfo_private_data, pinfo->ws_pinfo->private_data)
 
-static int Pinfo_visited(lua_State *L) {
-    Pinfo pinfo = checkPinfo(L,1);
-    if (!pinfo) return 0;
-    if (pinfo->expired) {
-        luaL_error(L,"expired_pinfo");
-        return 0;
-    }
-    lua_pushboolean(L,pinfo->ws_pinfo->fd->flags.visited);
-    return 1;
-}
-
-
 static int Pinfo_match(lua_State *L) {
     Pinfo pinfo = checkPinfo(L,1);
 
@@ -954,6 +1069,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,
@@ -968,7 +1116,8 @@ typedef enum {
     PARAM_CIRCUIT_ID,
     PARAM_DESEGMENT_LEN,
     PARAM_DESEGMENT_OFFSET,
-    PARAM_PORT_TYPE
+    PARAM_PORT_TYPE,
+    PARAM_ETHERTYPE
 } pinfo_param_type_t;
 
 static int pushnil_param(lua_State* L, packet_info* pinfo _U_, pinfo_param_type_t pt _U_ ) {
@@ -1042,6 +1191,9 @@ static int Pinfo_set_int(lua_State* L, packet_info* pinfo, pinfo_param_type_t pt
         case PARAM_DESEGMENT_OFFSET:
             pinfo->desegment_offset = (int)v;
             return 0;
+        case PARAM_ETHERTYPE:
+            pinfo->ethertype = (guint32)v;
+            return 0;
         default:
             g_assert(!"BUG: A bad parameter");
     }
@@ -1058,7 +1210,7 @@ typedef struct _pinfo_method_t {
 
 static int Pinfo_hi(lua_State *L) {
     Pinfo pinfo = checkPinfo(L,1);
-    Address addr = g_malloc(sizeof(address));
+    Address addr;
 
     if (!pinfo) return 0;
     if (pinfo->expired) {
@@ -1066,6 +1218,7 @@ static int Pinfo_hi(lua_State *L) {
         return 0;
     }
 
+    addr = g_malloc(sizeof(address));
     if (CMP_ADDRESS(&(pinfo->ws_pinfo->src), &(pinfo->ws_pinfo->dst) ) >= 0) {
         COPY_ADDRESS(addr, &(pinfo->ws_pinfo->src));
     } else {
@@ -1078,7 +1231,7 @@ static int Pinfo_hi(lua_State *L) {
 
 static int Pinfo_lo(lua_State *L) {
     Pinfo pinfo = checkPinfo(L,1);
-    Address addr = g_malloc(sizeof(address));
+    Address addr;
 
     if (!pinfo) return 0;
     if (pinfo->expired) {
@@ -1086,6 +1239,7 @@ static int Pinfo_lo(lua_State *L) {
         return 0;
     }
 
+    addr = g_malloc(sizeof(address));
     if (CMP_ADDRESS(&(pinfo->ws_pinfo->src), &(pinfo->ws_pinfo->dst) ) < 0) {
         COPY_ADDRESS(addr, &(pinfo->ws_pinfo->src));
     } else {
@@ -1183,6 +1337,24 @@ 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},
+
+       /* WSLUA_ATTRIBUTE Pinfo_fragmented RO If the protocol is only a fragment */
+    {"fragmented", Pinfo_fragmented, pushnil_param, PARAM_NONE},
+
+       /* WSLUA_ATTRIBUTE Pinfo_in_error_pkt RO If we're inside an error packet */
+    {"in_error_pkt", Pinfo_in_error_pkt, pushnil_param, PARAM_NONE},
+
+       /* WSLUA_ATTRIBUTE Pinfo_match_uint RO Matched uint for calling subdissector from table */
+    {"match_uint", Pinfo_match_uint, pushnil_param, PARAM_NONE },
+
+       /* WSLUA_ATTRIBUTE Pinfo_match_string RO Matched string for calling subdissector from table */
+    {"match_string", Pinfo_match_string, pushnil_param, PARAM_NONE },
+
     {NULL,NULL,NULL,PARAM_NONE}
 };
 
@@ -1260,7 +1432,7 @@ static int Pinfo_gc(lua_State* L) {
 
 }
 
-static const luaL_reg Pinfo_meta[] = {
+static const luaL_Reg Pinfo_meta[] = {
     {"__index", Pinfo_index},
     {"__newindex",Pinfo_setindex},
     {"__tostring", Pinfo_tostring},
@@ -1273,5 +1445,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;
 }