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.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +1 -0
  3. data/CHANGES.md +92 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +14 -0
  6. data/README.md +112 -0
  7. data/lib/czmq-ffi-gen.rb +7 -0
  8. data/lib/czmq-ffi-gen/czmq/ffi.rb +1210 -0
  9. data/lib/czmq-ffi-gen/czmq/ffi/version.rb +15 -0
  10. data/lib/czmq-ffi-gen/czmq/ffi/zactor.rb +186 -0
  11. data/lib/czmq-ffi-gen/czmq/ffi/zarmour.rb +286 -0
  12. data/lib/czmq-ffi-gen/czmq/ffi/zcert.rb +307 -0
  13. data/lib/czmq-ffi-gen/czmq/ffi/zcertstore.rb +222 -0
  14. data/lib/czmq-ffi-gen/czmq/ffi/zchunk.rb +388 -0
  15. data/lib/czmq-ffi-gen/czmq/ffi/zclock.rb +140 -0
  16. data/lib/czmq-ffi-gen/czmq/ffi/zconfig.rb +442 -0
  17. data/lib/czmq-ffi-gen/czmq/ffi/zdigest.rb +156 -0
  18. data/lib/czmq-ffi-gen/czmq/ffi/zdir.rb +283 -0
  19. data/lib/czmq-ffi-gen/czmq/ffi/zdir_patch.rb +194 -0
  20. data/lib/czmq-ffi-gen/czmq/ffi/zfile.rb +353 -0
  21. data/lib/czmq-ffi-gen/czmq/ffi/zframe.rb +359 -0
  22. data/lib/czmq-ffi-gen/czmq/ffi/zhash.rb +416 -0
  23. data/lib/czmq-ffi-gen/czmq/ffi/zhashx.rb +659 -0
  24. data/lib/czmq-ffi-gen/czmq/ffi/ziflist.rb +189 -0
  25. data/lib/czmq-ffi-gen/czmq/ffi/zlist.rb +365 -0
  26. data/lib/czmq-ffi-gen/czmq/ffi/zlistx.rb +478 -0
  27. data/lib/czmq-ffi-gen/czmq/ffi/zloop.rb +396 -0
  28. data/lib/czmq-ffi-gen/czmq/ffi/zmsg.rb +515 -0
  29. data/lib/czmq-ffi-gen/czmq/ffi/zpoller.rb +194 -0
  30. data/lib/czmq-ffi-gen/czmq/ffi/zproc.rb +294 -0
  31. data/lib/czmq-ffi-gen/czmq/ffi/zsock.rb +3479 -0
  32. data/lib/czmq-ffi-gen/czmq/ffi/zstr.rb +203 -0
  33. data/lib/czmq-ffi-gen/czmq/ffi/ztimerset.rb +203 -0
  34. data/lib/czmq-ffi-gen/czmq/ffi/ztrie.rb +221 -0
  35. data/lib/czmq-ffi-gen/czmq/ffi/zuuid.rb +227 -0
  36. data/lib/czmq-ffi-gen/errors.rb +12 -0
  37. data/lib/czmq-ffi-gen/gem_version.rb +5 -0
  38. data/lib/czmq-ffi-gen/legacy.rb +16 -0
  39. data/lib/czmq-ffi-gen/libzmq.rb +18 -0
  40. data/lib/czmq-ffi-gen/signals.rb +27 -0
  41. data/lib/czmq-ffi-gen/vendor.rb +5 -0
  42. data/lib/czmq-ffi-gen/versions.rb +19 -0
  43. data/vendor/local/bin/inproc_lat.exe +0 -0
  44. data/vendor/local/bin/inproc_thr.exe +0 -0
  45. data/vendor/local/bin/libczmq.dll +0 -0
  46. data/vendor/local/bin/libgcc_s_seh-1.dll +0 -0
  47. data/vendor/local/bin/libstdc++-6.dll +0 -0
  48. data/vendor/local/bin/libzmq.dll +0 -0
  49. data/vendor/local/bin/local_lat.exe +0 -0
  50. data/vendor/local/bin/local_thr.exe +0 -0
  51. data/vendor/local/bin/remote_lat.exe +0 -0
  52. data/vendor/local/bin/remote_thr.exe +0 -0
  53. data/vendor/local/include/czmq.h +31 -0
  54. data/vendor/local/include/czmq_library.h +199 -0
  55. data/vendor/local/include/czmq_prelude.h +641 -0
  56. data/vendor/local/include/readme.txt +83 -0
  57. data/vendor/local/include/sha1.h +76 -0
  58. data/vendor/local/include/sha1.inc_c +335 -0
  59. data/vendor/local/include/slre.h +92 -0
  60. data/vendor/local/include/slre.inc_c +660 -0
  61. data/vendor/local/include/zactor.h +76 -0
  62. data/vendor/local/include/zarmour.h +114 -0
  63. data/vendor/local/include/zauth.h +100 -0
  64. data/vendor/local/include/zauth_v2.h +88 -0
  65. data/vendor/local/include/zbeacon.h +86 -0
  66. data/vendor/local/include/zbeacon_v2.h +75 -0
  67. data/vendor/local/include/zcert.h +136 -0
  68. data/vendor/local/include/zcertstore.h +100 -0
  69. data/vendor/local/include/zchunk.h +163 -0
  70. data/vendor/local/include/zclock.h +73 -0
  71. data/vendor/local/include/zconfig.h +185 -0
  72. data/vendor/local/include/zctx.h +107 -0
  73. data/vendor/local/include/zdigest.h +65 -0
  74. data/vendor/local/include/zdir.h +149 -0
  75. data/vendor/local/include/zdir_patch.h +82 -0
  76. data/vendor/local/include/zfile.h +177 -0
  77. data/vendor/local/include/zframe.h +176 -0
  78. data/vendor/local/include/zgossip.h +95 -0
  79. data/vendor/local/include/zgossip_engine.inc +927 -0
  80. data/vendor/local/include/zgossip_msg.h +129 -0
  81. data/vendor/local/include/zhash.h +195 -0
  82. data/vendor/local/include/zhash_primes.inc +329 -0
  83. data/vendor/local/include/zhashx.h +298 -0
  84. data/vendor/local/include/ziflist.h +77 -0
  85. data/vendor/local/include/zlist.h +158 -0
  86. data/vendor/local/include/zlistx.h +205 -0
  87. data/vendor/local/include/zloop.h +168 -0
  88. data/vendor/local/include/zmonitor.h +73 -0
  89. data/vendor/local/include/zmonitor_v2.h +56 -0
  90. data/vendor/local/include/zmq.h +617 -0
  91. data/vendor/local/include/zmq_utils.h +48 -0
  92. data/vendor/local/include/zmsg.h +280 -0
  93. data/vendor/local/include/zmutex.h +55 -0
  94. data/vendor/local/include/zpoller.h +92 -0
  95. data/vendor/local/include/zproc.h +168 -0
  96. data/vendor/local/include/zproxy.h +111 -0
  97. data/vendor/local/include/zproxy_v2.h +62 -0
  98. data/vendor/local/include/zrex.h +82 -0
  99. data/vendor/local/include/zsock.h +912 -0
  100. data/vendor/local/include/zsock_option.inc +4126 -0
  101. data/vendor/local/include/zsocket.h +110 -0
  102. data/vendor/local/include/zsockopt.h +256 -0
  103. data/vendor/local/include/zstr.h +110 -0
  104. data/vendor/local/include/zsys.h +386 -0
  105. data/vendor/local/include/zthread.h +50 -0
  106. data/vendor/local/include/ztimerset.h +90 -0
  107. data/vendor/local/include/ztrie.h +106 -0
  108. data/vendor/local/include/zuuid.h +96 -0
  109. data/vendor/local/lib/libczmq.dll.a +0 -0
  110. data/vendor/local/lib/liblibzmq.dll.a +0 -0
  111. data/vendor/local/lib/libzmq-static.a +0 -0
  112. data/vendor/local/lib/pkgconfig/libczmq.pc +23 -0
  113. data/vendor/local/lib/pkgconfig/libzmq.pc +11 -0
  114. data/vendor/local/share/zmq/AUTHORS.txt +147 -0
  115. data/vendor/local/share/zmq/COPYING.LESSER.txt +181 -0
  116. data/vendor/local/share/zmq/COPYING.txt +674 -0
  117. data/vendor/local/share/zmq/NEWS.txt +978 -0
  118. 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
+ }