mosquitto 0.2
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/.gitignore +21 -0
- data/.travis.yml +29 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +25 -0
- data/LICENSE.md +13 -0
- data/README.md +244 -0
- data/Rakefile +42 -0
- data/TODO.md +19 -0
- data/examples/pub_sub.rb +41 -0
- data/ext/mosquitto/client.c +2163 -0
- data/ext/mosquitto/client.h +145 -0
- data/ext/mosquitto/extconf.rb +31 -0
- data/ext/mosquitto/message.c +168 -0
- data/ext/mosquitto/message.h +16 -0
- data/ext/mosquitto/mosquitto_ext.c +88 -0
- data/ext/mosquitto/mosquitto_ext.h +35 -0
- data/ext/mosquitto/mosquitto_prelude.h +26 -0
- data/ext/mosquitto/rubinius.h +6 -0
- data/ext/mosquitto/ruby18.h +6 -0
- data/ext/mosquitto/ruby19.h +9 -0
- data/ext/mosquitto/ruby2.h +6 -0
- data/lib/mosquitto.rb +11 -0
- data/lib/mosquitto/client.rb +8 -0
- data/lib/mosquitto/logging.rb +32 -0
- data/lib/mosquitto/version.rb +5 -0
- data/mosquitto.gemspec +23 -0
- data/test/helper.rb +59 -0
- data/test/ssl/all-ca.crt +75 -0
- data/test/ssl/client-expired.crt +61 -0
- data/test/ssl/client-revoked.crt +61 -0
- data/test/ssl/client-revoked.csr +12 -0
- data/test/ssl/client-revoked.key +15 -0
- data/test/ssl/client.crt +61 -0
- data/test/ssl/client.csr +12 -0
- data/test/ssl/client.key +15 -0
- data/test/ssl/crl.pem +10 -0
- data/test/ssl/demoCA/crlnumber +1 -0
- data/test/ssl/demoCA/index.txt +1 -0
- data/test/ssl/demoCA/index.txt.attr +1 -0
- data/test/ssl/demoCA/serial +1 -0
- data/test/ssl/gen.sh +70 -0
- data/test/ssl/mosquitto.org.crt +18 -0
- data/test/ssl/openssl.cnf +406 -0
- data/test/ssl/readme.txt +2 -0
- data/test/ssl/rootCA/crlnumber +1 -0
- data/test/ssl/rootCA/index.txt +2 -0
- data/test/ssl/rootCA/index.txt.attr +1 -0
- data/test/ssl/rootCA/serial +1 -0
- data/test/ssl/server-expired.crt +0 -0
- data/test/ssl/server.crt +60 -0
- data/test/ssl/server.csr +12 -0
- data/test/ssl/server.key +15 -0
- data/test/ssl/signingCA/crlnumber +1 -0
- data/test/ssl/signingCA/index.txt +4 -0
- data/test/ssl/signingCA/index.txt.attr +1 -0
- data/test/ssl/signingCA/serial +1 -0
- data/test/ssl/test-alt-ca.crt +58 -0
- data/test/ssl/test-alt-ca.key +15 -0
- data/test/ssl/test-bad-root-ca.crt +17 -0
- data/test/ssl/test-bad-root-ca.key +15 -0
- data/test/ssl/test-ca.srl +1 -0
- data/test/ssl/test-fake-root-ca.crt +17 -0
- data/test/ssl/test-fake-root-ca.key +15 -0
- data/test/ssl/test-root-ca.crt +17 -0
- data/test/ssl/test-root-ca.key +15 -0
- data/test/ssl/test-signing-ca.crt +58 -0
- data/test/ssl/test-signing-ca.key +15 -0
- data/test/test_callbacks.rb +93 -0
- data/test/test_client.rb +141 -0
- data/test/test_custom_logger.rb +30 -0
- data/test/test_integration.rb +572 -0
- data/test/test_loops.rb +56 -0
- data/test/test_mosquitto.rb +28 -0
- data/test/test_pub_sub.rb +51 -0
- data/test/test_threads.rb +69 -0
- data/test/test_tls.rb +67 -0
- metadata +203 -0
@@ -0,0 +1,2163 @@
|
|
1
|
+
#include "mosquitto_ext.h"
|
2
|
+
|
3
|
+
static void rb_mosquitto_run_callback(mosquitto_callback_t *callback);
|
4
|
+
|
5
|
+
VALUE mosquitto_tls_password;
|
6
|
+
|
7
|
+
static int rb_mosquitto_tls_password_callback(char *buf, int size, int rwflag, void *obj)
|
8
|
+
{
|
9
|
+
strncpy(buf, StringValueCStr(mosquitto_tls_password), size);
|
10
|
+
return RSTRING_LEN(mosquitto_tls_password);
|
11
|
+
rb_gc_unregister_address(&mosquitto_tls_password);
|
12
|
+
}
|
13
|
+
|
14
|
+
/*
|
15
|
+
* :nodoc:
|
16
|
+
* Pushes a callback onto the client's callback queue. The callback runs within the context of an event thread.
|
17
|
+
*
|
18
|
+
*/
|
19
|
+
static void mosquitto_callback_queue_push(mosquitto_callback_t *cb)
|
20
|
+
{
|
21
|
+
mosquitto_client_wrapper *client = cb->client;
|
22
|
+
cb->next = client->callback_queue;
|
23
|
+
client->callback_queue = cb;
|
24
|
+
}
|
25
|
+
|
26
|
+
/*
|
27
|
+
* :nodoc:
|
28
|
+
* Pops a callback off the client's callback queue. The callback runs within the context of an event thread.
|
29
|
+
*
|
30
|
+
*/
|
31
|
+
static mosquitto_callback_t *mosquitto_callback_queue_pop(mosquitto_client_wrapper *client)
|
32
|
+
{
|
33
|
+
mosquitto_callback_t *cb = client->callback_queue;
|
34
|
+
if(cb)
|
35
|
+
{
|
36
|
+
client->callback_queue = cb->next;
|
37
|
+
}
|
38
|
+
|
39
|
+
return cb;
|
40
|
+
}
|
41
|
+
|
42
|
+
/*
|
43
|
+
* :nodoc:
|
44
|
+
* Runs without the GIL (Global Interpreter Lock) and polls the client's callback queue for any callbacks
|
45
|
+
* to handle.
|
46
|
+
*
|
47
|
+
* Only applicable to clients that run with the threaded Mosquitto::Client#loop_start event loop
|
48
|
+
*
|
49
|
+
*/
|
50
|
+
static void *mosquitto_wait_for_callbacks(void *w)
|
51
|
+
{
|
52
|
+
mosquitto_callback_waiting_t *waiter = (mosquitto_callback_waiting_t *)w;
|
53
|
+
mosquitto_client_wrapper *client = waiter->client;
|
54
|
+
|
55
|
+
pthread_mutex_lock(&client->callback_mutex);
|
56
|
+
while (!waiter->abort && (waiter->callback = mosquitto_callback_queue_pop(client)) == NULL)
|
57
|
+
{
|
58
|
+
pthread_cond_wait(&client->callback_cond, &client->callback_mutex);
|
59
|
+
}
|
60
|
+
pthread_mutex_unlock(&client->callback_mutex);
|
61
|
+
|
62
|
+
return (void *)Qnil;
|
63
|
+
}
|
64
|
+
|
65
|
+
/*
|
66
|
+
* :nodoc:
|
67
|
+
* Unblocking function for the callback poller - invoked when the event thread should exit.
|
68
|
+
*
|
69
|
+
* Only applicable to clients that run with the threaded Mosquitto::Client#loop_start event loop
|
70
|
+
*
|
71
|
+
*/
|
72
|
+
static void mosquitto_stop_waiting_for_callbacks(void *w)
|
73
|
+
{
|
74
|
+
mosquitto_callback_waiting_t *waiter = (mosquitto_callback_waiting_t *)w;
|
75
|
+
mosquitto_client_wrapper *client = waiter->client;
|
76
|
+
|
77
|
+
pthread_mutex_lock(&client->callback_mutex);
|
78
|
+
waiter->abort = 1;
|
79
|
+
pthread_mutex_unlock(&client->callback_mutex);
|
80
|
+
pthread_cond_signal(&client->callback_cond);
|
81
|
+
}
|
82
|
+
|
83
|
+
/*
|
84
|
+
* :nodoc:
|
85
|
+
* Enqueues a callback to be handled by the event thread for a given client.
|
86
|
+
*
|
87
|
+
* Callbacks for clients that don't use the threaded Mosquitto::Client#loop_start event loop are invoked
|
88
|
+
* directly within context of the current Ruby thread. Thus there's no locking overhead and associated
|
89
|
+
* cruft.
|
90
|
+
*
|
91
|
+
*/
|
92
|
+
static void rb_mosquitto_queue_callback(mosquitto_callback_t *callback)
|
93
|
+
{
|
94
|
+
mosquitto_client_wrapper *client = callback->client;
|
95
|
+
if (!NIL_P(client->callback_thread)) {
|
96
|
+
pthread_mutex_lock(&client->callback_mutex);
|
97
|
+
mosquitto_callback_queue_push(callback);
|
98
|
+
pthread_mutex_unlock(&client->callback_mutex);
|
99
|
+
pthread_cond_signal(&client->callback_cond);
|
100
|
+
} else {
|
101
|
+
rb_mosquitto_run_callback(callback);
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
/*
|
106
|
+
* :nodoc:
|
107
|
+
* Main callback dispatch method. Invokes callback procedures with variable argument counts. It's expected
|
108
|
+
* to raise exceptions - they're handled by a wrapper function.
|
109
|
+
*
|
110
|
+
*/
|
111
|
+
static VALUE rb_mosquitto_funcall_protected0(VALUE *args)
|
112
|
+
{
|
113
|
+
int argc = args[1];
|
114
|
+
VALUE proc = args[0];
|
115
|
+
if (NIL_P(proc)) MosquittoError("invalid callback");
|
116
|
+
if (argc == 1) {
|
117
|
+
rb_funcall(proc, intern_call, 1, args[2]);
|
118
|
+
} else if (argc == 2) {
|
119
|
+
rb_funcall(proc, intern_call, 2, args[2], args[3]);
|
120
|
+
} else if (argc == 3) {
|
121
|
+
rb_funcall(proc, intern_call, 3, args[2], args[3], args[4]);
|
122
|
+
}
|
123
|
+
return Qnil;
|
124
|
+
}
|
125
|
+
|
126
|
+
/*
|
127
|
+
* :nodoc:
|
128
|
+
* Invokes the main callback dispatch method, but tracks error state and allows us to take appropriate action
|
129
|
+
* on exception.
|
130
|
+
*
|
131
|
+
*/
|
132
|
+
static VALUE rb_mosquitto_funcall_protected(int *error_tag, VALUE *args)
|
133
|
+
{
|
134
|
+
rb_protect((VALUE(*)(VALUE))rb_mosquitto_funcall_protected0, (VALUE)args, error_tag);
|
135
|
+
return Qnil;
|
136
|
+
}
|
137
|
+
|
138
|
+
/*
|
139
|
+
* :nodoc:
|
140
|
+
* Releases resources allocated for a given callback. Mostly callback specific arguments copied from libmosquitto
|
141
|
+
* callback arguments for later processing.
|
142
|
+
*
|
143
|
+
*/
|
144
|
+
static void rb_mosquitto_free_callback(mosquitto_callback_t *callback)
|
145
|
+
{
|
146
|
+
if (callback->type == ON_LOG_CALLBACK) {
|
147
|
+
on_log_callback_args_t *args = (on_log_callback_args_t *)callback->data;
|
148
|
+
xfree(args->str);
|
149
|
+
}
|
150
|
+
|
151
|
+
xfree(callback->data);
|
152
|
+
xfree(callback);
|
153
|
+
}
|
154
|
+
|
155
|
+
/*
|
156
|
+
* :nodoc:
|
157
|
+
* Our main callback handler within the Ruby VM. I sets up arguments, it's safe to raise exceptions here and coerces
|
158
|
+
* C specific callback arguments to Ruby counterparts prior to method dispatch.
|
159
|
+
*
|
160
|
+
*/
|
161
|
+
static void rb_mosquitto_handle_callback(int *error_tag, mosquitto_callback_t *callback)
|
162
|
+
{
|
163
|
+
VALUE args[5];
|
164
|
+
mosquitto_client_wrapper *client = callback->client;
|
165
|
+
switch (callback->type) {
|
166
|
+
case ON_CONNECT_CALLBACK: {
|
167
|
+
on_connect_callback_args_t *cb = (on_connect_callback_args_t *)callback->data;
|
168
|
+
args[0] = client->connect_cb;
|
169
|
+
args[1] = (VALUE)1;
|
170
|
+
args[2] = INT2NUM(cb->rc);
|
171
|
+
switch (cb->rc) {
|
172
|
+
case 1:
|
173
|
+
MosquittoError("connection refused (unacceptable protocol version)");
|
174
|
+
break;
|
175
|
+
case 2:
|
176
|
+
MosquittoError("connection refused (identifier rejected)");
|
177
|
+
break;
|
178
|
+
case 3:
|
179
|
+
MosquittoError("connection refused (broker unavailable)");
|
180
|
+
break;
|
181
|
+
default:
|
182
|
+
rb_mosquitto_funcall_protected(error_tag, args);
|
183
|
+
}
|
184
|
+
}
|
185
|
+
break;
|
186
|
+
|
187
|
+
case ON_DISCONNECT_CALLBACK: {
|
188
|
+
on_disconnect_callback_args_t *cb = (on_disconnect_callback_args_t *)callback->data;
|
189
|
+
args[0] = client->disconnect_cb;
|
190
|
+
args[1] = (VALUE)1;
|
191
|
+
args[2] = INT2NUM(cb->rc);
|
192
|
+
rb_mosquitto_funcall_protected(error_tag, args);
|
193
|
+
}
|
194
|
+
break;
|
195
|
+
|
196
|
+
case ON_PUBLISH_CALLBACK: {
|
197
|
+
on_publish_callback_args_t *cb = (on_publish_callback_args_t *)callback->data;
|
198
|
+
args[0] = client->publish_cb;
|
199
|
+
args[1] = (VALUE)1;
|
200
|
+
args[2] = INT2NUM(cb->mid);
|
201
|
+
rb_mosquitto_funcall_protected(error_tag, args);
|
202
|
+
}
|
203
|
+
break;
|
204
|
+
|
205
|
+
case ON_MESSAGE_CALLBACK: {
|
206
|
+
on_message_callback_args_t *cb = (on_message_callback_args_t *)callback->data;
|
207
|
+
args[0] = client->message_cb;
|
208
|
+
args[1] = (VALUE)1;
|
209
|
+
args[2] = rb_mosquitto_message_alloc(cb->msg);
|
210
|
+
rb_mosquitto_funcall_protected(error_tag, args);
|
211
|
+
}
|
212
|
+
break;
|
213
|
+
|
214
|
+
case ON_SUBSCRIBE_CALLBACK: {
|
215
|
+
int i;
|
216
|
+
on_subscribe_callback_args_t *cb = (on_subscribe_callback_args_t *)callback->data;
|
217
|
+
VALUE granted_qos = rb_ary_new2(cb->qos_count);
|
218
|
+
for (i = 0; i < cb->qos_count; i++) {
|
219
|
+
rb_ary_push(granted_qos, INT2NUM(cb->granted_qos[i]));
|
220
|
+
}
|
221
|
+
args[0] = client->subscribe_cb;
|
222
|
+
args[1] = (VALUE)2;
|
223
|
+
args[2] = INT2NUM(cb->mid);
|
224
|
+
args[3] = granted_qos;
|
225
|
+
rb_mosquitto_funcall_protected(error_tag, args);
|
226
|
+
}
|
227
|
+
break;
|
228
|
+
|
229
|
+
case ON_UNSUBSCRIBE_CALLBACK: {
|
230
|
+
on_unsubscribe_callback_args_t *cb = (on_unsubscribe_callback_args_t *)callback->data;
|
231
|
+
args[0] = client->unsubscribe_cb;
|
232
|
+
args[1] = (VALUE)1;
|
233
|
+
args[2] = INT2NUM(cb->mid);
|
234
|
+
rb_mosquitto_funcall_protected(error_tag, args);
|
235
|
+
}
|
236
|
+
break;
|
237
|
+
|
238
|
+
case ON_LOG_CALLBACK: {
|
239
|
+
on_log_callback_args_t *cb = (on_log_callback_args_t *)callback->data;
|
240
|
+
args[0] = client->log_cb;
|
241
|
+
args[1] = (VALUE)2;
|
242
|
+
args[2] = INT2NUM(cb->level);
|
243
|
+
args[3] = MosquittoEncode(rb_str_new2(cb->str));
|
244
|
+
rb_mosquitto_funcall_protected(error_tag, args);
|
245
|
+
}
|
246
|
+
break;
|
247
|
+
}
|
248
|
+
}
|
249
|
+
|
250
|
+
/*
|
251
|
+
* :nodoc:
|
252
|
+
* Wrapper function for running callbacks. It respects error / exception status as well as frees any resources
|
253
|
+
* allocated specific to callback processing.
|
254
|
+
*
|
255
|
+
*/
|
256
|
+
static void rb_mosquitto_run_callback(mosquitto_callback_t *callback)
|
257
|
+
{
|
258
|
+
int error_tag;
|
259
|
+
rb_mosquitto_handle_callback(&error_tag, callback);
|
260
|
+
rb_mosquitto_free_callback(callback);
|
261
|
+
if (error_tag) rb_jump_tag(error_tag);
|
262
|
+
}
|
263
|
+
|
264
|
+
/*
|
265
|
+
* :nodoc:
|
266
|
+
* The callback thread - the main workhorse for the threaded Mosquitto::Client#loop_start event loop.
|
267
|
+
*
|
268
|
+
*/
|
269
|
+
static VALUE rb_mosquitto_callback_thread(void *obj)
|
270
|
+
{
|
271
|
+
mosquitto_client_wrapper *client = (mosquitto_client_wrapper *)obj;
|
272
|
+
mosquitto_callback_waiting_t waiter;
|
273
|
+
waiter.callback = NULL;
|
274
|
+
waiter.abort = 0;
|
275
|
+
waiter.client = client;
|
276
|
+
while (!waiter.abort)
|
277
|
+
{
|
278
|
+
rb_thread_call_without_gvl(mosquitto_wait_for_callbacks, (void *)&waiter, mosquitto_stop_waiting_for_callbacks, (void *)&waiter);
|
279
|
+
if (waiter.callback)
|
280
|
+
{
|
281
|
+
rb_mosquitto_run_callback(waiter.callback);
|
282
|
+
}
|
283
|
+
}
|
284
|
+
|
285
|
+
return Qnil;
|
286
|
+
}
|
287
|
+
|
288
|
+
/*
|
289
|
+
* :nodoc:
|
290
|
+
* On connect callback - invoked by libmosquitto.
|
291
|
+
*
|
292
|
+
*/
|
293
|
+
static void rb_mosquitto_client_on_connect_cb(MOSQ_UNUSED struct mosquitto *mosq, void *obj, int rc)
|
294
|
+
{
|
295
|
+
mosquitto_callback_t *callback = MOSQ_ALLOC(mosquitto_callback_t);
|
296
|
+
callback->type = ON_CONNECT_CALLBACK;
|
297
|
+
callback->client = (mosquitto_client_wrapper *)obj;
|
298
|
+
|
299
|
+
on_connect_callback_args_t *args = MOSQ_ALLOC(on_connect_callback_args_t);
|
300
|
+
args->rc = rc;
|
301
|
+
|
302
|
+
callback->data = (void *)args;
|
303
|
+
rb_mosquitto_queue_callback(callback);
|
304
|
+
}
|
305
|
+
|
306
|
+
/*
|
307
|
+
* :nodoc:
|
308
|
+
* On disconnect callback - invoked by libmosquitto.
|
309
|
+
*
|
310
|
+
*/
|
311
|
+
static void rb_mosquitto_client_on_disconnect_cb(MOSQ_UNUSED struct mosquitto *mosq, void *obj, int rc)
|
312
|
+
{
|
313
|
+
mosquitto_callback_t *callback = MOSQ_ALLOC(mosquitto_callback_t);
|
314
|
+
callback->type = ON_DISCONNECT_CALLBACK;
|
315
|
+
callback->client = (mosquitto_client_wrapper *)obj;
|
316
|
+
|
317
|
+
on_disconnect_callback_args_t *args = MOSQ_ALLOC(on_disconnect_callback_args_t);
|
318
|
+
args->rc = rc;
|
319
|
+
|
320
|
+
callback->data = (void *)args;
|
321
|
+
rb_mosquitto_queue_callback(callback);
|
322
|
+
}
|
323
|
+
|
324
|
+
/*
|
325
|
+
* :nodoc:
|
326
|
+
* On publish callback - invoked by libmosquitto.
|
327
|
+
*
|
328
|
+
*/
|
329
|
+
static void rb_mosquitto_client_on_publish_cb(MOSQ_UNUSED struct mosquitto *mosq, void *obj, int mid)
|
330
|
+
{
|
331
|
+
mosquitto_callback_t *callback = MOSQ_ALLOC(mosquitto_callback_t);
|
332
|
+
callback->type = ON_PUBLISH_CALLBACK;
|
333
|
+
callback->client = (mosquitto_client_wrapper *)obj;
|
334
|
+
|
335
|
+
on_publish_callback_args_t *args = MOSQ_ALLOC(on_publish_callback_args_t);
|
336
|
+
args->mid = mid;
|
337
|
+
|
338
|
+
callback->data = (void *)args;
|
339
|
+
rb_mosquitto_queue_callback(callback);
|
340
|
+
}
|
341
|
+
|
342
|
+
/*
|
343
|
+
* :nodoc:
|
344
|
+
* On message callback - invoked by libmosquitto.
|
345
|
+
*
|
346
|
+
*/
|
347
|
+
static void rb_mosquitto_client_on_message_cb(MOSQ_UNUSED struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
|
348
|
+
{
|
349
|
+
mosquitto_callback_t *callback = MOSQ_ALLOC(mosquitto_callback_t);
|
350
|
+
callback->type = ON_MESSAGE_CALLBACK;
|
351
|
+
callback->client = (mosquitto_client_wrapper *)obj;
|
352
|
+
|
353
|
+
on_message_callback_args_t *args = MOSQ_ALLOC(on_message_callback_args_t);
|
354
|
+
args->msg = MOSQ_ALLOC(struct mosquitto_message);
|
355
|
+
mosquitto_message_copy(args->msg, msg);
|
356
|
+
|
357
|
+
callback->data = (void *)args;
|
358
|
+
rb_mosquitto_queue_callback(callback);
|
359
|
+
}
|
360
|
+
|
361
|
+
/*
|
362
|
+
* :nodoc:
|
363
|
+
* On subscribe callback - invoked by libmosquitto.
|
364
|
+
*
|
365
|
+
*/
|
366
|
+
static void rb_mosquitto_client_on_subscribe_cb(MOSQ_UNUSED struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
|
367
|
+
{
|
368
|
+
mosquitto_callback_t *callback = MOSQ_ALLOC(mosquitto_callback_t);
|
369
|
+
callback->type = ON_SUBSCRIBE_CALLBACK;
|
370
|
+
callback->client = (mosquitto_client_wrapper *)obj;
|
371
|
+
|
372
|
+
on_subscribe_callback_args_t *args = MOSQ_ALLOC(on_subscribe_callback_args_t);
|
373
|
+
args->mid = mid;
|
374
|
+
args->qos_count = qos_count;
|
375
|
+
args->granted_qos = granted_qos;
|
376
|
+
|
377
|
+
callback->data = (void *)args;
|
378
|
+
rb_mosquitto_queue_callback(callback);
|
379
|
+
}
|
380
|
+
|
381
|
+
/*
|
382
|
+
* :nodoc:
|
383
|
+
* On unsubscribe callback - invoked by libmosquitto.
|
384
|
+
*
|
385
|
+
*/
|
386
|
+
static void rb_mosquitto_client_on_unsubscribe_cb(MOSQ_UNUSED struct mosquitto *mosq, void *obj, int mid)
|
387
|
+
{
|
388
|
+
mosquitto_callback_t *callback = MOSQ_ALLOC(mosquitto_callback_t);
|
389
|
+
callback->type = ON_UNSUBSCRIBE_CALLBACK;
|
390
|
+
callback->client = (mosquitto_client_wrapper *)obj;
|
391
|
+
|
392
|
+
on_unsubscribe_callback_args_t *args = MOSQ_ALLOC(on_unsubscribe_callback_args_t);
|
393
|
+
args->mid = mid;
|
394
|
+
|
395
|
+
callback->data = (void *)args;
|
396
|
+
rb_mosquitto_queue_callback(callback);
|
397
|
+
}
|
398
|
+
|
399
|
+
/*
|
400
|
+
* :nodoc:
|
401
|
+
* On log callback - invoked by libmosquitto.
|
402
|
+
*
|
403
|
+
*/
|
404
|
+
static void rb_mosquitto_client_on_log_cb(MOSQ_UNUSED struct mosquitto *mosq, void *obj, int level, const char *str)
|
405
|
+
{
|
406
|
+
mosquitto_callback_t *callback = MOSQ_ALLOC(mosquitto_callback_t);
|
407
|
+
callback->type = ON_LOG_CALLBACK;
|
408
|
+
callback->client = (mosquitto_client_wrapper *)obj;
|
409
|
+
|
410
|
+
on_log_callback_args_t *args = MOSQ_ALLOC(on_log_callback_args_t);
|
411
|
+
args->level = level;
|
412
|
+
args->str = strdup(str);
|
413
|
+
|
414
|
+
callback->data = (void *)args;
|
415
|
+
rb_mosquitto_queue_callback(callback);
|
416
|
+
}
|
417
|
+
|
418
|
+
/*
|
419
|
+
* :nodoc:
|
420
|
+
* GC callback for Mosquitto::Client objects - invoked during the GC mark phase.
|
421
|
+
*
|
422
|
+
*/
|
423
|
+
static void rb_mosquitto_mark_client(void *ptr)
|
424
|
+
{
|
425
|
+
mosquitto_client_wrapper *client = (mosquitto_client_wrapper *)ptr;
|
426
|
+
if (client) {
|
427
|
+
rb_gc_mark(client->connect_cb);
|
428
|
+
rb_gc_mark(client->disconnect_cb);
|
429
|
+
rb_gc_mark(client->publish_cb);
|
430
|
+
rb_gc_mark(client->message_cb);
|
431
|
+
rb_gc_mark(client->subscribe_cb);
|
432
|
+
rb_gc_mark(client->unsubscribe_cb);
|
433
|
+
rb_gc_mark(client->log_cb);
|
434
|
+
rb_gc_mark(client->callback_thread);
|
435
|
+
}
|
436
|
+
}
|
437
|
+
|
438
|
+
/*
|
439
|
+
* :nodoc:
|
440
|
+
* GC callback for releasing an out of scope Mosquitto::Client object
|
441
|
+
*
|
442
|
+
*/
|
443
|
+
static void rb_mosquitto_free_client(void *ptr)
|
444
|
+
{
|
445
|
+
mosquitto_client_wrapper *client = (mosquitto_client_wrapper *)ptr;
|
446
|
+
if (client) {
|
447
|
+
mosquitto_destroy(client->mosq);
|
448
|
+
xfree(client);
|
449
|
+
}
|
450
|
+
}
|
451
|
+
|
452
|
+
/*
|
453
|
+
* call-seq:
|
454
|
+
* Mosquitto::Client.new("some-id") -> Mosquitto::Client
|
455
|
+
*
|
456
|
+
* Create a new mosquitto client instance.
|
457
|
+
*
|
458
|
+
* @param identifier [String] the client identifier. Set to nil to have a random one generated.
|
459
|
+
* clean_session must be true if the identifier is nil.
|
460
|
+
* @param clean_session [true, false] set to true to instruct the broker to clean all messages
|
461
|
+
* and subscriptions on disconnect, false to instruct it to
|
462
|
+
* keep them
|
463
|
+
* @return [Mosquitto::Client] mosquitto client instance
|
464
|
+
* @raise [Mosquitto::Error] on invalid input params
|
465
|
+
* @note As per the MQTT spec, client identifiers cannot exceed 23 characters
|
466
|
+
* @example
|
467
|
+
* Mosquitto::Client.new("session_id") -> Mosquitto::Client
|
468
|
+
* Mosquitto::Client.new(nil, true) -> Mosquitto::Client
|
469
|
+
*
|
470
|
+
*/
|
471
|
+
static VALUE rb_mosquitto_client_s_new(int argc, VALUE *argv, VALUE client)
|
472
|
+
{
|
473
|
+
VALUE client_id;
|
474
|
+
VALUE cl_session;
|
475
|
+
char *cl_id = NULL;
|
476
|
+
mosquitto_client_wrapper *cl = NULL;
|
477
|
+
bool clean_session;
|
478
|
+
rb_scan_args(argc, argv, "02", &client_id, &cl_session);
|
479
|
+
if (NIL_P(client_id)) {
|
480
|
+
clean_session = true;
|
481
|
+
} else {
|
482
|
+
clean_session = false;
|
483
|
+
Check_Type(client_id, T_STRING);
|
484
|
+
MosquittoEncode(client_id);
|
485
|
+
cl_id = StringValueCStr(client_id);
|
486
|
+
}
|
487
|
+
client = Data_Make_Struct(rb_cMosquittoClient, mosquitto_client_wrapper, rb_mosquitto_mark_client, rb_mosquitto_free_client, cl);
|
488
|
+
cl->mosq = mosquitto_new(cl_id, clean_session, (void *)cl);
|
489
|
+
if (cl->mosq == NULL) {
|
490
|
+
xfree(cl);
|
491
|
+
switch (errno) {
|
492
|
+
case EINVAL:
|
493
|
+
MosquittoError("invalid input params");
|
494
|
+
break;
|
495
|
+
case ENOMEM:
|
496
|
+
rb_memerror();
|
497
|
+
break;
|
498
|
+
default:
|
499
|
+
return Qfalse;
|
500
|
+
}
|
501
|
+
}
|
502
|
+
cl->connect_cb = Qnil;
|
503
|
+
cl->disconnect_cb = Qnil;
|
504
|
+
cl->publish_cb = Qnil;
|
505
|
+
cl->message_cb = Qnil;
|
506
|
+
cl->subscribe_cb = Qnil;
|
507
|
+
cl->unsubscribe_cb = Qnil;
|
508
|
+
cl->log_cb = Qnil;
|
509
|
+
cl->callback_thread = Qnil;
|
510
|
+
cl->callback_queue = NULL;
|
511
|
+
rb_obj_call_init(client, 0, NULL);
|
512
|
+
return client;
|
513
|
+
}
|
514
|
+
|
515
|
+
static void *rb_mosquitto_client_reinitialise_nogvl(void *ptr)
|
516
|
+
{
|
517
|
+
struct nogvl_reinitialise_args *args = ptr;
|
518
|
+
return (void *)mosquitto_reinitialise(args->mosq, args->client_id, args->clean_session, args->obj);
|
519
|
+
}
|
520
|
+
|
521
|
+
/*
|
522
|
+
* call-seq:
|
523
|
+
* client.reinitialise("some-id") -> Mosquitto::Client
|
524
|
+
*
|
525
|
+
* Allows an existing mosquitto client to be reused. Call on a mosquitto instance to close any
|
526
|
+
* open network connections, free memory and reinitialise the client with the new parameters.
|
527
|
+
*
|
528
|
+
* @param identifier [String] the client identifier. Set to nil to have a random one generated.
|
529
|
+
* clean_session must be true if the identifier is nil.
|
530
|
+
* @param clean_session [true, false] set to true to instruct the broker to clean all messages
|
531
|
+
* and subscriptions on disconnect, false to instruct it to
|
532
|
+
* keep them
|
533
|
+
* @return [Mosquitto::Client] mosquitto client instance
|
534
|
+
* @raise [Mosquitto::Error] on invalid input params
|
535
|
+
* @note As per the MQTT spec, client identifiers cannot exceed 23 characters
|
536
|
+
* @example
|
537
|
+
* client.reinitialise("session_id") -> Mosquitto::Client
|
538
|
+
* client.reinitialise(nil, true) -> Mosquitto::Client
|
539
|
+
*
|
540
|
+
*/
|
541
|
+
static VALUE rb_mosquitto_client_reinitialise(int argc, VALUE *argv, VALUE obj)
|
542
|
+
{
|
543
|
+
struct nogvl_reinitialise_args args;
|
544
|
+
VALUE client_id;
|
545
|
+
int ret;
|
546
|
+
bool clean_session;
|
547
|
+
char *cl_id = NULL;
|
548
|
+
MosquittoGetClient(obj);
|
549
|
+
rb_scan_args(argc, argv, "01", &client_id);
|
550
|
+
if (NIL_P(client_id)) {
|
551
|
+
clean_session = true;
|
552
|
+
} else {
|
553
|
+
clean_session = false;
|
554
|
+
Check_Type(client_id, T_STRING);
|
555
|
+
MosquittoEncode(client_id);
|
556
|
+
cl_id = StringValueCStr(client_id);
|
557
|
+
}
|
558
|
+
args.mosq = client->mosq;
|
559
|
+
args.client_id = cl_id;
|
560
|
+
args.clean_session = clean_session;
|
561
|
+
args.obj = (void *)obj;
|
562
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_reinitialise_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
563
|
+
switch (ret) {
|
564
|
+
case MOSQ_ERR_INVAL:
|
565
|
+
MosquittoError("invalid input params");
|
566
|
+
break;
|
567
|
+
case MOSQ_ERR_NOMEM:
|
568
|
+
rb_memerror();
|
569
|
+
break;
|
570
|
+
default:
|
571
|
+
return Qtrue;
|
572
|
+
}
|
573
|
+
}
|
574
|
+
|
575
|
+
/*
|
576
|
+
* call-seq:
|
577
|
+
* client.will_set("topic", "died", Mosquitto::AT_MOST_ONCE, false) -> Mosquitto::Client
|
578
|
+
*
|
579
|
+
* Configure will information for a mosquitto instance. By default, clients do not have a will.
|
580
|
+
*
|
581
|
+
* @param topic [String] the topic on which to publish the will
|
582
|
+
* @param payload [String] the message payload. Max 256MB
|
583
|
+
* @param qos [Mosquitto::AT_MOST_ONCE, Mosquitto::AT_LEAST_ONCE, Mosquitto::EXACTLY_ONCE] quality
|
584
|
+
* of service used for the will
|
585
|
+
* @param retain [true, false] set to true to make the will a retained message
|
586
|
+
* @return [true] on success
|
587
|
+
* @raise [Mosquitto::Error] on invalid input params or a too large payload size
|
588
|
+
* @note This must be called before calling Mosquitto::Client#connect
|
589
|
+
* @example
|
590
|
+
* client.will_set("will_set", "test", Mosquitto::AT_MOST_ONCE, true)
|
591
|
+
*
|
592
|
+
*/
|
593
|
+
static VALUE rb_mosquitto_client_will_set(VALUE obj, VALUE topic, VALUE payload, VALUE qos, VALUE retain)
|
594
|
+
{
|
595
|
+
int ret;
|
596
|
+
int payload_len;
|
597
|
+
MosquittoGetClient(obj);
|
598
|
+
Check_Type(topic, T_STRING);
|
599
|
+
MosquittoEncode(topic);
|
600
|
+
Check_Type(payload, T_STRING);
|
601
|
+
MosquittoEncode(payload);
|
602
|
+
Check_Type(qos, T_FIXNUM);
|
603
|
+
payload_len = (int)RSTRING_LEN(payload);
|
604
|
+
ret = mosquitto_will_set(client->mosq, StringValueCStr(topic), payload_len, (payload_len == 0 ? NULL : StringValueCStr(payload)), NUM2INT(qos), ((retain == Qtrue) ? true : false));
|
605
|
+
switch (ret) {
|
606
|
+
case MOSQ_ERR_INVAL:
|
607
|
+
MosquittoError("invalid input params");
|
608
|
+
break;
|
609
|
+
case MOSQ_ERR_NOMEM:
|
610
|
+
rb_memerror();
|
611
|
+
break;
|
612
|
+
case MOSQ_ERR_PAYLOAD_SIZE:
|
613
|
+
MosquittoError("payload too large");
|
614
|
+
break;
|
615
|
+
default:
|
616
|
+
return Qtrue;
|
617
|
+
}
|
618
|
+
}
|
619
|
+
|
620
|
+
/*
|
621
|
+
* call-seq:
|
622
|
+
* client.will_clear -> Boolean
|
623
|
+
*
|
624
|
+
* Remove a previously configured will.
|
625
|
+
*
|
626
|
+
* @return [true] on success
|
627
|
+
* @raise [Mosquitto::Error] on invalid input params
|
628
|
+
* @note This must be called before calling Mosquitto::Client#connect
|
629
|
+
* @example
|
630
|
+
* client.will_clear
|
631
|
+
*
|
632
|
+
*/
|
633
|
+
static VALUE rb_mosquitto_client_will_clear(VALUE obj)
|
634
|
+
{
|
635
|
+
int ret;
|
636
|
+
MosquittoGetClient(obj);
|
637
|
+
ret = mosquitto_will_clear(client->mosq);
|
638
|
+
switch (ret) {
|
639
|
+
case MOSQ_ERR_INVAL:
|
640
|
+
MosquittoError("invalid input params");
|
641
|
+
break;
|
642
|
+
default:
|
643
|
+
return Qtrue;
|
644
|
+
}
|
645
|
+
}
|
646
|
+
|
647
|
+
/*
|
648
|
+
* call-seq:
|
649
|
+
* client.auth("username", "password") -> Boolean
|
650
|
+
*
|
651
|
+
* Configure username and password for a mosquitto instance. This is only supported by brokers that
|
652
|
+
* implement the MQTT spec v3.1. By default, no username or password will be sent.
|
653
|
+
*
|
654
|
+
* @param username [String] the username to send, or nil to disable authentication.
|
655
|
+
* @param password [String] the password to send. Set to nil when username is valid in order to send
|
656
|
+
* just a username.
|
657
|
+
* @return [true] on success
|
658
|
+
* @raise [Mosquitto::Error] on invalid input params
|
659
|
+
* @note This must be called before calling Mosquitto::Client#connect
|
660
|
+
* @example
|
661
|
+
* client.auth("username", "password")
|
662
|
+
*
|
663
|
+
*/
|
664
|
+
static VALUE rb_mosquitto_client_auth(VALUE obj, VALUE username, VALUE password)
|
665
|
+
{
|
666
|
+
int ret;
|
667
|
+
MosquittoGetClient(obj);
|
668
|
+
if (!NIL_P(username)) {
|
669
|
+
Check_Type(username, T_STRING);
|
670
|
+
MosquittoEncode(username);
|
671
|
+
}
|
672
|
+
if (!NIL_P(password)) {
|
673
|
+
Check_Type(password, T_STRING);
|
674
|
+
MosquittoEncode(password);
|
675
|
+
}
|
676
|
+
ret = mosquitto_username_pw_set(client->mosq, (NIL_P(username) ? NULL : StringValueCStr(username)), (NIL_P(password) ? NULL : StringValueCStr(password)));
|
677
|
+
switch (ret) {
|
678
|
+
case MOSQ_ERR_INVAL:
|
679
|
+
MosquittoError("invalid input params");
|
680
|
+
break;
|
681
|
+
case MOSQ_ERR_NOMEM:
|
682
|
+
rb_memerror();
|
683
|
+
break;
|
684
|
+
default:
|
685
|
+
return Qtrue;
|
686
|
+
}
|
687
|
+
}
|
688
|
+
|
689
|
+
/*
|
690
|
+
* call-seq:
|
691
|
+
* client.tls_set('/certs/all-ca.crt'), '/certs', '/certs/client.crt'), '/certs/client.key') -> Boolean
|
692
|
+
*
|
693
|
+
* Configure the client for certificate based SSL/TLS support.
|
694
|
+
*
|
695
|
+
* Cannot be used in conjunction with Mosquitto::Client#tls_psk_set.
|
696
|
+
*
|
697
|
+
* Define the Certificate Authority certificates to be trusted (ie. the server
|
698
|
+
* certificate must be signed with one of these certificates) using cafile.
|
699
|
+
*
|
700
|
+
* If the server you are connecting to requires clients to provide a
|
701
|
+
* certificate, define certfile and keyfile with your client certificate and
|
702
|
+
* private key
|
703
|
+
*
|
704
|
+
* @param cafile [String] path to a file containing the PEM encoded trusted CA certificate files.
|
705
|
+
* Either cafile or capath must not be nil.
|
706
|
+
* @param capath [String] path to a directory containing the PEM encoded trusted CA certificate files.
|
707
|
+
* Either cafile or capath must not be nil.
|
708
|
+
* @param certfile [String] path to a file containing the PEM encoded certificate file for this client.
|
709
|
+
* If nil, keyfile must also be nil and no client certificate will be used.
|
710
|
+
* @param keyfile [String] path to a file containing the PEM encoded private key for this client. If nil,
|
711
|
+
* certfile must also be NULL and no client certificate will be used.
|
712
|
+
* @param password [String] password for encrypted keyfile
|
713
|
+
* @return [true] on success
|
714
|
+
* @raise [Mosquitto::Error] on invalid input params or when TLS is not supported
|
715
|
+
* @note This must be called before calling Mosquitto::Client#connect
|
716
|
+
* @example
|
717
|
+
* client.tls_set('/certs/all-ca.crt'), '/certs', '/certs/client.crt'), '/certs/client.key')
|
718
|
+
*
|
719
|
+
*/
|
720
|
+
static VALUE rb_mosquitto_client_tls_set(VALUE obj, VALUE cafile, VALUE capath, VALUE certfile, VALUE keyfile, VALUE password)
|
721
|
+
{
|
722
|
+
int ret;
|
723
|
+
int (*pw_callback)(char *, int, int, void *) = NULL;
|
724
|
+
MosquittoGetClient(obj);
|
725
|
+
if (!NIL_P(cafile)) {
|
726
|
+
Check_Type(cafile, T_STRING);
|
727
|
+
MosquittoEncode(cafile);
|
728
|
+
}
|
729
|
+
if (!NIL_P(capath)) {
|
730
|
+
Check_Type(capath, T_STRING);
|
731
|
+
MosquittoEncode(capath);
|
732
|
+
}
|
733
|
+
if (!NIL_P(certfile)) {
|
734
|
+
Check_Type(certfile, T_STRING);
|
735
|
+
MosquittoEncode(certfile);
|
736
|
+
}
|
737
|
+
if (!NIL_P(keyfile)) {
|
738
|
+
Check_Type(keyfile, T_STRING);
|
739
|
+
MosquittoEncode(keyfile);
|
740
|
+
}
|
741
|
+
|
742
|
+
if (!NIL_P(password)) {
|
743
|
+
Check_Type(password, T_STRING);
|
744
|
+
mosquitto_tls_password = password;
|
745
|
+
rb_gc_register_address(&mosquitto_tls_password);
|
746
|
+
pw_callback = rb_mosquitto_tls_password_callback;
|
747
|
+
}
|
748
|
+
|
749
|
+
if (NIL_P(cafile) && NIL_P(capath)) MosquittoError("Either CA path or CA file is required!");
|
750
|
+
if (NIL_P(certfile) && !NIL_P(keyfile)) MosquittoError("Key file can only be used with a certificate file!");
|
751
|
+
if (NIL_P(keyfile) && !NIL_P(certfile)) MosquittoError("Certificate file also requires a key file!");
|
752
|
+
|
753
|
+
ret = mosquitto_tls_set(client->mosq, (NIL_P(cafile) ? NULL : StringValueCStr(cafile)), (NIL_P(capath) ? NULL : StringValueCStr(capath)), (NIL_P(certfile) ? NULL : StringValueCStr(certfile)), (NIL_P(keyfile) ? NULL : StringValueCStr(keyfile)), pw_callback);
|
754
|
+
switch (ret) {
|
755
|
+
case MOSQ_ERR_INVAL:
|
756
|
+
MosquittoError("invalid input params");
|
757
|
+
break;
|
758
|
+
case MOSQ_ERR_NOMEM:
|
759
|
+
rb_memerror();
|
760
|
+
break;
|
761
|
+
case MOSQ_ERR_NOT_SUPPORTED:
|
762
|
+
MosquittoError("TLS support is not available");
|
763
|
+
default:
|
764
|
+
return Qtrue;
|
765
|
+
}
|
766
|
+
}
|
767
|
+
|
768
|
+
/*
|
769
|
+
* call-seq:
|
770
|
+
* client.insecure = true -> Boolean
|
771
|
+
*
|
772
|
+
* Configure verification of the server hostname in the server certificate. If
|
773
|
+
* value is set to true, it is impossible to guarantee that the host you are
|
774
|
+
* connecting to is not impersonating your server. This can be useful in
|
775
|
+
* initial server testing, but makes it possible for a malicious third party to
|
776
|
+
* impersonate your server through DNS spoofing, for example.
|
777
|
+
* Do not use this function in a real system. Setting value to true makes the
|
778
|
+
* connection encryption pointless.
|
779
|
+
*
|
780
|
+
* @param insecure [true, false] if set to false, the default, certificate hostname checking is
|
781
|
+
* performed. If set to true, no hostname checking is performed and
|
782
|
+
* the connection is insecure.
|
783
|
+
* @return [true] on success
|
784
|
+
* @raise [Mosquitto::Error] on invalid input params or when TLS is not supported
|
785
|
+
* @note This must be called before calling Mosquitto::Client#connect
|
786
|
+
* @example
|
787
|
+
* client.insecure = true
|
788
|
+
*
|
789
|
+
*/
|
790
|
+
static VALUE rb_mosquitto_client_tls_insecure_set(VALUE obj, VALUE insecure)
|
791
|
+
{
|
792
|
+
int ret;
|
793
|
+
MosquittoGetClient(obj);
|
794
|
+
if (insecure != Qtrue && insecure != Qfalse) {
|
795
|
+
rb_raise(rb_eTypeError, "changing TLS verification semantics requires a boolean value");
|
796
|
+
}
|
797
|
+
|
798
|
+
ret = mosquitto_tls_insecure_set(client->mosq, ((insecure == Qtrue) ? true : false));
|
799
|
+
switch (ret) {
|
800
|
+
case MOSQ_ERR_INVAL:
|
801
|
+
MosquittoError("invalid input params");
|
802
|
+
break;
|
803
|
+
case MOSQ_ERR_NOT_SUPPORTED:
|
804
|
+
MosquittoError("TLS support is not available");
|
805
|
+
default:
|
806
|
+
return Qtrue;
|
807
|
+
}
|
808
|
+
}
|
809
|
+
|
810
|
+
/*
|
811
|
+
* call-seq:
|
812
|
+
* client.tls_opts_set(Mosquitto::SSL_VERIFY_PEER, "tlsv1.2", nil) -> Boolean
|
813
|
+
*
|
814
|
+
* Set advanced SSL/TLS options.
|
815
|
+
*
|
816
|
+
* @param cert_reqs [Mosquitto::SSL_VERIFY_NONE, Mosquitto::SSL_VERIFY_NONE] an integer defining the verification
|
817
|
+
* requirements the client will impose on the server. The default and recommended value is
|
818
|
+
* Mosquitto::SSL_VERIFY_PEER. Using Mosquitto::SSL_VERIFY_NONE provides no security.
|
819
|
+
* @param tls_version ["tlsv1.2", "tlsv1.1", "tlsv1"] the version of the SSL/TLS protocol to use as a string. If
|
820
|
+
nil, the default value is used.
|
821
|
+
* @param ciphers [String] a string describing the ciphers available for use. See the `openssl ciphers` tool for
|
822
|
+
more information. If nil, the default ciphers will be used.
|
823
|
+
* @return [true] on success
|
824
|
+
* @raise [Mosquitto::Error] on invalid input params or when TLS is not supported
|
825
|
+
* @note This must be called before calling Mosquitto::Client#connect
|
826
|
+
* @see `openssl ciphers`
|
827
|
+
* @example
|
828
|
+
* client.tls_opts_set(Mosquitto::SSL_VERIFY_PEER, "tlsv1.2", nil)
|
829
|
+
*
|
830
|
+
*/
|
831
|
+
static VALUE rb_mosquitto_client_tls_opts_set(VALUE obj, VALUE cert_reqs, VALUE tls_version, VALUE ciphers)
|
832
|
+
{
|
833
|
+
int ret;
|
834
|
+
MosquittoGetClient(obj);
|
835
|
+
Check_Type(cert_reqs, T_FIXNUM);
|
836
|
+
if (!NIL_P(tls_version)) {
|
837
|
+
Check_Type(tls_version, T_STRING);
|
838
|
+
MosquittoEncode(tls_version);
|
839
|
+
}
|
840
|
+
if (!NIL_P(ciphers)) {
|
841
|
+
Check_Type(ciphers, T_STRING);
|
842
|
+
MosquittoEncode(ciphers);
|
843
|
+
}
|
844
|
+
|
845
|
+
if (NUM2INT(cert_reqs) != 0 && NUM2INT(cert_reqs) != 1) {
|
846
|
+
MosquittoError("TLS verification requirement should be one of Mosquitto::SSL_VERIFY_NONE or Mosquitto::SSL_VERIFY_PEER");
|
847
|
+
}
|
848
|
+
|
849
|
+
ret = mosquitto_tls_opts_set(client->mosq, NUM2INT(cert_reqs), (NIL_P(tls_version) ? NULL : StringValueCStr(tls_version)), (NIL_P(ciphers) ? NULL : StringValueCStr(ciphers)));
|
850
|
+
switch (ret) {
|
851
|
+
case MOSQ_ERR_INVAL:
|
852
|
+
MosquittoError("invalid input params");
|
853
|
+
break;
|
854
|
+
case MOSQ_ERR_NOMEM:
|
855
|
+
rb_memerror();
|
856
|
+
break;
|
857
|
+
case MOSQ_ERR_NOT_SUPPORTED:
|
858
|
+
MosquittoError("TLS support is not available");
|
859
|
+
default:
|
860
|
+
return Qtrue;
|
861
|
+
}
|
862
|
+
}
|
863
|
+
|
864
|
+
/*
|
865
|
+
* call-seq:
|
866
|
+
* client.tls_psk_set("deadbeef", "psk-id", nil) -> Boolean
|
867
|
+
*
|
868
|
+
* Configure the client for pre-shared-key based TLS support.
|
869
|
+
*
|
870
|
+
* @param psk [String] the pre-shared-key in hex format with no leading "0x".
|
871
|
+
* @param identity [String] the identity of this client. May be used as the username depending on the server
|
872
|
+
* settings.
|
873
|
+
* @param ciphers [String] a string describing the ciphers available for use. See the `openssl ciphers` tool for
|
874
|
+
more information. If nil, the default ciphers will be used.
|
875
|
+
* @return [true] on success
|
876
|
+
* @raise [Mosquitto::Error] on invalid input params or when TLS is not supported
|
877
|
+
* @note This must be called before calling Mosquitto::Client#connect
|
878
|
+
* @see `openssl ciphers`
|
879
|
+
* @example
|
880
|
+
* client.tls_psk_set("deadbeef", "psk-id", nil)
|
881
|
+
*
|
882
|
+
*/
|
883
|
+
static VALUE rb_mosquitto_client_tls_psk_set(VALUE obj, VALUE psk, VALUE identity, VALUE ciphers)
|
884
|
+
{
|
885
|
+
int ret;
|
886
|
+
MosquittoGetClient(obj);
|
887
|
+
Check_Type(psk, T_STRING);
|
888
|
+
Check_Type(identity, T_STRING);
|
889
|
+
if (!NIL_P(ciphers)) {
|
890
|
+
Check_Type(ciphers, T_STRING);
|
891
|
+
MosquittoEncode(ciphers);
|
892
|
+
}
|
893
|
+
|
894
|
+
ret = mosquitto_tls_psk_set(client->mosq, StringValueCStr(psk), StringValueCStr(identity), (NIL_P(ciphers) ? NULL : StringValueCStr(ciphers)));
|
895
|
+
switch (ret) {
|
896
|
+
case MOSQ_ERR_INVAL:
|
897
|
+
MosquittoError("invalid input params");
|
898
|
+
break;
|
899
|
+
case MOSQ_ERR_NOMEM:
|
900
|
+
rb_memerror();
|
901
|
+
break;
|
902
|
+
case MOSQ_ERR_NOT_SUPPORTED:
|
903
|
+
MosquittoError("TLS support is not available");
|
904
|
+
default:
|
905
|
+
return Qtrue;
|
906
|
+
}
|
907
|
+
}
|
908
|
+
|
909
|
+
static void *rb_mosquitto_client_connect_nogvl(void *ptr)
|
910
|
+
{
|
911
|
+
struct nogvl_connect_args *args = ptr;
|
912
|
+
return (void *)mosquitto_connect(args->mosq, args->host, args->port, args->keepalive);
|
913
|
+
}
|
914
|
+
|
915
|
+
/*
|
916
|
+
* call-seq:
|
917
|
+
* client.connect("localhost", 1883, 10) -> Boolean
|
918
|
+
*
|
919
|
+
* Connect to an MQTT broker.
|
920
|
+
*
|
921
|
+
* @param host [String] the hostname or ip address of the broker to connect to.
|
922
|
+
* @param port [Integer] the network port to connect to. Usually 1883 (or 8883 for TLS)
|
923
|
+
* @param keepalive [Integer] the number of seconds after which the broker should send a PING message
|
924
|
+
* to the client if no other messages have been exchanged in that time.
|
925
|
+
* @return [true] on success
|
926
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
927
|
+
* @example
|
928
|
+
* client.connect("localhost", 1883, 10)
|
929
|
+
*
|
930
|
+
*/
|
931
|
+
static VALUE rb_mosquitto_client_connect(VALUE obj, VALUE host, VALUE port, VALUE keepalive)
|
932
|
+
{
|
933
|
+
struct nogvl_connect_args args;
|
934
|
+
int ret;
|
935
|
+
MosquittoGetClient(obj);
|
936
|
+
Check_Type(host, T_STRING);
|
937
|
+
MosquittoEncode(host);
|
938
|
+
Check_Type(port, T_FIXNUM);
|
939
|
+
Check_Type(keepalive, T_FIXNUM);
|
940
|
+
args.mosq = client->mosq;
|
941
|
+
args.host = StringValueCStr(host);
|
942
|
+
args.port = NUM2INT(port);
|
943
|
+
args.keepalive = NUM2INT(keepalive);
|
944
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_connect_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
945
|
+
switch (ret) {
|
946
|
+
case MOSQ_ERR_INVAL:
|
947
|
+
MosquittoError("invalid input params");
|
948
|
+
break;
|
949
|
+
case MOSQ_ERR_ERRNO:
|
950
|
+
rb_sys_fail("mosquitto_connect");
|
951
|
+
break;
|
952
|
+
default:
|
953
|
+
return Qtrue;
|
954
|
+
}
|
955
|
+
}
|
956
|
+
|
957
|
+
static void *rb_mosquitto_client_connect_bind_nogvl(void *ptr)
|
958
|
+
{
|
959
|
+
struct nogvl_connect_args *args = ptr;
|
960
|
+
return (void *)mosquitto_connect_bind(args->mosq, args->host, args->port, args->keepalive, args->bind_address);
|
961
|
+
}
|
962
|
+
|
963
|
+
/*
|
964
|
+
* call-seq:
|
965
|
+
* client.connect_bind("localhost", 1883, 10, "10.0.0.3") -> Boolean
|
966
|
+
*
|
967
|
+
* Connect to an MQTT broker. This extends the functionality of Mosquitto::Client#connect by adding the bind_address
|
968
|
+
* parameter. Use this function if you need to restrict network communication over a particular interface.
|
969
|
+
*
|
970
|
+
* @param host [String] the hostname or ip address of the broker to connect to.
|
971
|
+
* @param port [Integer] the network port to connect to. Usually 1883 (or 8883 for TLS)
|
972
|
+
* @param keepalive [Integer] the number of seconds after which the broker should send a PING message
|
973
|
+
* to the client if no other messages have been exchanged in that time.
|
974
|
+
* @param bind_address [String] the hostname or ip address of the local network interface to bind to
|
975
|
+
* @return [true] on success
|
976
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
977
|
+
* @example
|
978
|
+
* client.connect_bind("localhost", 1883, 10, "10.0.0.3")
|
979
|
+
*
|
980
|
+
*/
|
981
|
+
static VALUE rb_mosquitto_client_connect_bind(VALUE obj, VALUE host, VALUE port, VALUE keepalive, VALUE bind_address)
|
982
|
+
{
|
983
|
+
struct nogvl_connect_args args;
|
984
|
+
int ret;
|
985
|
+
MosquittoGetClient(obj);
|
986
|
+
Check_Type(host, T_STRING);
|
987
|
+
MosquittoEncode(host);
|
988
|
+
Check_Type(port, T_FIXNUM);
|
989
|
+
Check_Type(keepalive, T_FIXNUM);
|
990
|
+
Check_Type(bind_address, T_STRING);
|
991
|
+
MosquittoEncode(bind_address);
|
992
|
+
args.mosq = client->mosq;
|
993
|
+
args.host = StringValueCStr(host);
|
994
|
+
args.port = NUM2INT(port);
|
995
|
+
args.keepalive = NUM2INT(keepalive);
|
996
|
+
args.bind_address = StringValueCStr(bind_address);
|
997
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_connect_bind_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
998
|
+
switch (ret) {
|
999
|
+
case MOSQ_ERR_INVAL:
|
1000
|
+
MosquittoError("invalid input params");
|
1001
|
+
break;
|
1002
|
+
case MOSQ_ERR_ERRNO:
|
1003
|
+
rb_sys_fail("mosquitto_connect_bind");
|
1004
|
+
break;
|
1005
|
+
default:
|
1006
|
+
return Qtrue;
|
1007
|
+
}
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
static void *rb_mosquitto_client_connect_async_nogvl(void *ptr)
|
1011
|
+
{
|
1012
|
+
struct nogvl_connect_args *args = ptr;
|
1013
|
+
return mosquitto_connect_async(args->mosq, args->host, args->port, args->keepalive);
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
/*
|
1017
|
+
* call-seq:
|
1018
|
+
* client.connect_async("localhost", 1883, 10) -> Boolean
|
1019
|
+
*
|
1020
|
+
* Connect to an MQTT broker. This is a non-blocking call. If you use
|
1021
|
+
* Mosquitto::Client#connect_async your client must use the threaded interface
|
1022
|
+
* Mosquitto::Client#loop_start. If you need to use Mosquitto::Client#loop, you must use
|
1023
|
+
* Mosquitto::Client#connect to connect the client.
|
1024
|
+
*
|
1025
|
+
* @param host [String] the hostname or ip address of the broker to connect to.
|
1026
|
+
* @param port [Integer] the network port to connect to. Usually 1883 (or 8883 for TLS)
|
1027
|
+
* @param keepalive [Integer] the number of seconds after which the broker should send a PING message
|
1028
|
+
* to the client if no other messages have been exchanged in that time.
|
1029
|
+
* @return [true] on success
|
1030
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
1031
|
+
* @example
|
1032
|
+
* client.connect_async("localhost", 1883, 10)
|
1033
|
+
*
|
1034
|
+
*/
|
1035
|
+
static VALUE rb_mosquitto_client_connect_async(VALUE obj, VALUE host, VALUE port, VALUE keepalive)
|
1036
|
+
{
|
1037
|
+
struct nogvl_connect_args args;
|
1038
|
+
int ret;
|
1039
|
+
MosquittoGetClient(obj);
|
1040
|
+
Check_Type(host, T_STRING);
|
1041
|
+
MosquittoEncode(host);
|
1042
|
+
Check_Type(port, T_FIXNUM);
|
1043
|
+
Check_Type(keepalive, T_FIXNUM);
|
1044
|
+
args.mosq = client->mosq;
|
1045
|
+
args.host = StringValueCStr(host);
|
1046
|
+
args.port = NUM2INT(port);
|
1047
|
+
args.keepalive = NUM2INT(keepalive);
|
1048
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_connect_async_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
1049
|
+
switch (ret) {
|
1050
|
+
case MOSQ_ERR_INVAL:
|
1051
|
+
MosquittoError("invalid input params");
|
1052
|
+
break;
|
1053
|
+
case MOSQ_ERR_ERRNO:
|
1054
|
+
rb_sys_fail("mosquitto_connect_async");
|
1055
|
+
break;
|
1056
|
+
default:
|
1057
|
+
return Qtrue;
|
1058
|
+
}
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
static void *rb_mosquitto_client_connect_bind_async_nogvl(void *ptr)
|
1062
|
+
{
|
1063
|
+
struct nogvl_connect_args *args = ptr;
|
1064
|
+
return mosquitto_connect_bind_async(args->mosq, args->host, args->port, args->keepalive, args->bind_address);
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
/*
|
1068
|
+
* call-seq:
|
1069
|
+
* client.connect_bind_async("localhost", 1883, 10, "10.0.0.3") -> Boolean
|
1070
|
+
*
|
1071
|
+
* Connect to an MQTT broker. This is a non-blocking call. If you use
|
1072
|
+
* Mosquitto::Client#connect_async your client must use the threaded interface
|
1073
|
+
* Mosquitto::Client#loop_start. If you need to use Mosquitto::Client#loop, you must use
|
1074
|
+
* Mosquitto::Client#connect to connect the client.
|
1075
|
+
*
|
1076
|
+
* This extends the functionality of Mosquitto::Client#connect_async by adding the
|
1077
|
+
* bind_address parameter. Use this function if you need to restrict network
|
1078
|
+
* communication over a particular interface.
|
1079
|
+
*
|
1080
|
+
* @param host [String] the hostname or ip address of the broker to connect to.
|
1081
|
+
* @param port [Integer] the network port to connect to. Usually 1883 (or 8883 for TLS)
|
1082
|
+
* @param keepalive [Integer] the number of seconds after which the broker should send a PING message
|
1083
|
+
* to the client if no other messages have been exchanged in that time.
|
1084
|
+
* @param bind_address [String] the hostname or ip address of the local network interface to bind to
|
1085
|
+
* @return [true] on success
|
1086
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
1087
|
+
* @example
|
1088
|
+
* client.connect_bind_async("localhost", 1883, 10, "10.0.0.3")
|
1089
|
+
*
|
1090
|
+
*/
|
1091
|
+
static VALUE rb_mosquitto_client_connect_bind_async(VALUE obj, VALUE host, VALUE port, VALUE keepalive, VALUE bind_address)
|
1092
|
+
{
|
1093
|
+
struct nogvl_connect_args args;
|
1094
|
+
int ret;
|
1095
|
+
MosquittoGetClient(obj);
|
1096
|
+
Check_Type(host, T_STRING);
|
1097
|
+
MosquittoEncode(host);
|
1098
|
+
Check_Type(port, T_FIXNUM);
|
1099
|
+
Check_Type(keepalive, T_FIXNUM);
|
1100
|
+
Check_Type(bind_address, T_STRING);
|
1101
|
+
MosquittoEncode(bind_address);
|
1102
|
+
args.mosq = client->mosq;
|
1103
|
+
args.host = StringValueCStr(host);
|
1104
|
+
args.port = NUM2INT(port);
|
1105
|
+
args.keepalive = NUM2INT(keepalive);
|
1106
|
+
args.bind_address = StringValueCStr(bind_address);
|
1107
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_connect_bind_async_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
1108
|
+
switch (ret) {
|
1109
|
+
case MOSQ_ERR_INVAL:
|
1110
|
+
MosquittoError("invalid input params");
|
1111
|
+
break;
|
1112
|
+
case MOSQ_ERR_ERRNO:
|
1113
|
+
rb_sys_fail("mosquitto_connect_bind_async");
|
1114
|
+
break;
|
1115
|
+
default:
|
1116
|
+
return Qtrue;
|
1117
|
+
}
|
1118
|
+
}
|
1119
|
+
|
1120
|
+
static void *rb_mosquitto_client_reconnect_nogvl(void *ptr)
|
1121
|
+
{
|
1122
|
+
return mosquitto_reconnect((struct mosquitto *)ptr);
|
1123
|
+
}
|
1124
|
+
|
1125
|
+
/*
|
1126
|
+
* call-seq:
|
1127
|
+
* client.reconnect -> Boolean
|
1128
|
+
*
|
1129
|
+
* Reconnect to a broker.
|
1130
|
+
*
|
1131
|
+
* This function provides an easy way of reconnecting to a broker after a connection has been lost.
|
1132
|
+
* It uses the values that were provided in the Mosquitto::Client#connect call.
|
1133
|
+
*
|
1134
|
+
* @return [true] on success
|
1135
|
+
* @note It must not be called before Mosquitto::Client#connect
|
1136
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
1137
|
+
* @example
|
1138
|
+
* client.reconnect
|
1139
|
+
*
|
1140
|
+
*/
|
1141
|
+
static VALUE rb_mosquitto_client_reconnect(VALUE obj)
|
1142
|
+
{
|
1143
|
+
int ret;
|
1144
|
+
MosquittoGetClient(obj);
|
1145
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_reconnect_nogvl, (void *)client->mosq, RUBY_UBF_IO, 0);
|
1146
|
+
switch (ret) {
|
1147
|
+
case MOSQ_ERR_INVAL:
|
1148
|
+
MosquittoError("invalid input params");
|
1149
|
+
break;
|
1150
|
+
case MOSQ_ERR_ERRNO:
|
1151
|
+
rb_sys_fail("mosquitto_reconnect");
|
1152
|
+
break;
|
1153
|
+
default:
|
1154
|
+
return Qtrue;
|
1155
|
+
}
|
1156
|
+
}
|
1157
|
+
|
1158
|
+
static void *rb_mosquitto_client_disconnect_nogvl(void *ptr)
|
1159
|
+
{
|
1160
|
+
return (VALUE)mosquitto_disconnect((struct mosquitto *)ptr);
|
1161
|
+
}
|
1162
|
+
|
1163
|
+
/*
|
1164
|
+
* call-seq:
|
1165
|
+
* client.disconnect-> Boolean
|
1166
|
+
*
|
1167
|
+
* Disconnect from the broker.
|
1168
|
+
*
|
1169
|
+
* @return [true] on success
|
1170
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or if the client is not connected
|
1171
|
+
* @example
|
1172
|
+
* client.disconnect
|
1173
|
+
*
|
1174
|
+
*/
|
1175
|
+
static VALUE rb_mosquitto_client_disconnect(VALUE obj)
|
1176
|
+
{
|
1177
|
+
int ret;
|
1178
|
+
MosquittoGetClient(obj);
|
1179
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_disconnect_nogvl, (void *)client->mosq, RUBY_UBF_IO, 0);
|
1180
|
+
switch (ret) {
|
1181
|
+
case MOSQ_ERR_INVAL:
|
1182
|
+
MosquittoError("invalid input params");
|
1183
|
+
break;
|
1184
|
+
case MOSQ_ERR_NO_CONN:
|
1185
|
+
MosquittoError("client not connected to broker");
|
1186
|
+
break;
|
1187
|
+
default:
|
1188
|
+
return Qtrue;
|
1189
|
+
}
|
1190
|
+
}
|
1191
|
+
|
1192
|
+
static void *rb_mosquitto_client_publish_nogvl(void *ptr)
|
1193
|
+
{
|
1194
|
+
struct nogvl_publish_args *args = ptr;
|
1195
|
+
return (VALUE)mosquitto_publish(args->mosq, args->mid, args->topic, args->payloadlen, args->payload, args->qos, args->retain);
|
1196
|
+
}
|
1197
|
+
|
1198
|
+
/*
|
1199
|
+
* call-seq:
|
1200
|
+
* client.publish(3, "publish", "test", Mosquitto::AT_MOST_ONCE, true) -> Boolean
|
1201
|
+
*
|
1202
|
+
* Publish a message on a given topic.
|
1203
|
+
*
|
1204
|
+
* @param mid [Integer, nil] If not nil, the function will set this to the message id of this particular message.
|
1205
|
+
* This can be then used with the publish callback to determine when the message has been
|
1206
|
+
* sent. Note that although the MQTT protocol doesn't use message ids for messages with
|
1207
|
+
* QoS=0, libmosquitto assigns them message ids so they can be tracked with this parameter.
|
1208
|
+
* @param payload [String] Message payload to send. Max 256MB
|
1209
|
+
* @param qos [Mosquitto::AT_MOST_ONCE, Mosquitto::AT_LEAST_ONCE, Mosquitto::EXACTLY_ONCE] Quality of Service to be
|
1210
|
+
* used for the message.
|
1211
|
+
* @param retain [true, false] set to true to make the message retained
|
1212
|
+
* @return [true] on success
|
1213
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
1214
|
+
* @example
|
1215
|
+
* client.publish(3, "publish", "test", Mosquitto::AT_MOST_ONCE, true)
|
1216
|
+
*
|
1217
|
+
*/
|
1218
|
+
static VALUE rb_mosquitto_client_publish(VALUE obj, VALUE mid, VALUE topic, VALUE payload, VALUE qos, VALUE retain)
|
1219
|
+
{
|
1220
|
+
struct nogvl_publish_args args;
|
1221
|
+
int ret, msg_id;
|
1222
|
+
MosquittoGetClient(obj);
|
1223
|
+
Check_Type(topic, T_STRING);
|
1224
|
+
MosquittoEncode(topic);
|
1225
|
+
Check_Type(payload, T_STRING);
|
1226
|
+
MosquittoEncode(payload);
|
1227
|
+
Check_Type(qos, T_FIXNUM);
|
1228
|
+
if (!NIL_P(mid)) {
|
1229
|
+
Check_Type(mid, T_FIXNUM);
|
1230
|
+
msg_id = NUM2INT(mid);
|
1231
|
+
}
|
1232
|
+
args.mosq = client->mosq;
|
1233
|
+
args.mid = NIL_P(mid) ? NULL : &msg_id;
|
1234
|
+
args.topic = StringValueCStr(topic);
|
1235
|
+
args.payloadlen = (int)RSTRING_LEN(payload);
|
1236
|
+
args.payload = (const char *)(args.payloadlen == 0 ? NULL : StringValueCStr(payload));
|
1237
|
+
args.qos = NUM2INT(qos);
|
1238
|
+
args.retain = (retain == Qtrue) ? true : false;
|
1239
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_publish_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
1240
|
+
switch (ret) {
|
1241
|
+
case MOSQ_ERR_INVAL:
|
1242
|
+
MosquittoError("invalid input params");
|
1243
|
+
break;
|
1244
|
+
case MOSQ_ERR_NOMEM:
|
1245
|
+
rb_memerror();
|
1246
|
+
break;
|
1247
|
+
case MOSQ_ERR_NO_CONN:
|
1248
|
+
MosquittoError("client not connected to broker");
|
1249
|
+
break;
|
1250
|
+
case MOSQ_ERR_PROTOCOL:
|
1251
|
+
MosquittoError("protocol error communicating with broker");
|
1252
|
+
break;
|
1253
|
+
case MOSQ_ERR_PAYLOAD_SIZE:
|
1254
|
+
MosquittoError("payload too large");
|
1255
|
+
break;
|
1256
|
+
default:
|
1257
|
+
return Qtrue;
|
1258
|
+
}
|
1259
|
+
}
|
1260
|
+
|
1261
|
+
static void *rb_mosquitto_client_subscribe_nogvl(void *ptr)
|
1262
|
+
{
|
1263
|
+
struct nogvl_subscribe_args *args = ptr;
|
1264
|
+
return (VALUE)mosquitto_subscribe(args->mosq, args->mid, args->subscription, args->qos);
|
1265
|
+
}
|
1266
|
+
|
1267
|
+
/*
|
1268
|
+
* call-seq:
|
1269
|
+
* client.subscribe(3, "subscribe", Mosquitto::AT_MOST_ONCE) -> Boolean
|
1270
|
+
*
|
1271
|
+
* Subscribe to a topic.
|
1272
|
+
*
|
1273
|
+
* @param mid [Integer, nil] If not nil, the function will set this to the message id of this particular message.
|
1274
|
+
* This can be then used with the subscribe callback to determine when the message has been
|
1275
|
+
* sent.
|
1276
|
+
* @param subscription [String] The subscription pattern
|
1277
|
+
* @param qos [Mosquitto::AT_MOST_ONCE, Mosquitto::AT_LEAST_ONCE, Mosquitto::EXACTLY_ONCE] Quality of Service to be
|
1278
|
+
* used for the subscription
|
1279
|
+
* @return [true] on success
|
1280
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
1281
|
+
* @example
|
1282
|
+
* client.subscribe(3, "subscribe", Mosquitto::AT_MOST_ONCE)
|
1283
|
+
*
|
1284
|
+
*/
|
1285
|
+
static VALUE rb_mosquitto_client_subscribe(VALUE obj, VALUE mid, VALUE subscription, VALUE qos)
|
1286
|
+
{
|
1287
|
+
struct nogvl_subscribe_args args;
|
1288
|
+
int ret, msg_id;
|
1289
|
+
MosquittoGetClient(obj);
|
1290
|
+
Check_Type(subscription, T_STRING);
|
1291
|
+
MosquittoEncode(subscription);
|
1292
|
+
Check_Type(qos, T_FIXNUM);
|
1293
|
+
if (!NIL_P(mid)) {
|
1294
|
+
Check_Type(mid, T_FIXNUM);
|
1295
|
+
msg_id = NUM2INT(mid);
|
1296
|
+
}
|
1297
|
+
args.mosq = client->mosq;
|
1298
|
+
args.mid = NIL_P(mid) ? NULL : &msg_id;
|
1299
|
+
args.subscription = StringValueCStr(subscription);
|
1300
|
+
args.qos = NUM2INT(qos);
|
1301
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_subscribe_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
1302
|
+
switch (ret) {
|
1303
|
+
case MOSQ_ERR_INVAL:
|
1304
|
+
MosquittoError("invalid input params");
|
1305
|
+
break;
|
1306
|
+
case MOSQ_ERR_NOMEM:
|
1307
|
+
rb_memerror();
|
1308
|
+
break;
|
1309
|
+
case MOSQ_ERR_NO_CONN:
|
1310
|
+
MosquittoError("client not connected to broker");
|
1311
|
+
break;
|
1312
|
+
default:
|
1313
|
+
return Qtrue;
|
1314
|
+
}
|
1315
|
+
}
|
1316
|
+
|
1317
|
+
static void *rb_mosquitto_client_unsubscribe_nogvl(void *ptr)
|
1318
|
+
{
|
1319
|
+
struct nogvl_subscribe_args *args = ptr;
|
1320
|
+
return (VALUE)mosquitto_unsubscribe(args->mosq, args->mid, args->subscription);
|
1321
|
+
}
|
1322
|
+
|
1323
|
+
/*
|
1324
|
+
* call-seq:
|
1325
|
+
* client.unsubscribe(3, "unsubscribe") -> Boolean
|
1326
|
+
*
|
1327
|
+
* Unsubscribe from a topic.
|
1328
|
+
*
|
1329
|
+
* @param mid [Integer, nil] If not nil, the function will set this to the message id of this particular message.
|
1330
|
+
* This can be then used with the unsubscribe callback to determine when the message has been
|
1331
|
+
* sent.
|
1332
|
+
* @param subscription [String] the unsubscription pattern.
|
1333
|
+
* @return [true] on success
|
1334
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
1335
|
+
* @example
|
1336
|
+
* client.unsubscribe(3, "unsubscribe")
|
1337
|
+
*
|
1338
|
+
*/
|
1339
|
+
static VALUE rb_mosquitto_client_unsubscribe(VALUE obj, VALUE mid, VALUE subscription)
|
1340
|
+
{
|
1341
|
+
struct nogvl_subscribe_args args;
|
1342
|
+
int ret, msg_id;
|
1343
|
+
MosquittoGetClient(obj);
|
1344
|
+
Check_Type(subscription, T_STRING);
|
1345
|
+
MosquittoEncode(subscription);
|
1346
|
+
if (!NIL_P(mid)) {
|
1347
|
+
Check_Type(mid, T_FIXNUM);
|
1348
|
+
msg_id = NUM2INT(mid);
|
1349
|
+
}
|
1350
|
+
args.mosq = client->mosq;
|
1351
|
+
args.mid = NIL_P(mid) ? NULL : &msg_id;
|
1352
|
+
args.subscription = StringValueCStr(subscription);
|
1353
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_unsubscribe_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
1354
|
+
switch (ret) {
|
1355
|
+
case MOSQ_ERR_INVAL:
|
1356
|
+
MosquittoError("invalid input params");
|
1357
|
+
break;
|
1358
|
+
case MOSQ_ERR_NOMEM:
|
1359
|
+
rb_memerror();
|
1360
|
+
break;
|
1361
|
+
case MOSQ_ERR_NO_CONN:
|
1362
|
+
MosquittoError("client not connected to broker");
|
1363
|
+
break;
|
1364
|
+
default:
|
1365
|
+
return Qtrue;
|
1366
|
+
}
|
1367
|
+
}
|
1368
|
+
|
1369
|
+
/*
|
1370
|
+
* call-seq:
|
1371
|
+
* client.socket -> Integer
|
1372
|
+
*
|
1373
|
+
* Return the socket handle for a mosquitto instance. Useful if you want to include a mosquitto client in your own
|
1374
|
+
* select() calls.
|
1375
|
+
*
|
1376
|
+
* @return [Integer] socket identifier, or -1 on failure
|
1377
|
+
* @example
|
1378
|
+
* client.socket
|
1379
|
+
*
|
1380
|
+
*/
|
1381
|
+
static VALUE rb_mosquitto_client_socket(VALUE obj)
|
1382
|
+
{
|
1383
|
+
int socket;
|
1384
|
+
MosquittoGetClient(obj);
|
1385
|
+
socket = mosquitto_socket(client->mosq);
|
1386
|
+
return INT2NUM(socket);
|
1387
|
+
}
|
1388
|
+
|
1389
|
+
static void *rb_mosquitto_client_loop_nogvl(void *ptr)
|
1390
|
+
{
|
1391
|
+
struct nogvl_loop_args *args = ptr;
|
1392
|
+
return (VALUE)mosquitto_loop(args->mosq, args->timeout, args->max_packets);
|
1393
|
+
}
|
1394
|
+
|
1395
|
+
/*
|
1396
|
+
* call-seq:
|
1397
|
+
* client.loop(10, 10) -> Boolean
|
1398
|
+
*
|
1399
|
+
* The main network loop for the client. You must call this frequently in order
|
1400
|
+
* to keep communications between the client and broker working. If incoming
|
1401
|
+
* data is present it will then be processed. Outgoing commands, from e.g.
|
1402
|
+
* Mosquitto::Client#publish, are normally sent immediately that their function is
|
1403
|
+
* called, but this is not always possible. Mosquitto::Client#loop will also attempt
|
1404
|
+
* to send any remaining outgoing messages, which also includes commands that
|
1405
|
+
* are part of the flow for messages with QoS>0.
|
1406
|
+
*
|
1407
|
+
* An alternative approach is to use Mosquitto::Client#loop_start to run the client
|
1408
|
+
* loop in its own thread.
|
1409
|
+
*
|
1410
|
+
* This calls select() to monitor the client network socket. If you want to
|
1411
|
+
* integrate mosquitto client operation with your own select() call, use
|
1412
|
+
* Mosquitto::Client#socket, Mosquitto::Client#loop_read, Mosquitto::Client#loop_write and
|
1413
|
+
* Mosquitto::Client#loop_misc.
|
1414
|
+
*
|
1415
|
+
* @param timeout [Integer] Maximum number of milliseconds to wait for network activity in the select()
|
1416
|
+
* call before timing out. Set to 0 for instant return. Set negative to use the
|
1417
|
+
* default of 1000ms
|
1418
|
+
* @param max_packets [Integer] this parameter is currently unused and should be set to 1 for future compatibility.
|
1419
|
+
* @return [true] on success
|
1420
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
1421
|
+
* @example
|
1422
|
+
* client.loop(10, 10)
|
1423
|
+
*
|
1424
|
+
*/
|
1425
|
+
static VALUE rb_mosquitto_client_loop(VALUE obj, VALUE timeout, VALUE max_packets)
|
1426
|
+
{
|
1427
|
+
struct nogvl_loop_args args;
|
1428
|
+
int ret;
|
1429
|
+
MosquittoGetClient(obj);
|
1430
|
+
Check_Type(timeout, T_FIXNUM);
|
1431
|
+
Check_Type(max_packets, T_FIXNUM);
|
1432
|
+
args.mosq = client->mosq;
|
1433
|
+
args.timeout = NUM2INT(timeout);
|
1434
|
+
args.max_packets = NUM2INT(max_packets);
|
1435
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_loop_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
1436
|
+
switch (ret) {
|
1437
|
+
case MOSQ_ERR_INVAL:
|
1438
|
+
MosquittoError("invalid input params");
|
1439
|
+
break;
|
1440
|
+
case MOSQ_ERR_NOMEM:
|
1441
|
+
rb_memerror();
|
1442
|
+
break;
|
1443
|
+
case MOSQ_ERR_NO_CONN:
|
1444
|
+
MosquittoError("client not connected to broker");
|
1445
|
+
break;
|
1446
|
+
case MOSQ_ERR_CONN_LOST:
|
1447
|
+
MosquittoError("connection to the broker was lost");
|
1448
|
+
break;
|
1449
|
+
case MOSQ_ERR_PROTOCOL:
|
1450
|
+
MosquittoError("protocol error communicating with the broker");
|
1451
|
+
break;
|
1452
|
+
case MOSQ_ERR_ERRNO:
|
1453
|
+
rb_sys_fail("mosquitto_loop");
|
1454
|
+
break;
|
1455
|
+
default:
|
1456
|
+
return Qtrue;
|
1457
|
+
}
|
1458
|
+
}
|
1459
|
+
|
1460
|
+
static void *rb_mosquitto_client_loop_forever_nogvl(void *ptr)
|
1461
|
+
{
|
1462
|
+
struct nogvl_loop_args *args = ptr;
|
1463
|
+
return (VALUE)mosquitto_loop_forever(args->mosq, args->timeout, args->max_packets);
|
1464
|
+
}
|
1465
|
+
|
1466
|
+
static void rb_mosquitto_client_loop_forever_ubf(void *ptr)
|
1467
|
+
{
|
1468
|
+
mosquitto_client_wrapper *client = (mosquitto_client_wrapper *)ptr;
|
1469
|
+
mosquitto_disconnect(client->mosq);
|
1470
|
+
}
|
1471
|
+
|
1472
|
+
/*
|
1473
|
+
* call-seq:
|
1474
|
+
* client.loop_forever(10, 1) -> Boolean
|
1475
|
+
*
|
1476
|
+
* This function calls Mosquitto::Client#loop for you in an infinite blocking loop. It is useful
|
1477
|
+
* for the case where you only want to run the MQTT client loop in your program.
|
1478
|
+
*
|
1479
|
+
* It handles reconnecting in case server connection is lost. If you call Mosquitto::Client#disconnect in
|
1480
|
+
* a callback it will return.
|
1481
|
+
*
|
1482
|
+
* @param timeout [Integer] Maximum number of milliseconds to wait for network activity in the select()
|
1483
|
+
* call before timing out. Set to 0 for instant return. Set negative to use the
|
1484
|
+
* default of 1000ms
|
1485
|
+
* @param max_packets [Integer] this parameter is currently unused and should be set to 1 for future compatibility.
|
1486
|
+
* @return [true] on success
|
1487
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
1488
|
+
* @example
|
1489
|
+
* client.loop_forever(10, 1)
|
1490
|
+
*
|
1491
|
+
*/
|
1492
|
+
static VALUE rb_mosquitto_client_loop_forever(VALUE obj, VALUE timeout, VALUE max_packets)
|
1493
|
+
{
|
1494
|
+
struct nogvl_loop_args args;
|
1495
|
+
int ret;
|
1496
|
+
MosquittoGetClient(obj);
|
1497
|
+
Check_Type(timeout, T_FIXNUM);
|
1498
|
+
Check_Type(max_packets, T_FIXNUM);
|
1499
|
+
args.mosq = client->mosq;
|
1500
|
+
args.timeout = NUM2INT(timeout);
|
1501
|
+
args.max_packets = NUM2INT(max_packets);
|
1502
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_loop_forever_nogvl, (void *)&args, rb_mosquitto_client_loop_forever_ubf, client);
|
1503
|
+
switch (ret) {
|
1504
|
+
case MOSQ_ERR_INVAL:
|
1505
|
+
MosquittoError("invalid input params");
|
1506
|
+
break;
|
1507
|
+
case MOSQ_ERR_NOMEM:
|
1508
|
+
rb_memerror();
|
1509
|
+
break;
|
1510
|
+
case MOSQ_ERR_NO_CONN:
|
1511
|
+
MosquittoError("client not connected to broker");
|
1512
|
+
break;
|
1513
|
+
case MOSQ_ERR_CONN_LOST:
|
1514
|
+
MosquittoError("connection to the broker was lost");
|
1515
|
+
break;
|
1516
|
+
case MOSQ_ERR_PROTOCOL:
|
1517
|
+
MosquittoError("protocol error communicating with the broker");
|
1518
|
+
break;
|
1519
|
+
case MOSQ_ERR_ERRNO:
|
1520
|
+
rb_sys_fail("mosquitto_loop");
|
1521
|
+
break;
|
1522
|
+
default:
|
1523
|
+
return Qtrue;
|
1524
|
+
}
|
1525
|
+
}
|
1526
|
+
|
1527
|
+
static void *rb_mosquitto_client_loop_start_nogvl(void *ptr)
|
1528
|
+
{
|
1529
|
+
return (VALUE)mosquitto_loop_start((struct mosquitto *)ptr);
|
1530
|
+
}
|
1531
|
+
|
1532
|
+
/*
|
1533
|
+
* call-seq:
|
1534
|
+
* client.loop_start -> Boolean
|
1535
|
+
*
|
1536
|
+
* This is part of the threaded client interface. Call this once to start a new
|
1537
|
+
* thread to process network traffic. This provides an alternative to repeatedly calling
|
1538
|
+
* Mosquitto::Client#loop yourself.
|
1539
|
+
*
|
1540
|
+
* @return [true] on success
|
1541
|
+
* @raise [Mosquitto::Error] on invalid input params or if thread support is not available
|
1542
|
+
* @example
|
1543
|
+
* client.loop_start
|
1544
|
+
*
|
1545
|
+
*/
|
1546
|
+
static VALUE rb_mosquitto_client_loop_start(VALUE obj)
|
1547
|
+
{
|
1548
|
+
int ret;
|
1549
|
+
struct timeval time;
|
1550
|
+
MosquittoGetClient(obj);
|
1551
|
+
/* Let's not spawn duplicate threaded loops */
|
1552
|
+
if (!NIL_P(client->callback_thread)) return Qtrue;
|
1553
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_loop_start_nogvl, (void *)client->mosq, RUBY_UBF_IO, 0);
|
1554
|
+
switch (ret) {
|
1555
|
+
case MOSQ_ERR_INVAL:
|
1556
|
+
MosquittoError("invalid input params");
|
1557
|
+
break;
|
1558
|
+
case MOSQ_ERR_NOT_SUPPORTED :
|
1559
|
+
MosquittoError("thread support is not available");
|
1560
|
+
break;
|
1561
|
+
default:
|
1562
|
+
pthread_mutex_init(&client->callback_mutex, NULL);
|
1563
|
+
pthread_cond_init(&client->callback_cond, NULL);
|
1564
|
+
client->callback_thread = rb_thread_create(rb_mosquitto_callback_thread, client);
|
1565
|
+
/* Allow the callback thread some startup time */
|
1566
|
+
time.tv_sec = 0;
|
1567
|
+
time.tv_usec = 100 * 1000; /* 0.1 sec */
|
1568
|
+
rb_thread_wait_for(time);
|
1569
|
+
return Qtrue;
|
1570
|
+
}
|
1571
|
+
}
|
1572
|
+
|
1573
|
+
static void *rb_mosquitto_client_loop_stop_nogvl(void *ptr)
|
1574
|
+
{
|
1575
|
+
struct nogvl_loop_stop_args *args = ptr;
|
1576
|
+
return (VALUE)mosquitto_loop_stop(args->mosq, args->force);
|
1577
|
+
}
|
1578
|
+
|
1579
|
+
/*
|
1580
|
+
* call-seq:
|
1581
|
+
* client.loop_start -> Boolean
|
1582
|
+
*
|
1583
|
+
* This is part of the threaded client interface. Call this once to stop the
|
1584
|
+
* network thread previously created with Mosquitto::Client#loop_start. This call
|
1585
|
+
* will block until the network thread finishes. For the network thread to end,
|
1586
|
+
* you must have previously called Mosquitto::Client#disconnect or have set the force
|
1587
|
+
* parameter to true.
|
1588
|
+
*
|
1589
|
+
* @param force [Boolean] set to true to force thread cancellation. If false, Mosquitto::Client#disconnect
|
1590
|
+
* must have already been called.
|
1591
|
+
* @return [true] on success
|
1592
|
+
* @raise [Mosquitto::Error] on invalid input params or if thread support is not available
|
1593
|
+
* @example
|
1594
|
+
* client.loop_start
|
1595
|
+
*
|
1596
|
+
*/
|
1597
|
+
static VALUE rb_mosquitto_client_loop_stop(VALUE obj, VALUE force)
|
1598
|
+
{
|
1599
|
+
struct nogvl_loop_stop_args args;
|
1600
|
+
int ret;
|
1601
|
+
MosquittoGetClient(obj);
|
1602
|
+
args.mosq = client->mosq;
|
1603
|
+
args.force = ((force == Qtrue) ? true : false);
|
1604
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_loop_stop_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
1605
|
+
switch (ret) {
|
1606
|
+
case MOSQ_ERR_INVAL:
|
1607
|
+
MosquittoError("invalid input params");
|
1608
|
+
break;
|
1609
|
+
case MOSQ_ERR_NOT_SUPPORTED :
|
1610
|
+
MosquittoError("thread support is not available");
|
1611
|
+
break;
|
1612
|
+
default:
|
1613
|
+
pthread_mutex_destroy(&client->callback_mutex);
|
1614
|
+
pthread_cond_destroy(&client->callback_cond);
|
1615
|
+
rb_thread_kill(client->callback_thread);
|
1616
|
+
client->callback_thread = Qnil;
|
1617
|
+
return Qtrue;
|
1618
|
+
}
|
1619
|
+
}
|
1620
|
+
|
1621
|
+
static void *rb_mosquitto_client_loop_read_nogvl(void *ptr)
|
1622
|
+
{
|
1623
|
+
struct nogvl_loop_args *args = ptr;
|
1624
|
+
return (VALUE)mosquitto_loop_read(args->mosq, args->max_packets);
|
1625
|
+
}
|
1626
|
+
|
1627
|
+
/*
|
1628
|
+
* call-seq:
|
1629
|
+
* client.loop_read(10) -> Boolean
|
1630
|
+
*
|
1631
|
+
* Carry out network read operations. This should only be used if you are not using Mosquitto::Client#loop and
|
1632
|
+
* are monitoring the client network socket for activity yourself.
|
1633
|
+
*
|
1634
|
+
* @param max_packets [Integer] this parameter is currently unused and should be set to 1 for
|
1635
|
+
* future compatibility.
|
1636
|
+
* @return [true] on success
|
1637
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
1638
|
+
* @example
|
1639
|
+
* client.loop_read(10)
|
1640
|
+
*
|
1641
|
+
*/
|
1642
|
+
static VALUE rb_mosquitto_client_loop_read(VALUE obj, VALUE max_packets)
|
1643
|
+
{
|
1644
|
+
struct nogvl_loop_args args;
|
1645
|
+
int ret;
|
1646
|
+
MosquittoGetClient(obj);
|
1647
|
+
Check_Type(max_packets, T_FIXNUM);
|
1648
|
+
args.mosq = client->mosq;
|
1649
|
+
args.max_packets = NUM2INT(max_packets);
|
1650
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_loop_read_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
1651
|
+
switch (ret) {
|
1652
|
+
case MOSQ_ERR_INVAL:
|
1653
|
+
MosquittoError("invalid input params");
|
1654
|
+
break;
|
1655
|
+
case MOSQ_ERR_NOMEM:
|
1656
|
+
rb_memerror();
|
1657
|
+
break;
|
1658
|
+
case MOSQ_ERR_NO_CONN:
|
1659
|
+
MosquittoError("client not connected to broker");
|
1660
|
+
break;
|
1661
|
+
case MOSQ_ERR_CONN_LOST:
|
1662
|
+
MosquittoError("connection to the broker was lost");
|
1663
|
+
break;
|
1664
|
+
case MOSQ_ERR_PROTOCOL:
|
1665
|
+
MosquittoError("protocol error communicating with the broker");
|
1666
|
+
break;
|
1667
|
+
case MOSQ_ERR_ERRNO:
|
1668
|
+
rb_sys_fail("mosquitto_loop");
|
1669
|
+
break;
|
1670
|
+
default:
|
1671
|
+
return Qtrue;
|
1672
|
+
}
|
1673
|
+
}
|
1674
|
+
|
1675
|
+
static void *rb_mosquitto_client_loop_write_nogvl(void *ptr)
|
1676
|
+
{
|
1677
|
+
struct nogvl_loop_args *args = ptr;
|
1678
|
+
return (VALUE)mosquitto_loop_write(args->mosq, args->max_packets);
|
1679
|
+
}
|
1680
|
+
|
1681
|
+
/*
|
1682
|
+
* call-seq:
|
1683
|
+
* client.loop_write(1) -> Boolean
|
1684
|
+
*
|
1685
|
+
* Carry out network write operations. This should only be used if you are not using Mosquitto::Client#loop and
|
1686
|
+
* are monitoring the client network socket for activity yourself.
|
1687
|
+
*
|
1688
|
+
* @param max_packets [Integer] this parameter is currently unused and should be set to 1 for
|
1689
|
+
* future compatibility.
|
1690
|
+
* @return [true] on success
|
1691
|
+
* @raise [Mosquitto::Error, SystemCallError] on invalid input params or system call errors
|
1692
|
+
* @example
|
1693
|
+
* client.loop_write(1)
|
1694
|
+
*
|
1695
|
+
*/
|
1696
|
+
static VALUE rb_mosquitto_client_loop_write(VALUE obj, VALUE max_packets)
|
1697
|
+
{
|
1698
|
+
struct nogvl_loop_args args;
|
1699
|
+
int ret;
|
1700
|
+
MosquittoGetClient(obj);
|
1701
|
+
Check_Type(max_packets, T_FIXNUM);
|
1702
|
+
args.mosq = client->mosq;
|
1703
|
+
args.max_packets = NUM2INT(max_packets);
|
1704
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_loop_write_nogvl, (void *)&args, RUBY_UBF_IO, 0);
|
1705
|
+
switch (ret) {
|
1706
|
+
case MOSQ_ERR_INVAL:
|
1707
|
+
MosquittoError("invalid input params");
|
1708
|
+
break;
|
1709
|
+
case MOSQ_ERR_NOMEM:
|
1710
|
+
rb_memerror();
|
1711
|
+
break;
|
1712
|
+
case MOSQ_ERR_NO_CONN:
|
1713
|
+
MosquittoError("client not connected to broker");
|
1714
|
+
break;
|
1715
|
+
case MOSQ_ERR_CONN_LOST:
|
1716
|
+
MosquittoError("connection to the broker was lost");
|
1717
|
+
break;
|
1718
|
+
case MOSQ_ERR_PROTOCOL:
|
1719
|
+
MosquittoError("protocol error communicating with the broker");
|
1720
|
+
break;
|
1721
|
+
case MOSQ_ERR_ERRNO:
|
1722
|
+
rb_sys_fail("mosquitto_loop");
|
1723
|
+
break;
|
1724
|
+
default:
|
1725
|
+
return Qtrue;
|
1726
|
+
}
|
1727
|
+
}
|
1728
|
+
|
1729
|
+
static void *rb_mosquitto_client_loop_misc_nogvl(void *ptr)
|
1730
|
+
{
|
1731
|
+
return (VALUE)mosquitto_loop_misc((struct mosquitto *)ptr);
|
1732
|
+
}
|
1733
|
+
|
1734
|
+
/*
|
1735
|
+
* call-seq:
|
1736
|
+
* client.loop_misc -> Boolean
|
1737
|
+
*
|
1738
|
+
* Carry out miscellaneous operations required as part of the network loop.
|
1739
|
+
* This should only be used if you are not using Mosquitto::Client#loop and are
|
1740
|
+
* monitoring the client network socket for activity yourself.
|
1741
|
+
*
|
1742
|
+
* This function deals with handling PINGs and checking whether messages need
|
1743
|
+
* to be retried, so should be called fairly frequently.
|
1744
|
+
*
|
1745
|
+
* @return [true] on success
|
1746
|
+
* @raise [Mosquitto::Error] on invalid input params or when not connected to the broker
|
1747
|
+
* @example
|
1748
|
+
* client.loop_misc
|
1749
|
+
*
|
1750
|
+
*/
|
1751
|
+
static VALUE rb_mosquitto_client_loop_misc(VALUE obj)
|
1752
|
+
{
|
1753
|
+
int ret;
|
1754
|
+
MosquittoGetClient(obj);
|
1755
|
+
ret = (int)rb_thread_call_without_gvl(rb_mosquitto_client_loop_misc_nogvl, (void *)client->mosq, RUBY_UBF_IO, 0);
|
1756
|
+
switch (ret) {
|
1757
|
+
case MOSQ_ERR_INVAL:
|
1758
|
+
MosquittoError("invalid input params");
|
1759
|
+
break;
|
1760
|
+
case MOSQ_ERR_NO_CONN:
|
1761
|
+
MosquittoError("client not connected to broker");
|
1762
|
+
break;
|
1763
|
+
default:
|
1764
|
+
return Qtrue;
|
1765
|
+
}
|
1766
|
+
}
|
1767
|
+
|
1768
|
+
/*
|
1769
|
+
* call-seq:
|
1770
|
+
* client.want_write? -> Boolean
|
1771
|
+
*
|
1772
|
+
* Returns true if there is data ready to be written on the socket.
|
1773
|
+
*
|
1774
|
+
* @return [true, false] true if there is data ready to be written on the socket
|
1775
|
+
* @example
|
1776
|
+
* client.want_write
|
1777
|
+
*
|
1778
|
+
*/
|
1779
|
+
static VALUE rb_mosquitto_client_want_write(VALUE obj)
|
1780
|
+
{
|
1781
|
+
bool ret;
|
1782
|
+
MosquittoGetClient(obj);
|
1783
|
+
ret = mosquitto_want_write(client->mosq);
|
1784
|
+
return (ret == true) ? Qtrue : Qfalse;
|
1785
|
+
}
|
1786
|
+
|
1787
|
+
/*
|
1788
|
+
* call-seq:
|
1789
|
+
* client.reconnect_delay_set(2, 10, true) -> Boolean
|
1790
|
+
*
|
1791
|
+
* Control the behaviour of the client when it has unexpectedly disconnected in
|
1792
|
+
* Mosquitto::Client#loop_forever or after Mosquitto::Client#loop_start. The default
|
1793
|
+
* behaviour if this function is not used is to repeatedly attempt to reconnect
|
1794
|
+
* with a delay of 1 second until the connection succeeds.
|
1795
|
+
*
|
1796
|
+
* Use reconnect_delay parameter to change the delay between successive
|
1797
|
+
* reconnection attempts. You may also enable exponential backoff of the time
|
1798
|
+
* between reconnections by setting reconnect_exponential_backoff to true and
|
1799
|
+
* set an upper bound on the delay with reconnect_delay_max.
|
1800
|
+
*
|
1801
|
+
* Example 1:
|
1802
|
+
* delay=2, delay_max=10, exponential_backoff=False
|
1803
|
+
* Delays would be: 2, 4, 6, 8, 10, 10, ...
|
1804
|
+
*
|
1805
|
+
* Example 2:
|
1806
|
+
* delay=3, delay_max=30, exponential_backoff=True
|
1807
|
+
* Delays would be: 3, 6, 12, 24, 30, 30, ...
|
1808
|
+
*
|
1809
|
+
* @param delay [Integer] the number of seconds to wait between reconnects
|
1810
|
+
* @param delay_max [Integer] the maximum number of seconds to wait between reconnects
|
1811
|
+
* @param exponential_backoff [true, false] use exponential backoff between reconnect attempts.
|
1812
|
+
Set to true to enable exponential backoff.
|
1813
|
+
* @return [true] on success
|
1814
|
+
* @raise [Mosquitto::Error] on invalid input params
|
1815
|
+
* @example
|
1816
|
+
* client.reconnect_delay_set(2, 10, true)
|
1817
|
+
*
|
1818
|
+
*/
|
1819
|
+
static VALUE rb_mosquitto_client_reconnect_delay_set(VALUE obj, VALUE delay, VALUE delay_max, VALUE exp_backoff)
|
1820
|
+
{
|
1821
|
+
int ret;
|
1822
|
+
MosquittoGetClient(obj);
|
1823
|
+
Check_Type(delay, T_FIXNUM);
|
1824
|
+
Check_Type(delay_max, T_FIXNUM);
|
1825
|
+
ret = mosquitto_reconnect_delay_set(client->mosq, INT2NUM(delay), INT2NUM(delay_max), ((exp_backoff == Qtrue) ? true : false));
|
1826
|
+
switch (ret) {
|
1827
|
+
case MOSQ_ERR_INVAL:
|
1828
|
+
MosquittoError("invalid input params");
|
1829
|
+
break;
|
1830
|
+
default:
|
1831
|
+
return Qtrue;
|
1832
|
+
}
|
1833
|
+
}
|
1834
|
+
|
1835
|
+
/*
|
1836
|
+
* call-seq:
|
1837
|
+
* client.max_inflight_messages = 10 -> Boolean
|
1838
|
+
*
|
1839
|
+
* Set the number of QoS 1 and 2 messages that can be "in flight" at one time.
|
1840
|
+
* An in flight message is part way through its delivery flow. Attempts to send
|
1841
|
+
* further messages with mosquitto::Client#publish will result in the messages being
|
1842
|
+
* queued until the number of in flight messages reduces.
|
1843
|
+
*
|
1844
|
+
* A higher number here results in greater message throughput, but if set
|
1845
|
+
* higher than the maximum in flight messages on the broker may lead to
|
1846
|
+
* delays in the messages being acknowledged.
|
1847
|
+
*
|
1848
|
+
* Set to 0 for no maximum.
|
1849
|
+
*
|
1850
|
+
* @param max_messages [Integer] the maximum number of inflight messages. Defaults to 20.
|
1851
|
+
* @return [true] on success
|
1852
|
+
* @raise [Mosquitto::Error] on invalid input params
|
1853
|
+
* @example
|
1854
|
+
* client.max_inflight_messages = 10
|
1855
|
+
*
|
1856
|
+
*/
|
1857
|
+
static VALUE rb_mosquitto_client_max_inflight_messages_equals(VALUE obj, VALUE max_messages)
|
1858
|
+
{
|
1859
|
+
int ret;
|
1860
|
+
MosquittoGetClient(obj);
|
1861
|
+
Check_Type(max_messages, T_FIXNUM);
|
1862
|
+
ret = mosquitto_max_inflight_messages_set(client->mosq, INT2NUM(max_messages));
|
1863
|
+
switch (ret) {
|
1864
|
+
case MOSQ_ERR_INVAL:
|
1865
|
+
MosquittoError("invalid input params");
|
1866
|
+
break;
|
1867
|
+
default:
|
1868
|
+
return Qtrue;
|
1869
|
+
}
|
1870
|
+
}
|
1871
|
+
|
1872
|
+
/*
|
1873
|
+
* call-seq:
|
1874
|
+
* client.message_retry = 10 -> Boolean
|
1875
|
+
*
|
1876
|
+
* Set the number of seconds to wait before retrying messages. This applies to
|
1877
|
+
* publish messages with QoS>0. May be called at any time.
|
1878
|
+
*
|
1879
|
+
* @param message_retry [Integer] the number of seconds to wait for a response before retrying. Defaults to 20.
|
1880
|
+
* @return [true] on success
|
1881
|
+
* @raise [Mosquitto::Error] on invalid input params
|
1882
|
+
* @example
|
1883
|
+
* client.message_retry = 10
|
1884
|
+
*
|
1885
|
+
*/
|
1886
|
+
static VALUE rb_mosquitto_client_message_retry_equals(VALUE obj, VALUE seconds)
|
1887
|
+
{
|
1888
|
+
MosquittoGetClient(obj);
|
1889
|
+
Check_Type(seconds, T_FIXNUM);
|
1890
|
+
mosquitto_message_retry_set(client->mosq, INT2NUM(seconds));
|
1891
|
+
return Qtrue;
|
1892
|
+
}
|
1893
|
+
|
1894
|
+
/*
|
1895
|
+
* call-seq:
|
1896
|
+
* client.on_connect{|rc| p :connected } -> Boolean
|
1897
|
+
*
|
1898
|
+
* Set the connect callback. This is called when the broker sends a CONNACK
|
1899
|
+
* message in response to a connection.
|
1900
|
+
*
|
1901
|
+
* @yield connect callback
|
1902
|
+
* @yieldparam rc [Integer] the return code of the connection response, one of: 0 - success,
|
1903
|
+
* 1 - connection refused (unacceptable protocol version),
|
1904
|
+
* 2 - connection refused (identifier rejected)
|
1905
|
+
* 3 - connection refused (broker unavailable)
|
1906
|
+
* @return [true] on success
|
1907
|
+
* @raise [TypeError, ArgumentError] if callback is not a Proc or if the method arity is wrong
|
1908
|
+
* @example
|
1909
|
+
* client.on_connect{|rc| p :connected }
|
1910
|
+
*
|
1911
|
+
*/
|
1912
|
+
static VALUE rb_mosquitto_client_on_connect(int argc, VALUE *argv, VALUE obj)
|
1913
|
+
{
|
1914
|
+
VALUE proc, cb;
|
1915
|
+
MosquittoGetClient(obj);
|
1916
|
+
rb_scan_args(argc, argv, "01&", &proc, &cb);
|
1917
|
+
MosquittoAssertCallback(cb, 1);
|
1918
|
+
if (!NIL_P(client->connect_cb)) rb_gc_unregister_address(&client->connect_cb);
|
1919
|
+
mosquitto_connect_callback_set(client->mosq, rb_mosquitto_client_on_connect_cb);
|
1920
|
+
client->connect_cb = cb;
|
1921
|
+
rb_gc_register_address(&client->connect_cb);
|
1922
|
+
return Qtrue;
|
1923
|
+
}
|
1924
|
+
|
1925
|
+
/*
|
1926
|
+
* call-seq:
|
1927
|
+
* client.on_disconnect{|rc| p :disconnected } -> Boolean
|
1928
|
+
*
|
1929
|
+
* Set the disconnect callback. This is called when the broker has received the
|
1930
|
+
* DISCONNECT command and has disconnected the client.
|
1931
|
+
*
|
1932
|
+
* @yield disconnect callback
|
1933
|
+
* @yieldparam rc [Integer] integer value indicating the reason for the disconnect. A value of 0
|
1934
|
+
* means the client has called Mosquitto::Client#disconnect. Any other value indicates that
|
1935
|
+
* the disconnect is unexpected.
|
1936
|
+
* @return [true] on success
|
1937
|
+
* @raise [TypeError, ArgumentError] if callback is not a Proc or if the method arity is wrong
|
1938
|
+
* @example
|
1939
|
+
* client.on_disconnect{|rc| p :disconnected }
|
1940
|
+
*
|
1941
|
+
*/
|
1942
|
+
static VALUE rb_mosquitto_client_on_disconnect(int argc, VALUE *argv, VALUE obj)
|
1943
|
+
{
|
1944
|
+
VALUE proc, cb;
|
1945
|
+
MosquittoGetClient(obj);
|
1946
|
+
rb_scan_args(argc, argv, "01&", &proc, &cb);
|
1947
|
+
MosquittoAssertCallback(cb, 1);
|
1948
|
+
if (!NIL_P(client->disconnect_cb)) rb_gc_unregister_address(&client->disconnect_cb);
|
1949
|
+
mosquitto_disconnect_callback_set(client->mosq, rb_mosquitto_client_on_disconnect_cb);
|
1950
|
+
client->disconnect_cb = cb;
|
1951
|
+
rb_gc_register_address(&client->disconnect_cb);
|
1952
|
+
return Qtrue;
|
1953
|
+
}
|
1954
|
+
|
1955
|
+
/*
|
1956
|
+
* call-seq:
|
1957
|
+
* client.on_publish{|mid| p :published } -> Boolean
|
1958
|
+
*
|
1959
|
+
* Set the publish callback. This is called when a message initiated with
|
1960
|
+
* Mosquitto::Client#publish has been sent to the broker successfully.
|
1961
|
+
*
|
1962
|
+
* @yield publish callback
|
1963
|
+
* @yieldparam mid [Integer] the message id of the sent message
|
1964
|
+
* @return [true] on success
|
1965
|
+
* @raise [TypeError, ArgumentError] if callback is not a Proc or if the method arity is wrong
|
1966
|
+
* @example
|
1967
|
+
* client.on_publish{|mid| p :published }
|
1968
|
+
*
|
1969
|
+
*/
|
1970
|
+
static VALUE rb_mosquitto_client_on_publish(int argc, VALUE *argv, VALUE obj)
|
1971
|
+
{
|
1972
|
+
VALUE proc, cb;
|
1973
|
+
MosquittoGetClient(obj);
|
1974
|
+
rb_scan_args(argc, argv, "01&", &proc, &cb);
|
1975
|
+
MosquittoAssertCallback(cb, 1);
|
1976
|
+
if (!NIL_P(client->publish_cb)) rb_gc_unregister_address(&client->publish_cb);
|
1977
|
+
mosquitto_publish_callback_set(client->mosq, rb_mosquitto_client_on_publish_cb);
|
1978
|
+
client->publish_cb = cb;
|
1979
|
+
rb_gc_register_address(&client->publish_cb);
|
1980
|
+
return Qtrue;
|
1981
|
+
}
|
1982
|
+
|
1983
|
+
/*
|
1984
|
+
* call-seq:
|
1985
|
+
* client.on_message{|msg| p msg } -> Boolean
|
1986
|
+
*
|
1987
|
+
* Set the message callback. This is called when a message is received from the
|
1988
|
+
* broker.
|
1989
|
+
*
|
1990
|
+
* @yield message callback
|
1991
|
+
* @yieldparam msg [Mosquitto::Message] the message data
|
1992
|
+
* @return [true] on success
|
1993
|
+
* @raise [TypeError, ArgumentError] if callback is not a Proc or if the method arity is wrong
|
1994
|
+
* @example
|
1995
|
+
* client.on_message{|msg| p msg }
|
1996
|
+
*
|
1997
|
+
*/
|
1998
|
+
static VALUE rb_mosquitto_client_on_message(int argc, VALUE *argv, VALUE obj)
|
1999
|
+
{
|
2000
|
+
VALUE proc, cb;
|
2001
|
+
MosquittoGetClient(obj);
|
2002
|
+
rb_scan_args(argc, argv, "01&", &proc, &cb);
|
2003
|
+
MosquittoAssertCallback(cb, 1);
|
2004
|
+
if (!NIL_P(client->message_cb)) rb_gc_unregister_address(&client->message_cb);
|
2005
|
+
mosquitto_message_callback_set(client->mosq, rb_mosquitto_client_on_message_cb);
|
2006
|
+
client->message_cb = cb;
|
2007
|
+
rb_gc_register_address(&client->message_cb);
|
2008
|
+
return Qtrue;
|
2009
|
+
}
|
2010
|
+
|
2011
|
+
/*
|
2012
|
+
* call-seq:
|
2013
|
+
* client.on_subscribe{|mid, granted_qos| p :subscribed } -> Boolean
|
2014
|
+
*
|
2015
|
+
* Set the subscribe callback. This is called when the broker responds to a
|
2016
|
+
* subscription request.
|
2017
|
+
*
|
2018
|
+
* @yield subscription callback
|
2019
|
+
* @yieldparam mid [Integer] the message id of the subscribe message.
|
2020
|
+
* @yieldparam granted_qos [Array] an array of integers indicating the granted QoS for each of
|
2021
|
+
* the subscriptions.
|
2022
|
+
* @return [true] on success
|
2023
|
+
* @raise [TypeError, ArgumentError] if callback is not a Proc or if the method arity is wrong
|
2024
|
+
* @example
|
2025
|
+
* client.on_subscribe{|mid, granted_qos| p :subscribed }
|
2026
|
+
*
|
2027
|
+
*/
|
2028
|
+
static VALUE rb_mosquitto_client_on_subscribe(int argc, VALUE *argv, VALUE obj)
|
2029
|
+
{
|
2030
|
+
VALUE proc, cb;
|
2031
|
+
MosquittoGetClient(obj);
|
2032
|
+
rb_scan_args(argc, argv, "01&", &proc, &cb);
|
2033
|
+
MosquittoAssertCallback(cb, 2);
|
2034
|
+
if (!NIL_P(client->subscribe_cb)) rb_gc_unregister_address(&client->subscribe_cb);
|
2035
|
+
mosquitto_subscribe_callback_set(client->mosq, rb_mosquitto_client_on_subscribe_cb);
|
2036
|
+
client->subscribe_cb = cb;
|
2037
|
+
rb_gc_register_address(&client->subscribe_cb);
|
2038
|
+
return Qtrue;
|
2039
|
+
}
|
2040
|
+
|
2041
|
+
/*
|
2042
|
+
* call-seq:
|
2043
|
+
* client.on_unsubscribe{|mid| p :unsubscribed } -> Boolean
|
2044
|
+
*
|
2045
|
+
* Set the unsubscribe callback. This is called when the broker responds to a
|
2046
|
+
* unsubscription request.
|
2047
|
+
*
|
2048
|
+
* @yield unsubscribe callback
|
2049
|
+
* @yieldparam mid [Integer] the message id of the unsubscribe message.
|
2050
|
+
|
2051
|
+
* @return [true] on success
|
2052
|
+
* @raise [TypeError, ArgumentError] if callback is not a Proc or if the method arity is wrong
|
2053
|
+
* @example
|
2054
|
+
* client.on_unsubscribe{|mid| p :unsubscribed }
|
2055
|
+
*
|
2056
|
+
*/
|
2057
|
+
static VALUE rb_mosquitto_client_on_unsubscribe(int argc, VALUE *argv, VALUE obj)
|
2058
|
+
{
|
2059
|
+
VALUE proc, cb;
|
2060
|
+
MosquittoGetClient(obj);
|
2061
|
+
rb_scan_args(argc, argv, "01&", &proc, &cb);
|
2062
|
+
MosquittoAssertCallback(cb, 1);
|
2063
|
+
if (!NIL_P(client->unsubscribe_cb)) rb_gc_unregister_address(&client->unsubscribe_cb);
|
2064
|
+
mosquitto_unsubscribe_callback_set(client->mosq, rb_mosquitto_client_on_unsubscribe_cb);
|
2065
|
+
client->unsubscribe_cb = cb;
|
2066
|
+
rb_gc_register_address(&client->unsubscribe_cb);
|
2067
|
+
return Qtrue;
|
2068
|
+
}
|
2069
|
+
|
2070
|
+
/*
|
2071
|
+
* call-seq:
|
2072
|
+
* client.on_log{|level, msg| p msg } -> Boolean
|
2073
|
+
*
|
2074
|
+
* Set the logging callback. This should be used if you want event logging
|
2075
|
+
* information from the client library.
|
2076
|
+
*
|
2077
|
+
* @yield unsubscribe callback
|
2078
|
+
* @yieldparam level [Mosquitto::LOG_INFO, Mosquitto::LOG_NOTICE, Mosquitto::LOG_WARNING,
|
2079
|
+
* Mosquitto::LOG_ERR, Mosquitto::LOG_DEBUG] the log message level
|
2080
|
+
* @yieldparam msg [String] log message
|
2081
|
+
* @return [true] on success
|
2082
|
+
* @raise [TypeError, ArgumentError] if callback is not a Proc or if the method arity is wrong
|
2083
|
+
* @example
|
2084
|
+
* client.on_log{|level, msg| p msg }
|
2085
|
+
*
|
2086
|
+
*/
|
2087
|
+
static VALUE rb_mosquitto_client_on_log(int argc, VALUE *argv, VALUE obj)
|
2088
|
+
{
|
2089
|
+
VALUE proc, cb;
|
2090
|
+
MosquittoGetClient(obj);
|
2091
|
+
rb_scan_args(argc, argv, "01&", &proc, &cb);
|
2092
|
+
MosquittoAssertCallback(cb, 2);
|
2093
|
+
if (!NIL_P(client->log_cb)) rb_gc_unregister_address(&client->log_cb);
|
2094
|
+
mosquitto_log_callback_set(client->mosq, rb_mosquitto_client_on_log_cb);
|
2095
|
+
client->log_cb = cb;
|
2096
|
+
rb_gc_register_address(&client->log_cb);
|
2097
|
+
return Qtrue;
|
2098
|
+
}
|
2099
|
+
|
2100
|
+
void _init_rb_mosquitto_client()
|
2101
|
+
{
|
2102
|
+
mosquitto_tls_password = Qnil;
|
2103
|
+
|
2104
|
+
rb_cMosquittoClient = rb_define_class_under(rb_mMosquitto, "Client", rb_cObject);
|
2105
|
+
|
2106
|
+
/* Init / setup specific methods */
|
2107
|
+
|
2108
|
+
rb_define_singleton_method(rb_cMosquittoClient, "new", rb_mosquitto_client_s_new, -1);
|
2109
|
+
rb_define_method(rb_cMosquittoClient, "reinitialise", rb_mosquitto_client_reinitialise, -1);
|
2110
|
+
rb_define_method(rb_cMosquittoClient, "will_set", rb_mosquitto_client_will_set, 4);
|
2111
|
+
rb_define_method(rb_cMosquittoClient, "will_clear", rb_mosquitto_client_will_clear, 0);
|
2112
|
+
rb_define_method(rb_cMosquittoClient, "auth", rb_mosquitto_client_auth, 2);
|
2113
|
+
|
2114
|
+
/* Network specific methods */
|
2115
|
+
|
2116
|
+
rb_define_method(rb_cMosquittoClient, "connect", rb_mosquitto_client_connect, 3);
|
2117
|
+
rb_define_method(rb_cMosquittoClient, "connect_bind", rb_mosquitto_client_connect_bind, 4);
|
2118
|
+
rb_define_method(rb_cMosquittoClient, "connect_async", rb_mosquitto_client_connect_async, 3);
|
2119
|
+
rb_define_method(rb_cMosquittoClient, "connect_bind_async", rb_mosquitto_client_connect_bind_async, 4);
|
2120
|
+
rb_define_method(rb_cMosquittoClient, "reconnect", rb_mosquitto_client_reconnect, 0);
|
2121
|
+
rb_define_method(rb_cMosquittoClient, "disconnect", rb_mosquitto_client_disconnect, 0);
|
2122
|
+
|
2123
|
+
/* Messaging specific methods */
|
2124
|
+
|
2125
|
+
rb_define_method(rb_cMosquittoClient, "publish", rb_mosquitto_client_publish, 5);
|
2126
|
+
rb_define_method(rb_cMosquittoClient, "subscribe", rb_mosquitto_client_subscribe, 3);
|
2127
|
+
rb_define_method(rb_cMosquittoClient, "unsubscribe", rb_mosquitto_client_unsubscribe, 2);
|
2128
|
+
|
2129
|
+
/* Main / event loop specific methods */
|
2130
|
+
|
2131
|
+
rb_define_method(rb_cMosquittoClient, "socket", rb_mosquitto_client_socket, 0);
|
2132
|
+
rb_define_method(rb_cMosquittoClient, "loop", rb_mosquitto_client_loop, 2);
|
2133
|
+
rb_define_method(rb_cMosquittoClient, "loop_start", rb_mosquitto_client_loop_start, 0);
|
2134
|
+
rb_define_method(rb_cMosquittoClient, "loop_forever", rb_mosquitto_client_loop_forever, 2);
|
2135
|
+
rb_define_method(rb_cMosquittoClient, "loop_stop", rb_mosquitto_client_loop_stop, 1);
|
2136
|
+
rb_define_method(rb_cMosquittoClient, "loop_read", rb_mosquitto_client_loop_read, 1);
|
2137
|
+
rb_define_method(rb_cMosquittoClient, "loop_write", rb_mosquitto_client_loop_write, 1);
|
2138
|
+
rb_define_method(rb_cMosquittoClient, "loop_misc", rb_mosquitto_client_loop_misc, 0);
|
2139
|
+
rb_define_method(rb_cMosquittoClient, "want_write?", rb_mosquitto_client_want_write, 0);
|
2140
|
+
|
2141
|
+
/* Tuning specific methods */
|
2142
|
+
|
2143
|
+
rb_define_method(rb_cMosquittoClient, "reconnect_delay_set", rb_mosquitto_client_reconnect_delay_set, 3);
|
2144
|
+
rb_define_method(rb_cMosquittoClient, "max_inflight_messages=", rb_mosquitto_client_max_inflight_messages_equals, 1);
|
2145
|
+
rb_define_method(rb_cMosquittoClient, "message_retry=", rb_mosquitto_client_message_retry_equals, 1);
|
2146
|
+
|
2147
|
+
/* TLS specific methods */
|
2148
|
+
|
2149
|
+
rb_define_method(rb_cMosquittoClient, "tls_set", rb_mosquitto_client_tls_set, 5);
|
2150
|
+
rb_define_method(rb_cMosquittoClient, "tls_insecure=", rb_mosquitto_client_tls_insecure_set, 1);
|
2151
|
+
rb_define_method(rb_cMosquittoClient, "tls_opts_set", rb_mosquitto_client_tls_opts_set, 3);
|
2152
|
+
rb_define_method(rb_cMosquittoClient, "tls_psk_set", rb_mosquitto_client_tls_psk_set, 3);
|
2153
|
+
|
2154
|
+
/* Callback specific methods */
|
2155
|
+
|
2156
|
+
rb_define_method(rb_cMosquittoClient, "on_connect", rb_mosquitto_client_on_connect, -1);
|
2157
|
+
rb_define_method(rb_cMosquittoClient, "on_disconnect", rb_mosquitto_client_on_disconnect, -1);
|
2158
|
+
rb_define_method(rb_cMosquittoClient, "on_publish", rb_mosquitto_client_on_publish, -1);
|
2159
|
+
rb_define_method(rb_cMosquittoClient, "on_message", rb_mosquitto_client_on_message, -1);
|
2160
|
+
rb_define_method(rb_cMosquittoClient, "on_subscribe", rb_mosquitto_client_on_subscribe, -1);
|
2161
|
+
rb_define_method(rb_cMosquittoClient, "on_unsubscribe", rb_mosquitto_client_on_unsubscribe, -1);
|
2162
|
+
rb_define_method(rb_cMosquittoClient, "on_log", rb_mosquitto_client_on_log, -1);
|
2163
|
+
}
|