ffi-nats-core 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }