blob: 52149e49a574023a9d1199f70b95cc137862e7ef [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 */
21
22#include "uv.h"
23#include "uv-common.h"
24
25#include <assert.h>
26#include <errno.h>
27#include <stdarg.h>
28#include <stddef.h> /* NULL */
29#include <stdio.h>
30#include <stdlib.h> /* malloc */
31#include <string.h> /* memset */
32
33#if defined(_WIN32)
34# include <malloc.h> /* malloc */
35#else
36# include <net/if.h> /* if_nametoindex */
37#endif
38
39
40typedef struct {
41 uv_malloc_func local_malloc;
42 uv_realloc_func local_realloc;
43 uv_calloc_func local_calloc;
44 uv_free_func local_free;
45} uv__allocator_t;
46
47static uv__allocator_t uv__allocator = {
48 malloc,
49 realloc,
50 calloc,
51 free,
52};
53
54char* uv__strdup(const char* s) {
55 size_t len = strlen(s) + 1;
56 char* m = (char*)uv__malloc(len);
57 if (m == NULL)
58 return NULL;
59 return (char*)memcpy(m, s, len);
60}
61
62char* uv__strndup(const char* s, size_t n) {
63 char* m;
64 size_t len = strlen(s);
65 if (n < len)
66 len = n;
67 m = (char*)uv__malloc(len + 1);
68 if (m == NULL)
69 return NULL;
70 m[len] = '\0';
71 return (char*)memcpy(m, s, len);
72}
73
74void* uv__malloc(size_t size) {
75 return uv__allocator.local_malloc(size);
76}
77
78void uv__free(void* ptr) {
79 int saved_errno;
80
81 /* Libuv expects that free() does not clobber errno. The system allocator
82 * honors that assumption but custom allocators may not be so careful.
83 */
84 saved_errno = errno;
85 uv__allocator.local_free(ptr);
86 errno = saved_errno;
87}
88
89void* uv__calloc(size_t count, size_t size) {
90 return uv__allocator.local_calloc(count, size);
91}
92
93void* uv__realloc(void* ptr, size_t size) {
94 return uv__allocator.local_realloc(ptr, size);
95}
96
97int uv_replace_allocator(uv_malloc_func malloc_func,
98 uv_realloc_func realloc_func,
99 uv_calloc_func calloc_func,
100 uv_free_func free_func) {
101 if (malloc_func == NULL || realloc_func == NULL ||
102 calloc_func == NULL || free_func == NULL) {
103 return UV_EINVAL;
104 }
105
106 uv__allocator.local_malloc = malloc_func;
107 uv__allocator.local_realloc = realloc_func;
108 uv__allocator.local_calloc = calloc_func;
109 uv__allocator.local_free = free_func;
110
111 return 0;
112}
113
114#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);
115
116size_t uv_handle_size(uv_handle_type type) {
117 switch (type) {
118 UV_HANDLE_TYPE_MAP(XX)
119 default:
120 return -1;
121 }
122}
123
124size_t uv_req_size(uv_req_type type) {
125 switch(type) {
126 UV_REQ_TYPE_MAP(XX)
127 default:
128 return -1;
129 }
130}
131
132#undef XX
133
134
135size_t uv_loop_size(void) {
136 return sizeof(uv_loop_t);
137}
138
139
140uv_buf_t uv_buf_init(char* base, unsigned int len) {
141 uv_buf_t buf;
142 buf.base = base;
143 buf.len = len;
144 return buf;
145}
146
147
148static const char* uv__unknown_err_code(int err) {
149 char buf[32];
150 char* copy;
151
152 snprintf(buf, sizeof(buf), "Unknown system error %d", err);
153 copy = uv__strdup(buf);
154
155 return copy != NULL ? copy : "Unknown system error";
156}
157
158
159#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
160const char* uv_err_name(int err) {
161 switch (err) {
162 UV_ERRNO_MAP(UV_ERR_NAME_GEN)
163 }
164 return uv__unknown_err_code(err);
165}
166#undef UV_ERR_NAME_GEN
167
168
169#define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
170const char* uv_strerror(int err) {
171 switch (err) {
172 UV_ERRNO_MAP(UV_STRERROR_GEN)
173 }
174 return uv__unknown_err_code(err);
175}
176#undef UV_STRERROR_GEN
177
178
179int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
180 memset(addr, 0, sizeof(*addr));
181 addr->sin_family = AF_INET;
182 addr->sin_port = htons(port);
183 return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));
184}
185
186
187int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
188 char address_part[40];
189 size_t address_part_size;
190 const char* zone_index;
191
192 memset(addr, 0, sizeof(*addr));
193 addr->sin6_family = AF_INET6;
194 addr->sin6_port = htons(port);
195
196 zone_index = strchr(ip, '%');
197 if (zone_index != NULL) {
198 address_part_size = zone_index - ip;
199 if (address_part_size >= sizeof(address_part))
200 address_part_size = sizeof(address_part) - 1;
201
202 memcpy(address_part, ip, address_part_size);
203 address_part[address_part_size] = '\0';
204 ip = address_part;
205
206 zone_index++; /* skip '%' */
207 /* NOTE: unknown interface (id=0) is silently ignored */
208#ifdef _WIN32
209 addr->sin6_scope_id = atoi(zone_index);
210#else
211 addr->sin6_scope_id = if_nametoindex(zone_index);
212#endif
213 }
214
215 return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr);
216}
217
218
219int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) {
220 return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
221}
222
223
224int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {
225 return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
226}
227
228
229int uv_tcp_bind(uv_tcp_t* handle,
230 const struct sockaddr* addr,
231 unsigned int flags) {
232 unsigned int addrlen;
233
234 if (handle->type != UV_TCP)
235 return UV_EINVAL;
236
237 if (addr->sa_family == AF_INET)
238 addrlen = sizeof(struct sockaddr_in);
239 else if (addr->sa_family == AF_INET6)
240 addrlen = sizeof(struct sockaddr_in6);
241 else
242 return UV_EINVAL;
243
244 return uv__tcp_bind(handle, addr, addrlen, flags);
245}
246
247
248int uv_udp_bind(uv_udp_t* handle,
249 const struct sockaddr* addr,
250 unsigned int flags) {
251 unsigned int addrlen;
252
253 if (handle->type != UV_UDP)
254 return UV_EINVAL;
255
256 if (addr->sa_family == AF_INET)
257 addrlen = sizeof(struct sockaddr_in);
258 else if (addr->sa_family == AF_INET6)
259 addrlen = sizeof(struct sockaddr_in6);
260 else
261 return UV_EINVAL;
262
263 return uv__udp_bind(handle, addr, addrlen, flags);
264}
265
266
267int uv_tcp_connect(uv_connect_t* req,
268 uv_tcp_t* handle,
269 const struct sockaddr* addr,
270 uv_connect_cb cb) {
271 unsigned int addrlen;
272
273 if (handle->type != UV_TCP)
274 return UV_EINVAL;
275
276 if (addr->sa_family == AF_INET)
277 addrlen = sizeof(struct sockaddr_in);
278 else if (addr->sa_family == AF_INET6)
279 addrlen = sizeof(struct sockaddr_in6);
280 else
281 return UV_EINVAL;
282
283 return uv__tcp_connect(req, handle, addr, addrlen, cb);
284}
285
286
287int uv_udp_send(uv_udp_send_t* req,
288 uv_udp_t* handle,
289 const uv_buf_t bufs[],
290 unsigned int nbufs,
291 const struct sockaddr* addr,
292 uv_udp_send_cb send_cb) {
293 unsigned int addrlen;
294
295 if (handle->type != UV_UDP)
296 return UV_EINVAL;
297
298 if (addr->sa_family == AF_INET)
299 addrlen = sizeof(struct sockaddr_in);
300 else if (addr->sa_family == AF_INET6)
301 addrlen = sizeof(struct sockaddr_in6);
302 else
303 return UV_EINVAL;
304
305 return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
306}
307
308
309int uv_udp_try_send(uv_udp_t* handle,
310 const uv_buf_t bufs[],
311 unsigned int nbufs,
312 const struct sockaddr* addr) {
313 unsigned int addrlen;
314
315 if (handle->type != UV_UDP)
316 return UV_EINVAL;
317
318 if (addr->sa_family == AF_INET)
319 addrlen = sizeof(struct sockaddr_in);
320 else if (addr->sa_family == AF_INET6)
321 addrlen = sizeof(struct sockaddr_in6);
322 else
323 return UV_EINVAL;
324
325 return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
326}
327
328
329int uv_udp_recv_start(uv_udp_t* handle,
330 uv_alloc_cb alloc_cb,
331 uv_udp_recv_cb recv_cb) {
332 if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL)
333 return UV_EINVAL;
334 else
335 return uv__udp_recv_start(handle, alloc_cb, recv_cb);
336}
337
338
339int uv_udp_recv_stop(uv_udp_t* handle) {
340 if (handle->type != UV_UDP)
341 return UV_EINVAL;
342 else
343 return uv__udp_recv_stop(handle);
344}
345
346
347void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
348 QUEUE queue;
349 QUEUE* q;
350 uv_handle_t* h;
351
352 QUEUE_MOVE(&loop->handle_queue, &queue);
353 while (!QUEUE_EMPTY(&queue)) {
354 q = QUEUE_HEAD(&queue);
355 h = QUEUE_DATA(q, uv_handle_t, handle_queue);
356
357 QUEUE_REMOVE(q);
358 QUEUE_INSERT_TAIL(&loop->handle_queue, q);
359
360 if (h->flags & UV__HANDLE_INTERNAL) continue;
361 walk_cb(h, arg);
362 }
363}
364
365
366static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
367 const char* type;
368 QUEUE* q;
369 uv_handle_t* h;
370
371 if (loop == NULL)
372 loop = uv_default_loop();
373
374 QUEUE_FOREACH(q, &loop->handle_queue) {
375 h = QUEUE_DATA(q, uv_handle_t, handle_queue);
376
377 if (only_active && !uv__is_active(h))
378 continue;
379
380 switch (h->type) {
381#define X(uc, lc) case UV_##uc: type = #lc; break;
382 UV_HANDLE_TYPE_MAP(X)
383#undef X
384 default: type = "<unknown>";
385 }
386
387 fprintf(stream,
388 "[%c%c%c] %-8s %p\n",
389 "R-"[!(h->flags & UV__HANDLE_REF)],
390 "A-"[!(h->flags & UV__HANDLE_ACTIVE)],
391 "I-"[!(h->flags & UV__HANDLE_INTERNAL)],
392 type,
393 (void*)h);
394 }
395}
396
397
398void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
399 uv__print_handles(loop, 0, stream);
400}
401
402
403void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
404 uv__print_handles(loop, 1, stream);
405}
406
407
408void uv_ref(uv_handle_t* handle) {
409 uv__handle_ref(handle);
410}
411
412
413void uv_unref(uv_handle_t* handle) {
414 uv__handle_unref(handle);
415}
416
417
418int uv_has_ref(const uv_handle_t* handle) {
419 return uv__has_ref(handle);
420}
421
422
423void uv_stop(uv_loop_t* loop) {
424 loop->stop_flag = 1;
425}
426
427
428uint64_t uv_now(const uv_loop_t* loop) {
429 return loop->time;
430}
431
432
433
434size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
435 unsigned int i;
436 size_t bytes;
437
438 bytes = 0;
439 for (i = 0; i < nbufs; i++)
440 bytes += (size_t) bufs[i].len;
441
442 return bytes;
443}
444
445int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
446 return uv__socket_sockopt(handle, SO_RCVBUF, value);
447}
448
449int uv_send_buffer_size(uv_handle_t* handle, int *value) {
450 return uv__socket_sockopt(handle, SO_SNDBUF, value);
451}
452
453int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
454 size_t required_len;
455
456 if (!uv__is_active(handle)) {
457 *size = 0;
458 return UV_EINVAL;
459 }
460
461 required_len = strlen(handle->path);
462 if (required_len >= *size) {
463 *size = required_len + 1;
464 return UV_ENOBUFS;
465 }
466
467 memcpy(buffer, handle->path, required_len);
468 *size = required_len;
469 buffer[required_len] = '\0';
470
471 return 0;
472}
473
474/* The windows implementation does not have the same structure layout as
475 * the unix implementation (nbufs is not directly inside req but is
476 * contained in a nested union/struct) so this function locates it.
477*/
478static unsigned int* uv__get_nbufs(uv_fs_t* req) {
479#ifdef _WIN32
480 return &req->fs.info.nbufs;
481#else
482 return &req->nbufs;
483#endif
484}
485
486/* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows
487 * systems. So, the memory should be released using free(). On Windows,
488 * uv__malloc() is used, so use uv__free() to free memory.
489*/
490#ifdef _WIN32
491# define uv__fs_scandir_free uv__free
492#else
493# define uv__fs_scandir_free free
494#endif
495
496void uv__fs_scandir_cleanup(uv_fs_t* req) {
497 uv__dirent_t** dents;
498
499 unsigned int* nbufs = uv__get_nbufs(req);
500
501 dents = (uv__dirent_t**)(req->ptr);
502 if (*nbufs > 0 && *nbufs != (unsigned int) req->result)
503 (*nbufs)--;
504 for (; *nbufs < (unsigned int) req->result; (*nbufs)++)
505 uv__fs_scandir_free(dents[*nbufs]);
506
507 uv__fs_scandir_free(req->ptr);
508 req->ptr = NULL;
509}
510
511
512int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
513 uv__dirent_t** dents;
514 uv__dirent_t* dent;
515 unsigned int* nbufs;
516
517 /* Check to see if req passed */
518 if (req->result < 0)
519 return req->result;
520
521 /* Ptr will be null if req was canceled or no files found */
522 if (!req->ptr)
523 return UV_EOF;
524
525 nbufs = uv__get_nbufs(req);
526 assert(nbufs);
527
528 dents = (uv__dirent_t**)(req->ptr);
529
530 /* Free previous entity */
531 if (*nbufs > 0)
532 uv__fs_scandir_free(dents[*nbufs - 1]);
533
534 /* End was already reached */
535 if (*nbufs == (unsigned int) req->result) {
536 uv__fs_scandir_free(dents);
537 req->ptr = NULL;
538 return UV_EOF;
539 }
540
541 dent = dents[(*nbufs)++];
542
543 ent->name = dent->d_name;
544#ifdef HAVE_DIRENT_TYPES
545 switch (dent->d_type) {
546 case UV__DT_DIR:
547 ent->type = UV_DIRENT_DIR;
548 break;
549 case UV__DT_FILE:
550 ent->type = UV_DIRENT_FILE;
551 break;
552 case UV__DT_LINK:
553 ent->type = UV_DIRENT_LINK;
554 break;
555 case UV__DT_FIFO:
556 ent->type = UV_DIRENT_FIFO;
557 break;
558 case UV__DT_SOCKET:
559 ent->type = UV_DIRENT_SOCKET;
560 break;
561 case UV__DT_CHAR:
562 ent->type = UV_DIRENT_CHAR;
563 break;
564 case UV__DT_BLOCK:
565 ent->type = UV_DIRENT_BLOCK;
566 break;
567 default:
568 ent->type = UV_DIRENT_UNKNOWN;
569 }
570#else
571 ent->type = UV_DIRENT_UNKNOWN;
572#endif
573
574 return 0;
575}
576
577
578#ifdef __clang__
579# pragma clang diagnostic push
580# pragma clang diagnostic ignored "-Wvarargs"
581#endif
582
583int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {
584 va_list ap;
585 int err;
586
587 va_start(ap, option);
588 /* Any platform-agnostic options should be handled here. */
589 err = uv__loop_configure(loop, option, ap);
590 va_end(ap);
591
592 return err;
593}
594
595#ifdef __clang__
596# pragma clang diagnostic pop
597#endif
598
599
600static uv_loop_t default_loop_struct;
601static uv_loop_t* default_loop_ptr;
602
603
604uv_loop_t* uv_default_loop(void) {
605 if (default_loop_ptr != NULL)
606 return default_loop_ptr;
607
608 if (uv_loop_init(&default_loop_struct))
609 return NULL;
610
611 default_loop_ptr = &default_loop_struct;
612 return default_loop_ptr;
613}
614
615
616uv_loop_t* uv_loop_new(void) {
617 uv_loop_t* loop;
618
619 loop = (uv_loop_t*)uv__malloc(sizeof(*loop));
620 if (loop == NULL)
621 return NULL;
622
623 if (uv_loop_init(loop)) {
624 uv__free(loop);
625 return NULL;
626 }
627
628 return loop;
629}
630
631
632int uv_loop_close(uv_loop_t* loop) {
633 QUEUE* q;
634 uv_handle_t* h;
635#ifndef NDEBUG
636 void* saved_data;
637#endif
638
639 if (uv__has_active_reqs(loop))
640 return UV_EBUSY;
641
642 QUEUE_FOREACH(q, &loop->handle_queue) {
643 h = QUEUE_DATA(q, uv_handle_t, handle_queue);
644 if (!(h->flags & UV__HANDLE_INTERNAL))
645 return UV_EBUSY;
646 }
647
648 uv__loop_close(loop);
649
650#ifndef NDEBUG
651 saved_data = loop->data;
652 memset(loop, -1, sizeof(*loop));
653 loop->data = saved_data;
654#endif
655 if (loop == default_loop_ptr)
656 default_loop_ptr = NULL;
657
658 return 0;
659}
660
661
662void uv_loop_delete(uv_loop_t* loop) {
663 uv_loop_t* default_loop;
664 int err;
665
666 default_loop = default_loop_ptr;
667
668 err = uv_loop_close(loop);
669 (void) err; /* Squelch compiler warnings. */
670 assert(err == 0);
671 if (loop != default_loop)
672 uv__free(loop);
673}