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,19 @@
1
+ // Copyright 2015 Apcera Inc. All rights reserved.
2
+
3
+ #ifndef OPTS_H_
4
+ #define OPTS_H_
5
+
6
+ #include "natsp.h"
7
+
8
+ #define NATS_OPTS_DEFAULT_MAX_RECONNECT (60)
9
+ #define NATS_OPTS_DEFAULT_TIMEOUT (2 * 1000) // 2 seconds
10
+ #define NATS_OPTS_DEFAULT_RECONNECT_WAIT (2 * 1000) // 2 seconds
11
+ #define NATS_OPTS_DEFAULT_PING_INTERVAL (2 * 60 * 1000) // 2 minutes
12
+ #define NATS_OPTS_DEFAULT_MAX_PING_OUT (2)
13
+ #define NATS_OPTS_DEFAULT_MAX_PENDING_MSGS (65536)
14
+ #define NATS_OPTS_DEFAULT_RECONNECT_BUF_SIZE (8 * 1024 * 1024) // 8 MB
15
+
16
+ natsOptions*
17
+ natsOptions_clone(natsOptions *opts);
18
+
19
+ #endif /* OPTS_H_ */
@@ -0,0 +1,869 @@
1
+ // Copyright 2015 Apcera Inc. All rights reserved.
2
+
3
+ #include <string.h>
4
+ #include <stdio.h>
5
+
6
+ #include "natsp.h"
7
+ #include "conn.h"
8
+ #include "util.h"
9
+ #include "mem.h"
10
+
11
+ // cloneMsgArg is used when the split buffer scenario has the pubArg in the existing read buffer, but
12
+ // we need to hold onto it into the next read.
13
+ static natsStatus
14
+ _cloneMsgArg(natsConnection *nc)
15
+ {
16
+ natsStatus s;
17
+ int subjLen = natsBuf_Len(nc->ps->ma.subject);
18
+
19
+ s = natsBuf_InitWithBackend(&(nc->ps->argBufRec),
20
+ nc->ps->scratch,
21
+ 0,
22
+ sizeof(nc->ps->scratch));
23
+ if (s == NATS_OK)
24
+ {
25
+ nc->ps->argBuf = &(nc->ps->argBufRec);
26
+
27
+ s = natsBuf_Append(nc->ps->argBuf,
28
+ natsBuf_Data(nc->ps->ma.subject),
29
+ natsBuf_Len(nc->ps->ma.subject));
30
+ if (s == NATS_OK)
31
+ {
32
+ natsBuf_Destroy(nc->ps->ma.subject);
33
+ nc->ps->ma.subject = NULL;
34
+
35
+ s = natsBuf_InitWithBackend(&(nc->ps->ma.subjectRec),
36
+ nc->ps->scratch,
37
+ subjLen,
38
+ subjLen);
39
+ if (s == NATS_OK)
40
+ nc->ps->ma.subject = &(nc->ps->ma.subjectRec);
41
+ }
42
+ }
43
+ if ((s == NATS_OK) && (nc->ps->ma.reply != NULL))
44
+ {
45
+ s = natsBuf_Append(nc->ps->argBuf,
46
+ natsBuf_Data(nc->ps->ma.reply),
47
+ natsBuf_Len(nc->ps->ma.reply));
48
+ if (s == NATS_OK)
49
+ {
50
+ int replyLen = natsBuf_Len(nc->ps->ma.reply);
51
+
52
+ natsBuf_Destroy(nc->ps->ma.reply);
53
+ nc->ps->ma.reply = NULL;
54
+
55
+ s = natsBuf_InitWithBackend(&(nc->ps->ma.replyRec),
56
+ nc->ps->scratch + subjLen,
57
+ replyLen,
58
+ replyLen);
59
+ if (s == NATS_OK)
60
+ nc->ps->ma.reply = &(nc->ps->ma.replyRec);
61
+
62
+ }
63
+ }
64
+
65
+ return s;
66
+ }
67
+
68
+ struct slice
69
+ {
70
+ char *start;
71
+ int len;
72
+ };
73
+
74
+ static natsStatus
75
+ _processMsgArgs(natsConnection *nc, char *buf, int bufLen)
76
+ {
77
+ natsStatus s = NATS_OK;
78
+ bool started = false;
79
+ char *start = buf;
80
+ int len = 0;
81
+ int index = 0;
82
+ int i;
83
+ char b;
84
+ struct slice slices[4];
85
+
86
+ for (i = 0; i < bufLen; i++)
87
+ {
88
+ b = buf[i];
89
+
90
+ if (((b == ' ') || (b == '\t') || (b == '\r') || (b == '\n'))
91
+ && started)
92
+ {
93
+ slices[index].start = start;
94
+ slices[index].len = len;
95
+ index++;
96
+
97
+ started = false;
98
+ len = 0;
99
+ }
100
+ else
101
+ {
102
+ if (!started)
103
+ {
104
+ start = buf + i;
105
+ started = true;
106
+ }
107
+ len++;
108
+ }
109
+ }
110
+ if (started)
111
+ {
112
+ slices[index].start = start;
113
+ slices[index].len = len;
114
+ index++;
115
+ }
116
+
117
+ if ((index == 3) || (index == 4))
118
+ {
119
+ int maSizeIndex = 2;
120
+
121
+ s = natsBuf_InitWithBackend(&(nc->ps->ma.subjectRec),
122
+ slices[0].start,
123
+ slices[0].len,
124
+ slices[0].len);
125
+ if (s == NATS_OK)
126
+ {
127
+ nc->ps->ma.subject = &(nc->ps->ma.subjectRec);
128
+
129
+ nc->ps->ma.sid = nats_ParseInt64(slices[1].start, slices[1].len);
130
+
131
+ if (index == 3)
132
+ {
133
+ nc->ps->ma.reply = NULL;
134
+ }
135
+ else
136
+ {
137
+ s = natsBuf_InitWithBackend(&(nc->ps->ma.replyRec),
138
+ slices[2].start,
139
+ slices[2].len,
140
+ slices[2].len);
141
+ if (s == NATS_OK)
142
+ {
143
+ nc->ps->ma.reply = &(nc->ps->ma.replyRec);
144
+ maSizeIndex = 3;
145
+ }
146
+ }
147
+ }
148
+ if (s == NATS_OK)
149
+ nc->ps->ma.size = (int) nats_ParseInt64(slices[maSizeIndex].start,
150
+ slices[maSizeIndex].len);
151
+ }
152
+ else
153
+ {
154
+ snprintf(nc->errStr, sizeof(nc->errStr), "processMsgArgs Parse Error: '%.*s'",
155
+ bufLen, buf);
156
+ s = NATS_PROTOCOL_ERROR;
157
+ }
158
+ if (nc->ps->ma.sid < 0)
159
+ {
160
+ snprintf(nc->errStr, sizeof(nc->errStr), "processMsgArgs Bad or Missing Sid: '%.*s'",
161
+ bufLen, buf);
162
+ s = NATS_PROTOCOL_ERROR;
163
+ }
164
+ if (nc->ps->ma.size < 0)
165
+ {
166
+ snprintf(nc->errStr, sizeof(nc->errStr), "processMsgArgs Bad or Missing Size: '%.*s'",
167
+ bufLen, buf);
168
+ s = NATS_PROTOCOL_ERROR;
169
+ }
170
+
171
+ return s;
172
+ }
173
+
174
+ // parse is the fast protocol parser engine.
175
+ natsStatus
176
+ natsParser_Parse(natsConnection *nc, char* buf, int bufLen)
177
+ {
178
+ natsStatus s = NATS_OK;
179
+ int i;
180
+ char b;
181
+
182
+ for (i = 0; (s == NATS_OK) && (i < bufLen); i++)
183
+ {
184
+ b = buf[i];
185
+
186
+ switch (nc->ps->state)
187
+ {
188
+ case OP_START:
189
+ {
190
+ switch (b)
191
+ {
192
+ case 'M':
193
+ case 'm':
194
+ nc->ps->state = OP_M;
195
+ break;
196
+ case 'P':
197
+ case 'p':
198
+ nc->ps->state = OP_P;
199
+ break;
200
+ case '+':
201
+ nc->ps->state = OP_PLUS;
202
+ break;
203
+ case '-':
204
+ nc->ps->state = OP_MINUS;
205
+ break;
206
+ case 'I':
207
+ case 'i':
208
+ nc->ps->state = OP_I;
209
+ break;
210
+ default:
211
+ goto parseErr;
212
+ }
213
+ break;
214
+ }
215
+ case OP_M:
216
+ {
217
+ switch (b)
218
+ {
219
+ case 'S':
220
+ case 's':
221
+ nc->ps->state = OP_MS;
222
+ break;
223
+ default:
224
+ goto parseErr;
225
+ }
226
+ break;
227
+ }
228
+ case OP_MS:
229
+ {
230
+ switch (b)
231
+ {
232
+ case 'G':
233
+ case 'g':
234
+ nc->ps->state = OP_MSG;
235
+ break;
236
+ default:
237
+ goto parseErr;
238
+ }
239
+ break;
240
+ }
241
+ case OP_MSG:
242
+ {
243
+ switch (b)
244
+ {
245
+ case ' ':
246
+ case '\t':
247
+ nc->ps->state = OP_MSG_SPC;
248
+ break;
249
+ default:
250
+ goto parseErr;
251
+ }
252
+ break;
253
+ }
254
+ case OP_MSG_SPC:
255
+ {
256
+ switch (b)
257
+ {
258
+ case ' ':
259
+ case '\t':
260
+ continue;
261
+ default:
262
+ nc->ps->state = MSG_ARG;
263
+ nc->ps->afterSpace = i;
264
+ break;
265
+ }
266
+ break;
267
+ }
268
+ case MSG_ARG:
269
+ {
270
+ switch (b)
271
+ {
272
+ case '\r':
273
+ nc->ps->drop = 1;
274
+ break;
275
+ case '\n':
276
+ {
277
+ char *start = NULL;
278
+ int len = 0;
279
+
280
+ if (nc->ps->argBuf != NULL)
281
+ {
282
+ start = natsBuf_Data(nc->ps->argBuf);
283
+ len = natsBuf_Len(nc->ps->argBuf);
284
+ }
285
+ else
286
+ {
287
+ start = buf + nc->ps->afterSpace;
288
+ len = (i - nc->ps->drop) - nc->ps->afterSpace;
289
+ }
290
+
291
+ s = _processMsgArgs(nc, start, len);
292
+ if (s == NATS_OK)
293
+ {
294
+ nc->ps->drop = 0;
295
+ nc->ps->afterSpace = i+1;
296
+ nc->ps->state = MSG_PAYLOAD;
297
+
298
+ // jump ahead with the index. If this overruns
299
+ // what is left we fall out and process split
300
+ // buffer.
301
+ i = nc->ps->afterSpace + nc->ps->ma.size - 1;
302
+ }
303
+ break;
304
+ }
305
+ default:
306
+ {
307
+ if (nc->ps->argBuf != NULL)
308
+ s = natsBuf_AppendByte(nc->ps->argBuf, b);
309
+ break;
310
+ }
311
+ }
312
+ break;
313
+ }
314
+ case MSG_PAYLOAD:
315
+ {
316
+ bool done = false;
317
+
318
+ if (nc->ps->msgBuf != NULL)
319
+ {
320
+ if (natsBuf_Len(nc->ps->msgBuf) >= nc->ps->ma.size)
321
+ {
322
+ s = natsConn_processMsg(nc,
323
+ natsBuf_Data(nc->ps->msgBuf),
324
+ natsBuf_Len(nc->ps->msgBuf));
325
+ done = true;
326
+ }
327
+ else
328
+ {
329
+ // copy as much as we can to the buffer and skip ahead.
330
+ int toCopy = nc->ps->ma.size - natsBuf_Len(nc->ps->msgBuf);
331
+ int avail = bufLen - i;
332
+
333
+ if (avail < toCopy)
334
+ toCopy = avail;
335
+
336
+ if (toCopy > 0)
337
+ {
338
+ s = natsBuf_Append(nc->ps->msgBuf, buf+i, toCopy);
339
+ if (s == NATS_OK)
340
+ i += toCopy - 1;
341
+ }
342
+ else
343
+ {
344
+ s = natsBuf_AppendByte(nc->ps->msgBuf, b);
345
+ }
346
+ }
347
+ }
348
+ else if (i-nc->ps->afterSpace >= nc->ps->ma.size)
349
+ {
350
+ char *start = NULL;
351
+ int len = 0;
352
+
353
+ start = buf + nc->ps->afterSpace;
354
+ len = (i - nc->ps->afterSpace);
355
+
356
+ s = natsConn_processMsg(nc, start, len);
357
+
358
+ done = true;
359
+ }
360
+
361
+ if (done)
362
+ {
363
+ natsBuf_Destroy(nc->ps->argBuf);
364
+ nc->ps->argBuf = NULL;
365
+ natsBuf_Destroy(nc->ps->msgBuf);
366
+ nc->ps->msgBuf = NULL;
367
+ nc->ps->state = MSG_END;
368
+ }
369
+
370
+ break;
371
+ }
372
+ case MSG_END:
373
+ {
374
+ switch (b)
375
+ {
376
+ case '\n':
377
+ nc->ps->drop = 0;
378
+ nc->ps->afterSpace = i+1;
379
+ nc->ps->state = OP_START;
380
+ break;
381
+ default:
382
+ continue;
383
+ }
384
+ break;
385
+ }
386
+ case OP_PLUS:
387
+ {
388
+ switch (b)
389
+ {
390
+ case 'O':
391
+ case 'o':
392
+ nc->ps->state = OP_PLUS_O;
393
+ break;
394
+ default:
395
+ goto parseErr;
396
+ }
397
+ break;
398
+ }
399
+ case OP_PLUS_O:
400
+ {
401
+ switch (b)
402
+ {
403
+ case 'K':
404
+ case 'k':
405
+ nc->ps->state = OP_PLUS_OK;
406
+ break;
407
+ default:
408
+ goto parseErr;
409
+ }
410
+ break;
411
+ }
412
+ case OP_PLUS_OK:
413
+ {
414
+ switch (b)
415
+ {
416
+ case '\n':
417
+ natsConn_processOK(nc);
418
+ nc->ps->drop = 0;
419
+ nc->ps->state = OP_START;
420
+ break;
421
+ }
422
+ break;
423
+ }
424
+ case OP_MINUS:
425
+ {
426
+ switch (b)
427
+ {
428
+ case 'E':
429
+ case 'e':
430
+ nc->ps->state = OP_MINUS_E;
431
+ break;
432
+ default:
433
+ goto parseErr;
434
+ }
435
+ break;
436
+ }
437
+ case OP_MINUS_E:
438
+ {
439
+ switch (b)
440
+ {
441
+ case 'R':
442
+ case 'r':
443
+ nc->ps->state = OP_MINUS_ER;
444
+ break;
445
+ default:
446
+ goto parseErr;
447
+ }
448
+ break;
449
+ }
450
+ case OP_MINUS_ER:
451
+ {
452
+ switch (b)
453
+ {
454
+ case 'R':
455
+ case 'r':
456
+ nc->ps->state = OP_MINUS_ERR;
457
+ break;
458
+ default:
459
+ goto parseErr;
460
+ }
461
+ break;
462
+ }
463
+ case OP_MINUS_ERR:
464
+ {
465
+ switch (b)
466
+ {
467
+ case ' ':
468
+ case '\t':
469
+ nc->ps->state = OP_MINUS_ERR_SPC;
470
+ break;
471
+ default:
472
+ goto parseErr;
473
+ }
474
+ break;
475
+ }
476
+ case OP_MINUS_ERR_SPC:
477
+ {
478
+ switch (b)
479
+ {
480
+ case ' ':
481
+ case '\t':
482
+ continue;
483
+ default:
484
+ nc->ps->state = MINUS_ERR_ARG;
485
+ nc->ps->afterSpace = i;
486
+ break;
487
+ }
488
+ break;
489
+ }
490
+ case MINUS_ERR_ARG:
491
+ {
492
+ switch (b)
493
+ {
494
+ case '\r':
495
+ nc->ps->drop = 1;
496
+ break;
497
+ case '\n':
498
+ {
499
+ char *start = NULL;
500
+ int len = 0;
501
+
502
+ if (nc->ps->argBuf != NULL)
503
+ {
504
+ start = natsBuf_Data(nc->ps->argBuf);
505
+ len = natsBuf_Len(nc->ps->argBuf);
506
+ }
507
+ else
508
+ {
509
+ start = buf + nc->ps->afterSpace;
510
+ len = (i - nc->ps->drop) - nc->ps->afterSpace;
511
+ }
512
+
513
+ natsConn_processErr(nc, start, len);
514
+
515
+ nc->ps->drop = 0;
516
+ nc->ps->afterSpace = i+1;
517
+ nc->ps->state = OP_START;
518
+
519
+ if (nc->ps->argBuf != NULL)
520
+ {
521
+ natsBuf_Destroy(nc->ps->argBuf);
522
+ nc->ps->argBuf = NULL;
523
+ }
524
+
525
+ break;
526
+ }
527
+ default:
528
+ {
529
+ if (nc->ps->argBuf != NULL)
530
+ s = natsBuf_AppendByte(nc->ps->argBuf, b);
531
+
532
+ break;
533
+ }
534
+ }
535
+ break;
536
+ }
537
+ case OP_P:
538
+ {
539
+ switch (b)
540
+ {
541
+ case 'I':
542
+ case 'i':
543
+ nc->ps->state = OP_PI;
544
+ break;
545
+ case 'O':
546
+ case 'o':
547
+ nc->ps->state = OP_PO;
548
+ break;
549
+ default:
550
+ goto parseErr;
551
+ }
552
+ break;
553
+ }
554
+ case OP_PO:
555
+ {
556
+ switch (b)
557
+ {
558
+ case 'N':
559
+ case 'n':
560
+ nc->ps->state = OP_PON;
561
+ break;
562
+ default:
563
+ goto parseErr;
564
+ }
565
+ break;
566
+ }
567
+ case OP_PON:
568
+ {
569
+ switch (b)
570
+ {
571
+ case 'G':
572
+ case 'g':
573
+ nc->ps->state = OP_PONG;
574
+ break;
575
+ default:
576
+ goto parseErr;
577
+ }
578
+ break;
579
+ }
580
+ case OP_PONG:
581
+ {
582
+ switch (b)
583
+ {
584
+ case '\n':
585
+ natsConn_processPong(nc);
586
+
587
+ nc->ps->drop = 0;
588
+ nc->ps->afterSpace = i+1;
589
+ nc->ps->state = OP_START;
590
+ break;
591
+ }
592
+ break;
593
+ }
594
+ case OP_PI:
595
+ {
596
+ switch (b)
597
+ {
598
+ case 'N':
599
+ case 'n':
600
+ nc->ps->state = OP_PIN;
601
+ break;
602
+ default:
603
+ goto parseErr;
604
+ }
605
+ break;
606
+ }
607
+ case OP_PIN:
608
+ {
609
+ switch (b)
610
+ {
611
+ case 'G':
612
+ case 'g':
613
+ nc->ps->state = OP_PING;
614
+ break;
615
+ default:
616
+ goto parseErr;
617
+ }
618
+ break;
619
+ }
620
+ case OP_PING:
621
+ {
622
+ switch (b)
623
+ {
624
+ case '\n':
625
+ natsConn_processPing(nc);
626
+
627
+ nc->ps->drop = 0;
628
+ nc->ps->afterSpace = i+1;
629
+ nc->ps->state = OP_START;
630
+ break;
631
+ }
632
+ break;
633
+ }
634
+ case OP_I:
635
+ {
636
+ switch (b)
637
+ {
638
+ case 'N':
639
+ case 'n':
640
+ nc->ps->state = OP_IN;
641
+ break;
642
+ default:
643
+ goto parseErr;
644
+ }
645
+ break;
646
+ }
647
+ case OP_IN:
648
+ {
649
+ switch (b)
650
+ {
651
+ case 'F':
652
+ case 'f':
653
+ nc->ps->state = OP_INF;
654
+ break;
655
+ default:
656
+ goto parseErr;
657
+ }
658
+ break;
659
+ }
660
+ case OP_INF:
661
+ {
662
+ switch (b)
663
+ {
664
+ case 'O':
665
+ case 'o':
666
+ nc->ps->state = OP_INFO;
667
+ break;
668
+ default:
669
+ goto parseErr;
670
+ }
671
+ break;
672
+ }
673
+ case OP_INFO:
674
+ {
675
+ switch (b)
676
+ {
677
+ case ' ':
678
+ case '\t':
679
+ nc->ps->state = OP_INFO_SPC;
680
+ break;
681
+ default:
682
+ goto parseErr;
683
+ }
684
+ break;
685
+ }
686
+ case OP_INFO_SPC:
687
+ {
688
+ switch (b)
689
+ {
690
+ case ' ':
691
+ case 't':
692
+ continue;
693
+ default:
694
+ nc->ps->state = INFO_ARG;
695
+ nc->ps->afterSpace = i;
696
+ break;
697
+ }
698
+ break;
699
+ }
700
+ case INFO_ARG:
701
+ {
702
+ switch (b)
703
+ {
704
+ case '\r':
705
+ nc->ps->drop = 1;
706
+ break;
707
+ case '\n':
708
+ {
709
+ char *start = NULL;
710
+ int len = 0;
711
+
712
+ if (nc->ps->argBuf != NULL)
713
+ {
714
+ start = natsBuf_Data(nc->ps->argBuf);
715
+ len = natsBuf_Len(nc->ps->argBuf);
716
+ }
717
+ else
718
+ {
719
+ start = buf + nc->ps->afterSpace;
720
+ len = (i - nc->ps->drop) - nc->ps->afterSpace;
721
+ }
722
+ natsConn_processAsyncINFO(nc, start, len);
723
+ nc->ps->drop = 0;
724
+ nc->ps->afterSpace = i+1;
725
+ nc->ps->state = OP_START;
726
+
727
+ if (nc->ps->argBuf != NULL)
728
+ {
729
+ natsBuf_Destroy(nc->ps->argBuf);
730
+ nc->ps->argBuf = NULL;
731
+ }
732
+ break;
733
+ }
734
+ default:
735
+ {
736
+ if (nc->ps->argBuf != NULL)
737
+ s = natsBuf_AppendByte(nc->ps->argBuf, b);
738
+ break;
739
+ }
740
+ }
741
+ break;
742
+ }
743
+ default:
744
+ goto parseErr;
745
+ }
746
+ }
747
+
748
+ // Check for split buffer scenarios
749
+ if ((s == NATS_OK)
750
+ && ((nc->ps->state == MSG_ARG)
751
+ || (nc->ps->state == MINUS_ERR_ARG)
752
+ || (nc->ps->state == INFO_ARG))
753
+ && (nc->ps->argBuf == NULL))
754
+ {
755
+ s = natsBuf_InitWithBackend(&(nc->ps->argBufRec),
756
+ nc->ps->scratch,
757
+ 0,
758
+ sizeof(nc->ps->scratch));
759
+ if (s == NATS_OK)
760
+ {
761
+ nc->ps->argBuf = &(nc->ps->argBufRec);
762
+ s = natsBuf_Append(nc->ps->argBuf,
763
+ buf + nc->ps->afterSpace,
764
+ (i - nc->ps->drop) - nc->ps->afterSpace);
765
+ }
766
+ }
767
+ // Check for split msg
768
+ if ((s == NATS_OK)
769
+ && (nc->ps->state == MSG_PAYLOAD) && (nc->ps->msgBuf == NULL))
770
+ {
771
+ // We need to clone the msgArg if it is still referencing the
772
+ // read buffer and we are not able to process the msg.
773
+ if (nc->ps->argBuf == NULL)
774
+ s = _cloneMsgArg(nc);
775
+
776
+ if (s == NATS_OK)
777
+ {
778
+ int remainingInScratch;
779
+ int toCopy;
780
+
781
+ #ifdef _WIN32
782
+ // Suppresses the warning that nc->ps->argBuf may be NULL.
783
+ // If nc->ps->argBuf is NULL above, then _cloneMsgArg() will set it. If 's'
784
+ // is NATS_OK here, then nc->ps->argBuf can't be NULL.
785
+ #pragma warning(suppress: 6011)
786
+ #endif
787
+
788
+ // If we will overflow the scratch buffer, just create a
789
+ // new buffer to hold the split message.
790
+ remainingInScratch = sizeof(nc->ps->scratch) - natsBuf_Len(nc->ps->argBuf);
791
+ toCopy = bufLen - nc->ps->afterSpace;
792
+
793
+ if (nc->ps->ma.size > remainingInScratch)
794
+ {
795
+ s = natsBuf_Create(&(nc->ps->msgBuf), nc->ps->ma.size);
796
+ }
797
+ else
798
+ {
799
+ s = natsBuf_InitWithBackend(&(nc->ps->msgBufRec),
800
+ nc->ps->scratch + natsBuf_Len(nc->ps->argBuf),
801
+ 0, remainingInScratch);
802
+ if (s == NATS_OK)
803
+ nc->ps->msgBuf = &(nc->ps->msgBufRec);
804
+ }
805
+ if (s == NATS_OK)
806
+ s = natsBuf_Append(nc->ps->msgBuf,
807
+ buf + nc->ps->afterSpace,
808
+ toCopy);
809
+ }
810
+ }
811
+
812
+ if (s != NATS_OK)
813
+ {
814
+ // Let's clear all our pointers...
815
+ natsBuf_Destroy(nc->ps->argBuf);
816
+ nc->ps->argBuf = NULL;
817
+ natsBuf_Destroy(nc->ps->msgBuf);
818
+ nc->ps->msgBuf = NULL;
819
+ natsBuf_Destroy(nc->ps->ma.subject);
820
+ nc->ps->ma.subject = NULL;
821
+ natsBuf_Destroy(nc->ps->ma.reply);
822
+ nc->ps->ma.reply = NULL;
823
+ }
824
+
825
+ return s;
826
+
827
+ parseErr:
828
+ if (s == NATS_OK)
829
+ s = NATS_PROTOCOL_ERROR;
830
+
831
+ natsMutex_Lock(nc->mu);
832
+
833
+ snprintf(nc->errStr, sizeof(nc->errStr),
834
+ "Parse Error [%d]: '%.*s'",
835
+ nc->ps->state,
836
+ bufLen - i,
837
+ buf + i);
838
+
839
+ natsMutex_Unlock(nc->mu);
840
+
841
+ return s;
842
+ }
843
+
844
+ natsStatus
845
+ natsParser_Create(natsParser **newParser)
846
+ {
847
+ natsParser *parser = (natsParser *) NATS_CALLOC(1, sizeof(natsParser));
848
+
849
+ if (parser == NULL)
850
+ return NATS_NO_MEMORY;
851
+
852
+ *newParser = parser;
853
+
854
+ return NATS_OK;
855
+ }
856
+
857
+ void
858
+ natsParser_Destroy(natsParser *parser)
859
+ {
860
+ if (parser == NULL)
861
+ return;
862
+
863
+ natsBuf_Cleanup(&(parser->ma.subjectRec));
864
+ natsBuf_Cleanup(&(parser->ma.replyRec));
865
+ natsBuf_Cleanup(&(parser->argBufRec));
866
+ natsBuf_Cleanup(&(parser->msgBufRec));
867
+
868
+ NATS_FREE(parser);
869
+ }