aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremias Stotter <jeremias@stotter.eu>2023-11-22 02:50:23 +0100
committerJeremias Stotter <jeremias@stotter.eu>2023-11-22 02:50:23 +0100
commite9a47d2847a4b65e2d59bdd1b68f38235d45265a (patch)
tree56cdaa166fa670b0488c2734dfdff00a932f5cde
parent270b6d889016f05a75205abf326d125bb69d5603 (diff)
downloadnetwork-simulator-e9a47d2847a4b65e2d59bdd1b68f38235d45265a.tar.gz
network-simulator-e9a47d2847a4b65e2d59bdd1b68f38235d45265a.tar.bz2
network-simulator-e9a47d2847a4b65e2d59bdd1b68f38235d45265a.zip
Add ability to export to pcap
-rw-r--r--gui.c111
1 files changed, 84 insertions, 27 deletions
diff --git a/gui.c b/gui.c
index f1a9ff0..e3d9c88 100644
--- a/gui.c
+++ b/gui.c
@@ -80,7 +80,7 @@ GtkWidget* mode_label = NULL;
GtkWidget* zoom_label = NULL;
GtkWidget* device_view = NULL;
GtkWidget* connection_view = NULL;
-GtkWidget* packet_tree_scroll = NULL;
+GtkWidget* packet_list_box = NULL;
GtkWidget* rewind_button = NULL;
GtkWidget* play_button = NULL;
GtkWidget* forward_button = NULL;
@@ -521,7 +521,7 @@ void toggle_fast_mode(GtkWidget* self, gpointer data) {
NULL
);
fastmode = true;
- gtk_widget_set_visible(packet_tree_scroll, false);
+ gtk_widget_set_visible(packet_list_box, false);
// Make the buttons inacetive
gtk_widget_set_sensitive(rewind_button, false);
gtk_widget_set_sensitive(play_button, false);
@@ -545,7 +545,7 @@ void toggle_step_mode(GtkWidget* self, gpointer data) {
if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(self))) return;
if(fastmode) g_source_remove(timestep_timeout_source);
fastmode = false;
- gtk_widget_set_visible(packet_tree_scroll, true);
+ gtk_widget_set_visible(packet_list_box, true);
// Make the buttons active
gtk_widget_set_sensitive(rewind_button, true);
gtk_widget_set_sensitive(play_button, true);
@@ -1276,24 +1276,6 @@ void drawing_area_motion(GtkEventControllerKey* self, gdouble x, gdouble y, gpoi
int gui_send_info(struct interface* send_interface, const char* send_data, int data_len, const char* type) {
if(!fastmode) {
if(!send_interface || !send_interface->connection) return -1;
-
- /*GtkTreeIter packet_iter;
- gtk_list_store_append(packet_list, &packet_iter);
- // Copy the data to a buffer so that is stays persistent
- char* data_buffer = malloc_or_abort(data_len);
- memcpy(data_buffer, send_data, data_len);
- gtk_list_store_set(packet_list, &packet_iter,
- PACKET_COL_DEV1, send_interface->parent_device->name,
- PACKET_COL_DEV2, send_interface == send_interface->connection->interface1 ?
- send_interface->connection->interface2->parent_device->name :
- send_interface->connection->interface1->parent_device->name,
- PACKET_COL_SIZE, data_len,
- PACKET_COL_DATA, data_buffer,
- PACKET_COL_TYPE, type, PACKET_COL_STATUS,
- con ? "Buffered" : "Disconected", -1);
- // Get the index of the packet in the list
- GtkTreePath* new_path = gtk_tree_model_get_path(GTK_TREE_MODEL(packet_list), &packet_iter);
- int index = *(gtk_tree_path_get_indices(new_path));*/
GObject* data_object = g_object_new(G_TYPE_OBJECT, NULL);
g_object_set_data(data_object, "Status", "Buffered");
@@ -1309,6 +1291,11 @@ int gui_send_info(struct interface* send_interface, const char* send_data, int d
*size_buffer = data_len;
g_object_set_data_full(data_object, "Size", size_buffer, free);
+ // @todo this is not freed now
+ int* timestamp_buffer = malloc_or_abort(sizeof(unsigned long));
+ *timestamp_buffer = 0;
+ g_object_set_data(data_object, "Timestamp", timestamp_buffer);
+
g_object_set_data(data_object, "Type", (char*)type);
g_list_store_append(packet_list_store, data_object);
@@ -1326,6 +1313,7 @@ void gui_con_send(struct connection* con, int send_side) {
GObject* data_object = g_list_model_get_object(G_LIST_MODEL(packet_list_store), gui_index);
g_object_set_data(data_object, "Status", "Sent");
+ *(int*)g_object_get_data(data_object, "Timestamp") = timestamp;
}
}
@@ -1413,7 +1401,6 @@ void save_response(GObject* save_dialog, GAsyncResult* res, gpointer data) {
GFile* result_file = gtk_file_dialog_save_finish (GTK_FILE_DIALOG(save_dialog),
res,
NULL);
- printf("SAVE RESPONSE\n");
if(result_file) {
if(save_path)
g_free(save_path);
@@ -1432,7 +1419,6 @@ void save_response(GObject* save_dialog, GAsyncResult* res, gpointer data) {
}
void gui_save_as_action(GSimpleAction* self, GVariant* parameter, gpointer user_data) {
-
GtkFileDialog* save_dialog = gtk_file_dialog_new();
gtk_file_dialog_save(save_dialog, GTK_WINDOW(window), NULL, save_response, NULL);
}
@@ -1590,6 +1576,71 @@ GtkListItemFactory* packet_list_int_data_factory_new(char* key) {
return new_factory;
}
+struct {
+ uint32_t magic;
+ uint16_t major_version;
+ uint16_t minor_version;
+ int32_t tc_correction;
+ uint32_t timeacc;
+ uint32_t snaplen;
+ uint32_t ll_type;
+} pcap_header = {
+ 0xa1b2c3d4,
+ 2,4,
+ 0,
+ 0,
+ UINT32_MAX,
+ 1 // Ethernet
+};
+
+struct pcap_packet_header {
+ uint32_t sec;
+ uint32_t used;
+ // in this case these should always be the same
+ uint32_t ilen;
+ uint32_t olen;
+};
+
+void pcap_save_response(GObject* pcap_save_dialog, GAsyncResult* res, gpointer data) {
+
+ GFile* result_file = gtk_file_dialog_save_finish (GTK_FILE_DIALOG(pcap_save_dialog),
+ res,
+ NULL);
+ if(result_file) {
+ char* pcap_filename = g_file_get_path(result_file);
+ g_object_unref(result_file);
+ if(pcap_filename) {
+ int packet_n = g_list_model_get_n_items(G_LIST_MODEL(packet_list_store));
+ FILE* pcap_file = fopen(pcap_filename, "w");
+ fwrite(&pcap_header, sizeof(pcap_header), 1, pcap_file);
+ for(int i = 0; i < packet_n; i++) {
+ GObject* data_object = g_list_model_get_object(G_LIST_MODEL(packet_list_store), i);
+ struct pcap_packet_header current_header = {
+ *(uint32_t*)g_object_get_data(data_object, "Timestamp"),
+ 0,
+ *(uint32_t*)g_object_get_data(data_object, "Size")-8,
+ *(uint32_t*)g_object_get_data(data_object, "Size")-8
+ };
+ if(current_header.ilen < 0) {
+ fprintf(stderr, "Packet size too small!\n");
+ return;
+ }
+ fwrite(&current_header, sizeof(struct pcap_packet_header), 1, pcap_file);
+ fwrite((char*)g_object_get_data(data_object, "Data")+8, current_header.ilen, 1, pcap_file);
+ }
+ printf("Exported PCAP\n");
+ fclose(pcap_file);
+ g_free(pcap_filename);
+ }
+ }
+
+}
+
+void export_pcap(GtkButton* self, gpointer user_data) {
+ GtkFileDialog* save_dialog = gtk_file_dialog_new();
+ gtk_file_dialog_save(save_dialog, GTK_WINDOW(window), NULL, pcap_save_response, NULL);
+}
+
/*
* ====== GTK INITIALIZATION ======
*/
@@ -1812,7 +1863,7 @@ void activate_main_window(GtkApplication* app, gpointer user_data) {
// === Packet details
// Create a tree view
- packet_tree_scroll = gtk_scrolled_window_new();
+ GtkWidget* packet_tree_scroll = gtk_scrolled_window_new();
//packet_tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(packet_list));
packet_list_store = g_list_store_new(G_TYPE_OBJECT);
@@ -1822,7 +1873,8 @@ void activate_main_window(GtkApplication* app, gpointer user_data) {
gtk_column_view_set_single_click_activate(GTK_COLUMN_VIEW(packet_tree), true);
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(packet_tree_scroll), packet_tree);
g_signal_connect(G_OBJECT(packet_tree), "activate", G_CALLBACK(packet_selected), NULL);
-
+
+ gtk_column_view_append_column(GTK_COLUMN_VIEW(packet_tree), gtk_column_view_column_new("T", packet_list_int_data_factory_new("Timestamp")));
gtk_column_view_append_column(GTK_COLUMN_VIEW(packet_tree), gtk_column_view_column_new("Status", packet_list_string_data_factory_new("Status")));
gtk_column_view_append_column(GTK_COLUMN_VIEW(packet_tree), gtk_column_view_column_new("Device1", packet_list_string_data_factory_new("Device1")));
gtk_column_view_append_column(GTK_COLUMN_VIEW(packet_tree), gtk_column_view_column_new("Device2", packet_list_string_data_factory_new("Device2")));
@@ -1831,10 +1883,15 @@ void activate_main_window(GtkApplication* app, gpointer user_data) {
gtk_column_view_append_column(GTK_COLUMN_VIEW(packet_tree), gtk_column_view_column_new("Size", packet_list_int_data_factory_new("Size")));
- // Set the data with g_object_set_data
+ packet_list_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_set_vexpand(packet_tree_scroll, true);
+ gtk_box_append(GTK_BOX(packet_list_box), packet_tree_scroll);
- gtk_paned_set_end_child(GTK_PANED(right_pane), packet_tree_scroll);
+ GtkWidget* pcap_export_button = gtk_button_new_with_label("Export to PCAP file");
+ gtk_box_append(GTK_BOX(packet_list_box), pcap_export_button);
+ g_signal_connect(G_OBJECT(pcap_export_button), "clicked", G_CALLBACK(export_pcap), NULL);
+ gtk_paned_set_end_child(GTK_PANED(right_pane), packet_list_box);
// === Create the time controls
// There will be two different types of the simulation, fast and step
Jeremias Stotters git repositories generated by CGIT