summaryrefslogtreecommitdiff
path: root/response.c
blob: db008dd08b99369fd21d069626a9c9a081b4589e (plain)
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "response.h"
#include "socket-common.h"
#include "lcd.h"
#include "i2c.h"
#include "signalobject.h"
#include "parser.h"
#include <string.h>
#include <stdlib.h>
#include <glib.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 void writeOutput(GPollableOutputStream* stream, gchar* data);

//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;
	GError* error = NULL;

	if(!g_pollable_input_stream_is_readable(inStream)) { return FALSE; }
	size=g_pollable_input_stream_read_nonblocking(inStream, buffer, 1024, NULL, &error);
	
	if(error && error->message)
	{
		g_print_debug("Error: %s\n",error->message);
		return FALSE;
	}
	
	if(size <= 0) {
		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 void writeOutput(GPollableOutputStream* stream, gchar* data)
{
	gssize written_bytes = 0;

	gchar *terminated;
	if (data==NULL) {
		terminated = g_strdup("\r\n");
	} else if (!strlen(data)) {
		terminated = g_strdup("> ");
	} else {
		terminated = g_strdup_printf ("%s\r\n", data);
	}

	written_bytes = g_pollable_output_stream_write_nonblocking(stream, terminated, strlen(terminated), NULL, NULL);
	if (written_bytes == -1) {
		g_print("Could not send message to client\n");
	}

	g_free (terminated);
	return;
}

//initialize the signals
void initSignals(guint *signal)
{
	*signal = g_signal_new("runService", 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, "runService", G_CALLBACK (responseCb), NULL);
}

//parse message and send to client
void responseCb(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;

	g_strstrip(str);

	// I2C/LCD test functions - start
	guchar status = I2C_Read (PCF8574A + Upper_Encoder_Port);
	gchar *lcd_str = g_strdup_printf ("%s %x",str,status);
	LCD_display_error_message(lcd_str);
	// I2C/LCD test functions - stop

	// FIXME - Parser_main may generate multiple responses
	Parser_main(str, 1, data->cb, stream);

	g_static_mutex_unlock (&mutex);
}