diff options
Diffstat (limited to 'instr-client.c')
-rw-r--r-- | instr-client.c | 143 |
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 |