- itti_analyzer v0.2:

* Moved all GUI calls to main thread
	* Refine socket interface
	* Added origin/destination task id on message display list

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4258 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
Cedric Roux
2013-10-22 13:42:39 +00:00
parent 3dc3d6ae45
commit ecf07e3805
22 changed files with 890 additions and 420 deletions
+10 -8
View File
@@ -2,17 +2,19 @@ AM_CFLAGS = \
@ADD_CFLAGS@ \
-I$(top_srcdir)/common \
-I$(top_srcdir)/libbuffers \
-I$(top_srcdir)/libparser
-I$(top_srcdir)/libparser \
-I$(top_srcdir)/libresolver
noinst_LTLIBRARIES = libui.la
libui_la_LDFLAGS = -all-static
libui_la_SOURCES = \
ui_main_screen.c ui_main_screen.h \
ui_menu_bar.c ui_menu_bar.h \
ui_callbacks.c ui_callbacks.h \
ui_tree_view.c ui_tree_view.h \
ui_main_screen.c ui_main_screen.h \
ui_menu_bar.c ui_menu_bar.h \
ui_callbacks.c ui_callbacks.h \
ui_tree_view.c ui_tree_view.h \
ui_signal_dissect_view.c ui_signal_dissect_view.h \
ui_notifications.c ui_notifications.h \
ui_interface.c ui_interface.h \
ui_notebook.c ui_notebook.h
ui_notifications.c ui_notifications.h \
ui_notif_dlg.c ui_notif_dlg.h \
ui_interface.c ui_interface.h \
ui_notebook.c ui_notebook.h
+170 -18
View File
@@ -5,6 +5,9 @@
#include "rc.h"
#include "socket.h"
#include "ui_notif_dlg.h"
#include "ui_main_screen.h"
#include "ui_callbacks.h"
#include "ui_interface.h"
@@ -12,6 +15,12 @@
#include "ui_tree_view.h"
#include "ui_signal_dissect_view.h"
#include "types.h"
#include "locate_root.h"
#include "xml_parse.h"
static gboolean ui_handle_socket_connection_failed(gint fd);
gboolean ui_callback_on_open(GtkWidget *widget,
GdkEvent *event,
gpointer data)
@@ -41,23 +50,22 @@ ui_callback_on_select_signal(GtkTreeSelection *selection,
if (gtk_tree_model_get_iter(model, &iter, path))
{
gchar *name;
GValue buffer_store = G_VALUE_INIT;
gpointer buffer;
gtk_tree_model_get(model, &iter, 0, &name, -1);
// g_value_init (&buffer_store, G_TYPE_POINTER);
// gtk_tree_model_get(model, &iter, 0, &name, -1);
gtk_tree_model_get_value(model, &iter, COL_BUFFER, &buffer_store);
buffer = g_value_get_pointer(&buffer_store);
if (!path_currently_selected)
{
if (ui_interface.dissector_ready != 0) {
uint32_t message_number;
sscanf(name, "%u", &message_number);
/* Clear the view */
CHECK_FCT_DO(ui_signal_dissect_clear_view(), return FALSE);
// g_print ("%s is going to be selected.\n", name);
CHECK_FCT_DO(ui_interface.dissect_signal(message_number), return FALSE);
} else {
ui_notification_dialog(DIALOG_ERROR, "No XML signal description"
" provided\n");
}
/* Clear the view */
CHECK_FCT_DO(ui_signal_dissect_clear_view(), return FALSE);
CHECK_FCT_DO(dissect_signal((buffer_t*)buffer), return FALSE);
}
else
{
@@ -69,21 +77,162 @@ ui_callback_on_select_signal(GtkTreeSelection *selection,
return TRUE;
}
void ui_signal_add_to_list(gpointer data, gpointer user_data)
{
buffer_t *signal_buffer;
signal_buffer = (buffer_t *)data;
get_message_id(root, signal_buffer, &signal_buffer->message_id);
ui_tree_view_new_signal_ind(signal_buffer->message_number,
message_id_to_string(signal_buffer->message_id),
get_origin_task_id(signal_buffer),
get_destination_task_id(signal_buffer),
data);
}
static gboolean ui_handle_update_signal_list(gint fd, const void *data,
size_t data_length)
{
pipe_new_signals_list_message_t *signal_list_message;
signal_list_message = (pipe_new_signals_list_message_t *)data;
g_assert(signal_list_message != NULL);
g_assert(signal_list_message->signal_list != NULL);
g_list_foreach(signal_list_message->signal_list, ui_signal_add_to_list, NULL);
free(data);
return TRUE;
}
static gboolean ui_handle_socket_connection_failed(gint fd)
{
GtkWidget *dialogbox;
dialogbox = gtk_message_dialog_new(GTK_WINDOW(ui_main_data.window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"Failed to connect to provided host/ip address");
gtk_dialog_run(GTK_DIALOG(dialogbox));
gtk_widget_destroy(dialogbox);
/* Re-enable connect button */
ui_enable_connect_button();
return TRUE;
}
static gboolean ui_handle_socket_connection_lost(gint fd)
{
GtkWidget *dialogbox;
dialogbox = gtk_message_dialog_new(GTK_WINDOW(ui_main_data.window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"Connection with remote host has been lost");
gtk_dialog_run(GTK_DIALOG(dialogbox));
gtk_widget_destroy(dialogbox);
/* Re-enable connect button */
ui_enable_connect_button();
return TRUE;
}
static gboolean ui_handle_socket_xml_definition(gint fd, const void *data,
size_t data_length)
{
pipe_xml_definition_message_t *xml_definition_message;
xml_definition_message = (pipe_xml_definition_message_t *)data;
g_assert(xml_definition_message != NULL);
g_assert(data_length == sizeof(pipe_xml_definition_message_t));
xml_parse_buffer(xml_definition_message->xml_definition,
xml_definition_message->xml_definition_length);
free(data);
return TRUE;
}
gboolean ui_pipe_callback(gint source, gpointer user_data)
{
void *input_data = NULL;
size_t input_data_length = 0;
pipe_input_header_t input_header;
/* Read the header */
if (read(source, &input_header, sizeof(input_header)) < 0) {
g_warning("Failed to read from pipe %d: %s", source, g_strerror(errno));
return FALSE;
}
input_data_length = input_header.message_size - sizeof(input_header);
/* Checking for non-header part */
if (input_data_length > 0) {
input_data = malloc(input_data_length);
if (read(source, input_data, input_data_length) < 0) {
g_warning("Failed to read from pipe %d: %s", source, g_strerror(errno));
return FALSE;
}
}
switch (input_header.message_type) {
case UI_PIPE_CONNECTION_FAILED:
return ui_handle_socket_connection_failed(source);
case UI_PIPE_XML_DEFINITION:
return ui_handle_socket_xml_definition(source, input_data, input_data_length);
case UI_PIPE_CONNECTION_LOST:
return ui_handle_socket_connection_lost(source);
case UI_PIPE_UPDATE_SIGNAL_LIST:
return ui_handle_update_signal_list(source, input_data, input_data_length);
default:
g_debug("[gui] Unhandled message type %u", input_header.message_type);
g_assert_not_reached();
}
return FALSE;
}
gboolean ui_callback_on_connect(GtkWidget *widget,
GdkEvent *event,
gpointer data)
{
/* We have to retrieve the ip address and port of remote host */
uint16_t port;
const char *ip;
uint16_t port;
int pipe_fd[2];
g_debug("Connect event occurred");
port = atoi(gtk_entry_get_text(GTK_ENTRY(ui_main_data.portentry)));
ip = gtk_entry_get_text(GTK_ENTRY(ui_main_data.ipentry));
// ui_tree_view_destroy_list();
ui_interface.socket_connect(ip, port);
if ((ip == NULL) || (port == 0)) {
g_warning("NULL parameter given for ip address or port = 0");
/* TODO: add dialog box here */
return FALSE;
}
ui_pipe_new(pipe_fd, ui_pipe_callback, NULL);
memcpy(ui_main_data.pipe_fd, pipe_fd, sizeof(int) * 2);
/* Disable the connect button */
ui_disable_connect_button();
if (socket_connect_to_remote_host(ip, port, pipe_fd[1]) != 0) {
ui_enable_connect_button();
return FALSE;
}
return TRUE;
}
@@ -95,7 +244,11 @@ gboolean ui_callback_on_disconnect(GtkWidget *widget,
/* We have to retrieve the ip address and port of remote host */
g_debug("Disconnect event occurred");
ui_interface.socket_disconnect();
ui_pipe_write_message(ui_main_data.pipe_fd[0], UI_PIPE_DISCONNECT_EVT,
NULL, 0);
ui_enable_connect_button();
return TRUE;
}
@@ -107,4 +260,3 @@ gboolean ui_callback_on_tree_view_select(GtkWidget *widget,
g_debug("List selection event occurred");
return TRUE;
}
@@ -28,4 +28,6 @@ ui_callback_on_select_signal(GtkTreeSelection *selection,
gboolean path_currently_selected,
gpointer userdata);
gboolean ui_pipe_callback(gint source, gpointer user_data);
#endif /* UI_CALLBACKS_H_ */
+85 -15
View File
@@ -14,21 +14,91 @@
#include "xml_parse.h"
ui_interface_t ui_interface = {
.dissector_ready = 0,
/** core program -> UI **/
.ui_notification_dialog = ui_notification_dialog,
.ui_disable_connect_button = ui_disable_connect_button,
.ui_enable_connect_button = ui_enable_connect_button,
.ui_progress_bar_set_fraction = ui_progress_bar_set_fraction,
.ui_progress_bar_terminate = ui_progress_bar_terminate,
.ui_tree_view_new_signal_ind = ui_tree_view_new_signal_ind,
.ui_signal_set_text = ui_signal_set_text,
/** UI -> core program **/
.socket_connect = socket_connect_to_remote_host,
.socket_disconnect = socket_disconnect_from_remote_host,
.parse_signal_file = xml_parse_file,
.dissect_signal = dissect_signal,
};
static
gboolean ui_callback_on_pipe_notification(
GIOChannel *source, GIOCondition condition, gpointer user_data)
{
pipe_input_t *pipe_input = (pipe_input_t *)user_data;
/* avoid reentrancy problems and stack overflow */
g_source_remove(pipe_input->pipe_input_id);
g_debug("Received new data on pipe %d", pipe_input->pipe_input_id);
if (pipe_input->input_cb(pipe_input->source_fd, pipe_input->user_data)) {
/* restore pipe handler */
pipe_input->pipe_input_id = g_io_add_watch_full(pipe_input->pipe_channel,
G_PRIORITY_HIGH,
(GIOCondition)(G_IO_IN|G_IO_ERR|G_IO_HUP),
ui_callback_on_pipe_notification,
pipe_input,
NULL);
}
return TRUE;
}
int ui_pipe_new(int pipe_fd[2], pipe_input_cb_t input_cb, gpointer user_data)
{
static pipe_input_t pipe_input;
g_assert(pipe_fd != NULL);
/* Create a pipe between GUI and a thread or a process */
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pipe_fd) < 0) {
g_warning("Failed to create socketpair %s", g_strerror(errno));
return RC_FAIL;
}
/* Source taken from wireshark SVN repository */
pipe_input.source_fd = pipe_fd[0];
pipe_input.input_cb = input_cb;
pipe_input.user_data = user_data;
pipe_input.pipe_channel = g_io_channel_unix_new(pipe_fd[0]);
g_io_channel_set_encoding(pipe_input.pipe_channel, NULL, NULL);
pipe_input.pipe_input_id = g_io_add_watch_full(pipe_input.pipe_channel,
G_PRIORITY_HIGH,
G_IO_IN | G_IO_ERR | G_IO_HUP,
ui_callback_on_pipe_notification,
&pipe_input,
NULL);
return RC_OK;
}
int ui_pipe_write_message(int pipe_fd, const uint16_t message_type,
const void * const message, const uint16_t message_size)
{
int ret;
pipe_input_header_t pipe_input_header;
pipe_input_header.message_size = message_size + sizeof(pipe_input_header);
pipe_input_header.message_type = message_type;
if (message_size > 0 && message == NULL) {
g_error("message size = %u but message is NULL", message_size);
g_assert_not_reached();
}
ret = write(pipe_fd, &pipe_input_header, sizeof(pipe_input_header));
if (ret < 0) {
g_debug("Failed to write header to pipe: %s", g_strerror(errno));
return ret;
}
/* Only write the message to pipe if valid data to transmit */
if (message_size > 0) {
ret = write(pipe_fd, message, message_size);
if (ret < 0) {
g_debug("Failed to write message of size %u at 0x%p to pipe: %s",
message_size, message, g_strerror(errno));
return ret;
}
}
return 0;
}
+47 -47
View File
@@ -1,61 +1,61 @@
#include <glib.h>
#ifndef UI_INTERFACE_H_
#define UI_INTERFACE_H_
typedef enum dialog_type_e {
DIALOG_INFO,
DIALOG_WARNING,
DIALOG_QUESTION,
DIALOG_ERROR,
DIALOG_OTHER,
DIALOG_MAX
} dialog_type_t;
/**
* socket_connect_t
* @param remote_ip Remote ipv4 address
* @param port Remote port number
* @return RC_OK on Success, < 0 on failure
**/
typedef int (*socket_connect_t)(const char *remote_ip, const uint16_t port);
typedef int (*socket_disconnect_t)(void);
typedef int (*parse_signal_file_t)(const char *filename);
typedef int (*dissect_signal_t)(const uint32_t message_number);
/**
* ui_notification_dialog_t
* @param type Type for the new dialog box
* @param fmt String formater
* @param ... argument list
* @return RC_OK on Success, < 0 on failure
**/
typedef int (*ui_notification_dialog_t)(dialog_type_t type, const char *fmt, ...);
typedef int (*ui_disable_connect_button_t)(void);
typedef int (*ui_enable_connect_button_t)(void);
typedef int (*ui_progress_bar_set_fraction_t)(double fraction);
typedef int (*ui_progress_bar_terminate_t)(void);
typedef int (*ui_tree_view_new_signal_ind_t)(const uint32_t message_number, const char *signal_name);
typedef int (*ui_signal_set_text_t)(char *text, int length);
typedef struct {
/** UI -> core program */
socket_connect_t socket_connect;
socket_disconnect_t socket_disconnect;
parse_signal_file_t parse_signal_file;
dissect_signal_t dissect_signal;
/** core program -> UI */
int dissector_ready;
ui_notification_dialog_t ui_notification_dialog;
ui_disable_connect_button_t ui_disable_connect_button;
ui_enable_connect_button_t ui_enable_connect_button;
ui_progress_bar_set_fraction_t ui_progress_bar_set_fraction;
ui_progress_bar_terminate_t ui_progress_bar_terminate;
ui_tree_view_new_signal_ind_t ui_tree_view_new_signal_ind;
ui_signal_set_text_t ui_signal_set_text;
} ui_interface_t;
extern ui_interface_t ui_interface;
/*******************************************************************************
* Pipe interface between GUI thread and other thread
******************************************************************************/
typedef gboolean (*pipe_input_cb_t) (gint source, gpointer user_data);
typedef struct {
int source_fd;
guint pipe_input_id;
GIOChannel *pipe_channel;
pipe_input_cb_t input_cb;
gpointer user_data;
} pipe_input_t;
int ui_pipe_new(int pipe_fd[2], pipe_input_cb_t input_cb, gpointer user_data);
int ui_pipe_write_message(int pipe_fd, const uint16_t message_type,
const void * const message, const uint16_t message_size);
typedef struct {
uint16_t message_size;
uint16_t message_type;
} pipe_input_header_t;
enum ui_pipe_messages_id_e {
/* Other thread -> GUI interface ids */
UI_PIPE_CONNECTION_FAILED,
UI_PIPE_CONNECTION_LOST,
UI_PIPE_XML_DEFINITION,
UI_PIPE_UPDATE_SIGNAL_LIST,
/* GUI -> other threads */
UI_PIPE_DISCONNECT_EVT
};
typedef struct {
char *xml_definition;
size_t xml_definition_length;
} pipe_xml_definition_message_t;
typedef struct {
GList *signal_list;
} pipe_new_signals_list_message_t;
#endif /* UI_INTERFACE_H_ */
@@ -13,6 +13,8 @@ typedef struct {
/* Buttons */
GtkToolItem *connect;
GtkToolItem *disconnect;
int pipe_fd[2];
} ui_main_data_t;
extern ui_main_data_t ui_main_data;
@@ -0,0 +1,24 @@
#include "rc.h"
#include "ui_notif_dlg.h"
#include "ui_main_screen.h"
int ui_notification_dialog(dialog_type_t type, const char *fmt, ...)
{
va_list args;
GtkWidget *dialogbox;
va_start(args, fmt);
dialogbox = gtk_message_dialog_new(GTK_WINDOW(ui_main_data.window),
GTK_DIALOG_MODAL, type,
GTK_BUTTONS_OK, fmt, args);
gtk_dialog_run(GTK_DIALOG (dialogbox));
gtk_widget_destroy (dialogbox);
va_end(args);
return RC_OK;
}
@@ -0,0 +1,17 @@
#include <gtk/gtk.h>
#ifndef UI_NOTIF_DLG_H_
#define UI_NOTIF_DLG_H_
typedef enum dialog_type_e {
DIALOG_INFO,
DIALOG_WARNING,
DIALOG_QUESTION,
DIALOG_ERROR,
DIALOG_OTHER,
DIALOG_MAX
} dialog_type_t;
extern int ui_notification_dialog(dialog_type_t type, const char *fmt, ...);
#endif /* UI_NOTIF_DLG_H_ */
@@ -10,33 +10,7 @@
#include "ui_main_screen.h"
#include "ui_notifications.h"
int ui_notification_dialog(dialog_type_t type, const char *fmt, ...)
{
va_list ap;
GtkWidget *dialogbox;
va_start(ap, fmt);
/* In multi-threaded environnements gtk calls should be protected by
* gdk_threads_enter before calling the GTK function
* gdk_threads_leave when GTK function has exited
*/
gdk_threads_enter();
dialogbox = gtk_message_dialog_new(
GTK_WINDOW(ui_main_data.window), GTK_DIALOG_MODAL, type,
GTK_BUTTONS_OK, fmt, ap);
gtk_dialog_run(GTK_DIALOG (dialogbox));
gtk_widget_destroy (dialogbox);
gdk_threads_leave();
va_end(ap);
return RC_OK;
}
#include "xml_parse.h"
int ui_disable_connect_button(void)
{
@@ -71,8 +45,8 @@ int ui_file_chooser(void)
char *filename;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser));
ui_interface.parse_signal_file(filename);
g_free (filename);
xml_parse_file(filename);
g_free(filename);
}
gtk_widget_destroy (filechooser);
@@ -1,8 +1,6 @@
#ifndef UI_NOTIFICATIONS_H_
#define UI_NOTIFICATIONS_H_
int ui_notification_dialog(dialog_type_t type, const char *fmt, ...);
int ui_disable_connect_button(void);
int ui_enable_connect_button(void);
+39 -17
View File
@@ -5,21 +5,16 @@
#include "rc.h"
#include "buffers.h"
#include "ui_main_screen.h"
#include "ui_tree_view.h"
#include "ui_callbacks.h"
#include "ui_signal_dissect_view.h"
enum
{
COL_MSG_NUM = 0,
COL_SIGNAL,
NUM_COLS
} ;
static void
init_list(GtkWidget *list)
ui_tree_view_init_list(GtkWidget *list)
{
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
@@ -27,22 +22,40 @@ init_list(GtkWidget *list)
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(
"Message Number", renderer, "text", COL_MSG_NUM, NULL);
"MN", renderer, "text", COL_MSG_NUM, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
column = gtk_tree_view_column_new_with_attributes(
"Signal", renderer, "text", COL_SIGNAL, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
store = gtk_list_store_new(NUM_COLS, G_TYPE_STRING, G_TYPE_STRING);
column = gtk_tree_view_column_new_with_attributes(
"From", renderer, "text", COL_FROM_TASK, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
column = gtk_tree_view_column_new_with_attributes(
"To", renderer, "text", COL_TO_TASK, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
store = gtk_list_store_new(NUM_COLS,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
/* HACK: add a reference to the buffer here
* to avoid maintining multiple lists.
* The reference is not displayed
*/
G_TYPE_POINTER);
gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store));
g_object_unref(store);
}
static void
add_to_list(GtkWidget *list, const gchar *message_number, const gchar *signal_name)
static void ui_tree_view_add_to_list(GtkWidget *list, const gchar *message_number,
const gchar *signal_name, const char *origin_task,
const char *to_task, gpointer buffer)
{
GtkListStore *store;
GtkTreeIter iter;
@@ -51,8 +64,15 @@ add_to_list(GtkWidget *list, const gchar *message_number, const gchar *signal_na
(GTK_TREE_VIEW(list)));
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, COL_MSG_NUM, message_number,
COL_SIGNAL, signal_name, -1);
gtk_list_store_set(store, &iter,
/* Columns */
COL_MSG_NUM , message_number,
COL_SIGNAL , signal_name,
COL_FROM_TASK , origin_task,
COL_TO_TASK , to_task,
COL_BUFFER , buffer,
/* End of columns */
-1);
}
void ui_tree_view_destroy_list(GtkWidget *list)
@@ -92,7 +112,7 @@ int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox)
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
ui_main_data.signalslist);
init_list(ui_main_data.signalslist);
ui_tree_view_init_list(ui_main_data.signalslist);
// gtk_widget_get_size_request(GTK_WIDGET(ui_main_data.signalslist), &width, NULL);
gtk_widget_set_size_request(GTK_WIDGET(scrolled_window), 350, -1);
@@ -110,13 +130,15 @@ int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox)
return 0;
}
int ui_tree_view_new_signal_ind(const uint32_t message_number, const char *signal_name)
int ui_tree_view_new_signal_ind(const uint32_t message_number, const char *signal_name,
const char *origin_task, const char *to_task, gpointer buffer)
{
gchar message_number_str[11];
sprintf(message_number_str, "%u", message_number);
add_to_list(ui_main_data.signalslist, message_number_str, signal_name);
ui_tree_view_add_to_list(ui_main_data.signalslist, message_number_str, signal_name,
origin_task, to_task, (buffer_t *)buffer);
return RC_OK;
}
@@ -1,9 +1,20 @@
#ifndef UI_TREE_VIEW_H_
#define UI_TREE_VIEW_H_
enum
{
COL_MSG_NUM = 0,
COL_SIGNAL,
COL_FROM_TASK,
COL_TO_TASK,
COL_BUFFER,
NUM_COLS
};
int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox);
int ui_tree_view_new_signal_ind(const uint32_t message_number, const char *signal_name);
int ui_tree_view_new_signal_ind(const uint32_t message_number, const char *signal_name,
const char *origin_task, const char *to_task, gpointer buffer);
void ui_tree_view_destroy_list(GtkWidget *list);