Repository navigation
Expand file tree
/
Copy pathctrl.c
More file actions
129 lines (113 loc) · 4.12 KB
/
Copy pathctrl.c
File metadata and controls
129 lines (113 loc) · 4.12 KB
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
#include <glib.h>
#include <teenynet/unix.h>
#include "ctrl.h"
#include "apps.h"
#include "network.h"
#include "utils.h"
#include "tbus.h"
static GPtrArray* clientconnections;
static GHashTable* clientappmapping;
static GSocketService* socketservice;
static void ctrl_disconnectapp(gpointer data, gpointer user_data) {
GSocketConnection* connection = data;
gpointer existingmapping = g_hash_table_lookup(clientappmapping,
connection);
if (existingmapping != NULL) {
guint index = GPOINTER_TO_UINT(existingmapping);
g_hash_table_remove(clientappmapping, connection);
apps_onappdisconnected(index);
}
g_ptr_array_remove(clientconnections, connection);
g_object_unref(connection);
}
static void ctrl_fieldproc_appstate(struct tbus_fieldandbuff* field,
gpointer target, gpointer user_data) {
g_message("processing app state field");
struct apps_appstateupdate* appstate = target;
switch (field->field.raw.type) {
case THINGYMCCONFIG_FIELDTYPE_APPSTATEUPDATE_APPINDEX:
appstate->appindex =
((struct thingymcconfig_ctrl_field_index*) field)->index;
break;
case THINGYMCCONFIG_FIELDTYPE_APPSTATEUPDATE_APPSTATE: {
struct thingymcconfig_ctrl_field_stateanderror* f =
(struct thingymcconfig_ctrl_field_stateanderror*) field;
appstate->appstate = f->state;
appstate->apperror = f->error;
}
break;
case THINGYMCCONFIG_FIELDTYPE_APPSTATEUPDATE_CONNECTIVITY: {
struct thingymcconfig_ctrl_field_stateanderror* f =
(struct thingymcconfig_ctrl_field_stateanderror*) field;
appstate->connectivitystate = f->state;
appstate->connectivityerror = f->error;
}
break;
}
}
static void ctrl_emitter_appstate(gpointer target, gpointer user_data) {
struct apps_appstateupdate* appstate = target;
GSocketConnection* connection = user_data;
gpointer existingmapping = g_hash_table_lookup(clientappmapping,
connection);
if (existingmapping != NULL) {
guint index = GPOINTER_TO_UINT(existingmapping);
if (appstate->appindex != index) {
g_message("app has mysteriously changed it's index %u to %u", index,
appstate->appindex);
}
} else {
gpointer index = GUINT_TO_POINTER((guint ) appstate->appstate);
g_hash_table_insert(clientappmapping, connection, index);
}
apps_onappstateupdate(appstate);
}
static struct tbus_messageprocessor msgproc[] = {
[THINGYMCCONFIG_MSGTYPE_EVENT_APPSTATEUPDATE] = { .allocsize =
sizeof(struct apps_appstateupdate), .fieldprocessor =
ctrl_fieldproc_appstate, .emitter = ctrl_emitter_appstate } };
static gboolean ctrl_appincallback(GIOChannel *source, GIOCondition condition,
gpointer data) {
GSocketConnection* connection = data;
g_message("incoming data from app");
GInputStream* is = g_io_stream_get_input_stream(G_IO_STREAM(connection));
gboolean ret = tbus_readmsg(is, msgproc, G_N_ELEMENTS(msgproc), connection);
if (!ret)
ctrl_disconnectapp(connection, NULL);
return ret;
}
static gboolean ctrl_incomingcallback(GSocketService *service,
GSocketConnection *connection, GObject *source_object,
gpointer user_data) {
g_message("incoming control socket connection");
GOutputStream* os = g_io_stream_get_output_stream(G_IO_STREAM(connection));
if (apps_ctrl_sendconfig(os) && network_ctrl_sendstate(os)) {
g_object_ref(connection);
g_ptr_array_add(clientconnections, connection);
utils_addwatchforsocket(g_socket_connection_get_socket(connection),
G_IO_IN, ctrl_appincallback, connection);
}
return TRUE;
}
void ctrl_init() {
clientconnections = g_ptr_array_new();
clientappmapping = g_hash_table_new(g_direct_hash, g_direct_equal);
}
void ctrl_start() {
socketservice = unix_socketservice_create(THINGYMCCONFIG_CTRLSOCKPATH,
ctrl_incomingcallback, NULL);
}
static void ctrl_notifyclientofnetworkstatechange(gpointer data,
gpointer user_data) {
GSocketConnection* clientconnection = data;
network_ctrl_sendstate(
g_io_stream_get_output_stream(G_IO_STREAM(clientconnection)));
}
void ctrl_onnetworkstatechange() {
g_ptr_array_foreach(clientconnections,
ctrl_notifyclientofnetworkstatechange, NULL);
}
void ctrl_stop() {
unix_socketservice_destroy(socketservice, THINGYMCCONFIG_CTRLSOCKPATH);
g_ptr_array_foreach(clientconnections, ctrl_disconnectapp, NULL);
}