HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / wslua / wslua_listener.c
blob1406da39d44c75eddeec8c6285b45e103485975b
1 /*
2 * wslua_listener.c
4 * Wireshark's interface to the Lua Programming Language
6 * Implementation of tap Listeners
8 * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
10 * $Id$
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include "config.h"
33 #include <epan/emem.h>
35 /* WSLUA_MODULE Listener Post-dissection packet analysis */
37 #include "wslua.h"
39 WSLUA_CLASS_DEFINE(Listener,NOP,NOP);
41 A Listener, is called once for every packet that matches a certain filter or has a certain tap.
42 It can read the tree, the packet's Tvb eventually the tapped data but it cannot
43 add elements to the tree.
46 static int tap_packet_cb_error_handler(lua_State* L) {
47 const gchar* error = lua_tostring(L,1);
48 static gchar* last_error = NULL;
49 static int repeated = 0;
50 static int next = 2;
51 const gchar* where = (lua_pinfo) ?
53 ep_strdup_printf("Lua: on packet %i Error During execution of Listener Packet Callback",lua_pinfo->fd->num) :
54 ep_strdup_printf("Lua: Error During execution of Listener Packet Callback") ;
56 /* show the error the 1st, 3rd, 5th, 9th, 17th, 33th... time it appears to avoid window flooding */
57 /* XXX the last series of identical errors won't be shown (the user however gets at least one message) */
59 if (! last_error) {
60 report_failure("%s:\n%s",where,error);
61 last_error = g_strdup(error);
62 repeated = 0;
63 next = 2;
64 return 0;
67 if (g_str_equal(last_error,error) ) {
68 repeated++;
69 if ( repeated == next ) {
70 report_failure("%s happened %i times:\n %s",where,repeated,error);
71 next *= 2;
73 } else {
74 report_failure("%s happened %i times:\n %s",where,repeated,last_error);
75 g_free(last_error);
76 last_error = g_strdup(error);
77 repeated = 0;
78 next = 2;
79 report_failure("%s:\n %s",where,error);
82 return 0;
86 static int lua_tap_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *data) {
87 Listener tap = (Listener)tapdata;
88 int retval = 0;
90 if (tap->packet_ref == LUA_NOREF) return 0;
92 lua_settop(tap->L,0);
94 lua_pushcfunction(tap->L,tap_packet_cb_error_handler);
95 lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->packet_ref);
97 push_Pinfo(tap->L, pinfo);
98 push_Tvb(tap->L, edt->tvb);
100 if (tap->extractor) {
101 tap->extractor(tap->L,data);
102 } else {
103 lua_pushnil(tap->L);
106 lua_pinfo = pinfo;
107 lua_tvb = edt->tvb;
108 lua_tree = (struct _wslua_treeitem *)g_malloc(sizeof(struct _wslua_treeitem));
109 lua_tree->tree = edt->tree;
110 lua_tree->item = NULL;
111 lua_tree->expired = FALSE;
113 switch ( lua_pcall(tap->L,3,1,1) ) {
114 case 0:
115 retval = luaL_optint(tap->L,-1,1);
116 break;
117 case LUA_ERRRUN:
118 break;
119 case LUA_ERRMEM:
120 g_warning("Memory alloc error while calling listener tap callback packet");
121 break;
122 default:
123 g_assert_not_reached();
124 break;
127 clear_outstanding_Pinfo();
128 clear_outstanding_Tvb();
130 lua_pinfo = NULL;
131 lua_tvb = NULL;
132 lua_tree = NULL;
134 return retval;
137 static int tap_reset_cb_error_handler(lua_State* L) {
138 const gchar* error = lua_tostring(L,1);
139 report_failure("Lua: Error During execution of Listener init Callback:\n %s",error);
140 return 1;
143 static void lua_tap_reset(void *tapdata) {
144 Listener tap = (Listener)tapdata;
146 if (tap->init_ref == LUA_NOREF) return;
148 lua_pushcfunction(tap->L,tap_reset_cb_error_handler);
149 lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->init_ref);
151 switch ( lua_pcall(tap->L,0,0,1) ) {
152 case 0:
153 break;
154 case LUA_ERRRUN:
155 g_warning("Runtime error while calling a listener's init()");
156 break;
157 case LUA_ERRMEM:
158 g_warning("Memory alloc error while calling a listener's init()");
159 break;
160 default:
161 g_assert_not_reached();
162 break;
166 static void lua_tap_draw(void *tapdata) {
167 Listener tap = (Listener)tapdata;
168 const gchar* error;
169 if (tap->draw_ref == LUA_NOREF) return;
171 lua_pushcfunction(tap->L,tap_reset_cb_error_handler);
172 lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->draw_ref);
174 switch ( lua_pcall(tap->L,0,0,1) ) {
175 case 0:
176 /* OK */
177 break;
178 case LUA_ERRRUN:
179 error = lua_tostring(tap->L,-1);
180 g_warning("Runtime error while calling a listener's draw(): %s",error);
181 break;
182 case LUA_ERRMEM:
183 g_warning("Memory alloc error while calling a listener's draw()");
184 break;
185 default:
186 g_assert_not_reached();
187 break;
191 WSLUA_CONSTRUCTOR Listener_new(lua_State* L) {
192 /* Creates a new Listener listener */
193 #define WSLUA_OPTARG_Listener_new_TAP 1 /* The name of this tap */
194 #define WSLUA_OPTARG_Listener_new_FILTER 2 /* A filter that when matches the tap.packet function gets called (use nil to be called for every packet) */
196 const gchar* tap_type = luaL_optstring(L,WSLUA_OPTARG_Listener_new_TAP,"frame");
197 const gchar* filter = luaL_optstring(L,WSLUA_OPTARG_Listener_new_FILTER,NULL);
198 Listener tap;
199 GString* error;
201 tap = (Listener)g_malloc(sizeof(struct _wslua_tap));
203 tap->name = g_strdup(tap_type);
204 tap->filter = filter ? g_strdup(filter) : NULL;
205 tap->extractor = wslua_get_tap_extractor(tap_type);
206 tap->L = L;
207 tap->packet_ref = LUA_NOREF;
208 tap->draw_ref = LUA_NOREF;
209 tap->init_ref = LUA_NOREF;
212 * XXX - do all Lua taps require the protocol tree? If not, it might
213 * be useful to have a way to indicate whether any do.
215 * XXX - do any Lua taps require the columns? If so, we either need
216 * to request them for this tap, or do so if any Lua taps require them.
218 error = register_tap_listener(tap_type, tap, tap->filter, TL_REQUIRES_PROTO_TREE, lua_tap_reset, lua_tap_packet, lua_tap_draw);
220 if (error) {
221 g_free(tap->filter);
222 g_free(tap->name);
223 g_free(tap);
224 /* WSLUA_ERROR(new_tap,"tap registration error"); */
225 luaL_error(L,"Error while registering tap:\n%s",error->str);
226 g_string_free(error,TRUE); /* XXX LEAK? */
229 pushListener(L,tap);
230 WSLUA_RETURN(1); /* The newly created Listener listener object */
233 WSLUA_METHOD Listener_remove(lua_State* L) {
234 /* Removes a tap listener */
235 Listener tap = checkListener(L,1);
237 if (!tap) return 0;
239 remove_tap_listener(tap);
241 return 0;
244 WSLUA_METAMETHOD Listener__tostring(lua_State* L) {
245 /* Generates a string of debug info for the tap listener */
246 Listener tap = checkListener(L,1);
247 gchar* str;
249 if (!tap) return 0;
251 str = ep_strdup_printf("Listener(%s) filter: %s",tap->name, tap->filter ? tap->filter : "NONE");
252 lua_pushstring(L,str);
254 return 1;
258 static int Listener__newindex(lua_State* L) {
259 /* WSLUA_ATTRIBUTE Listener_packet WO A function that will be called once every packet matches the Listener listener filter.
261 function tap.packet(pinfo,tvb,tapinfo) ... end
262 Note: tapinfo is a table of info based on the Listener's type, or nil.
264 /* WSLUA_ATTRIBUTE Listener_draw WO A function that will be called once every few seconds to redraw the gui objects;
265 in tshark this funtion is called only at the very end of the capture file.
267 function tap.draw() ... end
269 /* WSLUA_ATTRIBUTE Listener_reset WO A function that will be called at the end of the capture run.
271 function tap.reset() ... end
273 Listener tap = shiftListener(L,1);
274 const gchar* idx = lua_shiftstring(L,1);
275 int* refp = NULL;
277 if (!idx) return 0;
279 if (g_str_equal(idx,"packet")) {
280 refp = &(tap->packet_ref);
281 } else if (g_str_equal(idx,"draw")) {
282 refp = &(tap->draw_ref);
283 } else if (g_str_equal(idx,"reset")) {
284 refp = &(tap->init_ref);
285 } else {
286 luaL_error(L,"No such attribute `%s' for a tap",idx);
287 return 0;
290 if (! lua_isfunction(L,1)) {
291 luaL_error(L,"Listener's attribute `%s' must be a function");
292 return 0;
295 lua_pushvalue(L, 1);
296 *refp = luaL_ref(L, LUA_REGISTRYINDEX);
298 return 0;
301 static int Listener__gc(lua_State* L _U_) {
302 /* do NOT free Listener, it's never free'd */
303 return 0;
306 static const luaL_Reg Listener_methods[] = {
307 {"new", Listener_new},
308 {"remove", Listener_remove},
309 { NULL, NULL }
312 static const luaL_Reg Listener_meta[] = {
313 {"__tostring", Listener__tostring},
314 {"__newindex", Listener__newindex},
315 { NULL, NULL }
318 int Listener_register(lua_State* L) {
319 wslua_set_tap_enums(L);
320 WSLUA_REGISTER_CLASS(Listener);
321 return 1;