summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Vogelgesang <matthias.vogelgesang@kit.edu>2016-02-16 16:56:34 +0100
committerMatthias Vogelgesang <matthias.vogelgesang@kit.edu>2016-02-16 16:56:34 +0100
commitb210f158f822ac721d83c0dc0ab29fc986979c97 (patch)
tree8ce9e755f272a9f345e9b6bd0c0462667d22285e
parent7b18a105db637d1ea625bd41f35e52df41165fa3 (diff)
downloaduca-net-b210f158f822ac721d83c0dc0ab29fc986979c97.tar.gz
uca-net-b210f158f822ac721d83c0dc0ab29fc986979c97.tar.bz2
uca-net-b210f158f822ac721d83c0dc0ab29fc986979c97.tar.xz
uca-net-b210f158f822ac721d83c0dc0ab29fc986979c97.zip
Refactor server code into ucad.c
-rw-r--r--CMakeLists.txt2
-rw-r--r--uca-net-protocol.h3
-rw-r--r--uca-net-server.c203
-rw-r--r--ucad.c214
4 files changed, 178 insertions, 244 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bfd96d6..a864fd0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,7 +27,7 @@ install(TARGETS ucanet LIBRARY DESTINATION ${LIBUCA_PLUGINDIR})
# uca-net server
configure_paths(UCAD)
-add_executable(ucad ucad.c uca-net-server.c)
+add_executable(ucad ucad.c)
target_link_libraries(ucad ${UCA_LIBRARIES} ${GIO_LIBRARIES})
diff --git a/uca-net-protocol.h b/uca-net-protocol.h
index 0b73c57..e28c13d 100644
--- a/uca-net-protocol.h
+++ b/uca-net-protocol.h
@@ -4,7 +4,8 @@
#include <gio/gio.h>
typedef enum {
- UCA_NET_MESSAGE_GET_PROPERTY = 0,
+ UCA_NET_MESSAGE_INVALID = 0,
+ UCA_NET_MESSAGE_GET_PROPERTY,
UCA_NET_MESSAGE_SET_PROPERTY,
UCA_NET_MESSAGE_START_RECORDING,
UCA_NET_MESSAGE_STOP_RECORDING,
diff --git a/uca-net-server.c b/uca-net-server.c
deleted file mode 100644
index 853319c..0000000
--- a/uca-net-server.c
+++ /dev/null
@@ -1,203 +0,0 @@
-#include <string.h>
-#include "uca-net-protocol.h"
-
-static UcaNetHandlers handlers;
-
-static void
-send_reply (GOutputStream *output, gpointer data, gsize size, GError **error)
-{
- gsize written;
-
- if (!g_output_stream_write_all (output, data, size, &written, NULL, error))
- return;
-
- if (!g_output_stream_flush (output, NULL, error))
- return;
-}
-
-static void
-prepare_error_reply (GError *error, UcaNetErrorReply *reply)
-{
- if (error != NULL) {
- reply->occurred = TRUE;
- reply->code = error->code;
- strncpy (reply->domain, g_quark_to_string (error->domain), sizeof (error->domain));
- strncpy (reply->message, error->message, sizeof (reply->message));
- g_error_free (error);
- }
- else {
- reply->occurred = FALSE;
- }
-}
-
-static void
-uca_net_server_handle_get_property (GOutputStream *output, UcaNetMessageGetPropertyRequest *request, GError **error)
-{
- UcaNetMessageGetPropertyReply reply = { .type = UCA_NET_MESSAGE_GET_PROPERTY };
-
- handlers.get_property (handlers.user_data, request->property_name, reply.property_value);
- send_reply (output, &reply, sizeof (reply), error);
-}
-
-static void
-uca_net_server_handle_set_property (GOutputStream *output, UcaNetMessageSetPropertyRequest *request, GError **stream_error)
-{
- UcaNetDefaultReply reply = { .type = UCA_NET_MESSAGE_SET_PROPERTY };
- GError *error = NULL;
-
- handlers.set_property (handlers.user_data, request->property_name, request->property_value, &error);
- prepare_error_reply (error, &reply.error);
- send_reply (output, &reply, sizeof (reply), stream_error);
-}
-
-static void
-handle_default (GOutputStream *output, UcaNetMessageType type,
- void (*handler) (gpointer user_data, GError **error), GError **stream_error)
-{
- UcaNetDefaultReply reply = { .type = type };
- GError *error = NULL;
-
- handler (handlers.user_data, &error);
- prepare_error_reply (error, &reply.error);
- send_reply (output, &reply, sizeof (reply), stream_error);
-}
-
-static void
-uca_net_server_handle_start_recording (GOutputStream *output, GError **stream_error)
-{
- handle_default (output, UCA_NET_MESSAGE_START_RECORDING, handlers.start_recording, stream_error);
-}
-
-static void
-uca_net_server_handle_stop_recording (GOutputStream *output, GError **stream_error)
-{
- handle_default (output, UCA_NET_MESSAGE_STOP_RECORDING, handlers.start_recording, stream_error);
-}
-
-static void
-uca_net_server_handle_start_readout (GOutputStream *output, GError **stream_error)
-{
- handle_default (output, UCA_NET_MESSAGE_START_READOUT, handlers.start_readout, stream_error);
-}
-
-static void
-uca_net_server_handle_stop_readout (GOutputStream *output, GError **stream_error)
-{
- handle_default (output, UCA_NET_MESSAGE_STOP_READOUT, handlers.stop_readout, stream_error);
-}
-
-static void
-uca_net_server_handle_trigger (GOutputStream *output, GError **stream_error)
-{
- handle_default (output, UCA_NET_MESSAGE_TRIGGER, handlers.trigger, stream_error);
-}
-
-static void
-uca_net_server_handle_grab (GOutputStream *output, UcaNetMessageGrabRequest *request, GError **stream_error)
-{
- UcaNetDefaultReply reply = { .type = UCA_NET_MESSAGE_GRAB };
- gsize bytes_left;
- GError *error = NULL;
- static gsize size = 0;
- static gchar *buffer = NULL;
-
- if (buffer == NULL || size != request->size) {
- buffer = g_realloc (buffer, request->size);
- size = request->size;
- }
-
- handlers.grab (buffer, handlers.user_data, &error);
- prepare_error_reply (error, &reply.error);
- send_reply (output, &reply, sizeof (reply), stream_error);
-
- /* send data if no error occured during grab */
- if (!reply.error.occurred) {
- bytes_left = size;
-
- while (bytes_left > 0) {
- gssize written;
-
- written = g_output_stream_write (output, &buffer[size - bytes_left], bytes_left, NULL, stream_error);
-
- if (written < 0)
- return;
-
- bytes_left -= written;
- }
- }
-}
-
-void
-uca_net_server_register_handlers (UcaNetHandlers *new_handlers)
-{
- memcpy (&handlers, new_handlers, sizeof (UcaNetHandlers));
-}
-
-void
-uca_net_server_handle (GSocketConnection *connection)
-{
- GInputStream *input;
- GOutputStream *output;
- gchar *buffer;
- gboolean active;
-
- buffer = g_malloc0 (4096);
- input = g_io_stream_get_input_stream (G_IO_STREAM (connection));
- output = g_io_stream_get_output_stream (G_IO_STREAM (connection));
- active = TRUE;
-
- while (active) {
- UcaNetMessageDefault *message;
- GError *error = NULL;
-
- /* looks dangerous */
- g_input_stream_read (input, buffer, 4096, NULL, &error);
- message = (UcaNetMessageDefault *) buffer;
-
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE)) {
- g_error_free (error);
- active = FALSE;
- break;
- }
-
- switch (message->type) {
- case UCA_NET_MESSAGE_GET_PROPERTY:
- uca_net_server_handle_get_property (output, (UcaNetMessageGetPropertyRequest *) buffer, &error);
- break;
- case UCA_NET_MESSAGE_SET_PROPERTY:
- uca_net_server_handle_set_property (output, (UcaNetMessageSetPropertyRequest *) buffer, &error);
- break;
- case UCA_NET_MESSAGE_START_RECORDING:
- uca_net_server_handle_start_recording (output, &error);
- break;
- case UCA_NET_MESSAGE_STOP_RECORDING:
- uca_net_server_handle_stop_recording (output, &error);
- break;
- case UCA_NET_MESSAGE_START_READOUT:
- uca_net_server_handle_start_readout (output, &error);
- break;
- case UCA_NET_MESSAGE_STOP_READOUT:
- uca_net_server_handle_stop_readout (output, &error);
- break;
- case UCA_NET_MESSAGE_TRIGGER:
- uca_net_server_handle_trigger (output, &error);
- break;
- case UCA_NET_MESSAGE_GRAB:
- uca_net_server_handle_grab (output, (UcaNetMessageGrabRequest *) buffer, &error);
- break;
- case UCA_NET_MESSAGE_CLOSE_CONNECTION:
- active = FALSE;
- break;
- default:
- g_warning ("Message type not known");
- }
-
- if (error != NULL) {
- g_warning ("Error handling requests: %s", error->message);
- g_error_free (error);
- active = FALSE;
- }
- }
-
- g_free (buffer);
-}
diff --git a/ucad.c b/ucad.c
index 6223058..699b420 100644
--- a/ucad.c
+++ b/ucad.c
@@ -22,6 +22,17 @@
#include <uca/uca-plugin-manager.h>
#include "uca-net-protocol.h"
+
+typedef void (*MessageHandler) (GSocketConnection *connection, UcaCamera *camera, gpointer message, GError **error);
+typedef void (*CameraFunc) (UcaCamera *camera, GError **error);
+
+
+typedef struct {
+ UcaNetMessageType type;
+ MessageHandler handler;
+} HandlerTable;
+
+
static gchar *
get_camera_list (UcaPluginManager *manager)
{
@@ -64,81 +75,219 @@ uca_option_context_new (UcaPluginManager *manager)
}
static void
-handle_get_property_request (gpointer user_data, const gchar *name, gchar *value)
+send_reply (GSocketConnection *connection, gpointer data, gsize size, GError **error)
{
- UcaCamera *camera;
+ GOutputStream *output;
+
+ output = g_io_stream_get_output_stream (G_IO_STREAM (connection));
+
+ if (!g_output_stream_write_all (output, data, size, NULL, NULL, error))
+ return;
+
+ if (!g_output_stream_flush (output, NULL, error))
+ return;
+}
+
+static void
+prepare_error_reply (GError *error, UcaNetErrorReply *reply)
+{
+ if (error != NULL) {
+ reply->occurred = TRUE;
+ reply->code = error->code;
+ strncpy (reply->domain, g_quark_to_string (error->domain), sizeof (error->domain));
+ strncpy (reply->message, error->message, sizeof (reply->message));
+ g_error_free (error);
+ }
+ else {
+ reply->occurred = FALSE;
+ }
+}
+
+static void
+handle_get_property_request (GSocketConnection *connection, UcaCamera *camera, gpointer message, GError **error)
+{
+ UcaNetMessageGetPropertyRequest *request;
+ UcaNetMessageGetPropertyReply reply;
GParamSpec *pspec;
GValue prop_value = {0};
GValue str_value = {0};
- camera = user_data;
- pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (camera), name);
+ request = (UcaNetMessageGetPropertyRequest *) message;
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (camera), request->property_name);
if (pspec == NULL)
return;
g_value_init (&prop_value, g_type_is_a (pspec->value_type, G_TYPE_ENUM) ? G_TYPE_INT : pspec->value_type);
- g_object_get_property (G_OBJECT (camera), name, &prop_value);
+ g_object_get_property (G_OBJECT (camera), request->property_name, &prop_value);
g_value_init (&str_value, G_TYPE_STRING);
g_value_transform (&prop_value, &str_value);
- strncpy (value, g_value_get_string (&str_value), sizeof (g_value_get_string (&str_value)));
+ reply.type = request->type;
+ strncpy (reply.property_value, g_value_get_string (&str_value), sizeof (reply.property_value));
+ send_reply (connection, &reply, sizeof (reply), error);
}
static void
-handle_set_property_request (gpointer user_data, const gchar *name, const gchar *value, GError **error)
+handle_set_property_request (GSocketConnection *connection, UcaCamera *camera, gpointer message, GError **error)
{
- UcaCamera *camera;
+ UcaNetMessageSetPropertyRequest *request;
+ UcaNetDefaultReply reply;
GParamSpec *pspec;
GValue prop_value = {0};
GValue str_value = {0};
- camera = user_data;
- pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (camera), name);
+ request = (UcaNetMessageSetPropertyRequest *) message;
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (camera), request->property_name);
g_value_init (&prop_value, g_type_is_a (pspec->value_type, G_TYPE_ENUM) ? G_TYPE_INT : pspec->value_type);
g_value_init (&str_value, G_TYPE_STRING);
- g_value_set_string (&str_value, value);
+ g_value_set_string (&str_value, request->property_value);
g_value_transform (&str_value, &prop_value);
- g_object_set_property (G_OBJECT (camera), name, &prop_value);
+ g_object_set_property (G_OBJECT (camera), request->property_name, &prop_value);
+ send_reply (connection, &reply, sizeof (reply), error);
+}
+
+static void
+handle_simple_request (GSocketConnection *connection, UcaCamera *camera,
+ UcaNetMessageDefault *message, CameraFunc func, GError **stream_error)
+{
+ UcaNetDefaultReply reply = { .type = message->type };
+ GError *error = NULL;
+
+ func (camera, &error);
+
+ prepare_error_reply (error, &reply.error);
+ send_reply (connection, &reply, sizeof (reply), stream_error);
}
static void
-handle_start_recording_request (gpointer user_data, GError **error)
+handle_start_recording_request (GSocketConnection *connection, UcaCamera *camera, gpointer message, GError **error)
{
- uca_camera_start_recording (UCA_CAMERA (user_data), error);
+ handle_simple_request (connection, camera, message, uca_camera_start_recording, error);
}
static void
-handle_stop_recording_request (gpointer user_data, GError **error)
+handle_stop_recording_request (GSocketConnection *connection, UcaCamera *camera, gpointer message, GError **error)
{
- uca_camera_stop_recording (UCA_CAMERA (user_data), error);
+ handle_simple_request (connection, camera, message, uca_camera_stop_recording, error);
}
static void
-handle_start_readout_request (gpointer user_data, GError **error)
+handle_start_readout_request (GSocketConnection *connection, UcaCamera *camera, gpointer message, GError **error)
{
- uca_camera_start_recording (UCA_CAMERA (user_data), error);
+ handle_simple_request (connection, camera, message, uca_camera_start_recording, error);
}
static void
-handle_stop_readout_request (gpointer user_data, GError **error)
+handle_stop_readout_request (GSocketConnection *connection, UcaCamera *camera, gpointer message, GError **error)
{
- uca_camera_stop_recording (UCA_CAMERA (user_data), error);
+ handle_simple_request (connection, camera, message, uca_camera_stop_recording, error);
}
static void
-handle_trigger_request (gpointer user_data, GError **error)
+handle_trigger_request (GSocketConnection *connection, UcaCamera *camera, gpointer message, GError **error)
{
- uca_camera_trigger (UCA_CAMERA (user_data), error);
+ handle_simple_request (connection, camera, message, uca_camera_trigger, error);
}
-static gboolean
-handle_grab_request (gpointer data, gpointer user_data, GError **error)
+static void
+handle_grab_request (GSocketConnection *connection, UcaCamera *camera, gpointer message, GError **stream_error)
{
- return uca_camera_grab (UCA_CAMERA (user_data), data, error);
+ GOutputStream *output;
+ UcaNetMessageGrabRequest *request;
+ gsize bytes_left;
+ GError *error = NULL;
+ UcaNetDefaultReply reply = { .type = UCA_NET_MESSAGE_GRAB };
+ static gsize size = 0;
+ static gchar *buffer = NULL;
+
+ request = (UcaNetMessageGrabRequest *) message;
+ output = g_io_stream_get_output_stream (G_IO_STREAM (connection));
+
+ if (buffer == NULL || size != request->size) {
+ buffer = g_realloc (buffer, request->size);
+ size = request->size;
+ }
+
+ uca_camera_grab (camera, buffer, &error);
+ prepare_error_reply (error, &reply.error);
+ send_reply (connection, &reply, sizeof (reply), stream_error);
+
+ /* send data if no error occured during grab */
+ if (!reply.error.occurred) {
+ bytes_left = size;
+
+ while (bytes_left > 0) {
+ gssize written;
+
+ written = g_output_stream_write (output, &buffer[size - bytes_left], bytes_left, NULL, stream_error);
+
+ if (written < 0)
+ return;
+
+ bytes_left -= written;
+ }
+ }
+}
+
+static void
+serve_connection (GSocketConnection *connection, UcaCamera *camera)
+{
+ GInputStream *input;
+ gchar *buffer;
+ gboolean active;
+
+ HandlerTable table[] = {
+ { UCA_NET_MESSAGE_GET_PROPERTY, handle_get_property_request },
+ { UCA_NET_MESSAGE_SET_PROPERTY, handle_set_property_request },
+ { UCA_NET_MESSAGE_START_RECORDING, handle_start_recording_request },
+ { UCA_NET_MESSAGE_STOP_RECORDING, handle_stop_recording_request },
+ { UCA_NET_MESSAGE_START_READOUT, handle_start_readout_request },
+ { UCA_NET_MESSAGE_STOP_READOUT, handle_stop_readout_request },
+ { UCA_NET_MESSAGE_TRIGGER, handle_trigger_request },
+ { UCA_NET_MESSAGE_GRAB, handle_grab_request },
+ { UCA_NET_MESSAGE_INVALID, NULL }
+ };
+
+ buffer = g_malloc0 (4096);
+ input = g_io_stream_get_input_stream (G_IO_STREAM (connection));
+ active = TRUE;
+
+ while (active) {
+ UcaNetMessageDefault *message;
+ GError *error = NULL;
+
+ /* looks dangerous */
+ g_input_stream_read (input, buffer, 4096, NULL, &error);
+ message = (UcaNetMessageDefault *) buffer;
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE)) {
+ g_error_free (error);
+ active = FALSE;
+ break;
+ }
+
+ if (message->type == UCA_NET_MESSAGE_CLOSE_CONNECTION) {
+ active = FALSE;
+ break;
+ }
+
+ for (guint i = 0; table[i].type != UCA_NET_MESSAGE_INVALID; i++) {
+ if (table[i].type == message->type)
+ table[i].handler (connection, camera, buffer, &error);
+ }
+
+ if (error != NULL) {
+ g_warning ("Error handling requests: %s", error->message);
+ g_error_free (error);
+ active = FALSE;
+ }
+ }
+
+ g_free (buffer);
}
static gboolean
@@ -148,18 +297,6 @@ run_callback (GSocketService *service, GSocketConnection *connection, GObject *s
GInetAddress *address;
gchar *address_string;
- UcaNetHandlers handlers = {
- .user_data = user_data,
- .get_property = handle_get_property_request,
- .set_property = handle_set_property_request,
- .start_recording = handle_start_recording_request,
- .stop_recording = handle_stop_recording_request,
- .start_readout = handle_start_readout_request,
- .stop_readout = handle_stop_readout_request,
- .trigger = handle_trigger_request,
- .grab = handle_grab_request,
- };
-
sock_address = G_INET_SOCKET_ADDRESS (g_socket_connection_get_remote_address (connection, NULL));
address = g_inet_socket_address_get_address (sock_address);
address_string = g_inet_address_to_string (address);
@@ -168,8 +305,7 @@ run_callback (GSocketService *service, GSocketConnection *connection, GObject *s
g_free (address_string);
g_object_unref (sock_address);
- uca_net_server_register_handlers (&handlers);
- uca_net_server_handle (connection);
+ serve_connection (connection, UCA_CAMERA (user_data));
return FALSE;
}