1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#include "response.h"
#include "socket-common.h"
#include <string.h>
//RESPONSE related functions from the server
extern guint signalMyCb; //signal id
extern GAsyncQueue* stdinQueue; //our queue
SignalObject* signalObject; //the signal object which registered the signal id
//write output to client
static gssize writeOutput(GPollableOutputStream* stream, gchar* data, gssize size);
//callback for client output, this is where the queue messages are sent to the client
gboolean cbClientOutput(gpointer data, gpointer additional)
{
GPollableOutputStream* outStream = (GPollableOutputStream*)data;
GAsyncQueue* queue = (GAsyncQueue*)additional;
if(g_async_queue_length(queue) <= 0) return FALSE;
gpointer elem;
g_print_debug("Try pop\n");
//try to pop an element from the queue
elem=g_async_queue_try_pop(queue);
g_print_debug("after pop\n");
if(elem)
{
char* buf = (char*)elem;
g_print_debug("Extracted %s\n", buf);
gssize size = strlen(buf);
gssize written = 0;
written=g_pollable_output_stream_write_nonblocking(outStream, buf, size+1, NULL, NULL);
if(written==-1) g_printerr("Could not write to client\n");
//free the alloc'ed memory
free(buf);
}
return FALSE;
}
//the client input callback
gboolean cbClientInput(gpointer data, gpointer additional)
{
char buffer[1024];
gssize size=0;
memset(buffer,0,1024);
GPollableInputStream* inStream = (GPollableInputStream*)data;
GPollableOutputStream* outStream = (GPollableOutputStream*)additional;
size=g_pollable_input_stream_read_nonblocking(inStream, buffer, 1024, NULL, NULL);
if(size <=0 || size == G_IO_ERROR_WOULD_BLOCK) { g_print_debug("Got: %d\n", size); return FALSE; }
//emit a signal which calls the echoCb function
SignalObjectClass myStruct;
myStruct.instance = NULL;
myStruct.cb = writeOutput;
myStruct.data = buffer;
myStruct.size = size;
myStruct.inStream = inStream;
myStruct.outStream = outStream;
g_signal_emit(signalObject, signalMyCb, 0, &myStruct, NULL);
return TRUE;
}
//write output to client
static gssize writeOutput(GPollableOutputStream* stream, gchar* data, gssize size)
{
gssize what=0;
what=g_pollable_output_stream_write_nonblocking(stream, data, size, NULL, NULL);
if(what < 0 || what == G_IO_ERROR_WOULD_BLOCK) { return -1; }
return what;
}
//initialize the signals
void initSignals(guint *signal)
{
*signal = g_signal_new("runEchoService", SIGNAL_OBJECT_TYPE, G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
g_cclosure_marshal_VOID__POINTER , G_TYPE_NONE, 1, G_TYPE_POINTER);
signalObject = g_object_new(SIGNAL_OBJECT_TYPE, NULL);
g_signal_connect (signalObject, "runEchoService", G_CALLBACK (echoCb), NULL);
}
//echo 3 times and send to client one time
void echoCb(gpointer instance, GObject *arg1, gpointer user_data)
{
static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
g_static_mutex_lock (&mutex);
SignalObjectClass *data = (SignalObjectClass*)arg1;
GPollableOutputStream* stream = (GPollableOutputStream*)data->outStream;
gchar* str = data->data;
gssize len = data->size;
gssize written = 0;
gchar* upper = g_ascii_strup(str, len);
int i;
for(i=0; i<3; i++) g_print("%s\n", upper);
//send response back to client
written = data->cb(stream, upper, len);
g_free(upper);
g_static_mutex_unlock (&mutex);
}
|