1/* 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# include <sys/un.h> /* AF_UNIX, sockaddr_un */
38#endif
39
40
41typedef struct {
42 uv_malloc_func local_malloc;
43 uv_realloc_func local_realloc;
44 uv_calloc_func local_calloc;
45 uv_free_func local_free;
46} uv__allocator_t;
47
48static uv__allocator_t uv__allocator = {
49 malloc,
50 realloc,
51 calloc,
52 free,
53};
54
55char* uv__strdup(const char* s) {
56 size_t len = strlen(s) + 1;
57 char* m = uv__malloc(len);
58 if (m == NULL)
59 return NULL;
60 return memcpy(m, s, len);
61}
62
63char* uv__strndup(const char* s, size_t n) {
64 char* m;
65 size_t len = strlen(s);
66 if (n < len)
67 len = n;
68 m = uv__malloc(len + 1);
69 if (m == NULL)
70 return NULL;
71 m[len] = '\0';
72 return memcpy(m, s, len);
73}
74
75void* uv__malloc(size_t size) {
76 if (size > 0)
77 return uv__allocator.local_malloc(size);
78 return NULL;
79}
80
81void uv__free(void* ptr) {
82 int saved_errno;
83
84 /* Libuv expects that free() does not clobber errno. The system allocator
85 * honors that assumption but custom allocators may not be so careful.
86 */
87 saved_errno = errno;
88 uv__allocator.local_free(ptr);
89 errno = saved_errno;
90}
91
92void* uv__calloc(size_t count, size_t size) {
93 return uv__allocator.local_calloc(count, size);
94}
95
96void* uv__realloc(void* ptr, size_t size) {
97 if (size > 0)
98 return uv__allocator.local_realloc(ptr, size);
99 uv__free(ptr);
100 return NULL;
101}
102
103int uv_replace_allocator(uv_malloc_func malloc_func,
104 uv_realloc_func realloc_func,
105 uv_calloc_func calloc_func,
106 uv_free_func free_func) {
107 if (malloc_func == NULL || realloc_func == NULL ||
108 calloc_func == NULL || free_func == NULL) {
109 return UV_EINVAL;
110 }
111
112 uv__allocator.local_malloc = malloc_func;
113 uv__allocator.local_realloc = realloc_func;
114 uv__allocator.local_calloc = calloc_func;
115 uv__allocator.local_free = free_func;
116
117 return 0;
118}
119
120#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);
121
122size_t uv_handle_size(uv_handle_type type) {
123 switch (type) {
124 UV_HANDLE_TYPE_MAP(XX)
125 default:
126 return -1;
127 }
128}
129
130size_t uv_req_size(uv_req_type type) {
131 switch(type) {
132 UV_REQ_TYPE_MAP(XX)
133 default:
134 return -1;
135 }
136}
137
138#undef XX
139
140
141size_t uv_loop_size(void) {
142 return sizeof(uv_loop_t);
143}
144
145
146uv_buf_t uv_buf_init(char* base, unsigned int len) {
147 uv_buf_t buf;
148 buf.base = base;
149 buf.len = len;
150 return buf;
151}
152
153
154static const char* uv__unknown_err_code(int err) {
155 char buf[32];
156 char* copy;
157
158 snprintf(buf, sizeof(buf), "Unknown system error %d", err);
159 copy = uv__strdup(buf);
160
161 return copy != NULL ? copy : "Unknown system error";
162}
163
164#define UV_ERR_NAME_GEN_R(name, _) \
165case UV_## name: \
166 uv__strscpy(buf, #name, buflen); break;
167char* uv_err_name_r(int err, char* buf, size_t buflen) {
168 switch (err) {
169 UV_ERRNO_MAP(UV_ERR_NAME_GEN_R)
170 default: snprintf(buf, buflen, "Unknown system error %d", err);
171 }
172 return buf;
173}
174#undef UV_ERR_NAME_GEN_R
175
176
177#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
178const char* uv_err_name(int err) {
179 switch (err) {
180 UV_ERRNO_MAP(UV_ERR_NAME_GEN)
181 }
182 return uv__unknown_err_code(err);
183}
184#undef UV_ERR_NAME_GEN
185
186
187#define UV_STRERROR_GEN_R(name, msg) \
188case UV_ ## name: \
189 snprintf(buf, buflen, "%s", msg); break;
190char* uv_strerror_r(int err, char* buf, size_t buflen) {
191 switch (err) {
192 UV_ERRNO_MAP(UV_STRERROR_GEN_R)
193 default: snprintf(buf, buflen, "Unknown system error %d", err);
194 }
195 return buf;
196}
197#undef UV_STRERROR_GEN_R
198
199
200#define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
201const char* uv_strerror(int err) {
202 switch (err) {
203 UV_ERRNO_MAP(UV_STRERROR_GEN)
204 }
205 return uv__unknown_err_code(err);
206}
207#undef UV_STRERROR_GEN
208
209
210int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
211 memset(addr, 0, sizeof(*addr));
212 addr->sin_family = AF_INET;
213 addr->sin_port = htons(port);
214 return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));
215}
216
217
218int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
219 char address_part[40];
220 size_t address_part_size;
221 const char* zone_index;
222
223 memset(addr, 0, sizeof(*addr));
224 addr->sin6_family = AF_INET6;
225 addr->sin6_port = htons(port);
226#ifdef SIN6_LEN
227 addr->sin6_len = sizeof(*addr);
228#endif
229
230 zone_index = strchr(ip, '%');
231 if (zone_index != NULL) {
232 address_part_size = zone_index - ip;
233 if (address_part_size >= sizeof(address_part))
234 address_part_size = sizeof(address_part) - 1;
235
236 memcpy(address_part, ip, address_part_size);
237 address_part[address_part_size] = '\0';
238 ip = address_part;
239
240 zone_index++; /* skip '%' */
241 /* NOTE: unknown interface (id=0) is silently ignored */
242#ifdef _WIN32
243 addr->sin6_scope_id = atoi(zone_index);
244#else
245 addr->sin6_scope_id = if_nametoindex(zone_index);
246#endif
247 }
248
249 return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr);
250}
251
252
253int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) {
254 return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
255}
256
257
258int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {
259 return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
260}
261
262
263int uv_tcp_bind(uv_tcp_t* handle,
264 const struct sockaddr* addr,
265 unsigned int flags) {
266 unsigned int addrlen;
267
268 if (handle->type != UV_TCP)
269 return UV_EINVAL;
270
271 if (addr->sa_family == AF_INET)
272 addrlen = sizeof(struct sockaddr_in);
273 else if (addr->sa_family == AF_INET6)
274 addrlen = sizeof(struct sockaddr_in6);
275 else
276 return UV_EINVAL;
277
278 return uv__tcp_bind(handle, addr, addrlen, flags);
279}
280
281
282int uv_udp_bind(uv_udp_t* handle,
283 const struct sockaddr* addr,
284 unsigned int flags) {
285 unsigned int addrlen;
286
287 if (handle->type != UV_UDP)
288 return UV_EINVAL;
289
290 if (addr->sa_family == AF_INET)
291 addrlen = sizeof(struct sockaddr_in);
292 else if (addr->sa_family == AF_INET6)
293 addrlen = sizeof(struct sockaddr_in6);
294 else
295 return UV_EINVAL;
296
297 return uv__udp_bind(handle, addr, addrlen, flags);
298}
299
300
301int uv_tcp_connect(uv_connect_t* req,
302 uv_tcp_t* handle,
303 const struct sockaddr* addr,
304 uv_connect_cb cb) {
305 unsigned int addrlen;
306
307 if (handle->type != UV_TCP)
308 return UV_EINVAL;
309
310 if (addr->sa_family == AF_INET)
311 addrlen = sizeof(struct sockaddr_in);
312 else if (addr->sa_family == AF_INET6)
313 addrlen = sizeof(struct sockaddr_in6);
314 else
315 return UV_EINVAL;
316
317 return uv__tcp_connect(req, handle, addr, addrlen, cb);
318}
319
320
321int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
322 unsigned int addrlen;
323
324 if (handle->type != UV_UDP)
325 return UV_EINVAL;
326
327 /* Disconnect the handle */
328 if (addr == NULL) {
329 if (!(handle->flags & UV_HANDLE_UDP_CONNECTED))
330 return UV_ENOTCONN;
331
332 return uv__udp_disconnect(handle);
333 }
334
335 if (addr->sa_family == AF_INET)
336 addrlen = sizeof(struct sockaddr_in);
337 else if (addr->sa_family == AF_INET6)
338 addrlen = sizeof(struct sockaddr_in6);
339 else
340 return UV_EINVAL;
341
342 if (handle->flags & UV_HANDLE_UDP_CONNECTED)
343 return UV_EISCONN;
344
345 return uv__udp_connect(handle, addr, addrlen);
346}
347
348
349int uv__udp_is_connected(uv_udp_t* handle) {
350 struct sockaddr_storage addr;
351 int addrlen;
352 if (handle->type != UV_UDP)
353 return 0;
354
355 addrlen = sizeof(addr);
356 if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0)
357 return 0;
358
359 return addrlen > 0;
360}
361
362
363int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
364 unsigned int addrlen;
365
366 if (handle->type != UV_UDP)
367 return UV_EINVAL;
368
369 if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED))
370 return UV_EISCONN;
371
372 if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED))
373 return UV_EDESTADDRREQ;
374
375 if (addr != NULL) {
376 if (addr->sa_family == AF_INET)
377 addrlen = sizeof(struct sockaddr_in);
378 else if (addr->sa_family == AF_INET6)
379 addrlen = sizeof(struct sockaddr_in6);
380#if defined(AF_UNIX) && !defined(_WIN32)
381 else if (addr->sa_family == AF_UNIX)
382 addrlen = sizeof(struct sockaddr_un);
383#endif
384 else
385 return UV_EINVAL;
386 } else {
387 addrlen = 0;
388 }
389
390 return addrlen;
391}
392
393
394int uv_udp_send(uv_udp_send_t* req,
395 uv_udp_t* handle,
396 const uv_buf_t bufs[],
397 unsigned int nbufs,
398 const struct sockaddr* addr,
399 uv_udp_send_cb send_cb) {
400 int addrlen;
401
402 addrlen = uv__udp_check_before_send(handle, addr);
403 if (addrlen < 0)
404 return addrlen;
405
406 return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
407}
408
409
410int uv_udp_try_send(uv_udp_t* handle,
411 const uv_buf_t bufs[],
412 unsigned int nbufs,
413 const struct sockaddr* addr) {
414 int addrlen;
415
416 addrlen = uv__udp_check_before_send(handle, addr);
417 if (addrlen < 0)
418 return addrlen;
419
420 return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
421}
422
423
424int uv_udp_recv_start(uv_udp_t* handle,
425 uv_alloc_cb alloc_cb,
426 uv_udp_recv_cb recv_cb) {
427 if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL)
428 return UV_EINVAL;
429 else
430 return uv__udp_recv_start(handle, alloc_cb, recv_cb);
431}
432
433
434int uv_udp_recv_stop(uv_udp_t* handle) {
435 if (handle->type != UV_UDP)
436 return UV_EINVAL;
437 else
438 return uv__udp_recv_stop(handle);
439}
440
441
442void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
443 QUEUE queue;
444 QUEUE* q;
445 uv_handle_t* h;
446
447 QUEUE_MOVE(&loop->handle_queue, &queue);
448 while (!QUEUE_EMPTY(&queue)) {
449 q = QUEUE_HEAD(&queue);
450 h = QUEUE_DATA(q, uv_handle_t, handle_queue);
451
452 QUEUE_REMOVE(q);
453 QUEUE_INSERT_TAIL(&loop->handle_queue, q);
454
455 if (h->flags & UV_HANDLE_INTERNAL) continue;
456 walk_cb(h, arg);
457 }
458}
459
460
461static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
462 const char* type;
463 QUEUE* q;
464 uv_handle_t* h;
465
466 if (loop == NULL)
467 loop = uv_default_loop();
468
469 QUEUE_FOREACH(q, &loop->handle_queue) {
470 h = QUEUE_DATA(q, uv_handle_t, handle_queue);
471
472 if (only_active && !uv__is_active(h))
473 continue;
474
475 switch (h->type) {
476#define X(uc, lc) case UV_##uc: type = #lc; break;
477 UV_HANDLE_TYPE_MAP(X)
478#undef X
479 default: type = "<unknown>";
480 }
481
482 fprintf(stream,
483 "[%c%c%c] %-8s %p\n",
484 "R-"[!(h->flags & UV_HANDLE_REF)],
485 "A-"[!(h->flags & UV_HANDLE_ACTIVE)],
486 "I-"[!(h->flags & UV_HANDLE_INTERNAL)],
487 type,
488 (void*)h);
489 }
490}
491
492
493void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
494 uv__print_handles(loop, 0, stream);
495}
496
497
498void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
499 uv__print_handles(loop, 1, stream);
500}
501
502
503void uv_ref(uv_handle_t* handle) {
504 uv__handle_ref(handle);
505}
506
507
508void uv_unref(uv_handle_t* handle) {
509 uv__handle_unref(handle);
510}
511
512
513int uv_has_ref(const uv_handle_t* handle) {
514 return uv__has_ref(handle);
515}
516
517
518void uv_stop(uv_loop_t* loop) {
519 loop->stop_flag = 1;
520}
521
522
523uint64_t uv_now(const uv_loop_t* loop) {
524 return loop->time;
525}
526
527
528
529size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
530 unsigned int i;
531 size_t bytes;
532
533 bytes = 0;
534 for (i = 0; i < nbufs; i++)
535 bytes += (size_t) bufs[i].len;
536
537 return bytes;
538}
539
540int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
541 return uv__socket_sockopt(handle, SO_RCVBUF, value);
542}
543
544int uv_send_buffer_size(uv_handle_t* handle, int *value) {
545 return uv__socket_sockopt(handle, SO_SNDBUF, value);
546}
547
548int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
549 size_t required_len;
550
551 if (!uv__is_active(handle)) {
552 *size = 0;
553 return UV_EINVAL;
554 }
555
556 required_len = strlen(handle->path);
557 if (required_len >= *size) {
558 *size = required_len + 1;
559 return UV_ENOBUFS;
560 }
561
562 memcpy(buffer, handle->path, required_len);
563 *size = required_len;
564 buffer[required_len] = '\0';
565
566 return 0;
567}
568
569/* The windows implementation does not have the same structure layout as
570 * the unix implementation (nbufs is not directly inside req but is
571 * contained in a nested union/struct) so this function locates it.
572*/
573static unsigned int* uv__get_nbufs(uv_fs_t* req) {
574#ifdef _WIN32
575 return &req->fs.info.nbufs;
576#else
577 return &req->nbufs;
578#endif
579}
580
581/* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows
582 * systems. So, the memory should be released using free(). On Windows,
583 * uv__malloc() is used, so use uv__free() to free memory.
584*/
585#ifdef _WIN32
586# define uv__fs_scandir_free uv__free
587#else
588# define uv__fs_scandir_free free
589#endif
590
591void uv__fs_scandir_cleanup(uv_fs_t* req) {
592 uv__dirent_t** dents;
593
594 unsigned int* nbufs = uv__get_nbufs(req);
595
596 dents = req->ptr;
597 if (*nbufs > 0 && *nbufs != (unsigned int) req->result)
598 (*nbufs)--;
599 for (; *nbufs < (unsigned int) req->result; (*nbufs)++)
600 uv__fs_scandir_free(dents[*nbufs]);
601
602 uv__fs_scandir_free(req->ptr);
603 req->ptr = NULL;
604}
605
606
607int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
608 uv__dirent_t** dents;
609 uv__dirent_t* dent;
610 unsigned int* nbufs;
611
612 /* Check to see if req passed */
613 if (req->result < 0)
614 return req->result;
615
616 /* Ptr will be null if req was canceled or no files found */
617 if (!req->ptr)
618 return UV_EOF;
619
620 nbufs = uv__get_nbufs(req);
621 assert(nbufs);
622
623 dents = req->ptr;
624
625 /* Free previous entity */
626 if (*nbufs > 0)
627 uv__fs_scandir_free(dents[*nbufs - 1]);
628
629 /* End was already reached */
630 if (*nbufs == (unsigned int) req->result) {
631 uv__fs_scandir_free(dents);
632 req->ptr = NULL;
633 return UV_EOF;
634 }
635
636 dent = dents[(*nbufs)++];
637
638 ent->name = dent->d_name;
639 ent->type = uv__fs_get_dirent_type(dent);
640
641 return 0;
642}
643
644uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) {
645 uv_dirent_type_t type;
646
647#ifdef HAVE_DIRENT_TYPES
648 switch (dent->d_type) {
649 case UV__DT_DIR:
650 type = UV_DIRENT_DIR;
651 break;
652 case UV__DT_FILE:
653 type = UV_DIRENT_FILE;
654 break;
655 case UV__DT_LINK:
656 type = UV_DIRENT_LINK;
657 break;
658 case UV__DT_FIFO:
659 type = UV_DIRENT_FIFO;
660 break;
661 case UV__DT_SOCKET:
662 type = UV_DIRENT_SOCKET;
663 break;
664 case UV__DT_CHAR:
665 type = UV_DIRENT_CHAR;
666 break;
667 case UV__DT_BLOCK:
668 type = UV_DIRENT_BLOCK;
669 break;
670 default:
671 type = UV_DIRENT_UNKNOWN;
672 }
673#else
674 type = UV_DIRENT_UNKNOWN;
675#endif
676
677 return type;
678}
679
680void uv__fs_readdir_cleanup(uv_fs_t* req) {
681 uv_dir_t* dir;
682 uv_dirent_t* dirents;
683 int i;
684
685 if (req->ptr == NULL)
686 return;
687
688 dir = req->ptr;
689 dirents = dir->dirents;
690 req->ptr = NULL;
691
692 if (dirents == NULL)
693 return;
694
695 for (i = 0; i < req->result; ++i) {
696 uv__free((char*) dirents[i].name);
697 dirents[i].name = NULL;
698 }
699}
700
701
702int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {
703 va_list ap;
704 int err;
705
706 va_start(ap, option);
707 /* Any platform-agnostic options should be handled here. */
708 err = uv__loop_configure(loop, option, ap);
709 va_end(ap);
710
711 return err;
712}
713
714
715static uv_loop_t default_loop_struct;
716static uv_loop_t* default_loop_ptr;
717
718
719uv_loop_t* uv_default_loop(void) {
720 if (default_loop_ptr != NULL)
721 return default_loop_ptr;
722
723 if (uv_loop_init(&default_loop_struct))
724 return NULL;
725
726 default_loop_ptr = &default_loop_struct;
727 return default_loop_ptr;
728}
729
730
731uv_loop_t* uv_loop_new(void) {
732 uv_loop_t* loop;
733
734 loop = uv__malloc(sizeof(*loop));
735 if (loop == NULL)
736 return NULL;
737
738 if (uv_loop_init(loop)) {
739 uv__free(loop);
740 return NULL;
741 }
742
743 return loop;
744}
745
746
747int uv_loop_close(uv_loop_t* loop) {
748 QUEUE* q;
749 uv_handle_t* h;
750#ifndef NDEBUG
751 void* saved_data;
752#endif
753
754 if (uv__has_active_reqs(loop))
755 return UV_EBUSY;
756
757 QUEUE_FOREACH(q, &loop->handle_queue) {
758 h = QUEUE_DATA(q, uv_handle_t, handle_queue);
759 if (!(h->flags & UV_HANDLE_INTERNAL))
760 return UV_EBUSY;
761 }
762
763 uv__loop_close(loop);
764
765#ifndef NDEBUG
766 saved_data = loop->data;
767 memset(loop, -1, sizeof(*loop));
768 loop->data = saved_data;
769#endif
770 if (loop == default_loop_ptr)
771 default_loop_ptr = NULL;
772
773 return 0;
774}
775
776
777void uv_loop_delete(uv_loop_t* loop) {
778 uv_loop_t* default_loop;
779 int err;
780
781 default_loop = default_loop_ptr;
782
783 err = uv_loop_close(loop);
784 (void) err; /* Squelch compiler warnings. */
785 assert(err == 0);
786 if (loop != default_loop)
787 uv__free(loop);
788}
789