diff options
author | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2016-02-16 11:53:28 +0100 |
---|---|---|
committer | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2016-02-16 11:53:28 +0100 |
commit | f431158ae2412ed23bd4d2336af00d2b5c170d31 (patch) | |
tree | 52c5fbbc7ba26f7444edbe7d0e8d80ed67796384 /uca-net-server.c | |
download | uca-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.c | 174 |
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); +} |