ffi-nats-core 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/ffi-nats-core.gemspec +8 -0
  3. data/lib/ffi/nats/core/version.rb +1 -1
  4. data/vendor/cnats/CMakeLists.txt +137 -0
  5. data/vendor/cnats/adapters/libevent.h +220 -0
  6. data/vendor/cnats/adapters/libuv.h +472 -0
  7. data/vendor/cnats/examples/CMakeLists.txt +56 -0
  8. data/vendor/cnats/examples/asynctimeout.c +83 -0
  9. data/vendor/cnats/examples/examples.h +322 -0
  10. data/vendor/cnats/examples/libevent-pub.c +136 -0
  11. data/vendor/cnats/examples/libevent-sub.c +104 -0
  12. data/vendor/cnats/examples/libuv-pub.c +120 -0
  13. data/vendor/cnats/examples/libuv-sub.c +114 -0
  14. data/vendor/cnats/examples/publisher.c +62 -0
  15. data/vendor/cnats/examples/queuegroup.c +132 -0
  16. data/vendor/cnats/examples/replier.c +149 -0
  17. data/vendor/cnats/examples/requestor.c +75 -0
  18. data/vendor/cnats/examples/subscriber.c +133 -0
  19. data/vendor/cnats/src/CMakeLists.txt +31 -0
  20. data/vendor/cnats/src/asynccb.c +66 -0
  21. data/vendor/cnats/src/asynccb.h +42 -0
  22. data/vendor/cnats/src/buf.c +246 -0
  23. data/vendor/cnats/src/buf.h +116 -0
  24. data/vendor/cnats/src/comsock.c +474 -0
  25. data/vendor/cnats/src/comsock.h +81 -0
  26. data/vendor/cnats/src/conn.c +2725 -0
  27. data/vendor/cnats/src/conn.h +75 -0
  28. data/vendor/cnats/src/err.h +31 -0
  29. data/vendor/cnats/src/gc.h +27 -0
  30. data/vendor/cnats/src/hash.c +725 -0
  31. data/vendor/cnats/src/hash.h +141 -0
  32. data/vendor/cnats/src/include/n-unix.h +56 -0
  33. data/vendor/cnats/src/include/n-win.h +59 -0
  34. data/vendor/cnats/src/mem.h +20 -0
  35. data/vendor/cnats/src/msg.c +155 -0
  36. data/vendor/cnats/src/msg.h +43 -0
  37. data/vendor/cnats/src/nats.c +1734 -0
  38. data/vendor/cnats/src/nats.h +2024 -0
  39. data/vendor/cnats/src/natsp.h +518 -0
  40. data/vendor/cnats/src/natstime.c +79 -0
  41. data/vendor/cnats/src/natstime.h +27 -0
  42. data/vendor/cnats/src/nuid.c +265 -0
  43. data/vendor/cnats/src/nuid.h +21 -0
  44. data/vendor/cnats/src/opts.c +1030 -0
  45. data/vendor/cnats/src/opts.h +19 -0
  46. data/vendor/cnats/src/parser.c +869 -0
  47. data/vendor/cnats/src/parser.h +87 -0
  48. data/vendor/cnats/src/pub.c +293 -0
  49. data/vendor/cnats/src/srvpool.c +380 -0
  50. data/vendor/cnats/src/srvpool.h +71 -0
  51. data/vendor/cnats/src/stats.c +54 -0
  52. data/vendor/cnats/src/stats.h +21 -0
  53. data/vendor/cnats/src/status.c +60 -0
  54. data/vendor/cnats/src/status.h +95 -0
  55. data/vendor/cnats/src/sub.c +956 -0
  56. data/vendor/cnats/src/sub.h +34 -0
  57. data/vendor/cnats/src/timer.c +86 -0
  58. data/vendor/cnats/src/timer.h +57 -0
  59. data/vendor/cnats/src/unix/cond.c +103 -0
  60. data/vendor/cnats/src/unix/mutex.c +107 -0
  61. data/vendor/cnats/src/unix/sock.c +105 -0
  62. data/vendor/cnats/src/unix/thread.c +162 -0
  63. data/vendor/cnats/src/url.c +134 -0
  64. data/vendor/cnats/src/url.h +24 -0
  65. data/vendor/cnats/src/util.c +823 -0
  66. data/vendor/cnats/src/util.h +75 -0
  67. data/vendor/cnats/src/version.h +29 -0
  68. data/vendor/cnats/src/version.h.in +29 -0
  69. data/vendor/cnats/src/win/cond.c +86 -0
  70. data/vendor/cnats/src/win/mutex.c +54 -0
  71. data/vendor/cnats/src/win/sock.c +158 -0
  72. data/vendor/cnats/src/win/strings.c +108 -0
  73. data/vendor/cnats/src/win/thread.c +180 -0
  74. data/vendor/cnats/test/CMakeLists.txt +35 -0
  75. data/vendor/cnats/test/certs/ca.pem +38 -0
  76. data/vendor/cnats/test/certs/client-cert.pem +30 -0
  77. data/vendor/cnats/test/certs/client-key.pem +51 -0
  78. data/vendor/cnats/test/certs/server-cert.pem +31 -0
  79. data/vendor/cnats/test/certs/server-key.pem +51 -0
  80. data/vendor/cnats/test/dylib/CMakeLists.txt +10 -0
  81. data/vendor/cnats/test/dylib/nonats.c +13 -0
  82. data/vendor/cnats/test/list.txt +125 -0
  83. data/vendor/cnats/test/test.c +11655 -0
  84. data/vendor/cnats/test/tls.conf +15 -0
  85. data/vendor/cnats/test/tlsverify.conf +19 -0
  86. metadata +83 -1
@@ -0,0 +1,474 @@
1
+ // Copyright 2015 Apcera Inc. All rights reserved.
2
+
3
+ #include "natsp.h"
4
+
5
+ #include <errno.h>
6
+ #include <string.h>
7
+ #include <stdio.h>
8
+ #include <assert.h>
9
+ #include <time.h>
10
+
11
+ #include "status.h"
12
+ #include "comsock.h"
13
+ #include "mem.h"
14
+
15
+ static void
16
+ _closeFd(natsSock fd)
17
+ {
18
+ if (fd != NATS_SOCK_INVALID)
19
+ NATS_SOCK_CLOSE(fd);
20
+ }
21
+
22
+ void
23
+ natsSock_Close(natsSock fd)
24
+ {
25
+ _closeFd(fd);
26
+ }
27
+
28
+ void
29
+ natsSock_Shutdown(natsSock fd)
30
+ {
31
+ if (fd != NATS_SOCK_INVALID)
32
+ NATS_SOCK_SHUTDOWN(fd);
33
+ }
34
+
35
+ natsStatus
36
+ natsSock_SetCommonTcpOptions(natsSock fd)
37
+ {
38
+ struct linger l;
39
+ int yes = 1;
40
+
41
+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*) &yes, sizeof(yes)) == -1)
42
+ return nats_setError(NATS_SYS_ERROR, "setsockopt TCP_NO_DELAY error: %d",
43
+ NATS_SOCK_GET_ERROR);
44
+
45
+ yes = 1;
46
+
47
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*) &yes, sizeof(yes)) == -1)
48
+ return nats_setError(NATS_SYS_ERROR, "setsockopt SO_REUSEADDR error: %d",
49
+ NATS_SOCK_GET_ERROR);
50
+
51
+ l.l_onoff = 1;
52
+ l.l_linger = 0;
53
+
54
+ if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (void*)&l, sizeof(l)) == -1)
55
+ return nats_setError(NATS_SYS_ERROR, "setsockopt SO_LINGER error: %d",
56
+ NATS_SOCK_GET_ERROR);
57
+
58
+ return NATS_OK;
59
+ }
60
+
61
+ natsStatus
62
+ natsSock_CreateFDSet(fd_set **newFDSet)
63
+ {
64
+ fd_set *fdSet = NULL;
65
+
66
+ #ifdef _WIN32
67
+ #else
68
+ assert(FD_SETSIZE == 32768);
69
+ #endif
70
+
71
+ fdSet = (fd_set*) NATS_MALLOC(sizeof(fd_set));
72
+
73
+ if (fdSet == NULL)
74
+ return nats_setDefaultError(NATS_NO_MEMORY);
75
+
76
+ FD_ZERO(fdSet);
77
+
78
+ *newFDSet = fdSet;
79
+
80
+ return NATS_OK;
81
+ }
82
+
83
+ void
84
+ natsSock_DestroyFDSet(fd_set *fdSet)
85
+ {
86
+ if (fdSet == NULL)
87
+ return;
88
+
89
+ NATS_FREE(fdSet);
90
+ }
91
+
92
+ #define MAX_HOST_NAME (256)
93
+
94
+ natsStatus
95
+ natsSock_ConnectTcp(natsSockCtx *ctx, const char *phost, int port)
96
+ {
97
+ natsStatus s = NATS_OK;
98
+ int res;
99
+ char sport[6];
100
+ struct addrinfo hints;
101
+ struct addrinfo *servinfo = NULL;
102
+ struct addrinfo *p;
103
+ bool waitForConnect = false;
104
+ bool error = false;
105
+ int i;
106
+ int max = 2;
107
+ char hosta[MAX_HOST_NAME];
108
+ int hostLen;
109
+ char *host;
110
+
111
+ if (phost == NULL)
112
+ return nats_setError(NATS_ADDRESS_MISSING, "%s", "No host specified");
113
+
114
+ hostLen = (int) strlen(phost);
115
+ if ((hostLen == 0) || ((hostLen == 1) && phost[0] == '['))
116
+ return nats_setError(NATS_INVALID_ARG, "Invalid host name: %s", phost);
117
+
118
+ if (phost[0] == '[')
119
+ {
120
+ snprintf(hosta, sizeof(hosta), "%.*s", hostLen - 2, phost + 1);
121
+ host = (char*) hosta;
122
+ }
123
+ else
124
+ host = (char*) phost;
125
+
126
+ snprintf(sport, sizeof(sport), "%d", port);
127
+
128
+ if ((ctx->orderIP == 4) || (ctx->orderIP == 6))
129
+ max = 1;
130
+
131
+ for (i=0; i<max; i++)
132
+ {
133
+ memset(&hints,0,sizeof(hints));
134
+ hints.ai_socktype = SOCK_STREAM;
135
+
136
+ switch (ctx->orderIP)
137
+ {
138
+ case 4: hints.ai_family = AF_INET; break;
139
+ case 6: hints.ai_family = AF_INET6; break;
140
+ case 46: hints.ai_family = (i == 0 ? AF_INET : AF_INET6); break;
141
+ case 64: hints.ai_family = (i == 0 ? AF_INET6 : AF_INET); break;
142
+ default: hints.ai_family = AF_UNSPEC;
143
+ }
144
+
145
+ s = NATS_OK;
146
+ if ((res = getaddrinfo(host, sport, &hints, &servinfo)) != 0)
147
+ {
148
+ s = nats_setError(NATS_SYS_ERROR, "getaddrinfo error: %s",
149
+ gai_strerror(res));
150
+ }
151
+ for (p = servinfo; (s == NATS_OK) && (p != NULL); p = p->ai_next)
152
+ {
153
+ ctx->fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
154
+ if (ctx->fd == NATS_SOCK_INVALID)
155
+ continue;
156
+
157
+ error = false;
158
+
159
+ s = natsSock_SetBlocking(ctx->fd, false);
160
+ if (s != NATS_OK)
161
+ break;
162
+
163
+ res = connect(ctx->fd, p->ai_addr, (natsSockLen) p->ai_addrlen);
164
+ if ((res == NATS_SOCK_ERROR)
165
+ && (NATS_SOCK_GET_ERROR == NATS_SOCK_CONNECT_IN_PROGRESS))
166
+ {
167
+ if ((natsSock_WaitReady(WAIT_FOR_CONNECT, ctx) != NATS_OK)
168
+ || !natsSock_IsConnected(ctx->fd))
169
+ {
170
+ error = true;
171
+ }
172
+ }
173
+ else if (res == NATS_SOCK_ERROR)
174
+ {
175
+ error = true;
176
+ }
177
+
178
+ if (error)
179
+ {
180
+ _closeFd(ctx->fd);
181
+ ctx->fd = NATS_SOCK_INVALID;
182
+ continue;
183
+ }
184
+
185
+ s = natsSock_SetCommonTcpOptions(ctx->fd);
186
+ if (s == NATS_OK)
187
+ break;
188
+ }
189
+
190
+ if (s == NATS_OK)
191
+ {
192
+ if (ctx->fd == NATS_SOCK_INVALID)
193
+ s = nats_setDefaultError(NATS_NO_SERVER);
194
+ }
195
+
196
+ freeaddrinfo(servinfo);
197
+ servinfo = NULL;
198
+
199
+ if (s == NATS_OK)
200
+ {
201
+ // Clear the error stack in case we got errors in the loop until
202
+ // being able to successfully connect.
203
+ nats_clearLastError();
204
+ break;
205
+ }
206
+ else
207
+ {
208
+ _closeFd(ctx->fd);
209
+ ctx->fd = NATS_SOCK_INVALID;
210
+ }
211
+ }
212
+
213
+ return NATS_UPDATE_ERR_STACK(s);
214
+ }
215
+
216
+ natsStatus
217
+ natsSock_ReadLine(natsSockCtx *ctx, char *buffer, size_t maxBufferSize)
218
+ {
219
+ natsStatus s = NATS_OK;
220
+ int readBytes = 0;
221
+ size_t totalBytes = 0;
222
+ char *p = buffer;
223
+ char *eol;
224
+
225
+ // By contract, the caller needs to set buffer[0] to '\0' before the first
226
+ // call.
227
+ if (*p != '\0')
228
+ {
229
+ // We assume that this is not the first call with the given buffer.
230
+ // Move possible data after the first line to the beginning of the
231
+ // buffer.
232
+ char *nextLine;
233
+ size_t nextStart;
234
+ size_t len = 0;
235
+
236
+ // The start of the next line will be the length of the line at the
237
+ // start of the buffer + 2, which is the number of characters
238
+ // representing CRLF.
239
+ nextStart = strlen(buffer) + 2;
240
+ nextLine = (char*) (buffer + nextStart);
241
+
242
+ // There is some data...
243
+ if (*nextLine != '\0')
244
+ {
245
+ // The next line (even if partial) is guaranteed to be NULL
246
+ // terminated.
247
+ len = strlen(nextLine);
248
+
249
+ // Move to the beginning of the buffer (and include the NULL char)
250
+ memmove(buffer, nextLine, len + 1);
251
+
252
+ // Now, if the string contains a CRLF, we don't even need to read
253
+ // from the socket. Update the buffer and return.
254
+ if ((eol = strstr(buffer, _CRLF_)) != NULL)
255
+ {
256
+ // Replace the '\r' with '\0' to NULL terminate the string.
257
+ *eol = '\0';
258
+
259
+ // We are done!
260
+ return NATS_OK;
261
+ }
262
+
263
+ // This is a partial, we need to read more data until we get to
264
+ // the end of the line (\r\n).
265
+ p = (char*) (p + len);
266
+ }
267
+ else
268
+ {
269
+ *p = '\0';
270
+ }
271
+ }
272
+
273
+ while (1)
274
+ {
275
+ s = natsSock_Read(ctx, p, (maxBufferSize - totalBytes), &readBytes);
276
+ if (s != NATS_OK)
277
+ return NATS_UPDATE_ERR_STACK(s);
278
+
279
+ if (totalBytes + readBytes == maxBufferSize)
280
+ return nats_setDefaultError(NATS_LINE_TOO_LONG);
281
+
282
+ // We need to append a NULL character after what we have received.
283
+ *(p + readBytes) = '\0';
284
+
285
+ if ((eol = strstr(p, _CRLF_)) != NULL)
286
+ {
287
+ *eol = '\0';
288
+ return NATS_OK;
289
+ }
290
+
291
+ p += readBytes;
292
+ totalBytes += readBytes;
293
+ }
294
+ }
295
+
296
+ natsStatus
297
+ natsSock_Read(natsSockCtx *ctx, char *buffer, size_t maxBufferSize, int *n)
298
+ {
299
+ natsStatus s = NATS_OK;
300
+ int readBytes = 0;
301
+ bool needRead = true;
302
+
303
+ while (needRead)
304
+ {
305
+ #if defined(NATS_HAS_TLS)
306
+ if (ctx->ssl != NULL)
307
+ readBytes = SSL_read(ctx->ssl, buffer, (int) maxBufferSize);
308
+ else
309
+ #endif
310
+ readBytes = recv(ctx->fd, buffer, (natsRecvLen) maxBufferSize, 0);
311
+
312
+ if (readBytes == 0)
313
+ {
314
+ return NATS_CONNECTION_CLOSED;
315
+ }
316
+ else if (readBytes == NATS_SOCK_ERROR)
317
+ {
318
+ #if defined(NATS_HAS_TLS)
319
+ if (ctx->ssl != NULL)
320
+ {
321
+ int sslErr = SSL_get_error(ctx->ssl, readBytes);
322
+
323
+ if ((sslErr != SSL_ERROR_WANT_READ)
324
+ && (sslErr != SSL_ERROR_WANT_WRITE))
325
+ {
326
+ return nats_setError(NATS_IO_ERROR, "SSL_read error: %s",
327
+ NATS_SSL_ERR_REASON_STRING);
328
+ }
329
+ else
330
+ {
331
+ // SSL requires that we go back with the same buffer
332
+ // and size. We can't return until SSL_read returns
333
+ // success (bytes read) or a different error.
334
+ continue;
335
+ }
336
+ }
337
+ else
338
+ #endif
339
+ if (NATS_SOCK_GET_ERROR != NATS_SOCK_WOULD_BLOCK)
340
+ {
341
+ return nats_setError(NATS_IO_ERROR, "recv error: %d",
342
+ NATS_SOCK_GET_ERROR);
343
+ }
344
+ else if (ctx->useEventLoop)
345
+ {
346
+ // When using an external event loop, we are done. We will be
347
+ // called again...
348
+ if (n != NULL)
349
+ *n = 0;
350
+
351
+ return NATS_OK;
352
+ }
353
+
354
+ // For non-blocking sockets, if the read would block, we need to
355
+ // wait up to the deadline.
356
+ s = natsSock_WaitReady(WAIT_FOR_READ, ctx);
357
+ if (s != NATS_OK)
358
+ return NATS_UPDATE_ERR_STACK(s);
359
+
360
+ continue;
361
+ }
362
+
363
+ if (n != NULL)
364
+ *n = readBytes;
365
+
366
+ needRead = false;
367
+ }
368
+
369
+ return NATS_OK;
370
+ }
371
+
372
+ natsStatus
373
+ natsSock_Write(natsSockCtx *ctx, const char *data, int len, int *n)
374
+ {
375
+ natsStatus s = NATS_OK;
376
+ int bytes = 0;
377
+ bool needWrite = true;
378
+
379
+ while (needWrite)
380
+ {
381
+ #if defined(NATS_HAS_TLS)
382
+ if (ctx->ssl != NULL)
383
+ bytes = SSL_write(ctx->ssl, data, len);
384
+ else
385
+ #endif
386
+ bytes = send(ctx->fd, data, len, 0);
387
+
388
+ if (bytes == 0)
389
+ {
390
+ return NATS_CONNECTION_CLOSED;
391
+ }
392
+ else if (bytes == NATS_SOCK_ERROR)
393
+ {
394
+ #if defined(NATS_HAS_TLS)
395
+ if (ctx->ssl != NULL)
396
+ {
397
+ int sslErr = SSL_get_error(ctx->ssl, bytes);
398
+ if ((sslErr != SSL_ERROR_WANT_READ)
399
+ && (sslErr != SSL_ERROR_WANT_WRITE))
400
+ {
401
+ return nats_setError(NATS_IO_ERROR, "SSL_write error: %s",
402
+ NATS_SSL_ERR_REASON_STRING);
403
+ }
404
+ else
405
+ {
406
+ // SSL requires that we go back with the same buffer
407
+ // and size. We can't return until SSL_write returns
408
+ // success (bytes written) a different error.
409
+ continue;
410
+ }
411
+ }
412
+ else
413
+ #endif
414
+ if (NATS_SOCK_GET_ERROR != NATS_SOCK_WOULD_BLOCK)
415
+ {
416
+ return nats_setError(NATS_IO_ERROR, "send error: %d",
417
+ NATS_SOCK_GET_ERROR);
418
+ }
419
+ else if (ctx->useEventLoop)
420
+ {
421
+ // With external event loop, we are done now, we will be
422
+ // called later for more.
423
+ if (n != NULL)
424
+ *n = 0;
425
+
426
+ return NATS_OK;
427
+ }
428
+
429
+ // For non-blocking sockets, if the write would block, we need to
430
+ // wait up to the deadline.
431
+ s = natsSock_WaitReady(WAIT_FOR_WRITE, ctx);
432
+ if (s != NATS_OK)
433
+ return NATS_UPDATE_ERR_STACK(s);
434
+
435
+ continue;
436
+ }
437
+
438
+ if (n != NULL)
439
+ *n = bytes;
440
+
441
+ needWrite = false;
442
+ }
443
+
444
+ return NATS_OK;
445
+ }
446
+
447
+ natsStatus
448
+ natsSock_WriteFully(natsSockCtx *ctx, const char *data, int len)
449
+ {
450
+ natsStatus s = NATS_OK;
451
+ int bytes = 0;
452
+ int n = 0;
453
+
454
+ do
455
+ {
456
+ s = natsSock_Write(ctx, data, len, &n);
457
+ if (s == NATS_OK)
458
+ {
459
+ if (n > 0)
460
+ {
461
+ data += n;
462
+ len -= n;
463
+ }
464
+
465
+ // We use an external event loop and got nothing, or we have
466
+ // sent the whole buffer. Return.
467
+ if ((n == 0) || (len == 0))
468
+ return NATS_OK;
469
+ }
470
+ }
471
+ while (s == NATS_OK);
472
+
473
+ return NATS_UPDATE_ERR_STACK(s);
474
+ }