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 /* Expose glibc-specific EAI_* error codes. Needs to be defined before we
23 * include any headers.
24 */
25 #ifndef _GNU_SOURCE
26 # define _GNU_SOURCE
27 #endif
28
29 #include "uv.h"
30 #include "uv-common.h"
31
32 #include <stdio.h>
33 #include <assert.h>
34 #include <stddef.h> /* NULL */
35 #include <stdlib.h> /* malloc */
36 #include <string.h> /* memset */
37
38 #if defined(UV_PLATFORM_HAS_IP6_LINK_LOCAL_ADDRESS) && !defined(_WIN32)
39 # include <net/if.h> /* if_nametoindex */
40 #endif
41
42 /* EAI_* constants. */
43 #if !defined(_WIN32)
44 # include <sys/types.h>
45 # include <sys/socket.h>
46 # include <netdb.h>
47 #endif
48
49 #define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);
50
uv_handle_size(uv_handle_type type)51 size_t uv_handle_size(uv_handle_type type) {
52 switch (type) {
53 UV_HANDLE_TYPE_MAP(XX)
54 default:
55 return -1;
56 }
57 }
58
uv_req_size(uv_req_type type)59 size_t uv_req_size(uv_req_type type) {
60 switch(type) {
61 UV_REQ_TYPE_MAP(XX)
62 default:
63 return -1;
64 }
65 }
66
67 #undef XX
68
69
uv_buf_init(char * base,unsigned int len)70 uv_buf_t uv_buf_init(char* base, unsigned int len) {
71 uv_buf_t buf;
72 buf.base = base;
73 buf.len = len;
74 return buf;
75 }
76
77
78 #define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
uv_err_name(int err)79 const char* uv_err_name(int err) {
80 switch (err) {
81 UV_ERRNO_MAP(UV_ERR_NAME_GEN)
82 default:
83 assert(0);
84 return NULL;
85 }
86 }
87 #undef UV_ERR_NAME_GEN
88
89
90 #define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
uv_strerror(int err)91 const char* uv_strerror(int err) {
92 switch (err) {
93 UV_ERRNO_MAP(UV_STRERROR_GEN)
94 default:
95 return "Unknown system error";
96 }
97 }
98 #undef UV_STRERROR_GEN
99
100
uv_ip4_addr(const char * ip,int port,struct sockaddr_in * addr)101 int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
102 memset(addr, 0, sizeof(*addr));
103 addr->sin_family = AF_INET;
104 addr->sin_port = htons(port);
105 return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));
106 }
107
108
uv_ip6_addr(const char * ip,int port,struct sockaddr_in6 * addr)109 int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
110 #if defined(UV_PLATFORM_HAS_IP6_LINK_LOCAL_ADDRESS)
111 char address_part[40];
112 size_t address_part_size;
113 const char* zone_index;
114 #endif
115
116 memset(addr, 0, sizeof(*addr));
117 addr->sin6_family = AF_INET6;
118 addr->sin6_port = htons(port);
119
120 #if defined(UV_PLATFORM_HAS_IP6_LINK_LOCAL_ADDRESS)
121 zone_index = strchr(ip, '%');
122 if (zone_index != NULL) {
123 address_part_size = zone_index - ip;
124 if (address_part_size >= sizeof(address_part))
125 address_part_size = sizeof(address_part) - 1;
126
127 memcpy(address_part, ip, address_part_size);
128 address_part[address_part_size] = '\0';
129 ip = address_part;
130
131 zone_index++; /* skip '%' */
132 /* NOTE: unknown interface (id=0) is silently ignored */
133 #ifdef _WIN32
134 addr->sin6_scope_id = atoi(zone_index);
135 #else
136 addr->sin6_scope_id = if_nametoindex(zone_index);
137 #endif
138 }
139 #endif
140
141 return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr);
142 }
143
144
uv_ip4_name(struct sockaddr_in * src,char * dst,size_t size)145 int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size) {
146 return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
147 }
148
149
uv_ip6_name(struct sockaddr_in6 * src,char * dst,size_t size)150 int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) {
151 return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
152 }
153
154
uv_tcp_bind(uv_tcp_t * handle,const struct sockaddr * addr,unsigned int flags)155 int uv_tcp_bind(uv_tcp_t* handle,
156 const struct sockaddr* addr,
157 unsigned int flags) {
158 unsigned int addrlen;
159
160 if (handle->type != UV_TCP)
161 return UV_EINVAL;
162
163 if (addr->sa_family == AF_INET)
164 addrlen = sizeof(struct sockaddr_in);
165 else if (addr->sa_family == AF_INET6)
166 addrlen = sizeof(struct sockaddr_in6);
167 else
168 return UV_EINVAL;
169
170 return uv__tcp_bind(handle, addr, addrlen, flags);
171 }
172
173
uv_udp_bind(uv_udp_t * handle,const struct sockaddr * addr,unsigned int flags)174 int uv_udp_bind(uv_udp_t* handle,
175 const struct sockaddr* addr,
176 unsigned int flags) {
177 unsigned int addrlen;
178
179 if (handle->type != UV_UDP)
180 return UV_EINVAL;
181
182 if (addr->sa_family == AF_INET)
183 addrlen = sizeof(struct sockaddr_in);
184 else if (addr->sa_family == AF_INET6)
185 addrlen = sizeof(struct sockaddr_in6);
186 else
187 return UV_EINVAL;
188
189 return uv__udp_bind(handle, addr, addrlen, flags);
190 }
191
192
uv_tcp_connect(uv_connect_t * req,uv_tcp_t * handle,const struct sockaddr * addr,uv_connect_cb cb)193 int uv_tcp_connect(uv_connect_t* req,
194 uv_tcp_t* handle,
195 const struct sockaddr* addr,
196 uv_connect_cb cb) {
197 unsigned int addrlen;
198
199 if (handle->type != UV_TCP)
200 return UV_EINVAL;
201
202 if (addr->sa_family == AF_INET)
203 addrlen = sizeof(struct sockaddr_in);
204 else if (addr->sa_family == AF_INET6)
205 addrlen = sizeof(struct sockaddr_in6);
206 else
207 return UV_EINVAL;
208
209 return uv__tcp_connect(req, handle, addr, addrlen, cb);
210 }
211
212
uv_udp_send(uv_udp_send_t * req,uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr,uv_udp_send_cb send_cb)213 int uv_udp_send(uv_udp_send_t* req,
214 uv_udp_t* handle,
215 const uv_buf_t bufs[],
216 unsigned int nbufs,
217 const struct sockaddr* addr,
218 uv_udp_send_cb send_cb) {
219 unsigned int addrlen;
220
221 if (handle->type != UV_UDP)
222 return UV_EINVAL;
223
224 if (addr->sa_family == AF_INET)
225 addrlen = sizeof(struct sockaddr_in);
226 else if (addr->sa_family == AF_INET6)
227 addrlen = sizeof(struct sockaddr_in6);
228 else
229 return UV_EINVAL;
230
231 return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
232 }
233
234
uv_udp_recv_start(uv_udp_t * handle,uv_alloc_cb alloc_cb,uv_udp_recv_cb recv_cb)235 int uv_udp_recv_start(uv_udp_t* handle,
236 uv_alloc_cb alloc_cb,
237 uv_udp_recv_cb recv_cb) {
238 if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL)
239 return UV_EINVAL;
240 else
241 return uv__udp_recv_start(handle, alloc_cb, recv_cb);
242 }
243
244
uv_udp_recv_stop(uv_udp_t * handle)245 int uv_udp_recv_stop(uv_udp_t* handle) {
246 if (handle->type != UV_UDP)
247 return UV_EINVAL;
248 else
249 return uv__udp_recv_stop(handle);
250 }
251
252
253 struct thread_ctx {
254 void (*entry)(void* arg);
255 void* arg;
256 };
257
258
259 #ifdef _WIN32
uv__thread_start(void * arg)260 static UINT __stdcall uv__thread_start(void* arg)
261 #else
262 static void* uv__thread_start(void *arg)
263 #endif
264 {
265 struct thread_ctx *ctx_p;
266 struct thread_ctx ctx;
267
268 ctx_p = arg;
269 ctx = *ctx_p;
270 free(ctx_p);
271 ctx.entry(ctx.arg);
272
273 return 0;
274 }
275
276
uv_thread_create(uv_thread_t * tid,void (* entry)(void * arg),void * arg)277 int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
278 struct thread_ctx* ctx;
279 int err;
280
281 ctx = malloc(sizeof(*ctx));
282 if (ctx == NULL)
283 return UV_ENOMEM;
284
285 ctx->entry = entry;
286 ctx->arg = arg;
287
288 #ifdef _WIN32
289 *tid = (HANDLE) _beginthreadex(NULL, 0, uv__thread_start, ctx, 0, NULL);
290 err = *tid ? 0 : errno;
291 #else
292 err = pthread_create(tid, NULL, uv__thread_start, ctx);
293 #endif
294
295 if (err)
296 free(ctx);
297
298 return err ? -1 : 0;
299 }
300
301
uv_thread_self(void)302 unsigned long uv_thread_self(void) {
303 #ifdef _WIN32
304 return (unsigned long) GetCurrentThreadId();
305 #else
306 return (unsigned long) pthread_self();
307 #endif
308 }
309
310
uv_walk(uv_loop_t * loop,uv_walk_cb walk_cb,void * arg)311 void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
312 QUEUE* q;
313 uv_handle_t* h;
314
315 QUEUE_FOREACH(q, &loop->handle_queue) {
316 h = QUEUE_DATA(q, uv_handle_t, handle_queue);
317 if (h->flags & UV__HANDLE_INTERNAL) continue;
318 walk_cb(h, arg);
319 }
320 }
321
322
323 #ifndef NDEBUG
uv__print_handles(uv_loop_t * loop,int only_active)324 static void uv__print_handles(uv_loop_t* loop, int only_active) {
325 const char* type;
326 QUEUE* q;
327 uv_handle_t* h;
328
329 if (loop == NULL)
330 loop = uv_default_loop();
331
332 QUEUE_FOREACH(q, &loop->handle_queue) {
333 h = QUEUE_DATA(q, uv_handle_t, handle_queue);
334
335 if (only_active && !uv__is_active(h))
336 continue;
337
338 switch (h->type) {
339 #define X(uc, lc) case UV_##uc: type = #lc; break;
340 UV_HANDLE_TYPE_MAP(X)
341 #undef X
342 default: type = "<unknown>";
343 }
344
345 fprintf(stderr,
346 "[%c%c%c] %-8s %p\n",
347 "R-"[!(h->flags & UV__HANDLE_REF)],
348 "A-"[!(h->flags & UV__HANDLE_ACTIVE)],
349 "I-"[!(h->flags & UV__HANDLE_INTERNAL)],
350 type,
351 (void*)h);
352 }
353 }
354
355
uv_print_all_handles(uv_loop_t * loop)356 void uv_print_all_handles(uv_loop_t* loop) {
357 uv__print_handles(loop, 0);
358 }
359
360
uv_print_active_handles(uv_loop_t * loop)361 void uv_print_active_handles(uv_loop_t* loop) {
362 uv__print_handles(loop, 1);
363 }
364 #endif
365
366
uv_ref(uv_handle_t * handle)367 void uv_ref(uv_handle_t* handle) {
368 uv__handle_ref(handle);
369 }
370
371
uv_unref(uv_handle_t * handle)372 void uv_unref(uv_handle_t* handle) {
373 uv__handle_unref(handle);
374 }
375
376
uv_has_ref(const uv_handle_t * handle)377 int uv_has_ref(const uv_handle_t* handle) {
378 return uv__has_ref(handle);
379 }
380
381
uv_stop(uv_loop_t * loop)382 void uv_stop(uv_loop_t* loop) {
383 loop->stop_flag = 1;
384 }
385
386
uv_now(uv_loop_t * loop)387 uint64_t uv_now(uv_loop_t* loop) {
388 return loop->time;
389 }
390
391
uv__getaddrinfo_translate_error(int sys_err)392 int uv__getaddrinfo_translate_error(int sys_err) {
393 switch (sys_err) {
394 case 0: return 0;
395 #if defined(EAI_ADDRFAMILY)
396 case EAI_ADDRFAMILY: return UV_EAI_ADDRFAMILY;
397 #endif
398 #if defined(EAI_AGAIN)
399 case EAI_AGAIN: return UV_EAI_AGAIN;
400 #endif
401 #if defined(EAI_BADFLAGS)
402 case EAI_BADFLAGS: return UV_EAI_BADFLAGS;
403 #endif
404 #if defined(EAI_BADHINTS)
405 case EAI_BADHINTS: return UV_EAI_BADHINTS;
406 #endif
407 #if defined(EAI_CANCELED)
408 case EAI_CANCELED: return UV_EAI_CANCELED;
409 #endif
410 #if defined(EAI_FAIL)
411 case EAI_FAIL: return UV_EAI_FAIL;
412 #endif
413 #if defined(EAI_FAMILY)
414 case EAI_FAMILY: return UV_EAI_FAMILY;
415 #endif
416 #if defined(EAI_MEMORY)
417 case EAI_MEMORY: return UV_EAI_MEMORY;
418 #endif
419 #if defined(EAI_NODATA)
420 case EAI_NODATA: return UV_EAI_NODATA;
421 #endif
422 #if defined(EAI_NONAME)
423 # if !defined(EAI_NODATA) || EAI_NODATA != EAI_NONAME
424 case EAI_NONAME: return UV_EAI_NONAME;
425 # endif
426 #endif
427 #if defined(EAI_OVERFLOW)
428 case EAI_OVERFLOW: return UV_EAI_OVERFLOW;
429 #endif
430 #if defined(EAI_PROTOCOL)
431 case EAI_PROTOCOL: return UV_EAI_PROTOCOL;
432 #endif
433 #if defined(EAI_SERVICE)
434 case EAI_SERVICE: return UV_EAI_SERVICE;
435 #endif
436 #if defined(EAI_SOCKTYPE)
437 case EAI_SOCKTYPE: return UV_EAI_SOCKTYPE;
438 #endif
439 #if defined(EAI_SYSTEM)
440 case EAI_SYSTEM: return UV_EAI_SYSTEM;
441 #endif
442 }
443 assert(!"unknown EAI_* error code");
444 abort();
445 return 0; /* Pacify compiler. */
446 }
447