#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; }