diff options
author | Will Thompson <will@willthompson.co.uk> | 2020-05-17 09:44:40 +0100 |
---|---|---|
committer | Will Thompson <will@willthompson.co.uk> | 2020-06-05 09:24:02 +0100 |
commit | dc19033ac72389f21f16d09445de266689a4af4c (patch) | |
tree | 932f8fb628d17d5fd260049d17e0c27a850247ba /c-sources/pcap-monitor.c | |
parent | 2b7de5136fbf9185f222de092afa99dc8e0ce1d7 (diff) |
monitor: Use tee to save pcap stream
Previously, Bustle read directly from dbus-monitor, parsed the pcap
stream, then reserialized it back to a file.
dbus-monitor → bustle → UI
↓
file
Instead, use tee between dbus-monitor and Bustle to write the raw pcap
stream to disk:
dbus-monitor → tee → bustle
↓
file
This makes the code in Bustle quite a bit simpler.
Diffstat (limited to 'c-sources/pcap-monitor.c')
-rw-r--r-- | c-sources/pcap-monitor.c | 77 |
1 files changed, 34 insertions, 43 deletions
diff --git a/c-sources/pcap-monitor.c b/c-sources/pcap-monitor.c index cb1d272..9ecba12 100644 --- a/c-sources/pcap-monitor.c +++ b/c-sources/pcap-monitor.c @@ -101,13 +101,12 @@ typedef struct _BustlePcapMonitor { GSubprocess *dbus_monitor; /* If >= 0, master side of controlling terminal for dbus_monitor */ int pt_master; - GSource *dbus_monitor_source; + GSubprocess *tee_proc; + GSource *tee_source; BustlePcapReader *reader; /* output */ gchar *filename; - pcap_t *pcap_out; - pcap_dumper_t *dumper; /* errors */ GError *pcap_error; @@ -208,16 +207,6 @@ bustle_pcap_monitor_set_property ( } static void -close_dump (BustlePcapMonitor *self) -{ - if (self->dumper != NULL) - pcap_dump_flush (self->dumper); - - g_clear_pointer (&self->dumper, pcap_dump_close); - g_clear_pointer (&self->pcap_out, pcap_close); -} - -static void bustle_pcap_monitor_dispose (GObject *object) { BustlePcapMonitor *self = BUSTLE_PCAP_MONITOR (object); @@ -231,12 +220,11 @@ bustle_pcap_monitor_dispose (GObject *object) } g_clear_object (&self->cancellable); - g_clear_pointer (&self->dbus_monitor_source, g_source_destroy); + g_clear_pointer (&self->tee_source, g_source_destroy); + g_clear_object (&self->tee_proc); g_clear_object (&self->reader); g_clear_object (&self->dbus_monitor); - close_dump (self); - if (parent_class->dispose != NULL) parent_class->dispose (object); } @@ -409,7 +397,6 @@ handle_error (BustlePcapMonitor *self) } self->state = STATE_STOPPED; - close_dump (self); g_debug ("%s: emitting ::stopped(%s, %d, %s)", G_STRFUNC, g_quark_to_string (error->domain), error->code, error->message); @@ -657,7 +644,7 @@ start_pcap ( gint stdout_fd = -1; FILE *dbus_monitor_filep = NULL; - stdout_pipe = g_subprocess_get_stdout_pipe (self->dbus_monitor); + stdout_pipe = g_subprocess_get_stdout_pipe (self->tee_proc); g_return_val_if_fail (stdout_pipe != NULL, FALSE); stdout_fd = g_unix_input_stream_get_fd (G_UNIX_INPUT_STREAM (stdout_pipe)); @@ -718,11 +705,6 @@ read_one ( g_signal_emit (self, signals[SIG_MESSAGE_LOGGED], 0, hdr->ts.tv_sec, hdr->ts.tv_usec, blob, hdr->caplen, message); - /* cast necessary because pcap_dump has a type matching the callback - * argument to pcap_loop() - * TODO don't block - */ - pcap_dump ((u_char *) self->dumper, hdr, blob); return TRUE; } } @@ -924,6 +906,27 @@ spawn_monitor (BustlePcapMonitor *self, return child; } +static GSubprocess * +spawn_tee (BustlePcapMonitor *self, + GError **error) +{ + g_autoptr(GSubprocessLauncher) launcher = + g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE); + GInputStream *stdout_pipe = NULL; + gint stdout_fd = -1; + + stdout_pipe = g_subprocess_get_stdout_pipe (self->dbus_monitor); + g_return_val_if_fail (stdout_pipe != NULL, FALSE); + + stdout_fd = g_unix_input_stream_get_fd (G_UNIX_INPUT_STREAM (stdout_pipe)); + g_return_val_if_fail (stdout_fd >= 0, FALSE); + + g_subprocess_launcher_take_stdin_fd (launcher, stdout_fd); + + return g_subprocess_launcher_spawn (launcher, error, + "tee", self->filename, NULL); +} + static gboolean initable_init ( GInitable *initable, @@ -950,36 +953,24 @@ initable_init ( G_CALLBACK (cancellable_cancelled_cb), self, NULL); - self->pcap_out = pcap_open_dead (DLT_DBUS, 1 << 27); - if (self->pcap_out == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "pcap_open_dead failed. wtf"); - return FALSE; - } - - self->dumper = pcap_dump_open (self->pcap_out, self->filename); - if (self->dumper == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't open target file %s", pcap_geterr (self->pcap_out)); - return FALSE; - } - self->dbus_monitor = spawn_monitor (self, (const char * const *) argv, error); if (self->dbus_monitor == NULL) return FALSE; - stdout_pipe = g_subprocess_get_stdout_pipe (self->dbus_monitor); + self->tee_proc = spawn_tee (self, error); + if (self->tee_proc == NULL) + return FALSE; + + stdout_pipe = g_subprocess_get_stdout_pipe (self->tee_proc); g_return_val_if_fail (stdout_pipe != NULL, FALSE); g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (stdout_pipe), FALSE); g_return_val_if_fail (G_IS_UNIX_INPUT_STREAM (stdout_pipe), FALSE); - self->dbus_monitor_source = g_pollable_input_stream_create_source ( + self->tee_source = g_pollable_input_stream_create_source ( G_POLLABLE_INPUT_STREAM (stdout_pipe), self->cancellable); - g_source_set_callback (self->dbus_monitor_source, + g_source_set_callback (self->tee_source, (GSourceFunc) dbus_monitor_readable, self, NULL); - g_source_attach (self->dbus_monitor_source, NULL); + g_source_attach (self->tee_source, NULL); g_subprocess_wait_check_async ( self->dbus_monitor, |