major capture engine rework: use two task model for EVERY capture mode

rework of the -b command line parameter (for Ethereal and Tethereal)

svn path=/trunk/; revision=13949
This commit is contained in:
Ulf Lamping 2005-03-28 00:19:02 +00:00
parent cb859703ca
commit 7e78ef354e
7 changed files with 154 additions and 41 deletions

View File

@ -72,7 +72,7 @@
#define O_BINARY 0
#endif
static gboolean normal_do_capture(capture_options *capture_opts, gboolean is_tempfile);
/*static gboolean normal_do_capture(capture_options *capture_opts, gboolean is_tempfile);*/
static void stop_capture_signal_handler(int signo);
@ -92,8 +92,16 @@ capture_open_output(capture_options *capture_opts, gboolean *is_tempfile) {
capfile_name = g_strdup(capture_opts->save_file);
if (capture_opts->multi_files_on) {
/* ringbuffer is enabled */
capture_opts->save_file_fd = ringbuf_init(capfile_name,
(capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0);
/* capture_opts->save_file_fd = ringbuf_init(capfile_name,
(capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0);*/
/* XXX - this is a hack, we need to find a way to move this whole function to capture_loop.c */
capture_opts->save_file_fd = -1;
if(capture_opts->save_file != NULL) {
g_free(capture_opts->save_file);
}
capture_opts->save_file = capfile_name;
*is_tempfile = FALSE;
return TRUE;
} else {
/* Try to open/create the specified file for use as a capture buffer. */
capture_opts->save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
@ -115,7 +123,7 @@ capture_open_output(capture_options *capture_opts, gboolean *is_tempfile) {
"could not be opened: %s.", capfile_name, strerror(errno));
} else {
if (capture_opts->multi_files_on) {
ringbuf_error_cleanup();
/* ringbuf_error_cleanup();*/
}
open_failure_alert_box(capfile_name, errno, TRUE);
}
@ -134,17 +142,19 @@ capture_open_output(capture_options *capture_opts, gboolean *is_tempfile) {
}
#if 0
/* close the output file (NOT the capture file) */
static void
capture_close_output(capture_options *capture_opts)
{
if (capture_opts->multi_files_on) {
ringbuf_free();
/* ringbuf_free();*/
} else {
g_free(capture_opts->save_file);
}
capture_opts->save_file = NULL;
}
#endif
/* Open a specified file, or create a temporary file, and start a capture
@ -173,17 +183,19 @@ do_capture(capture_options *capture_opts)
* If this is fixed, we could always use the sync mode, throwing away the
* normal mode completely and doing some more cleanup. */
/* if (TRUE) {*/
if (capture_opts->sync_mode) {
/* if (capture_opts->sync_mode) {*/
/* sync mode: do the capture in a child process */
ret = sync_pipe_do_capture(capture_opts, is_tempfile);
/* capture is still running */
cf_callback_invoke(cf_cb_live_capture_prepare, capture_opts);
#if 0
} else {
/* normal mode: do the capture synchronously */
cf_callback_invoke(cf_cb_live_capture_prepare, capture_opts);
ret = normal_do_capture(capture_opts, is_tempfile);
/* capture is finished here */
}
#endif
return ret;
}
@ -268,6 +280,7 @@ guint32 drops)
}
#if 0
/* start a normal capture session */
static gboolean
normal_do_capture(capture_options *capture_opts, gboolean is_tempfile)
@ -292,6 +305,7 @@ normal_do_capture(capture_options *capture_opts, gboolean is_tempfile)
capture_close_output(capture_opts);
return succeeded;
}
#endif
static void
@ -304,7 +318,7 @@ stop_capture_signal_handler(int signo _U_)
int
capture_child_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats)
{
gchar *err_msg;
/* gchar *err_msg;*/
g_assert(capture_opts->capture_child);
@ -316,6 +330,7 @@ capture_child_start(capture_options *capture_opts, gboolean *stats_known, struct
signal(SIGUSR1, stop_capture_signal_handler);
#endif
#if 0
/* parent must have send us a file descriptor for the opened output file */
if (capture_opts->save_file_fd == -1) {
/* send this to the standard output as something our parent
@ -325,6 +340,7 @@ capture_child_start(capture_options *capture_opts, gboolean *stats_known, struct
g_free(err_msg);
return FALSE;
}
#endif
return capture_loop_start(capture_opts, stats_known, stats);
}

View File

@ -1027,6 +1027,26 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
/* We haven't yet gotten the capture statistics. */
*stats_known = FALSE;
/*g_warning("capture_loop_start");
capture_opts_info(capture_opts);*/
/*_asm {int 3};*/
if (capture_opts->multi_files_on) {
/* ringbuffer is enabled */
capture_opts->save_file_fd = ringbuf_init(capture_opts->save_file,
(capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0);
if (capture_opts->save_file_fd == -1) {
ringbuf_error_cleanup();
goto error;
}
/* replace save_file by current ringbuffer filename */
if(capture_opts->save_file) {
g_free(capture_opts->save_file);
}
capture_opts->save_file = g_strdup(ringbuf_current_filename());
}
/* open the "input file" from network interface or capture pipe */
if (!capture_loop_open_input(capture_opts, &ld, errmsg, sizeof(errmsg))) {
@ -1123,6 +1143,9 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
if (cnd_file_duration) {
cnd_reset(cnd_file_duration);
}
if (capture_opts->capture_child) {
sync_pipe_filename_to_parent(capture_opts->save_file);
}
} else {
/* File switch failed: stop here */
ld.go = FALSE;
@ -1191,6 +1214,9 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
cnd_reset(cnd_file_duration);
if(cnd_autostop_size)
cnd_reset(cnd_autostop_size);
if (capture_opts->capture_child) {
sync_pipe_filename_to_parent(capture_opts->save_file);
}
} else {
/* File switch failed: stop here */
ld.go = FALSE;

View File

@ -85,6 +85,39 @@ capture_opts_init(capture_options *capture_opts, void *cfile)
capture_opts->fork_child = -1; /* invalid process handle */
}
/* debug only: print content of capture_opts to console */
void
capture_opts_info(capture_options *capture_opts) {
g_warning("CAPTURE OPTIONS :");
g_warning("File : %s", capture_opts->cf);
g_warning("Filter : %s", capture_opts->cfilter);
g_warning("Interface : %s", capture_opts->iface);
#ifdef _WIN32
g_warning("BufferSize : %u (MB)", capture_opts->buffer_size);
#endif
g_warning("SnapLen (%u): %u", capture_opts->has_snaplen, capture_opts->snaplen);
g_warning("Promisc : %u", capture_opts->promisc_mode);
g_warning("LinkType : %d", capture_opts->linktype);
g_warning("Child : %u", capture_opts->capture_child);
g_warning("SaveFile : %s", capture_opts->save_file);
g_warning("SaveFileFd : %d", capture_opts->save_file_fd);
g_warning("SyncMode : %u", capture_opts->sync_mode);
g_warning("ShowInfo : %u", capture_opts->show_info);
g_warning("QuitAfterCap : %u", capture_opts->quit_after_cap);
g_warning("MultiFilesOn : %u", capture_opts->multi_files_on);
g_warning("FileDuration (%u): %u", capture_opts->has_file_duration, capture_opts->file_duration);
g_warning("RingNumFiles (%u): %u", capture_opts->has_ring_num_files, capture_opts->ring_num_files);
g_warning("AutostopFiles (%u): %u", capture_opts->has_autostop_files, capture_opts->autostop_files);
g_warning("AutostopPackets (%u): %u", capture_opts->has_autostop_packets, capture_opts->autostop_packets);
g_warning("AutostopFilesize(%u): %u", capture_opts->has_autostop_filesize, capture_opts->autostop_filesize);
g_warning("AutostopDuration(%u): %u", capture_opts->has_autostop_duration, capture_opts->autostop_duration);
g_warning("ForkChild : %d", capture_opts->fork_child);
}
/*
* Given a string of the form "<autostop criterion>:<value>", as might appear
* as an argument to a "-a" option, parse it and set the criterion in
@ -148,18 +181,12 @@ get_ring_arguments(capture_options *capture_opts, const char *appname, const cha
gchar *p = NULL, *colonp;
colonp = strchr(arg, ':');
if (colonp != NULL) {
p = colonp;
*p++ = '\0';
}
capture_opts->ring_num_files =
get_natural_int(appname, arg, "number of ring buffer files");
if (colonp == NULL)
return TRUE;
p = colonp;
*p++ = '\0';
/*
* Skip over any white space (there probably won't be any, but
* as we allow it in the preferences file, we might as well
@ -177,9 +204,16 @@ get_ring_arguments(capture_options *capture_opts, const char *appname, const cha
return FALSE;
}
capture_opts->has_file_duration = TRUE;
capture_opts->file_duration = get_positive_int(appname, p,
"ring buffer duration");
if (strcmp(arg,"files") == 0) {
capture_opts->has_ring_num_files = TRUE;
capture_opts->ring_num_files = get_natural_int(appname, p, "number of ring buffer files");
} else if (strcmp(arg,"filesize") == 0) {
capture_opts->has_autostop_filesize = TRUE;
capture_opts->autostop_filesize = get_positive_int(appname, p, "ring buffer filesize");
} else if (strcmp(arg,"duration") == 0) {
capture_opts->has_file_duration = TRUE;
capture_opts->file_duration = get_positive_int(appname, p, "ring buffer duration");
}
*colonp = ':'; /* put the colon back */
return TRUE;
@ -202,7 +236,6 @@ capture_opts_add_opt(capture_options *capture_opts, const char *appname, int opt
break;
case 'b': /* Ringbuffer option */
capture_opts->multi_files_on = TRUE;
capture_opts->has_ring_num_files = TRUE;
if (get_ring_arguments(capture_opts, appname, optarg) == FALSE) {
fprintf(stderr, "%s: Invalid or unknown -b arg \"%s\"\n", appname, optarg);
exit(1);

View File

@ -221,7 +221,11 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
char *msg;
int err;
char ssnap[24];
char scount[24]; /* need a constant for len of numbers */
char scount[24]; /* need a constant for len of numbers */
char sfilesize[24]; /* need a constant for len of numbers */
char sfile_duration[24]; /* need a constant for len of numbers */
char sring_num_files[24]; /* need a constant for len of numbers */
char sautostop_files[24]; /* need a constant for len of numbers */
char sautostop_filesize[24]; /* need a constant for len of numbers */
char sautostop_duration[24]; /* need a constant for len of numbers */
char save_file_fd_str[24];
@ -239,6 +243,10 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
int sync_pipe[2]; /* pipes used to sync between instances */
/*g_warning("sync_pipe_do_capture");
capture_opts_info(capture_opts);*/
capture_opts->fork_child = -1;
/* Allocate the string pointer array with enough space for the
@ -260,12 +268,6 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
sprintf(save_file_fd_str,"%d",capture_opts->save_file_fd); /* in lieu of itoa */
argv = sync_pipe_add_arg(argv, &argc, save_file_fd_str);
if (capture_opts->has_autostop_packets) {
argv = sync_pipe_add_arg(argv, &argc, "-c");
sprintf(scount,"%d",capture_opts->autostop_packets);
argv = sync_pipe_add_arg(argv, &argc, scount);
}
if (capture_opts->has_snaplen) {
argv = sync_pipe_add_arg(argv, &argc, "-s");
sprintf(ssnap,"%d",capture_opts->snaplen);
@ -283,10 +285,42 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
argv = sync_pipe_add_arg(argv, &argc, ssnap);
}
if (capture_opts->has_autostop_filesize) {
argv = sync_pipe_add_arg(argv, &argc, "-a");
sprintf(sautostop_filesize,"filesize:%d",capture_opts->autostop_filesize);
argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
if(capture_opts->multi_files_on) {
if (capture_opts->has_autostop_filesize) {
argv = sync_pipe_add_arg(argv, &argc, "-b");
sprintf(sfilesize,"filesize:%d",capture_opts->autostop_filesize);
argv = sync_pipe_add_arg(argv, &argc, sfilesize);
}
if (capture_opts->has_file_duration) {
argv = sync_pipe_add_arg(argv, &argc, "-b");
sprintf(sfile_duration,"duration:%d",capture_opts->file_duration);
argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
}
if (capture_opts->has_ring_num_files) {
argv = sync_pipe_add_arg(argv, &argc, "-b");
sprintf(sring_num_files,"files:%d",capture_opts->ring_num_files);
argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
}
if (capture_opts->has_autostop_files) {
argv = sync_pipe_add_arg(argv, &argc, "-a");
sprintf(sautostop_files,"files:%d",capture_opts->autostop_files);
argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
}
} else {
if (capture_opts->has_autostop_filesize) {
argv = sync_pipe_add_arg(argv, &argc, "-a");
sprintf(sautostop_filesize,"filesize:%d",capture_opts->autostop_filesize);
argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
}
}
if (capture_opts->has_autostop_packets) {
argv = sync_pipe_add_arg(argv, &argc, "-c");
sprintf(scount,"%d",capture_opts->autostop_packets);
argv = sync_pipe_add_arg(argv, &argc, scount);
}
if (capture_opts->has_autostop_duration) {
@ -304,7 +338,6 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
#ifdef _WIN32
/* Create a pipe for the child process */
if(_pipe(sync_pipe, 512, O_BINARY) < 0) {
/* Couldn't create the pipe between parent and child. */
error = errno;
@ -402,7 +435,9 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
/* Close the save file FD, as we won't be using it - we'll be opening
it and reading the save file through Wiretap. */
close(capture_opts->save_file_fd);
if(capture_opts->save_file_fd != -1) {
close(capture_opts->save_file_fd);
}
if (capture_opts->fork_child == -1) {
/* We couldn't even create the child process. */
@ -676,10 +711,6 @@ sync_pipe_input_cb(gint source, gpointer user_data)
}
*r = '\0';
/* currently, both filenames must be equal */
/* (this will change, when multiple files together with sync_mode are captured) */
g_assert(strcmp(capture_opts->save_file, msg) == 0);
/* save the new filename */
if(capture_opts->save_file != NULL) {
g_free(capture_opts->save_file);

View File

@ -2070,12 +2070,12 @@ main(int argc, char *argv[])
fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
capture_opts->multi_files_on = FALSE;
}
if (capture_opts->sync_mode) {
/* if (capture_opts->sync_mode) {
fprintf(stderr, "ethereal: Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.\n");
capture_opts->multi_files_on = FALSE;
}
if (!capture_opts->has_autostop_filesize) {
fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n");
}*/
if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size or duration were specified.\n");
capture_opts->multi_files_on = FALSE;
}
}

View File

@ -232,6 +232,12 @@ ringbuf_init(const char *capfile_name, guint num_files)
return rb_data.fd;
}
const gchar *ringbuf_current_filename(void)
{
return rb_data.files[rb_data.curr_file_num % rb_data.num_files].name;
}
/*
* Calls wtap_dump_fdopen() for the current ringbuffer file
*/

View File

@ -38,6 +38,7 @@
#define RINGBUFFER_MAX_NUM_FILES 1024
int ringbuf_init(const char *capture_name, guint num_files);
const gchar *ringbuf_current_filename(void);
wtap_dumper* ringbuf_init_wtap_dump_fdopen(int filetype, int linktype,
int snaplen, int *err);
gboolean ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int *err);