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.
- checksums.yaml +4 -4
- data/ffi-nats-core.gemspec +8 -0
- data/lib/ffi/nats/core/version.rb +1 -1
- data/vendor/cnats/CMakeLists.txt +137 -0
- data/vendor/cnats/adapters/libevent.h +220 -0
- data/vendor/cnats/adapters/libuv.h +472 -0
- data/vendor/cnats/examples/CMakeLists.txt +56 -0
- data/vendor/cnats/examples/asynctimeout.c +83 -0
- data/vendor/cnats/examples/examples.h +322 -0
- data/vendor/cnats/examples/libevent-pub.c +136 -0
- data/vendor/cnats/examples/libevent-sub.c +104 -0
- data/vendor/cnats/examples/libuv-pub.c +120 -0
- data/vendor/cnats/examples/libuv-sub.c +114 -0
- data/vendor/cnats/examples/publisher.c +62 -0
- data/vendor/cnats/examples/queuegroup.c +132 -0
- data/vendor/cnats/examples/replier.c +149 -0
- data/vendor/cnats/examples/requestor.c +75 -0
- data/vendor/cnats/examples/subscriber.c +133 -0
- data/vendor/cnats/src/CMakeLists.txt +31 -0
- data/vendor/cnats/src/asynccb.c +66 -0
- data/vendor/cnats/src/asynccb.h +42 -0
- data/vendor/cnats/src/buf.c +246 -0
- data/vendor/cnats/src/buf.h +116 -0
- data/vendor/cnats/src/comsock.c +474 -0
- data/vendor/cnats/src/comsock.h +81 -0
- data/vendor/cnats/src/conn.c +2725 -0
- data/vendor/cnats/src/conn.h +75 -0
- data/vendor/cnats/src/err.h +31 -0
- data/vendor/cnats/src/gc.h +27 -0
- data/vendor/cnats/src/hash.c +725 -0
- data/vendor/cnats/src/hash.h +141 -0
- data/vendor/cnats/src/include/n-unix.h +56 -0
- data/vendor/cnats/src/include/n-win.h +59 -0
- data/vendor/cnats/src/mem.h +20 -0
- data/vendor/cnats/src/msg.c +155 -0
- data/vendor/cnats/src/msg.h +43 -0
- data/vendor/cnats/src/nats.c +1734 -0
- data/vendor/cnats/src/nats.h +2024 -0
- data/vendor/cnats/src/natsp.h +518 -0
- data/vendor/cnats/src/natstime.c +79 -0
- data/vendor/cnats/src/natstime.h +27 -0
- data/vendor/cnats/src/nuid.c +265 -0
- data/vendor/cnats/src/nuid.h +21 -0
- data/vendor/cnats/src/opts.c +1030 -0
- data/vendor/cnats/src/opts.h +19 -0
- data/vendor/cnats/src/parser.c +869 -0
- data/vendor/cnats/src/parser.h +87 -0
- data/vendor/cnats/src/pub.c +293 -0
- data/vendor/cnats/src/srvpool.c +380 -0
- data/vendor/cnats/src/srvpool.h +71 -0
- data/vendor/cnats/src/stats.c +54 -0
- data/vendor/cnats/src/stats.h +21 -0
- data/vendor/cnats/src/status.c +60 -0
- data/vendor/cnats/src/status.h +95 -0
- data/vendor/cnats/src/sub.c +956 -0
- data/vendor/cnats/src/sub.h +34 -0
- data/vendor/cnats/src/timer.c +86 -0
- data/vendor/cnats/src/timer.h +57 -0
- data/vendor/cnats/src/unix/cond.c +103 -0
- data/vendor/cnats/src/unix/mutex.c +107 -0
- data/vendor/cnats/src/unix/sock.c +105 -0
- data/vendor/cnats/src/unix/thread.c +162 -0
- data/vendor/cnats/src/url.c +134 -0
- data/vendor/cnats/src/url.h +24 -0
- data/vendor/cnats/src/util.c +823 -0
- data/vendor/cnats/src/util.h +75 -0
- data/vendor/cnats/src/version.h +29 -0
- data/vendor/cnats/src/version.h.in +29 -0
- data/vendor/cnats/src/win/cond.c +86 -0
- data/vendor/cnats/src/win/mutex.c +54 -0
- data/vendor/cnats/src/win/sock.c +158 -0
- data/vendor/cnats/src/win/strings.c +108 -0
- data/vendor/cnats/src/win/thread.c +180 -0
- data/vendor/cnats/test/CMakeLists.txt +35 -0
- data/vendor/cnats/test/certs/ca.pem +38 -0
- data/vendor/cnats/test/certs/client-cert.pem +30 -0
- data/vendor/cnats/test/certs/client-key.pem +51 -0
- data/vendor/cnats/test/certs/server-cert.pem +31 -0
- data/vendor/cnats/test/certs/server-key.pem +51 -0
- data/vendor/cnats/test/dylib/CMakeLists.txt +10 -0
- data/vendor/cnats/test/dylib/nonats.c +13 -0
- data/vendor/cnats/test/list.txt +125 -0
- data/vendor/cnats/test/test.c +11655 -0
- data/vendor/cnats/test/tls.conf +15 -0
- data/vendor/cnats/test/tlsverify.conf +19 -0
- 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
|
+
}
|