forked from osmocom/wireshark
capture engine:
add a new feature to clear the currently captured packets and restart the capture with the previous parameters various code cleanup and minor bugfixes Win32: use millisecond resolution in capture_loop, to smooth screen update a bit (500ms instead of 1000ms) svn path=/trunk/; revision=14059
This commit is contained in:
parent
fcb74124f8
commit
7e9cedfed8
28
capture.c
28
capture.c
|
@ -102,6 +102,15 @@ capture_stop(capture_options *capture_opts)
|
|||
sync_pipe_stop(capture_opts);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
capture_clear(capture_options *capture_opts)
|
||||
{
|
||||
capture_opts->restart = TRUE;
|
||||
capture_stop(capture_opts);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
capture_kill_child(capture_options *capture_opts)
|
||||
{
|
||||
|
@ -267,6 +276,7 @@ capture_input_new_packets(capture_options *capture_opts, int to_read)
|
|||
file.
|
||||
|
||||
XXX - abort on a read error? */
|
||||
main_window_update();
|
||||
break;
|
||||
|
||||
case CF_READ_ABORTED:
|
||||
|
@ -325,8 +335,22 @@ capture_input_closed(capture_options *capture_opts)
|
|||
cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
|
||||
}
|
||||
|
||||
/* We're not doing a capture any more, so we don't have a save file. */
|
||||
if(capture_opts->save_file) {
|
||||
/* does the user wants to restart the current capture? */
|
||||
if(capture_opts->restart) {
|
||||
capture_opts->restart = FALSE;
|
||||
|
||||
unlink(capture_opts->save_file);
|
||||
|
||||
/* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */
|
||||
if(cf_is_tempfile(capture_opts->cf)) {
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
}
|
||||
|
||||
/* ... and start the capture again */
|
||||
capture_start(capture_opts);
|
||||
} else {
|
||||
/* We're not doing a capture any more, so we don't have a save file. */
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
}
|
||||
|
|
|
@ -53,9 +53,10 @@ typedef struct capture_options_tag {
|
|||
gchar *save_file; /**< the capture file name */
|
||||
|
||||
/* GUI related */
|
||||
gboolean real_time_mode;/**< Update list of packets in real time */
|
||||
gboolean show_info; /**< show the info dialog */
|
||||
gboolean real_time_mode; /**< Update list of packets in real time */
|
||||
gboolean show_info; /**< show the info dialog */
|
||||
gboolean quit_after_cap; /** Makes a "capture only mode". Implies -k */
|
||||
gboolean restart; /**< restart after closing is done */
|
||||
|
||||
/* multiple files (and ringbuffer) */
|
||||
gboolean multi_files_on; /**< TRUE if ring buffer in use */
|
||||
|
@ -106,6 +107,9 @@ extern gboolean capture_start(capture_options *capture_opts);
|
|||
/** Stop a capture session (usually from a menu item). */
|
||||
extern void capture_stop(capture_options *capture_opts);
|
||||
|
||||
/** Clear the current captured packets and start again. */
|
||||
extern void capture_clear(capture_options *capture_opts);
|
||||
|
||||
/** Terminate the capture child cleanly when exiting. */
|
||||
extern void capture_kill_child(capture_options *capture_opts);
|
||||
|
||||
|
|
|
@ -1037,6 +1037,11 @@ capture_loop_stop_signal_handler(int signo _U_)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define TIME_GET() GetTickCount()
|
||||
#else
|
||||
#define TIME_GET() time(NULL)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This needs to be static, so that the SIGUSR1 handler can clear the "go"
|
||||
|
@ -1144,7 +1149,6 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
update its windows to indicate that we have a live capture in
|
||||
progress. */
|
||||
fflush(wtap_dump_file(ld.wtap_pdh));
|
||||
sync_pipe_capstart_to_parent();
|
||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||
|
||||
/* initialize capture stop (and alike) conditions */
|
||||
|
@ -1175,8 +1179,8 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
}
|
||||
|
||||
/* init the time values */
|
||||
start_time = time(NULL);
|
||||
upd_time = time(NULL);
|
||||
start_time = TIME_GET();
|
||||
upd_time = TIME_GET();
|
||||
|
||||
/* WOW, everything is prepared! */
|
||||
/* please fasten your seat belts, we will enter now the actual capture loop */
|
||||
|
@ -1186,6 +1190,26 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
/* dispatch incoming packets */
|
||||
inpkts = capture_loop_dispatch(capture_opts, &ld, errmsg, sizeof(errmsg));
|
||||
|
||||
main_window_update();
|
||||
|
||||
#ifdef _WIN32
|
||||
/* some news from our parent (signal pipe)? -> just stop the capture */
|
||||
{
|
||||
HANDLE handle;
|
||||
DWORD avail = 0;
|
||||
gboolean result;
|
||||
|
||||
|
||||
handle = (HANDLE) _get_osfhandle (0);
|
||||
result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
|
||||
|
||||
if(!result || avail > 0) {
|
||||
ld.go = FALSE;
|
||||
/*g_warning("loop closing");*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (inpkts > 0) {
|
||||
ld.packets_sync_pipe += inpkts;
|
||||
|
||||
|
@ -1223,9 +1247,13 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
} /* inpkts */
|
||||
|
||||
/* Only update once a second so as not to overload slow displays */
|
||||
cur_time = time(NULL);
|
||||
if (cur_time > upd_time) {
|
||||
upd_time = cur_time;
|
||||
cur_time = TIME_GET();
|
||||
#ifdef _WIN32
|
||||
if ( (cur_time - upd_time) > 500) {
|
||||
#else
|
||||
if (cur_time - upd_time > 0) {
|
||||
#endif
|
||||
upd_time = cur_time;
|
||||
|
||||
/*if (pcap_stats(pch, stats) >= 0) {
|
||||
*stats_known = TRUE;
|
||||
|
@ -1234,29 +1262,15 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
/* calculate and display running time */
|
||||
if(capture_opts->show_info) {
|
||||
cur_time -= start_time;
|
||||
#ifdef _WIN32
|
||||
capture_ui.running_time = cur_time / 1000;
|
||||
#else
|
||||
capture_ui.running_time = cur_time;
|
||||
#endif
|
||||
capture_ui.new_packets = ld.packets_sync_pipe;
|
||||
capture_info_update(&capture_ui);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* some news from our parent (signal pipe)? -> just stop the capture */
|
||||
{
|
||||
HANDLE handle;
|
||||
DWORD avail = 0;
|
||||
gboolean result;
|
||||
|
||||
|
||||
handle = (HANDLE) _get_osfhandle (0);
|
||||
result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
|
||||
|
||||
if(!result || avail > 0) {
|
||||
ld.go = FALSE;
|
||||
/*g_warning("loop closing");*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Let the parent process know. */
|
||||
if (ld.packets_sync_pipe) {
|
||||
/* do sync here */
|
||||
|
|
|
@ -63,6 +63,7 @@ capture_opts_init(capture_options *capture_opts, void *cfile)
|
|||
capture_opts->real_time_mode = TRUE;
|
||||
capture_opts->show_info = TRUE;
|
||||
capture_opts->quit_after_cap = FALSE;
|
||||
capture_opts->restart = FALSE;
|
||||
|
||||
capture_opts->multi_files_on = FALSE;
|
||||
capture_opts->has_file_duration = FALSE;
|
||||
|
|
|
@ -118,12 +118,11 @@ static void sync_pipe_wait_for_child(capture_options *capture_opts, gboolean alw
|
|||
/*
|
||||
* Indications sent out on the sync pipe.
|
||||
*/
|
||||
#define SP_CAPSTART 'S' /* capture start message */
|
||||
#define SP_CAPQUIT 'Q' /* capture quit message */
|
||||
#define SP_PACKET_COUNT 'P' /* count of packets captured since last message */
|
||||
#define SP_ERROR_MSG 'E' /* error message */
|
||||
#define SP_DROPS 'D' /* count of packets dropped in capture */
|
||||
#define SP_FILE 'F' /* the name of the recently opened file */
|
||||
#define SP_ERROR_MSG 'E' /* error message */
|
||||
#define SP_PACKET_COUNT 'P' /* count of packets captured since last message */
|
||||
#define SP_DROPS 'D' /* count of packets dropped in capture */
|
||||
#define SP_QUIT 'Q' /* capture quit message (from parent to child) */
|
||||
|
||||
|
||||
/* write a message to the recipient pipe in the standard format
|
||||
|
@ -132,7 +131,7 @@ static void sync_pipe_wait_for_child(capture_options *capture_opts, gboolean alw
|
|||
static void
|
||||
pipe_write_block(int pipe, char indicator, int len, const char *msg)
|
||||
{
|
||||
char lenbuf[SP_DECISIZE+1+1];
|
||||
char lenbuf[3+1+1]; /* 3 digit len + indicator + zero terminator */
|
||||
int ret;
|
||||
|
||||
/*g_warning("write %d enter", pipe);*/
|
||||
|
@ -140,17 +139,21 @@ pipe_write_block(int pipe, char indicator, int len, const char *msg)
|
|||
g_assert(len < 1000);
|
||||
g_assert(indicator < '0' || indicator > '9');
|
||||
|
||||
/* write header (3 digit len + indicator + zero terminator) */
|
||||
/* write header (3 digit len + indicator) */
|
||||
g_snprintf(lenbuf, 5, "%03u%c", len, indicator);
|
||||
|
||||
ret = write(pipe, lenbuf, strlen(lenbuf));
|
||||
g_assert(ret != -1);
|
||||
if(ret == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* write value (if we have one) */
|
||||
if(len) {
|
||||
/*g_warning("write %d indicator: %c value len: %u msg: %s", pipe, indicator, len, msg);*/
|
||||
ret = write(pipe, msg, len);
|
||||
g_assert(ret != -1);
|
||||
if(ret == -1) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/*g_warning("write %d indicator: %c no value", pipe, indicator);*/
|
||||
}
|
||||
|
@ -221,23 +224,13 @@ pipe_read_block(int pipe, char *indicator, int len, char *msg) {
|
|||
return len + 4;
|
||||
}
|
||||
|
||||
void
|
||||
sync_pipe_capstart_to_parent(void)
|
||||
{
|
||||
/* static const char capstart_msg = SP_CAPSTART;
|
||||
|
||||
write(1, &capstart_msg, 1);*/
|
||||
|
||||
pipe_write_block(1, SP_CAPSTART, 0, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
sync_pipe_packet_count_to_parent(int packet_count)
|
||||
{
|
||||
char tmp[SP_DECISIZE+1+1];
|
||||
|
||||
|
||||
g_snprintf(tmp, SP_DECISIZE, "%d", packet_count);
|
||||
g_snprintf(tmp, sizeof(tmp), "%d", packet_count);
|
||||
|
||||
pipe_write_block(1, SP_PACKET_COUNT, strlen(tmp)+1, tmp);
|
||||
}
|
||||
|
@ -260,7 +253,7 @@ sync_pipe_drops_to_parent(int drops)
|
|||
char tmp[SP_DECISIZE+1+1];
|
||||
|
||||
|
||||
g_snprintf(tmp, SP_DROPS, "%d", drops);
|
||||
g_snprintf(tmp, sizeof(tmp), "%d", drops);
|
||||
|
||||
pipe_write_block(1, SP_DROPS, strlen(tmp)+1, tmp);
|
||||
}
|
||||
|
@ -269,11 +262,11 @@ sync_pipe_drops_to_parent(int drops)
|
|||
#ifdef _WIN32
|
||||
|
||||
static void
|
||||
signal_pipe_capend_to_child(capture_options *capture_opts)
|
||||
signal_pipe_capquit_to_child(capture_options *capture_opts)
|
||||
{
|
||||
|
||||
|
||||
pipe_write_block(capture_opts->signal_pipe_fd, SP_CAPQUIT, 0, NULL);
|
||||
pipe_write_block(capture_opts->signal_pipe_fd, SP_QUIT, 0, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -603,37 +596,32 @@ sync_pipe_input_cb(gint source, gpointer user_data)
|
|||
}
|
||||
|
||||
switch(indicator) {
|
||||
case(SP_CAPSTART):
|
||||
break;
|
||||
case SP_FILE:
|
||||
if(!capture_input_new_file(capture_opts, buffer)) {
|
||||
/* We weren't able to open the new capture file; user has been
|
||||
alerted. Close the sync pipe. */
|
||||
/* XXX - is it safe to close the pipe inside this callback? */
|
||||
close(source);
|
||||
|
||||
/* the child has send us a filename which we couldn't open.
|
||||
this probably means, the child is creating files faster than we can handle it.
|
||||
this should only be the case for very fast file switches
|
||||
we can't do much more than telling the child to stop
|
||||
(this is the emergency brake if user e.g. wants to switch files every second) */
|
||||
sync_pipe_stop(capture_opts);
|
||||
}
|
||||
break;
|
||||
case SP_PACKET_COUNT:
|
||||
nread = atoi(buffer);
|
||||
capture_input_new_packets(capture_opts, nread);
|
||||
break;
|
||||
case SP_ERROR_MSG:
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, buffer);
|
||||
break;
|
||||
case SP_DROPS:
|
||||
cf_set_drops_known(capture_opts->cf, TRUE);
|
||||
cf_set_drops(capture_opts->cf, atoi(buffer));
|
||||
break;
|
||||
case SP_ERROR_MSG:
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, buffer);
|
||||
break;
|
||||
case SP_FILE:
|
||||
if(!capture_input_new_file(capture_opts, buffer)) {
|
||||
/* We weren't able to open the new capture file; user has been
|
||||
alerted. Close the sync pipe. */
|
||||
|
||||
/* XXX - how to kill things here ? */
|
||||
/* XXX - is it safe to close the pipe inside this callback? */
|
||||
close(source);
|
||||
|
||||
/* the child has send us a filename which we couldn't open.
|
||||
this probably means, the child is creating files faster than we can handle it.
|
||||
this should only be the case for very fast file switches
|
||||
we can't do much more than telling the child to stop
|
||||
(this is the emergency brake if user e.g. wants to switch files every second) */
|
||||
sync_pipe_stop(capture_opts);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
@ -803,7 +791,7 @@ sync_pipe_stop(capture_options *capture_opts)
|
|||
#else
|
||||
/* Win32 doesn't have the kill() system call, use the special signal pipe
|
||||
instead to close the capture child gracefully. */
|
||||
signal_pipe_capend_to_child(capture_opts);
|
||||
signal_pipe_capquit_to_child(capture_opts);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,10 +58,6 @@ extern void
|
|||
sync_pipe_kill(capture_options *capture_opts);
|
||||
|
||||
|
||||
/** the child will immediately start capturing, notify the parent */
|
||||
extern void
|
||||
sync_pipe_capstart_to_parent(void);
|
||||
|
||||
/** the child has opened a new capture file, notify the parent */
|
||||
extern void
|
||||
sync_pipe_filename_to_parent(const char *filename);
|
||||
|
|
|
@ -126,6 +126,12 @@ capture_stop_cb(GtkWidget *w _U_, gpointer d _U_)
|
|||
capture_stop(capture_opts);
|
||||
}
|
||||
|
||||
void
|
||||
capture_clear_cb(GtkWidget *w _U_, gpointer d _U_)
|
||||
{
|
||||
capture_clear(capture_opts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep a static pointer to the current "Capture Options" window, if
|
||||
* any, so that if somebody tries to do "Capture:Start" while there's
|
||||
|
|
|
@ -45,6 +45,13 @@ void capture_prep_cb(GtkWidget *widget, gpointer data);
|
|||
*/
|
||||
void capture_stop_cb(GtkWidget *widget, gpointer data);
|
||||
|
||||
/** User requested capture clear by menu or toolbar.
|
||||
*
|
||||
* @param widget parent widget (unused)
|
||||
* @param data unused
|
||||
*/
|
||||
void capture_clear_cb(GtkWidget *widget, gpointer data);
|
||||
|
||||
/** Create the "Capture Options" dialog box.
|
||||
*/
|
||||
void capture_prep(void);
|
||||
|
|
|
@ -300,9 +300,11 @@ static GtkItemFactoryEntry menu_items[] =
|
|||
capture_prep_cb, 0, ETHEREAL_STOCK_CAPTURE_START),
|
||||
ITEM_FACTORY_STOCK_ENTRY("/Capture/S_top", "<control>E", capture_stop_cb,
|
||||
0, GTK_STOCK_STOP),
|
||||
ITEM_FACTORY_STOCK_ENTRY("/Capture/_Clear", NULL, capture_clear_cb,
|
||||
0, GTK_STOCK_CLEAR),
|
||||
ITEM_FACTORY_ENTRY("/Capture/_Interfaces...", NULL,
|
||||
capture_if_cb, 0, NULL, NULL),
|
||||
ITEM_FACTORY_STOCK_ENTRY("/Capture/_Capture Filters...", NULL, cfilter_dialog_cb,
|
||||
ITEM_FACTORY_STOCK_ENTRY("/Capture/Capture _Filters...", NULL, cfilter_dialog_cb,
|
||||
0, ETHEREAL_STOCK_CAPTURE_FILTER),
|
||||
#endif /* HAVE_LIBPCAP */
|
||||
ITEM_FACTORY_ENTRY("/_Analyze", NULL, NULL, 0, "<Branch>", NULL),
|
||||
|
@ -566,6 +568,7 @@ menus_init(void) {
|
|||
set_menus_for_captured_packets(FALSE);
|
||||
set_menus_for_selected_packet(&cfile);
|
||||
set_menus_for_selected_tree_row(&cfile);
|
||||
set_menus_for_capture_in_progress(FALSE);
|
||||
|
||||
/* init with an empty recent files list */
|
||||
clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
|
||||
|
@ -1538,6 +1541,8 @@ set_menus_for_capture_in_progress(gboolean capture_in_progress)
|
|||
!capture_in_progress);
|
||||
set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
|
||||
capture_in_progress);
|
||||
set_menu_sensitivity(main_menu_factory, "/Capture/Clear",
|
||||
capture_in_progress);
|
||||
set_toolbar_for_capture_in_progress(capture_in_progress);
|
||||
|
||||
set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
|
||||
|
|
|
@ -117,7 +117,7 @@
|
|||
static gboolean toolbar_init = FALSE;
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
static GtkWidget *new_button, *stop_button;
|
||||
static GtkWidget *new_button, *stop_button, *clear_button;
|
||||
static GtkWidget *capture_filter_button;
|
||||
#endif /* HAVE_LIBPCAP */
|
||||
static GtkWidget *open_button, *save_button, *save_as_button, *close_button, *reload_button;
|
||||
|
@ -283,13 +283,15 @@ void set_toolbar_for_capture_in_progress(gboolean capture_in_progress) {
|
|||
if (toolbar_init) {
|
||||
#ifdef HAVE_LIBPCAP
|
||||
gtk_widget_set_sensitive(new_button, !capture_in_progress);
|
||||
if (capture_in_progress) {
|
||||
gtk_widget_set_sensitive(stop_button, capture_in_progress);
|
||||
gtk_widget_set_sensitive(clear_button, capture_in_progress);
|
||||
/*if (capture_in_progress) {
|
||||
gtk_widget_hide(new_button);
|
||||
gtk_widget_show(stop_button);
|
||||
} else {
|
||||
gtk_widget_show(new_button);
|
||||
gtk_widget_hide(stop_button);
|
||||
}
|
||||
}*/
|
||||
#endif /* HAVE_LIBPCAP */
|
||||
gtk_widget_set_sensitive(open_button, !capture_in_progress);
|
||||
}
|
||||
|
@ -391,13 +393,12 @@ toolbar_new(void)
|
|||
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
/* either start OR stop button can be valid at a time, so no space
|
||||
* between them is needed here (stop button is hidden by default) */
|
||||
|
||||
toolbar_item(new_button, window, main_tb,
|
||||
ETHEREAL_STOCK_CAPTURE_START, "Start a new live capture...", capture_24_xpm, capture_prep_cb, NULL);
|
||||
toolbar_item(stop_button, window, main_tb,
|
||||
GTK_STOCK_STOP, "Stop the running live capture", stock_stop_24_xpm, capture_stop_cb, NULL);
|
||||
toolbar_item(clear_button, window, main_tb,
|
||||
GTK_STOCK_CLEAR, "Clear the captured packets", stock_clear_24_xpm, capture_clear_cb, NULL);
|
||||
toolbar_append_separator(main_tb);
|
||||
#endif /* HAVE_LIBPCAP */
|
||||
|
||||
|
|
Loading…
Reference in New Issue