czmq-ffi-gen 0.9.2-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/AUTHORS +1 -0
- data/CHANGES.md +92 -0
- data/Gemfile +2 -0
- data/LICENSE +14 -0
- data/README.md +112 -0
- data/lib/czmq-ffi-gen.rb +7 -0
- data/lib/czmq-ffi-gen/czmq/ffi.rb +1210 -0
- data/lib/czmq-ffi-gen/czmq/ffi/version.rb +15 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zactor.rb +186 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zarmour.rb +286 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zcert.rb +307 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zcertstore.rb +222 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zchunk.rb +388 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zclock.rb +140 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zconfig.rb +442 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zdigest.rb +156 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zdir.rb +283 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zdir_patch.rb +194 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zfile.rb +353 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zframe.rb +359 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zhash.rb +416 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zhashx.rb +659 -0
- data/lib/czmq-ffi-gen/czmq/ffi/ziflist.rb +189 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zlist.rb +365 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zlistx.rb +478 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zloop.rb +396 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zmsg.rb +515 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zpoller.rb +194 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zproc.rb +294 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zsock.rb +3479 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zstr.rb +203 -0
- data/lib/czmq-ffi-gen/czmq/ffi/ztimerset.rb +203 -0
- data/lib/czmq-ffi-gen/czmq/ffi/ztrie.rb +221 -0
- data/lib/czmq-ffi-gen/czmq/ffi/zuuid.rb +227 -0
- data/lib/czmq-ffi-gen/errors.rb +12 -0
- data/lib/czmq-ffi-gen/gem_version.rb +5 -0
- data/lib/czmq-ffi-gen/legacy.rb +16 -0
- data/lib/czmq-ffi-gen/libzmq.rb +18 -0
- data/lib/czmq-ffi-gen/signals.rb +27 -0
- data/lib/czmq-ffi-gen/vendor.rb +5 -0
- data/lib/czmq-ffi-gen/versions.rb +19 -0
- data/vendor/local/bin/inproc_lat.exe +0 -0
- data/vendor/local/bin/inproc_thr.exe +0 -0
- data/vendor/local/bin/libczmq.dll +0 -0
- data/vendor/local/bin/libgcc_s_seh-1.dll +0 -0
- data/vendor/local/bin/libstdc++-6.dll +0 -0
- data/vendor/local/bin/libzmq.dll +0 -0
- data/vendor/local/bin/local_lat.exe +0 -0
- data/vendor/local/bin/local_thr.exe +0 -0
- data/vendor/local/bin/remote_lat.exe +0 -0
- data/vendor/local/bin/remote_thr.exe +0 -0
- data/vendor/local/include/czmq.h +31 -0
- data/vendor/local/include/czmq_library.h +199 -0
- data/vendor/local/include/czmq_prelude.h +641 -0
- data/vendor/local/include/readme.txt +83 -0
- data/vendor/local/include/sha1.h +76 -0
- data/vendor/local/include/sha1.inc_c +335 -0
- data/vendor/local/include/slre.h +92 -0
- data/vendor/local/include/slre.inc_c +660 -0
- data/vendor/local/include/zactor.h +76 -0
- data/vendor/local/include/zarmour.h +114 -0
- data/vendor/local/include/zauth.h +100 -0
- data/vendor/local/include/zauth_v2.h +88 -0
- data/vendor/local/include/zbeacon.h +86 -0
- data/vendor/local/include/zbeacon_v2.h +75 -0
- data/vendor/local/include/zcert.h +136 -0
- data/vendor/local/include/zcertstore.h +100 -0
- data/vendor/local/include/zchunk.h +163 -0
- data/vendor/local/include/zclock.h +73 -0
- data/vendor/local/include/zconfig.h +185 -0
- data/vendor/local/include/zctx.h +107 -0
- data/vendor/local/include/zdigest.h +65 -0
- data/vendor/local/include/zdir.h +149 -0
- data/vendor/local/include/zdir_patch.h +82 -0
- data/vendor/local/include/zfile.h +177 -0
- data/vendor/local/include/zframe.h +176 -0
- data/vendor/local/include/zgossip.h +95 -0
- data/vendor/local/include/zgossip_engine.inc +927 -0
- data/vendor/local/include/zgossip_msg.h +129 -0
- data/vendor/local/include/zhash.h +195 -0
- data/vendor/local/include/zhash_primes.inc +329 -0
- data/vendor/local/include/zhashx.h +298 -0
- data/vendor/local/include/ziflist.h +77 -0
- data/vendor/local/include/zlist.h +158 -0
- data/vendor/local/include/zlistx.h +205 -0
- data/vendor/local/include/zloop.h +168 -0
- data/vendor/local/include/zmonitor.h +73 -0
- data/vendor/local/include/zmonitor_v2.h +56 -0
- data/vendor/local/include/zmq.h +617 -0
- data/vendor/local/include/zmq_utils.h +48 -0
- data/vendor/local/include/zmsg.h +280 -0
- data/vendor/local/include/zmutex.h +55 -0
- data/vendor/local/include/zpoller.h +92 -0
- data/vendor/local/include/zproc.h +168 -0
- data/vendor/local/include/zproxy.h +111 -0
- data/vendor/local/include/zproxy_v2.h +62 -0
- data/vendor/local/include/zrex.h +82 -0
- data/vendor/local/include/zsock.h +912 -0
- data/vendor/local/include/zsock_option.inc +4126 -0
- data/vendor/local/include/zsocket.h +110 -0
- data/vendor/local/include/zsockopt.h +256 -0
- data/vendor/local/include/zstr.h +110 -0
- data/vendor/local/include/zsys.h +386 -0
- data/vendor/local/include/zthread.h +50 -0
- data/vendor/local/include/ztimerset.h +90 -0
- data/vendor/local/include/ztrie.h +106 -0
- data/vendor/local/include/zuuid.h +96 -0
- data/vendor/local/lib/libczmq.dll.a +0 -0
- data/vendor/local/lib/liblibzmq.dll.a +0 -0
- data/vendor/local/lib/libzmq-static.a +0 -0
- data/vendor/local/lib/pkgconfig/libczmq.pc +23 -0
- data/vendor/local/lib/pkgconfig/libzmq.pc +11 -0
- data/vendor/local/share/zmq/AUTHORS.txt +147 -0
- data/vendor/local/share/zmq/COPYING.LESSER.txt +181 -0
- data/vendor/local/share/zmq/COPYING.txt +674 -0
- data/vendor/local/share/zmq/NEWS.txt +978 -0
- metadata +230 -0
@@ -0,0 +1,927 @@
|
|
1
|
+
/* =========================================================================
|
2
|
+
zgossip_engine - zgossip engine
|
3
|
+
|
4
|
+
** WARNING *************************************************************
|
5
|
+
THIS SOURCE FILE IS 100% GENERATED. If you edit this file, you will lose
|
6
|
+
your changes at the next build cycle. This is great for temporary printf
|
7
|
+
statements. DO NOT MAKE ANY CHANGES YOU WISH TO KEEP. The correct places
|
8
|
+
for commits are:
|
9
|
+
|
10
|
+
* The XML model used for this code generation: zgossip.xml, or
|
11
|
+
* The code generation script that built this file: zproto_server_c
|
12
|
+
************************************************************************
|
13
|
+
Copyright (c) the Contributors as noted in the AUTHORS file.
|
14
|
+
This file is part of CZMQ, the high-level C binding for 0MQ:
|
15
|
+
http://czmq.zeromq.org.
|
16
|
+
|
17
|
+
This Source Code Form is subject to the terms of the Mozilla Public
|
18
|
+
License, v. 2.0. If a copy of the MPL was not distributed with this
|
19
|
+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
20
|
+
=========================================================================
|
21
|
+
*/
|
22
|
+
|
23
|
+
// ---------------------------------------------------------------------------
|
24
|
+
// State machine constants
|
25
|
+
|
26
|
+
typedef enum {
|
27
|
+
start_state = 1,
|
28
|
+
have_tuple_state = 2,
|
29
|
+
connected_state = 3,
|
30
|
+
external_state = 4
|
31
|
+
} state_t;
|
32
|
+
|
33
|
+
typedef enum {
|
34
|
+
NULL_event = 0,
|
35
|
+
terminate_event = 1,
|
36
|
+
hello_event = 2,
|
37
|
+
ok_event = 3,
|
38
|
+
finished_event = 4,
|
39
|
+
publish_event = 5,
|
40
|
+
forward_event = 6,
|
41
|
+
ping_event = 7,
|
42
|
+
expired_event = 8
|
43
|
+
} event_t;
|
44
|
+
|
45
|
+
// Names for state machine logging and error reporting
|
46
|
+
static char *
|
47
|
+
s_state_name [] = {
|
48
|
+
"(NONE)",
|
49
|
+
"start",
|
50
|
+
"have tuple",
|
51
|
+
"connected",
|
52
|
+
"external"
|
53
|
+
};
|
54
|
+
|
55
|
+
static char *
|
56
|
+
s_event_name [] = {
|
57
|
+
"(NONE)",
|
58
|
+
"terminate",
|
59
|
+
"HELLO",
|
60
|
+
"ok",
|
61
|
+
"finished",
|
62
|
+
"PUBLISH",
|
63
|
+
"forward",
|
64
|
+
"PING",
|
65
|
+
"expired"
|
66
|
+
};
|
67
|
+
|
68
|
+
// ---------------------------------------------------------------------------
|
69
|
+
// Context for the whole server task. This embeds the application-level
|
70
|
+
// server context at its start (the entire structure, not a reference),
|
71
|
+
// so we can cast a pointer between server_t and s_server_t arbitrarily.
|
72
|
+
|
73
|
+
typedef struct {
|
74
|
+
server_t server; // Application-level server context
|
75
|
+
zsock_t *pipe; // Socket to back to caller API
|
76
|
+
zsock_t *router; // Socket to talk to clients
|
77
|
+
int port; // Server port bound to
|
78
|
+
zloop_t *loop; // Reactor for server sockets
|
79
|
+
zgossip_msg_t *message; // Message received or sent
|
80
|
+
zhash_t *clients; // Clients we're connected to
|
81
|
+
zconfig_t *config; // Configuration tree
|
82
|
+
uint client_id; // Client identifier counter
|
83
|
+
size_t timeout; // Default client expiry timeout
|
84
|
+
bool verbose; // Verbose logging enabled?
|
85
|
+
char *log_prefix; // Default log prefix
|
86
|
+
} s_server_t;
|
87
|
+
|
88
|
+
|
89
|
+
// ---------------------------------------------------------------------------
|
90
|
+
// Context for each connected client. This embeds the application-level
|
91
|
+
// client context at its start (the entire structure, not a reference),
|
92
|
+
// so we can cast a pointer between client_t and s_client_t arbitrarily.
|
93
|
+
|
94
|
+
typedef struct {
|
95
|
+
client_t client; // Application-level client context
|
96
|
+
s_server_t *server; // Parent server context
|
97
|
+
char *hashkey; // Key into server->clients hash
|
98
|
+
zframe_t *routing_id; // Routing_id back to client
|
99
|
+
uint unique_id; // Client identifier in server
|
100
|
+
state_t state; // Current state
|
101
|
+
event_t event; // Current event
|
102
|
+
event_t next_event; // The next event
|
103
|
+
event_t exception; // Exception event, if any
|
104
|
+
int wakeup; // zloop timer for client alarms
|
105
|
+
void *ticket; // zloop ticket for client timeouts
|
106
|
+
event_t wakeup_event; // Wake up with this event
|
107
|
+
char log_prefix [41]; // Log prefix string
|
108
|
+
} s_client_t;
|
109
|
+
|
110
|
+
static int
|
111
|
+
server_initialize (server_t *self);
|
112
|
+
static void
|
113
|
+
server_terminate (server_t *self);
|
114
|
+
static zmsg_t *
|
115
|
+
server_method (server_t *self, const char *method, zmsg_t *msg);
|
116
|
+
static int
|
117
|
+
client_initialize (client_t *self);
|
118
|
+
static void
|
119
|
+
client_terminate (client_t *self);
|
120
|
+
static void
|
121
|
+
s_client_execute (s_client_t *client, event_t event);
|
122
|
+
static int
|
123
|
+
s_client_handle_wakeup (zloop_t *loop, int timer_id, void *argument);
|
124
|
+
static int
|
125
|
+
s_client_handle_ticket (zloop_t *loop, int timer_id, void *argument);
|
126
|
+
static void
|
127
|
+
get_first_tuple (client_t *self);
|
128
|
+
static void
|
129
|
+
get_next_tuple (client_t *self);
|
130
|
+
static void
|
131
|
+
store_tuple_if_new (client_t *self);
|
132
|
+
static void
|
133
|
+
get_tuple_to_forward (client_t *self);
|
134
|
+
|
135
|
+
// ---------------------------------------------------------------------------
|
136
|
+
// These methods are an internal API for actions
|
137
|
+
|
138
|
+
// Set the next event, needed in at least one action in an internal
|
139
|
+
// state; otherwise the state machine will wait for a message on the
|
140
|
+
// router socket and treat that as the event.
|
141
|
+
|
142
|
+
static void
|
143
|
+
engine_set_next_event (client_t *client, event_t event)
|
144
|
+
{
|
145
|
+
if (client) {
|
146
|
+
s_client_t *self = (s_client_t *) client;
|
147
|
+
self->next_event = event;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
// Raise an exception with 'event', halting any actions in progress.
|
152
|
+
// Continues execution of actions defined for the exception event.
|
153
|
+
|
154
|
+
static void
|
155
|
+
engine_set_exception (client_t *client, event_t event)
|
156
|
+
{
|
157
|
+
if (client) {
|
158
|
+
s_client_t *self = (s_client_t *) client;
|
159
|
+
self->exception = event;
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
// Set wakeup alarm after 'delay' msecs. The next state should
|
164
|
+
// handle the wakeup event. The alarm is cancelled on any other
|
165
|
+
// event.
|
166
|
+
|
167
|
+
static void
|
168
|
+
engine_set_wakeup_event (client_t *client, size_t delay, event_t event)
|
169
|
+
{
|
170
|
+
if (client) {
|
171
|
+
s_client_t *self = (s_client_t *) client;
|
172
|
+
if (self->wakeup) {
|
173
|
+
zloop_timer_end (self->server->loop, self->wakeup);
|
174
|
+
self->wakeup = 0;
|
175
|
+
}
|
176
|
+
self->wakeup = zloop_timer (
|
177
|
+
self->server->loop, delay, 1, s_client_handle_wakeup, self);
|
178
|
+
self->wakeup_event = event;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
// Execute 'event' on specified client. Use this to send events to
|
183
|
+
// other clients. Cancels any wakeup alarm on that client.
|
184
|
+
|
185
|
+
static void
|
186
|
+
engine_send_event (client_t *client, event_t event)
|
187
|
+
{
|
188
|
+
if (client) {
|
189
|
+
s_client_t *self = (s_client_t *) client;
|
190
|
+
s_client_execute (self, event);
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
// Execute 'event' on all clients known to the server. If you pass a
|
195
|
+
// client argument, that client will not receive the broadcast. If you
|
196
|
+
// want to pass any arguments, store them in the server context.
|
197
|
+
|
198
|
+
static void
|
199
|
+
engine_broadcast_event (server_t *server, client_t *client, event_t event)
|
200
|
+
{
|
201
|
+
if (server) {
|
202
|
+
s_server_t *self = (s_server_t *) server;
|
203
|
+
zlist_t *keys = zhash_keys (self->clients);
|
204
|
+
char *key = (char *) zlist_first (keys);
|
205
|
+
while (key) {
|
206
|
+
s_client_t *target = (s_client_t *) zhash_lookup (self->clients, key);
|
207
|
+
if (target != (s_client_t *) client)
|
208
|
+
s_client_execute (target, event);
|
209
|
+
key = (char *) zlist_next (keys);
|
210
|
+
}
|
211
|
+
zlist_destroy (&keys);
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
// Poll actor or zsock for activity, invoke handler on any received
|
216
|
+
// message. Handler must be a CZMQ zloop_fn function; receives server
|
217
|
+
// as arg.
|
218
|
+
|
219
|
+
static void
|
220
|
+
engine_handle_socket (server_t *server, void *sock, zloop_reader_fn handler)
|
221
|
+
{
|
222
|
+
if (server) {
|
223
|
+
s_server_t *self = (s_server_t *) server;
|
224
|
+
// Resolve zactor_t -> zsock_t
|
225
|
+
if (zactor_is (sock))
|
226
|
+
sock = zactor_sock ((zactor_t *) sock);
|
227
|
+
else
|
228
|
+
assert (zsock_is (sock));
|
229
|
+
if (handler != NULL) {
|
230
|
+
int rc = zloop_reader (self->loop, (zsock_t *) sock, handler, self);
|
231
|
+
assert (rc == 0);
|
232
|
+
zloop_reader_set_tolerant (self->loop, (zsock_t *) sock);
|
233
|
+
}
|
234
|
+
else
|
235
|
+
zloop_reader_end (self->loop, (zsock_t *) sock);
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
// Register monitor function that will be called at regular intervals
|
240
|
+
// by the server engine
|
241
|
+
|
242
|
+
static void
|
243
|
+
engine_set_monitor (server_t *server, size_t interval, zloop_timer_fn monitor)
|
244
|
+
{
|
245
|
+
if (server) {
|
246
|
+
s_server_t *self = (s_server_t *) server;
|
247
|
+
int rc = zloop_timer (self->loop, interval, 0, monitor, self);
|
248
|
+
assert (rc >= 0);
|
249
|
+
}
|
250
|
+
}
|
251
|
+
|
252
|
+
// Set log file prefix; this string will be added to log data, to make
|
253
|
+
// log data more searchable. The string is truncated to ~20 chars.
|
254
|
+
|
255
|
+
static void
|
256
|
+
engine_set_log_prefix (client_t *client, const char *string)
|
257
|
+
{
|
258
|
+
if (client) {
|
259
|
+
s_client_t *self = (s_client_t *) client;
|
260
|
+
snprintf (self->log_prefix, sizeof (self->log_prefix) - 1,
|
261
|
+
"%6d:%-33s", self->unique_id, string);
|
262
|
+
}
|
263
|
+
}
|
264
|
+
|
265
|
+
// Set a configuration value in the server's configuration tree. The
|
266
|
+
// properties this engine uses are: server/verbose, server/timeout, and
|
267
|
+
// server/background. You can also configure other abitrary properties.
|
268
|
+
|
269
|
+
static void
|
270
|
+
engine_configure (server_t *server, const char *path, const char *value)
|
271
|
+
{
|
272
|
+
if (server) {
|
273
|
+
s_server_t *self = (s_server_t *) server;
|
274
|
+
zconfig_put (self->config, path, value);
|
275
|
+
}
|
276
|
+
}
|
277
|
+
|
278
|
+
// Return true if server is running in verbose mode, else return false.
|
279
|
+
|
280
|
+
static bool
|
281
|
+
engine_verbose (server_t *server)
|
282
|
+
{
|
283
|
+
if (server) {
|
284
|
+
s_server_t *self = (s_server_t *) server;
|
285
|
+
return self->verbose;
|
286
|
+
}
|
287
|
+
return false;
|
288
|
+
}
|
289
|
+
|
290
|
+
// Pedantic compilers don't like unused functions, so we call the whole
|
291
|
+
// API, passing null references. It's nasty and horrid and sufficient.
|
292
|
+
|
293
|
+
static void
|
294
|
+
s_satisfy_pedantic_compilers (void)
|
295
|
+
{
|
296
|
+
engine_set_next_event (NULL, NULL_event);
|
297
|
+
engine_set_exception (NULL, NULL_event);
|
298
|
+
engine_set_wakeup_event (NULL, 0, NULL_event);
|
299
|
+
engine_send_event (NULL, NULL_event);
|
300
|
+
engine_broadcast_event (NULL, NULL, NULL_event);
|
301
|
+
engine_handle_socket (NULL, 0, NULL);
|
302
|
+
engine_set_monitor (NULL, 0, NULL);
|
303
|
+
engine_set_log_prefix (NULL, NULL);
|
304
|
+
engine_configure (NULL, NULL, NULL);
|
305
|
+
engine_verbose (NULL);
|
306
|
+
}
|
307
|
+
|
308
|
+
|
309
|
+
// ---------------------------------------------------------------------------
|
310
|
+
// Generic methods on protocol messages
|
311
|
+
// TODO: replace with lookup table, since ID is one byte
|
312
|
+
|
313
|
+
static event_t
|
314
|
+
s_protocol_event (zgossip_msg_t *message)
|
315
|
+
{
|
316
|
+
assert (message);
|
317
|
+
switch (zgossip_msg_id (message)) {
|
318
|
+
case ZGOSSIP_MSG_HELLO:
|
319
|
+
return hello_event;
|
320
|
+
break;
|
321
|
+
case ZGOSSIP_MSG_PUBLISH:
|
322
|
+
return publish_event;
|
323
|
+
break;
|
324
|
+
case ZGOSSIP_MSG_PING:
|
325
|
+
return ping_event;
|
326
|
+
break;
|
327
|
+
default:
|
328
|
+
// Invalid zgossip_msg_t
|
329
|
+
return terminate_event;
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
|
334
|
+
// ---------------------------------------------------------------------------
|
335
|
+
// Client methods
|
336
|
+
|
337
|
+
static s_client_t *
|
338
|
+
s_client_new (s_server_t *server, zframe_t *routing_id)
|
339
|
+
{
|
340
|
+
s_client_t *self = (s_client_t *) zmalloc (sizeof (s_client_t));
|
341
|
+
assert (self);
|
342
|
+
assert ((s_client_t *) &self->client == self);
|
343
|
+
|
344
|
+
self->server = server;
|
345
|
+
self->hashkey = zframe_strhex (routing_id);
|
346
|
+
self->routing_id = zframe_dup (routing_id);
|
347
|
+
self->unique_id = server->client_id++;
|
348
|
+
engine_set_log_prefix (&self->client, server->log_prefix);
|
349
|
+
|
350
|
+
self->client.server = (server_t *) server;
|
351
|
+
self->client.message = server->message;
|
352
|
+
|
353
|
+
// If expiry timers are being used, create client ticket
|
354
|
+
if (server->timeout)
|
355
|
+
self->ticket = zloop_ticket (server->loop, s_client_handle_ticket, self);
|
356
|
+
// Give application chance to initialize and set next event
|
357
|
+
self->state = start_state;
|
358
|
+
self->event = NULL_event;
|
359
|
+
client_initialize (&self->client);
|
360
|
+
return self;
|
361
|
+
}
|
362
|
+
|
363
|
+
static void
|
364
|
+
s_client_destroy (s_client_t **self_p)
|
365
|
+
{
|
366
|
+
assert (self_p);
|
367
|
+
if (*self_p) {
|
368
|
+
s_client_t *self = *self_p;
|
369
|
+
if (self->wakeup)
|
370
|
+
zloop_timer_end (self->server->loop, self->wakeup);
|
371
|
+
if (self->ticket)
|
372
|
+
zloop_ticket_delete (self->server->loop, self->ticket);
|
373
|
+
zframe_destroy (&self->routing_id);
|
374
|
+
// Provide visual clue if application misuses client reference
|
375
|
+
engine_set_log_prefix (&self->client, "*** TERMINATED ***");
|
376
|
+
client_terminate (&self->client);
|
377
|
+
free (self->hashkey);
|
378
|
+
free (self);
|
379
|
+
*self_p = NULL;
|
380
|
+
}
|
381
|
+
}
|
382
|
+
|
383
|
+
// Callback when we remove client from 'clients' hash table
|
384
|
+
static void
|
385
|
+
s_client_free (void *argument)
|
386
|
+
{
|
387
|
+
s_client_t *client = (s_client_t *) argument;
|
388
|
+
s_client_destroy (&client);
|
389
|
+
}
|
390
|
+
|
391
|
+
|
392
|
+
// Execute state machine as long as we have events
|
393
|
+
|
394
|
+
static void
|
395
|
+
s_client_execute (s_client_t *self, event_t event)
|
396
|
+
{
|
397
|
+
self->next_event = event;
|
398
|
+
// Cancel wakeup timer, if any was pending
|
399
|
+
if (self->wakeup) {
|
400
|
+
zloop_timer_end (self->server->loop, self->wakeup);
|
401
|
+
self->wakeup = 0;
|
402
|
+
}
|
403
|
+
while (self->next_event > 0) {
|
404
|
+
self->event = self->next_event;
|
405
|
+
self->next_event = NULL_event;
|
406
|
+
self->exception = NULL_event;
|
407
|
+
if (self->server->verbose) {
|
408
|
+
zsys_debug ("%s: %s:",
|
409
|
+
self->log_prefix, s_state_name [self->state]);
|
410
|
+
zsys_debug ("%s: %s",
|
411
|
+
self->log_prefix, s_event_name [self->event]);
|
412
|
+
}
|
413
|
+
switch (self->state) {
|
414
|
+
case start_state:
|
415
|
+
if (self->event == hello_event) {
|
416
|
+
if (!self->exception) {
|
417
|
+
// get first tuple
|
418
|
+
if (self->server->verbose)
|
419
|
+
zsys_debug ("%s: $ get first tuple", self->log_prefix);
|
420
|
+
get_first_tuple (&self->client);
|
421
|
+
}
|
422
|
+
if (!self->exception)
|
423
|
+
self->state = have_tuple_state;
|
424
|
+
}
|
425
|
+
else
|
426
|
+
if (self->event == ping_event) {
|
427
|
+
if (!self->exception) {
|
428
|
+
// send PONG
|
429
|
+
if (self->server->verbose)
|
430
|
+
zsys_debug ("%s: $ send PONG",
|
431
|
+
self->log_prefix);
|
432
|
+
zgossip_msg_set_id (self->server->message, ZGOSSIP_MSG_PONG);
|
433
|
+
zgossip_msg_set_routing_id (self->server->message, self->routing_id);
|
434
|
+
zgossip_msg_send (self->server->message, self->server->router);
|
435
|
+
}
|
436
|
+
}
|
437
|
+
else
|
438
|
+
if (self->event == expired_event) {
|
439
|
+
if (!self->exception) {
|
440
|
+
// terminate
|
441
|
+
if (self->server->verbose)
|
442
|
+
zsys_debug ("%s: $ terminate", self->log_prefix);
|
443
|
+
self->next_event = terminate_event;
|
444
|
+
}
|
445
|
+
}
|
446
|
+
else {
|
447
|
+
// Handle unexpected protocol events
|
448
|
+
if (!self->exception) {
|
449
|
+
// send INVALID
|
450
|
+
if (self->server->verbose)
|
451
|
+
zsys_debug ("%s: $ send INVALID",
|
452
|
+
self->log_prefix);
|
453
|
+
zgossip_msg_set_id (self->server->message, ZGOSSIP_MSG_INVALID);
|
454
|
+
zgossip_msg_set_routing_id (self->server->message, self->routing_id);
|
455
|
+
zgossip_msg_send (self->server->message, self->server->router);
|
456
|
+
}
|
457
|
+
if (!self->exception) {
|
458
|
+
// terminate
|
459
|
+
if (self->server->verbose)
|
460
|
+
zsys_debug ("%s: $ terminate", self->log_prefix);
|
461
|
+
self->next_event = terminate_event;
|
462
|
+
}
|
463
|
+
}
|
464
|
+
break;
|
465
|
+
|
466
|
+
case have_tuple_state:
|
467
|
+
if (self->event == ok_event) {
|
468
|
+
if (!self->exception) {
|
469
|
+
// send PUBLISH
|
470
|
+
if (self->server->verbose)
|
471
|
+
zsys_debug ("%s: $ send PUBLISH",
|
472
|
+
self->log_prefix);
|
473
|
+
zgossip_msg_set_id (self->server->message, ZGOSSIP_MSG_PUBLISH);
|
474
|
+
zgossip_msg_set_routing_id (self->server->message, self->routing_id);
|
475
|
+
zgossip_msg_send (self->server->message, self->server->router);
|
476
|
+
}
|
477
|
+
if (!self->exception) {
|
478
|
+
// get next tuple
|
479
|
+
if (self->server->verbose)
|
480
|
+
zsys_debug ("%s: $ get next tuple", self->log_prefix);
|
481
|
+
get_next_tuple (&self->client);
|
482
|
+
}
|
483
|
+
}
|
484
|
+
else
|
485
|
+
if (self->event == finished_event) {
|
486
|
+
if (!self->exception)
|
487
|
+
self->state = connected_state;
|
488
|
+
}
|
489
|
+
else {
|
490
|
+
// Handle unexpected internal events
|
491
|
+
zsys_warning ("%s: unhandled event %s in %s",
|
492
|
+
self->log_prefix,
|
493
|
+
s_event_name [self->event],
|
494
|
+
s_state_name [self->state]);
|
495
|
+
assert (false);
|
496
|
+
}
|
497
|
+
break;
|
498
|
+
|
499
|
+
case connected_state:
|
500
|
+
if (self->event == publish_event) {
|
501
|
+
if (!self->exception) {
|
502
|
+
// store tuple if new
|
503
|
+
if (self->server->verbose)
|
504
|
+
zsys_debug ("%s: $ store tuple if new", self->log_prefix);
|
505
|
+
store_tuple_if_new (&self->client);
|
506
|
+
}
|
507
|
+
}
|
508
|
+
else
|
509
|
+
if (self->event == forward_event) {
|
510
|
+
if (!self->exception) {
|
511
|
+
// get tuple to forward
|
512
|
+
if (self->server->verbose)
|
513
|
+
zsys_debug ("%s: $ get tuple to forward", self->log_prefix);
|
514
|
+
get_tuple_to_forward (&self->client);
|
515
|
+
}
|
516
|
+
if (!self->exception) {
|
517
|
+
// send PUBLISH
|
518
|
+
if (self->server->verbose)
|
519
|
+
zsys_debug ("%s: $ send PUBLISH",
|
520
|
+
self->log_prefix);
|
521
|
+
zgossip_msg_set_id (self->server->message, ZGOSSIP_MSG_PUBLISH);
|
522
|
+
zgossip_msg_set_routing_id (self->server->message, self->routing_id);
|
523
|
+
zgossip_msg_send (self->server->message, self->server->router);
|
524
|
+
}
|
525
|
+
}
|
526
|
+
else
|
527
|
+
if (self->event == ping_event) {
|
528
|
+
if (!self->exception) {
|
529
|
+
// send PONG
|
530
|
+
if (self->server->verbose)
|
531
|
+
zsys_debug ("%s: $ send PONG",
|
532
|
+
self->log_prefix);
|
533
|
+
zgossip_msg_set_id (self->server->message, ZGOSSIP_MSG_PONG);
|
534
|
+
zgossip_msg_set_routing_id (self->server->message, self->routing_id);
|
535
|
+
zgossip_msg_send (self->server->message, self->server->router);
|
536
|
+
}
|
537
|
+
}
|
538
|
+
else
|
539
|
+
if (self->event == expired_event) {
|
540
|
+
if (!self->exception) {
|
541
|
+
// terminate
|
542
|
+
if (self->server->verbose)
|
543
|
+
zsys_debug ("%s: $ terminate", self->log_prefix);
|
544
|
+
self->next_event = terminate_event;
|
545
|
+
}
|
546
|
+
}
|
547
|
+
else {
|
548
|
+
// Handle unexpected protocol events
|
549
|
+
if (!self->exception) {
|
550
|
+
// send INVALID
|
551
|
+
if (self->server->verbose)
|
552
|
+
zsys_debug ("%s: $ send INVALID",
|
553
|
+
self->log_prefix);
|
554
|
+
zgossip_msg_set_id (self->server->message, ZGOSSIP_MSG_INVALID);
|
555
|
+
zgossip_msg_set_routing_id (self->server->message, self->routing_id);
|
556
|
+
zgossip_msg_send (self->server->message, self->server->router);
|
557
|
+
}
|
558
|
+
if (!self->exception) {
|
559
|
+
// terminate
|
560
|
+
if (self->server->verbose)
|
561
|
+
zsys_debug ("%s: $ terminate", self->log_prefix);
|
562
|
+
self->next_event = terminate_event;
|
563
|
+
}
|
564
|
+
}
|
565
|
+
break;
|
566
|
+
|
567
|
+
case external_state:
|
568
|
+
if (self->event == ping_event) {
|
569
|
+
if (!self->exception) {
|
570
|
+
// send PONG
|
571
|
+
if (self->server->verbose)
|
572
|
+
zsys_debug ("%s: $ send PONG",
|
573
|
+
self->log_prefix);
|
574
|
+
zgossip_msg_set_id (self->server->message, ZGOSSIP_MSG_PONG);
|
575
|
+
zgossip_msg_set_routing_id (self->server->message, self->routing_id);
|
576
|
+
zgossip_msg_send (self->server->message, self->server->router);
|
577
|
+
}
|
578
|
+
}
|
579
|
+
else
|
580
|
+
if (self->event == expired_event) {
|
581
|
+
if (!self->exception) {
|
582
|
+
// terminate
|
583
|
+
if (self->server->verbose)
|
584
|
+
zsys_debug ("%s: $ terminate", self->log_prefix);
|
585
|
+
self->next_event = terminate_event;
|
586
|
+
}
|
587
|
+
}
|
588
|
+
else {
|
589
|
+
// Handle unexpected protocol events
|
590
|
+
if (!self->exception) {
|
591
|
+
// send INVALID
|
592
|
+
if (self->server->verbose)
|
593
|
+
zsys_debug ("%s: $ send INVALID",
|
594
|
+
self->log_prefix);
|
595
|
+
zgossip_msg_set_id (self->server->message, ZGOSSIP_MSG_INVALID);
|
596
|
+
zgossip_msg_set_routing_id (self->server->message, self->routing_id);
|
597
|
+
zgossip_msg_send (self->server->message, self->server->router);
|
598
|
+
}
|
599
|
+
if (!self->exception) {
|
600
|
+
// terminate
|
601
|
+
if (self->server->verbose)
|
602
|
+
zsys_debug ("%s: $ terminate", self->log_prefix);
|
603
|
+
self->next_event = terminate_event;
|
604
|
+
}
|
605
|
+
}
|
606
|
+
break;
|
607
|
+
}
|
608
|
+
// If we had an exception event, interrupt normal programming
|
609
|
+
if (self->exception) {
|
610
|
+
if (self->server->verbose)
|
611
|
+
zsys_debug ("%s: ! %s",
|
612
|
+
self->log_prefix, s_event_name [self->exception]);
|
613
|
+
|
614
|
+
self->next_event = self->exception;
|
615
|
+
}
|
616
|
+
if (self->next_event == terminate_event) {
|
617
|
+
// Automatically calls s_client_destroy
|
618
|
+
zhash_delete (self->server->clients, self->hashkey);
|
619
|
+
break;
|
620
|
+
}
|
621
|
+
else
|
622
|
+
if (self->server->verbose)
|
623
|
+
zsys_debug ("%s: > %s",
|
624
|
+
self->log_prefix, s_state_name [self->state]);
|
625
|
+
}
|
626
|
+
}
|
627
|
+
|
628
|
+
// zloop callback when client ticket expires
|
629
|
+
|
630
|
+
static int
|
631
|
+
s_client_handle_ticket (zloop_t *loop, int timer_id, void *argument)
|
632
|
+
{
|
633
|
+
s_client_t *self = (s_client_t *) argument;
|
634
|
+
self->ticket = NULL; // Ticket is now dead
|
635
|
+
s_client_execute (self, expired_event);
|
636
|
+
return 0;
|
637
|
+
}
|
638
|
+
|
639
|
+
// zloop callback when client wakeup timer expires
|
640
|
+
|
641
|
+
static int
|
642
|
+
s_client_handle_wakeup (zloop_t *loop, int timer_id, void *argument)
|
643
|
+
{
|
644
|
+
s_client_t *self = (s_client_t *) argument;
|
645
|
+
s_client_execute (self, self->wakeup_event);
|
646
|
+
return 0;
|
647
|
+
}
|
648
|
+
|
649
|
+
|
650
|
+
// Server methods
|
651
|
+
|
652
|
+
static void
|
653
|
+
s_server_config_global (s_server_t *self)
|
654
|
+
{
|
655
|
+
// Built-in server configuration options
|
656
|
+
//
|
657
|
+
// If we didn't already set verbose, check if the config tree wants it
|
658
|
+
if (!self->verbose
|
659
|
+
&& atoi (zconfig_resolve (self->config, "server/verbose", "0")))
|
660
|
+
self->verbose = true;
|
661
|
+
|
662
|
+
// Default client timeout is 60 seconds
|
663
|
+
self->timeout = atoi (
|
664
|
+
zconfig_resolve (self->config, "server/timeout", "60000"));
|
665
|
+
zloop_set_ticket_delay (self->loop, self->timeout);
|
666
|
+
|
667
|
+
// Do we want to run server in the background?
|
668
|
+
int background = atoi (
|
669
|
+
zconfig_resolve (self->config, "server/background", "0"));
|
670
|
+
if (!background)
|
671
|
+
zsys_set_logstream (stdout);
|
672
|
+
}
|
673
|
+
|
674
|
+
static s_server_t *
|
675
|
+
s_server_new (zsock_t *pipe)
|
676
|
+
{
|
677
|
+
s_server_t *self = (s_server_t *) zmalloc (sizeof (s_server_t));
|
678
|
+
assert (self);
|
679
|
+
assert ((s_server_t *) &self->server == self);
|
680
|
+
|
681
|
+
self->pipe = pipe;
|
682
|
+
self->router = zsock_new (ZMQ_ROUTER);
|
683
|
+
assert (self->router);
|
684
|
+
// By default the socket will discard outgoing messages above the
|
685
|
+
// HWM of 1,000. This isn't helpful for high-volume streaming. We
|
686
|
+
// will use a unbounded queue here. If applications need to guard
|
687
|
+
// against queue overflow, they should use a credit-based flow
|
688
|
+
// control scheme.
|
689
|
+
zsock_set_unbounded (self->router);
|
690
|
+
self->message = zgossip_msg_new ();
|
691
|
+
self->clients = zhash_new ();
|
692
|
+
self->config = zconfig_new ("root", NULL);
|
693
|
+
self->loop = zloop_new ();
|
694
|
+
srandom ((unsigned int) zclock_time ());
|
695
|
+
self->client_id = randof (1000);
|
696
|
+
s_server_config_global (self);
|
697
|
+
|
698
|
+
// Initialize application server context
|
699
|
+
self->server.pipe = self->pipe;
|
700
|
+
self->server.config = self->config;
|
701
|
+
server_initialize (&self->server);
|
702
|
+
|
703
|
+
s_satisfy_pedantic_compilers ();
|
704
|
+
return self;
|
705
|
+
}
|
706
|
+
|
707
|
+
static void
|
708
|
+
s_server_destroy (s_server_t **self_p)
|
709
|
+
{
|
710
|
+
assert (self_p);
|
711
|
+
if (*self_p) {
|
712
|
+
s_server_t *self = *self_p;
|
713
|
+
zgossip_msg_destroy (&self->message);
|
714
|
+
// Destroy clients before destroying the server
|
715
|
+
zhash_destroy (&self->clients);
|
716
|
+
server_terminate (&self->server);
|
717
|
+
zsock_destroy (&self->router);
|
718
|
+
zconfig_destroy (&self->config);
|
719
|
+
zloop_destroy (&self->loop);
|
720
|
+
free (self);
|
721
|
+
*self_p = NULL;
|
722
|
+
}
|
723
|
+
}
|
724
|
+
|
725
|
+
// Apply service-specific configuration tree:
|
726
|
+
// * apply server configuration
|
727
|
+
// * print any echo items in top-level sections
|
728
|
+
// * apply sections that match methods
|
729
|
+
|
730
|
+
static void
|
731
|
+
s_server_config_service (s_server_t *self)
|
732
|
+
{
|
733
|
+
// Apply echo commands and class methods
|
734
|
+
zconfig_t *section = zconfig_locate (self->config, "zgossip");
|
735
|
+
if (section)
|
736
|
+
section = zconfig_child (section);
|
737
|
+
|
738
|
+
while (section) {
|
739
|
+
if (streq (zconfig_name (section), "echo"))
|
740
|
+
zsys_notice ("%s", zconfig_value (section));
|
741
|
+
else
|
742
|
+
if (streq (zconfig_name (section), "bind")) {
|
743
|
+
char *endpoint = zconfig_resolve (section, "endpoint", "?");
|
744
|
+
if (zsock_bind (self->router, "%s", endpoint) == -1)
|
745
|
+
zsys_warning ("could not bind to %s (%s)", endpoint, zmq_strerror (zmq_errno ()));
|
746
|
+
}
|
747
|
+
#if (ZMQ_VERSION_MAJOR >= 4)
|
748
|
+
else
|
749
|
+
if (streq (zconfig_name (section), "security")) {
|
750
|
+
char *mechanism = zconfig_resolve (section, "mechanism", "null");
|
751
|
+
char *domain = zconfig_resolve (section, "domain", NULL);
|
752
|
+
if (streq (mechanism, "null")) {
|
753
|
+
zsys_notice ("server is using NULL security");
|
754
|
+
if (domain)
|
755
|
+
zsock_set_zap_domain (self->router, NULL);
|
756
|
+
}
|
757
|
+
else
|
758
|
+
if (streq (mechanism, "plain")) {
|
759
|
+
zsys_notice ("server is using PLAIN security");
|
760
|
+
zsock_set_plain_server (self->router, 1);
|
761
|
+
}
|
762
|
+
else
|
763
|
+
zsys_warning ("mechanism=%s is not supported", mechanism);
|
764
|
+
}
|
765
|
+
#endif
|
766
|
+
section = zconfig_next (section);
|
767
|
+
}
|
768
|
+
s_server_config_global (self);
|
769
|
+
}
|
770
|
+
|
771
|
+
// Process message from pipe
|
772
|
+
|
773
|
+
static int
|
774
|
+
s_server_handle_pipe (zloop_t *loop, zsock_t *reader, void *argument)
|
775
|
+
{
|
776
|
+
s_server_t *self = (s_server_t *) argument;
|
777
|
+
zmsg_t *msg = zmsg_recv (self->pipe);
|
778
|
+
if (!msg)
|
779
|
+
return -1; // Interrupted; exit zloop
|
780
|
+
char *method = zmsg_popstr (msg);
|
781
|
+
if (self->verbose)
|
782
|
+
zsys_debug ("%s: API command=%s", self->log_prefix, method);
|
783
|
+
|
784
|
+
if (streq (method, "VERBOSE"))
|
785
|
+
self->verbose = true;
|
786
|
+
else
|
787
|
+
if (streq (method, "$TERM")) {
|
788
|
+
// Shutdown the engine
|
789
|
+
free (method);
|
790
|
+
zmsg_destroy (&msg);
|
791
|
+
return -1;
|
792
|
+
}
|
793
|
+
else
|
794
|
+
if (streq (method, "BIND")) {
|
795
|
+
// Bind to a specified endpoint, which may use an ephemeral port
|
796
|
+
char *endpoint = zmsg_popstr (msg);
|
797
|
+
self->port = zsock_bind (self->router, "%s", endpoint);
|
798
|
+
if (self->port == -1)
|
799
|
+
zsys_warning ("could not bind to %s", endpoint);
|
800
|
+
free (endpoint);
|
801
|
+
}
|
802
|
+
else
|
803
|
+
if (streq (method, "PORT")) {
|
804
|
+
// Return PORT + port number from the last bind, if any
|
805
|
+
zstr_sendm (self->pipe, "PORT");
|
806
|
+
zstr_sendf (self->pipe, "%d", self->port);
|
807
|
+
}
|
808
|
+
else // Deprecated method name
|
809
|
+
if (streq (method, "LOAD") || streq (method, "CONFIGURE")) {
|
810
|
+
char *filename = zmsg_popstr (msg);
|
811
|
+
zconfig_destroy (&self->config);
|
812
|
+
self->config = zconfig_load (filename);
|
813
|
+
if (self->config) {
|
814
|
+
s_server_config_service (self);
|
815
|
+
self->server.config = self->config;
|
816
|
+
}
|
817
|
+
else {
|
818
|
+
zsys_warning ("cannot load config file '%s'", filename);
|
819
|
+
self->config = zconfig_new ("root", NULL);
|
820
|
+
}
|
821
|
+
free (filename);
|
822
|
+
}
|
823
|
+
else
|
824
|
+
if (streq (method, "SET")) {
|
825
|
+
char *path = zmsg_popstr (msg);
|
826
|
+
char *value = zmsg_popstr (msg);
|
827
|
+
zconfig_put (self->config, path, value);
|
828
|
+
if (streq (path, "server/animate")) {
|
829
|
+
zsys_warning ("'%s' is deprecated, use VERBOSE command instead", path);
|
830
|
+
self->verbose = (atoi (value) == 1);
|
831
|
+
}
|
832
|
+
s_server_config_global (self);
|
833
|
+
free (path);
|
834
|
+
free (value);
|
835
|
+
}
|
836
|
+
else
|
837
|
+
if (streq (method, "SAVE")) {
|
838
|
+
char *filename = zmsg_popstr (msg);
|
839
|
+
if (zconfig_save (self->config, filename))
|
840
|
+
zsys_warning ("cannot save config file '%s'", filename);
|
841
|
+
free (filename);
|
842
|
+
}
|
843
|
+
else {
|
844
|
+
// Execute custom method
|
845
|
+
zmsg_t *reply = server_method (&self->server, method, msg);
|
846
|
+
// If reply isn't null, send it to caller
|
847
|
+
zmsg_send (&reply, self->pipe);
|
848
|
+
}
|
849
|
+
free (method);
|
850
|
+
zmsg_destroy (&msg);
|
851
|
+
return 0;
|
852
|
+
}
|
853
|
+
|
854
|
+
// Handle a protocol message from the client
|
855
|
+
|
856
|
+
static int
|
857
|
+
s_server_handle_protocol (zloop_t *loop, zsock_t *reader, void *argument)
|
858
|
+
{
|
859
|
+
s_server_t *self = (s_server_t *) argument;
|
860
|
+
// We process as many messages as we can, to reduce the overhead
|
861
|
+
// of polling and the reactor:
|
862
|
+
while (zsock_events (self->router) & ZMQ_POLLIN) {
|
863
|
+
if (zgossip_msg_recv (self->message, self->router))
|
864
|
+
return -1; // Interrupted; exit zloop
|
865
|
+
|
866
|
+
// TODO: use binary hashing on routing_id
|
867
|
+
char *hashkey = zframe_strhex (zgossip_msg_routing_id (self->message));
|
868
|
+
s_client_t *client = (s_client_t *) zhash_lookup (self->clients, hashkey);
|
869
|
+
if (client == NULL) {
|
870
|
+
client = s_client_new (self, zgossip_msg_routing_id (self->message));
|
871
|
+
zhash_insert (self->clients, hashkey, client);
|
872
|
+
zhash_freefn (self->clients, hashkey, s_client_free);
|
873
|
+
}
|
874
|
+
free (hashkey);
|
875
|
+
// Any input from client counts as activity
|
876
|
+
if (client->ticket)
|
877
|
+
zloop_ticket_reset (self->loop, client->ticket);
|
878
|
+
|
879
|
+
// Pass to client state machine
|
880
|
+
s_client_execute (client, s_protocol_event (self->message));
|
881
|
+
}
|
882
|
+
return 0;
|
883
|
+
}
|
884
|
+
|
885
|
+
// Watch server config file and reload if changed
|
886
|
+
|
887
|
+
static int
|
888
|
+
s_watch_server_config (zloop_t *loop, int timer_id, void *argument)
|
889
|
+
{
|
890
|
+
s_server_t *self = (s_server_t *) argument;
|
891
|
+
if (zconfig_has_changed (self->config)
|
892
|
+
&& zconfig_reload (&self->config) == 0) {
|
893
|
+
s_server_config_service (self);
|
894
|
+
self->server.config = self->config;
|
895
|
+
zsys_notice ("reloaded configuration from %s",
|
896
|
+
zconfig_filename (self->config));
|
897
|
+
}
|
898
|
+
return 0;
|
899
|
+
}
|
900
|
+
|
901
|
+
|
902
|
+
// ---------------------------------------------------------------------------
|
903
|
+
// This is the server actor, which polls its two sockets and processes
|
904
|
+
// incoming messages
|
905
|
+
|
906
|
+
void
|
907
|
+
zgossip (zsock_t *pipe, void *args)
|
908
|
+
{
|
909
|
+
// Initialize
|
910
|
+
s_server_t *self = s_server_new (pipe);
|
911
|
+
assert (self);
|
912
|
+
zsock_signal (pipe, 0);
|
913
|
+
// Actor argument may be a string used for logging
|
914
|
+
self->log_prefix = args? (char *) args: "";
|
915
|
+
|
916
|
+
// Set-up server monitor to watch for config file changes
|
917
|
+
engine_set_monitor ((server_t *) self, 1000, s_watch_server_config);
|
918
|
+
// Set up handler for the two main sockets the server uses
|
919
|
+
engine_handle_socket ((server_t *) self, self->pipe, s_server_handle_pipe);
|
920
|
+
engine_handle_socket ((server_t *) self, self->router, s_server_handle_protocol);
|
921
|
+
|
922
|
+
// Run reactor until there's a termination signal
|
923
|
+
zloop_start (self->loop);
|
924
|
+
|
925
|
+
// Reactor has ended
|
926
|
+
s_server_destroy (&self);
|
927
|
+
}
|