summaryrefslogtreecommitdiffstats
path: root/uca-net-server.c
diff options
context:
space:
mode:
authorMatthias Vogelgesang <matthias.vogelgesang@kit.edu>2016-02-16 11:53:28 +0100
committerMatthias Vogelgesang <matthias.vogelgesang@kit.edu>2016-02-16 11:53:28 +0100
commitf431158ae2412ed23bd4d2336af00d2b5c170d31 (patch)
tree52c5fbbc7ba26f7444edbe7d0e8d80ed67796384 /uca-net-server.c
downloaduca-net-f431158ae2412ed23bd4d2336af00d2b5c170d31.tar.gz
uca-net-f431158ae2412ed23bd4d2336af00d2b5c170d31.tar.bz2
uca-net-f431158ae2412ed23bd4d2336af00d2b5c170d31.tar.xz
uca-net-f431158ae2412ed23bd4d2336af00d2b5c170d31.zip
Initial commit
Diffstat (limited to 'uca-net-server.c')
-rw-r--r--uca-net-server.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/uca-net-server.c b/uca-net-server.c
new file mode 100644
index 0000000..f038cd6
--- /dev/null
+++ b/uca-net-server.c
@@ -0,0 +1,174 @@
+#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
+uca_net_server_handle_start_recording (GOutputStream *output, GError **stream_error)
+{
+ UcaNetDefaultReply reply = { .type = UCA_NET_MESSAGE_START_RECORDING };
+ GError *error = NULL;
+
+ handlers.start_recording (handlers.user_data, &error);
+ prepare_error_reply (error, &reply.error);
+ send_reply (output, &reply, sizeof (reply), stream_error);
+}
+
+static void
+uca_net_server_handle_stop_recording (GOutputStream *output, GError **stream_error)
+{
+ UcaNetDefaultReply reply = { .type = UCA_NET_MESSAGE_STOP_RECORDING };
+ GError *error = NULL;
+
+ handlers.stop_recording (handlers.user_data, &error);
+ prepare_error_reply (error, &reply.error);
+ send_reply (output, &reply, sizeof (reply), 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_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);
+}