aboutsummaryrefslogtreecommitdiff
path: root/include/Gobbledegook.h
blob: 6213c0ff2ff8542499e604b63c4828909ef34ef5 (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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
// Copyright 2017 Paul Nettle. 
// 
// This file is part of Gobbledegook. 
// 
// Gobbledegook is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
// 
// Gobbledegook is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more details. 
// 
// You should have received a copy of the GNU General Public License 
// along with Gobbledegook.  If not, see <http://www.gnu.org/licenses/>. 
 
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
// 
// >> 
// >>>  INSIDE THIS FILE 
// >> 
// 
// This file represents the complete interface to Gobbledegook from a stand-alone application. 
// 
// >> 
// >>>  DISCUSSION 
// >> 
// 
// The interface to Gobbledegook is rether simple. It consists of the following categories of functionality: 
// 
//     * Logging 
// 
//       The server defers all logging to the application. The application registers a set of logging delegates (one for each 
//       log level) so it can manage the logs however it wants (syslog, console, file, an external logging service, etc.) 
// 
//     * Managing updates to server data 
// 
//       The application is required to implement two delegates (`GGKServerDataGetter` and `GGKServerDataSetter`) for sharing data 
//       with the server. See standalone.cpp for an example of how this is done. 
// 
//       In addition, the server provides a thread-safe queue for notifications of data updates to the server. Generally, the only 
//       methods an application will need to call are `ggkNofifyUpdatedCharacteristic` and `ggkNofifyUpdatedDescriptor`. The other 
//       methods are provided in case an application requies extended functionality. 
// 
//     * Server control 
// 
//       A small set of methods for starting and stopping the server. 
// 
//     * Server state 
// 
//       These routines allow the application to query the server's current state. The server runs through these states during its 
//       lifecycle: 
// 
//           EUninitialized -> EInitializing -> ERunning -> EStopping -> EStopped 
// 
//     * Server health 
// 
//       The server maintains its own health information. The states are: 
// 
//           EOk         - the server is A-OK 
//           EFailedInit - the server had a failure prior to the ERunning state 
//           EFailedRun  - the server had a failure during the ERunning state 
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 
#pragma once
 
#ifdef __cplusplus
extern "C"
{
#endif //__cplusplus 
 
// ----------------------------------------------------------------------------------------------------------------------------- 
// LOGGING 
// ----------------------------------------------------------------------------------------------------------------------------- 
 
// Type definition for callback delegates that receive log messages 
typedef void (*GGKLogReceiver)(const char *pMessage);
 
// Each of these methods registers a log receiver method. Receivers are set when registered. To unregister a log receiver, 
// simply register with `nullptr`. 
void ggkLogRegisterDebug(GGKLogReceiver receiver);
void ggkLogRegisterInfo(GGKLogReceiver receiver);
void ggkLogRegisterStatus(GGKLogReceiver receiver);
void ggkLogRegisterWarn(GGKLogReceiver receiver);
void ggkLogRegisterError(GGKLogReceiver receiver);
void ggkLogRegisterFatal(GGKLogReceiver receiver);
void ggkLogRegisterAlways(GGKLogReceiver receiver);
void ggkLogRegisterTrace(GGKLogReceiver receiver);
 
// ----------------------------------------------------------------------------------------------------------------------------- 
// SERVER DATA 
// ----------------------------------------------------------------------------------------------------------------------------- 
 
// Type definition for a delegate that the server will use when it needs to receive data from the host application 
// 
// IMPORTANT: 
// 
// This will be called from the server's thread. Be careful to ensure your implementation is thread safe. 
// 
// Similarly, the pointer to data returned to the server should point to non-volatile memory so that the server can use it 
// safely for an indefinite period of time. 
typedef const void *(*GGKServerDataGetter)(const char *pName);
 
// Type definition for a delegate that the server will use when it needs to notify the host application that data has changed 
// 
// IMPORTANT: 
// 
// This will be called from the server's thread. Be careful to ensure your implementation is thread safe. 
// 
// The data setter uses void* types to allow receipt of unknown data types from the server. Ensure that you do not store these 
// pointers. Copy the data before returning from your getter delegate. 
// 
// This method returns a non-zero value on success or 0 on failure. 
// 
// Possible failures: 
// 
//   * pName is null 
//   * pData is null 
//   * pName is not a supported value to store 
//   * Any other failure, as deemed by the delegate handler 
typedef int (*GGKServerDataSetter)(const char *pName, const void *pData);
 
// ----------------------------------------------------------------------------------------------------------------------------- 
// SERVER DATA UPDATE MANAGEMENT 
// ----------------------------------------------------------------------------------------------------------------------------- 
 
// Adds an update to the front of the queue for a characteristic at the given object path 
// 
// Returns non-zero value on success or 0 on failure. 
int ggkNofifyUpdatedCharacteristic(const char *pObjectPath);
 
// Adds an update to the front of the queue for a descriptor at the given object path 
// 
// Returns non-zero value on success or 0 on failure. 
int ggkNofifyUpdatedDescriptor(const char *pObjectPath);
 
// Adds a named update to the front of the queue. Generally, this routine should not be used directly. Instead, use the 
// `ggkNofifyUpdatedCharacteristic()` instead. 
// 
// Returns non-zero value on success or 0 on failure. 
int ggkPushUpdateQueue(const char *pObjectPath, const char *pInterfaceName);
 
// Get the next update from the back of the queue and returns the element in `element` as a string in the format: 
// 
//     "com/object/path|com.interface.name" 
// 
// If the queue is empty, this method returns `0` and does nothing. 
// 
// `elementLen` is the size of the `element` buffer in bytes. If the resulting string (including the null terminator) will not 
// fit within `elementLen` bytes, the method returns `-1` and does nothing. 
// 
// If `keep` is set to non-zero, the entry is not removed and will be retrieved again on the next call. Otherwise, the element 
// is removed. 
// 
// Returns 1 on success, 0 if the queue is empty, -1 on error (such as the length too small to store the element) 
int ggkPopUpdateQueue(char *pElement, int elementLen, int keep);
 
// Returns 1 if the queue is empty, otherwise 0 
int ggkUpdateQueueIsEmpty();
 
// Returns the number of entries waiting in the queue 
int ggkUpdateQueueSize();
 
// Removes all entries from the queue 
void ggkUpdateQueueClear();
 
// ----------------------------------------------------------------------------------------------------------------------------- 
// SERVER CONTROL 
// ----------------------------------------------------------------------------------------------------------------------------- 
 
// Set the server state to 'EInitializing' and then immediately create a server thread and initiate the server's async 
// processing on the server thread. 
// 
// At that point the current thread will block for maxAsyncInitTimeoutMS milliseconds or until initialization completes. 
// 
// If initialization was successful, the method will return a non-zero value with the server running on its own thread in 
// 'runServerThread'. 
// 
// If initialization was unsuccessful, this method will continue to block until the server has stopped. This method will then 
// return 0. 
// 
// IMPORTANT: 
// 
// The data setter uses void* types to allow receipt of unknown data types from the server. Ensure that you do not store these 
// pointers. Copy the data before returning from your getter delegate. 
// 
// Similarly, the pointer to data returned to the data getter should point to non-volatile memory so that the server can use it 
// safely for an indefinite period of time. 
int ggkStart(GGKServerDataGetter getter, GGKServerDataSetter setter, int maxAsyncInitTimeoutMS);
 
// Blocks for up to maxAsyncInitTimeoutMS milliseconds until the server shuts down. 
// 
// If shutdown is successful, this method will return a non-zero value. Otherwise, it will return 0. 
// 
// If the server fails to stop for some reason, the thread will be killed. 
// 
// Typically, a call to this method would follow `ggkTriggerShutdown()`. 
int ggkWait();
 
// Tells the server to begin the shutdown process 
// 
// The shutdown process will interrupt any currently running asynchronous operation and prevent new operations from starting. 
// Once the server has stabilized, its event processing loop is terminated and the server is cleaned up. 
// 
// `ggkGetServerRunState` will return EStopped when shutdown is complete. To block until the shutdown is complete, see 
// `ggkWait()`. 
// 
// Alternatively, you can use `ggkShutdownAndWait()` to request the shutdown and block until the shutdown is complete. 
void ggkTriggerShutdown();
 
// Convenience method to trigger a shutdown (via `ggkTriggerShutdown()`) and also waits for shutdown to complete (via 
// `ggkWait()`) 
int ggkShutdownAndWait();
 
// ----------------------------------------------------------------------------------------------------------------------------- 
// SERVER STATE 
// ----------------------------------------------------------------------------------------------------------------------------- 
 
// Current state of the server 
// 
// States should progress through states in this order: 
// 
//     EUninitialized -> EInitializing -> ERunning -> EStopping -> EStopped 
// 
// Note that in some cases, a server may skip one or more states, as is the case of a failed initialization where the server 
// will progress from EInitializing directly to EStopped. 
// 
// Use `ggkGetServerRunState` to retrive the state and `ggkGetServerRunStateString` to convert a `GGKServerRunState` into a 
// human-readable string. 
enum GGKServerRunState
{
EUninitialized,
EInitializing,
ERunning,
EStopping,
EStopped
};
 
// Retrieve the current running state of the server 
// 
// See `GGKServerRunState` (enumeration) for more information. 
enum GGKServerRunState ggkGetServerRunState();
 
// Convert a `GGKServerRunState` into a human-readable string 
const char *ggkGetServerRunStateString(enum GGKServerRunState state);
 
// Convenience method to check ServerRunState for a running server 
int ggkIsServerRunning();
 
// ----------------------------------------------------------------------------------------------------------------------------- 
// SERVER HEALTH 
// ----------------------------------------------------------------------------------------------------------------------------- 
 
// The current health of the server 
// 
// A running server's health will always be EOk, therefore it is only necessary to check the health status after the server 
// has shut down to determine if it was shut down due to an unhealthy condition. 
// 
// Use `ggkGetServerHealth` to retrieve the health and `ggkGetServerHealthString` to convert a `GGKServerHealth` into a 
// human-readable string. 
enum GGKServerHealth
{
EOk,
EFailedInit,
EFailedRun
};
 
// Retrieve the current health of the server 
// 
// See `GGKServerHealth` (enumeration) for more information. 
enum GGKServerHealth ggkGetServerHealth();
 
// Convert a `GGKServerHealth` into a human-readable string 
const char *ggkGetServerHealthString(enum GGKServerHealth state);
 
#ifdef __cplusplus
}
#endif //__cplusplus