summaryrefslogtreecommitdiff
path: root/c-sources/pcap-monitor.c
diff options
context:
space:
mode:
authorWill Thompson <will@willthompson.co.uk>2020-05-17 09:44:40 +0100
committerWill Thompson <will@willthompson.co.uk>2020-06-05 09:24:02 +0100
commitdc19033ac72389f21f16d09445de266689a4af4c (patch)
tree932f8fb628d17d5fd260049d17e0c27a850247ba /c-sources/pcap-monitor.c
parent2b7de5136fbf9185f222de092afa99dc8e0ce1d7 (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.c77
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,