summaryrefslogtreecommitdiff
path: root/instr-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'instr-client.c')
-rw-r--r--instr-client.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/instr-client.c b/instr-client.c
new file mode 100644
index 0000000..0269f61
--- /dev/null
+++ b/instr-client.c
@@ -0,0 +1,143 @@
+#include <stdio.h>
+#include <gio/gio.h>
+#include <string.h>
+#include "response.h"
+#include <stdlib.h>
+#include <strings.h>
+
+static int port = 3333;
+#define BUFSIZE 1024
+
+GMainContext *context=NULL;
+GMainLoop *mainLoop=NULL;
+GSocketConnection * connection = NULL;
+GSocketClient * client = NULL;
+
+char exitTokens[5][7] = {"quit", "exit", "logout", "logoff", "local"};
+
+//helper function to nicely terminate the client
+static void terminate(char *message, int exitCode)
+{
+ g_object_unref(client);
+ g_object_unref(connection);
+ if (message) {
+ g_print("%s\n", message);
+ }
+ exit(exitCode);
+}
+
+//a sort of strncmp but with \n or \r exception
+static gboolean Matches(char *src, char* dst, gssize size)
+{
+ for(; *src != '\0', (size--)>0; src++) {
+ if(g_ascii_toupper(*src) != g_ascii_toupper(*dst)) {
+ return FALSE;
+ }
+ dst++;
+ }
+ for(; *dst != '\0'; dst++)
+ if (*dst != '\r' && *dst != '\n') {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+//GIOChannel callback
+static gboolean
+stdinAvailable (GIOChannel *source, GIOCondition condition, gpointer data)
+{
+ char tmp[BUFSIZE];
+ memset(tmp,0,BUFSIZE);
+ int size = read(0, tmp, BUFSIZE);
+ if(size<=0) {
+ return TRUE;
+ }
+
+ //test if we have an exit word
+ int idx=0;
+ for(idx=0; idx<sizeof(exitTokens)/sizeof(exitTokens[0]); idx++) {
+ if(Matches(exitTokens[idx], tmp, strlen(exitTokens[idx]))) {
+ g_socket_close(g_socket_connection_get_socket(connection), NULL);
+ terminate("Goodbye", 0);
+ }
+ }
+
+ //write the message
+ gssize written=0;
+ GPollableOutputStream* out = (GPollableOutputStream*)data;
+ written = g_pollable_output_stream_write_nonblocking(out, tmp, size, NULL, NULL);
+ if (written <=0 || written == G_IO_ERROR_WOULD_BLOCK) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//callback for server input
+static gboolean cbServerInput(gpointer data, gpointer additional)
+{
+ char buffer[BUFSIZE];
+ gssize size=0;
+ memset(buffer,0,BUFSIZE);
+
+ GPollableInputStream* inStream = (GPollableInputStream*)data;
+
+ size=g_pollable_input_stream_read_nonblocking(inStream, buffer, BUFSIZE, NULL, NULL);
+ if(size <=0 || size == G_IO_ERROR_WOULD_BLOCK) {
+ terminate("Connection to server lost", -1);
+ }
+ g_print("\n%s", buffer);
+ g_print("> ");
+ return TRUE;
+}
+
+int main(int argc, char** argv)
+{
+ /* create a new connection */
+ g_type_init ();
+
+ GOutputStream *out;
+ GInputStream *in;
+ GError* error = NULL;
+ GIOChannel* stdinChannel = NULL;
+ client = g_socket_client_new();
+ GSource *source = NULL;
+
+ /* connect to the host */
+ connection = g_socket_client_connect_to_host (client,
+ (gchar*)"localhost",
+ port,
+ NULL,
+ &error);
+
+ if (error != NULL) {
+ g_print("Could not connect to server on port %d\n", port);
+ g_object_unref(client);
+ return -1;
+ }
+ g_print("> ");
+
+
+ //register Pollable sources
+ out = g_io_stream_get_output_stream (G_IO_STREAM (connection));
+ in = g_io_stream_get_input_stream (G_IO_STREAM (connection));
+ GSource *outSource = NULL;
+ GSource *inSource = g_pollable_input_stream_create_source((struct GPollableInputStream*)in, NULL);
+ outSource = g_pollable_output_stream_create_source((struct GPollableOutputStream*)out, NULL);
+
+ //register stdin channel
+ stdinChannel = g_io_channel_unix_new(0);
+ if(stdinChannel == NULL) {
+ terminate("Could not open STDIN channel", -2);
+ }
+
+ //attach the sources
+ g_io_add_watch(stdinChannel, G_IO_IN, stdinAvailable, (struct GPollableOutputStream*)out);
+ g_source_set_callback(inSource, cbServerInput, (GPollableOutputStream*)in, NULL);
+
+ g_source_attach(inSource, NULL);
+ g_main_loop_run (g_main_loop_new (NULL, FALSE));
+ return 0;
+} \ No newline at end of file