libuv-svace-build

Форк
0
1143 строки · 33.9 Кб
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 <assert.h>
23
#include <stdlib.h>
24

25
#include "uv.h"
26
#include "internal.h"
27
#include "handle-inl.h"
28
#include "stream-inl.h"
29
#include "req-inl.h"
30

31

32
/* A zero-size buffer for use by uv_udp_read */
33
static char uv_zero_[] = "";
34
int uv_udp_getpeername(const uv_udp_t* handle,
35
                       struct sockaddr* name,
36
                       int* namelen) {
37

38
  return uv__getsockpeername((const uv_handle_t*) handle,
39
                             getpeername,
40
                             name,
41
                             namelen,
42
                             0);
43
}
44

45

46
int uv_udp_getsockname(const uv_udp_t* handle,
47
                       struct sockaddr* name,
48
                       int* namelen) {
49

50
  return uv__getsockpeername((const uv_handle_t*) handle,
51
                             getsockname,
52
                             name,
53
                             namelen,
54
                             0);
55
}
56

57

58
static int uv__udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
59
    int family) {
60
  DWORD yes = 1;
61
  WSAPROTOCOL_INFOW info;
62
  int opt_len;
63

64
  if (handle->socket != INVALID_SOCKET)
65
    return UV_EBUSY;
66

67
  /* Set the socket to nonblocking mode */
68
  if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
69
    return WSAGetLastError();
70
  }
71

72
  /* Make the socket non-inheritable */
73
  if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) {
74
    return GetLastError();
75
  }
76

77
  /* Associate it with the I/O completion port. Use uv_handle_t pointer as
78
   * completion key. */
79
  if (CreateIoCompletionPort((HANDLE)socket,
80
                             loop->iocp,
81
                             (ULONG_PTR)socket,
82
                             0) == NULL) {
83
    return GetLastError();
84
  }
85

86
  /* All known Windows that support SetFileCompletionNotificationModes have a
87
   * bug that makes it impossible to use this function in conjunction with
88
   * datagram sockets. We can work around that but only if the user is using
89
   * the default UDP driver (AFD) and has no other. LSPs stacked on top. Here
90
   * we check whether that is the case. */
91
  opt_len = (int) sizeof info;
92
  if (getsockopt(
93
          socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) ==
94
      SOCKET_ERROR) {
95
    return GetLastError();
96
  }
97

98
  if (info.ProtocolChain.ChainLen == 1) {
99
    if (SetFileCompletionNotificationModes(
100
            (HANDLE) socket,
101
            FILE_SKIP_SET_EVENT_ON_HANDLE |
102
                FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
103
      handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
104
      handle->func_wsarecv = uv__wsarecv_workaround;
105
      handle->func_wsarecvfrom = uv__wsarecvfrom_workaround;
106
    } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
107
      return GetLastError();
108
    }
109
  }
110

111
  handle->socket = socket;
112

113
  if (family == AF_INET6) {
114
    handle->flags |= UV_HANDLE_IPV6;
115
  } else {
116
    assert(!(handle->flags & UV_HANDLE_IPV6));
117
  }
118

119
  return 0;
120
}
121

122

123
int uv__udp_init_ex(uv_loop_t* loop,
124
                    uv_udp_t* handle,
125
                    unsigned flags,
126
                    int domain) {
127
  uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP);
128
  handle->socket = INVALID_SOCKET;
129
  handle->reqs_pending = 0;
130
  handle->activecnt = 0;
131
  handle->func_wsarecv = WSARecv;
132
  handle->func_wsarecvfrom = WSARecvFrom;
133
  handle->send_queue_size = 0;
134
  handle->send_queue_count = 0;
135
  UV_REQ_INIT(&handle->recv_req, UV_UDP_RECV);
136
  handle->recv_req.data = handle;
137

138
  /* If anything fails beyond this point we need to remove the handle from
139
   * the handle queue, since it was added by uv__handle_init.
140
   */
141

142
  if (domain != AF_UNSPEC) {
143
    SOCKET sock;
144
    DWORD err;
145

146
    sock = socket(domain, SOCK_DGRAM, 0);
147
    if (sock == INVALID_SOCKET) {
148
      err = WSAGetLastError();
149
      uv__queue_remove(&handle->handle_queue);
150
      return uv_translate_sys_error(err);
151
    }
152

153
    err = uv__udp_set_socket(handle->loop, handle, sock, domain);
154
    if (err) {
155
      closesocket(sock);
156
      uv__queue_remove(&handle->handle_queue);
157
      return uv_translate_sys_error(err);
158
    }
159
  }
160

161
  return 0;
162
}
163

164

165
void uv__udp_close(uv_loop_t* loop, uv_udp_t* handle) {
166
  uv_udp_recv_stop(handle);
167
  closesocket(handle->socket);
168
  handle->socket = INVALID_SOCKET;
169

170
  uv__handle_closing(handle);
171

172
  if (handle->reqs_pending == 0) {
173
    uv__want_endgame(loop, (uv_handle_t*) handle);
174
  }
175
}
176

177

178
void uv__udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
179
  if (handle->flags & UV_HANDLE_CLOSING &&
180
      handle->reqs_pending == 0) {
181
    assert(!(handle->flags & UV_HANDLE_CLOSED));
182
    uv__handle_close(handle);
183
  }
184
}
185

186

187
int uv_udp_using_recvmmsg(const uv_udp_t* handle) {
188
  return 0;
189
}
190

191

192
static int uv__udp_maybe_bind(uv_udp_t* handle,
193
                              const struct sockaddr* addr,
194
                              unsigned int addrlen,
195
                              unsigned int flags) {
196
  int r;
197
  int err;
198
  DWORD no = 0;
199

200
  if (handle->flags & UV_HANDLE_BOUND)
201
    return 0;
202

203
  /* There is no SO_REUSEPORT on Windows, Windows only knows SO_REUSEADDR.
204
   * so we just return an error directly when UV_UDP_REUSEPORT is requested
205
   * for binding the socket. */
206
  if (flags & UV_UDP_REUSEPORT)
207
    return ERROR_NOT_SUPPORTED;
208

209
  if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) {
210
    /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */
211
    return ERROR_INVALID_PARAMETER;
212
  }
213

214
  if (handle->socket == INVALID_SOCKET) {
215
    SOCKET sock = socket(addr->sa_family, SOCK_DGRAM, 0);
216
    if (sock == INVALID_SOCKET) {
217
      return WSAGetLastError();
218
    }
219

220
    err = uv__udp_set_socket(handle->loop, handle, sock, addr->sa_family);
221
    if (err) {
222
      closesocket(sock);
223
      return err;
224
    }
225
  }
226

227
  if (flags & UV_UDP_REUSEADDR) {
228
    DWORD yes = 1;
229
    /* Set SO_REUSEADDR on the socket. */
230
    if (setsockopt(handle->socket,
231
                   SOL_SOCKET,
232
                   SO_REUSEADDR,
233
                   (char*) &yes,
234
                   sizeof yes) == SOCKET_ERROR) {
235
      err = WSAGetLastError();
236
      return err;
237
    }
238
  }
239

240
  if (addr->sa_family == AF_INET6)
241
    handle->flags |= UV_HANDLE_IPV6;
242

243
  if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
244
    /* On windows IPV6ONLY is on by default. If the user doesn't specify it
245
     * libuv turns it off. */
246

247
    /* TODO: how to handle errors? This may fail if there is no ipv4 stack
248
     * available, or when run on XP/2003 which have no support for dualstack
249
     * sockets. For now we're silently ignoring the error. */
250
    setsockopt(handle->socket,
251
               IPPROTO_IPV6,
252
               IPV6_V6ONLY,
253
               (char*) &no,
254
               sizeof no);
255
  }
256

257
  r = bind(handle->socket, addr, addrlen);
258
  if (r == SOCKET_ERROR) {
259
    return WSAGetLastError();
260
  }
261

262
  handle->flags |= UV_HANDLE_BOUND;
263

264
  return 0;
265
}
266

267

268
static void uv__udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
269
  uv_req_t* req;
270
  uv_buf_t buf;
271
  DWORD bytes, flags;
272
  int result;
273

274
  assert(handle->flags & UV_HANDLE_READING);
275
  assert(!(handle->flags & UV_HANDLE_READ_PENDING));
276

277
  req = &handle->recv_req;
278
  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
279

280
  handle->flags |= UV_HANDLE_ZERO_READ;
281

282
  buf.base = (char*) uv_zero_;
283
  buf.len = 0;
284
  flags = MSG_PEEK;
285

286
  result = handle->func_wsarecv(handle->socket,
287
                                (WSABUF*) &buf,
288
                                1,
289
                                &bytes,
290
                                &flags,
291
                                &req->u.io.overlapped,
292
                                NULL);
293

294
  if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
295
    /* Process the req without IOCP. */
296
    handle->flags |= UV_HANDLE_READ_PENDING;
297
    req->u.io.overlapped.InternalHigh = bytes;
298
    handle->reqs_pending++;
299
    uv__insert_pending_req(loop, req);
300
  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
301
    /* The req will be processed with IOCP. */
302
    handle->flags |= UV_HANDLE_READ_PENDING;
303
    handle->reqs_pending++;
304
  } else {
305
    /* Make this req pending reporting an error. */
306
    SET_REQ_ERROR(req, WSAGetLastError());
307
    uv__insert_pending_req(loop, req);
308
    handle->reqs_pending++;
309
  }
310
}
311

312

313
int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
314
    uv_udp_recv_cb recv_cb) {
315
  uv_loop_t* loop = handle->loop;
316
  int err;
317

318
  if (handle->flags & UV_HANDLE_READING) {
319
    return UV_EALREADY;
320
  }
321

322
  err = uv__udp_maybe_bind(handle,
323
                           (const struct sockaddr*) &uv_addr_ip4_any_,
324
                           sizeof(uv_addr_ip4_any_),
325
                           0);
326
  if (err)
327
    return uv_translate_sys_error(err);
328

329
  handle->flags |= UV_HANDLE_READING;
330
  INCREASE_ACTIVE_COUNT(loop, handle);
331

332
  handle->recv_cb = recv_cb;
333
  handle->alloc_cb = alloc_cb;
334

335
  /* If reading was stopped and then started again, there could still be a recv
336
   * request pending. */
337
  if (!(handle->flags & UV_HANDLE_READ_PENDING))
338
    uv__udp_queue_recv(loop, handle);
339

340
  return 0;
341
}
342

343

344
int uv__udp_recv_stop(uv_udp_t* handle) {
345
  if (handle->flags & UV_HANDLE_READING) {
346
    handle->flags &= ~UV_HANDLE_READING;
347
    DECREASE_ACTIVE_COUNT(loop, handle);
348
  }
349

350
  return 0;
351
}
352

353

354
static int uv__send(uv_udp_send_t* req,
355
                    uv_udp_t* handle,
356
                    const uv_buf_t bufs[],
357
                    unsigned int nbufs,
358
                    const struct sockaddr* addr,
359
                    unsigned int addrlen,
360
                    uv_udp_send_cb cb) {
361
  uv_loop_t* loop = handle->loop;
362
  DWORD result, bytes;
363

364
  UV_REQ_INIT(req, UV_UDP_SEND);
365
  req->handle = handle;
366
  req->cb = cb;
367
  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
368

369
  result = WSASendTo(handle->socket,
370
                     (WSABUF*)bufs,
371
                     nbufs,
372
                     &bytes,
373
                     0,
374
                     addr,
375
                     addrlen,
376
                     &req->u.io.overlapped,
377
                     NULL);
378

379
  if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
380
    /* Request completed immediately. */
381
    req->u.io.queued_bytes = 0;
382
    handle->reqs_pending++;
383
    handle->send_queue_size += req->u.io.queued_bytes;
384
    handle->send_queue_count++;
385
    REGISTER_HANDLE_REQ(loop, handle, req);
386
    uv__insert_pending_req(loop, (uv_req_t*)req);
387
  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
388
    /* Request queued by the kernel. */
389
    req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);
390
    handle->reqs_pending++;
391
    handle->send_queue_size += req->u.io.queued_bytes;
392
    handle->send_queue_count++;
393
    REGISTER_HANDLE_REQ(loop, handle, req);
394
  } else {
395
    /* Send failed due to an error. */
396
    return WSAGetLastError();
397
  }
398

399
  return 0;
400
}
401

402

403
void uv__process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
404
    uv_req_t* req) {
405
  uv_buf_t buf;
406
  int partial;
407

408
  assert(handle->type == UV_UDP);
409

410
  handle->flags &= ~UV_HANDLE_READ_PENDING;
411

412
  if (!REQ_SUCCESS(req)) {
413
    DWORD err = GET_REQ_SOCK_ERROR(req);
414
    if (err == WSAEMSGSIZE) {
415
      /* Not a real error, it just indicates that the received packet was
416
       * bigger than the receive buffer. */
417
    } else if (err == WSAECONNRESET || err == WSAENETRESET) {
418
      /* A previous sendto operation failed; ignore this error. If zero-reading
419
       * we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to
420
       * clear out the error queue. For nonzero reads, immediately queue a new
421
       * receive. */
422
      if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
423
        goto done;
424
      }
425
    } else {
426
      /* A real error occurred. Report the error to the user only if we're
427
       * currently reading. */
428
      if (handle->flags & UV_HANDLE_READING) {
429
        uv_udp_recv_stop(handle);
430
        buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
431
              uv_buf_init(NULL, 0) : handle->recv_buffer;
432
        handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);
433
      }
434
      goto done;
435
    }
436
  }
437

438
  if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
439
    /* Successful read */
440
    partial = !REQ_SUCCESS(req);
441
    handle->recv_cb(handle,
442
                    req->u.io.overlapped.InternalHigh,
443
                    &handle->recv_buffer,
444
                    (const struct sockaddr*) &handle->recv_from,
445
                    partial ? UV_UDP_PARTIAL : 0);
446
  } else if (handle->flags & UV_HANDLE_READING) {
447
    DWORD bytes, err, flags;
448
    struct sockaddr_storage from;
449
    int from_len;
450
    int count;
451

452
    /* Prevent loop starvation when the data comes in as fast as
453
     * (or faster than) we can read it. */
454
    count = 32;
455

456
    do {
457
      /* Do at most `count` nonblocking receive. */
458
      buf = uv_buf_init(NULL, 0);
459
      handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf);
460
      if (buf.base == NULL || buf.len == 0) {
461
        handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);
462
        goto done;
463
      }
464

465
      memset(&from, 0, sizeof from);
466
      from_len = sizeof from;
467

468
      flags = 0;
469

470
      if (WSARecvFrom(handle->socket,
471
                      (WSABUF*)&buf,
472
                      1,
473
                      &bytes,
474
                      &flags,
475
                      (struct sockaddr*) &from,
476
                      &from_len,
477
                      NULL,
478
                      NULL) != SOCKET_ERROR) {
479

480
        /* Message received */
481
        err = ERROR_SUCCESS;
482
        handle->recv_cb(handle, bytes, &buf, (const struct sockaddr*) &from, 0);
483
      } else {
484
        err = WSAGetLastError();
485
        if (err == WSAEMSGSIZE) {
486
          /* Message truncated */
487
          handle->recv_cb(handle,
488
                          bytes,
489
                          &buf,
490
                          (const struct sockaddr*) &from,
491
                          UV_UDP_PARTIAL);
492
        } else if (err == WSAEWOULDBLOCK) {
493
          /* Kernel buffer empty */
494
          handle->recv_cb(handle, 0, &buf, NULL, 0);
495
        } else if (err == WSAECONNRESET || err == WSAENETRESET) {
496
          /* WSAECONNRESET/WSANETRESET is ignored because this just indicates
497
           * that a previous sendto operation failed.
498
           */
499
          handle->recv_cb(handle, 0, &buf, NULL, 0);
500
        } else {
501
          /* Any other error that we want to report back to the user. */
502
          uv_udp_recv_stop(handle);
503
          handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);
504
        }
505
      }
506
    }
507
    while (err == ERROR_SUCCESS &&
508
           count-- > 0 &&
509
           /* The recv_cb callback may decide to pause or close the handle. */
510
           (handle->flags & UV_HANDLE_READING) &&
511
           !(handle->flags & UV_HANDLE_READ_PENDING));
512
  }
513

514
done:
515
  /* Post another read if still reading and not closing. */
516
  if ((handle->flags & UV_HANDLE_READING) &&
517
      !(handle->flags & UV_HANDLE_READ_PENDING)) {
518
    uv__udp_queue_recv(loop, handle);
519
  }
520

521
  DECREASE_PENDING_REQ_COUNT(handle);
522
}
523

524

525
void uv__process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
526
    uv_udp_send_t* req) {
527
  int err;
528

529
  assert(handle->type == UV_UDP);
530

531
  assert(handle->send_queue_size >= req->u.io.queued_bytes);
532
  assert(handle->send_queue_count >= 1);
533
  handle->send_queue_size -= req->u.io.queued_bytes;
534
  handle->send_queue_count--;
535

536
  UNREGISTER_HANDLE_REQ(loop, handle, req);
537

538
  if (req->cb) {
539
    err = 0;
540
    if (!REQ_SUCCESS(req)) {
541
      err = GET_REQ_SOCK_ERROR(req);
542
    }
543
    req->cb(req, uv_translate_sys_error(err));
544
  }
545

546
  DECREASE_PENDING_REQ_COUNT(handle);
547
}
548

549

550
static int uv__udp_set_membership4(uv_udp_t* handle,
551
                                   const struct sockaddr_in* multicast_addr,
552
                                   const char* interface_addr,
553
                                   uv_membership membership) {
554
  int err;
555
  int optname;
556
  struct ip_mreq mreq;
557

558
  if (handle->flags & UV_HANDLE_IPV6)
559
    return UV_EINVAL;
560

561
  /* If the socket is unbound, bind to inaddr_any. */
562
  err = uv__udp_maybe_bind(handle,
563
                           (const struct sockaddr*) &uv_addr_ip4_any_,
564
                           sizeof(uv_addr_ip4_any_),
565
                           UV_UDP_REUSEADDR);
566
  if (err)
567
    return uv_translate_sys_error(err);
568

569
  memset(&mreq, 0, sizeof mreq);
570

571
  if (interface_addr) {
572
    err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
573
    if (err)
574
      return err;
575
  } else {
576
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
577
  }
578

579
  mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
580

581
  switch (membership) {
582
    case UV_JOIN_GROUP:
583
      optname = IP_ADD_MEMBERSHIP;
584
      break;
585
    case UV_LEAVE_GROUP:
586
      optname = IP_DROP_MEMBERSHIP;
587
      break;
588
    default:
589
      return UV_EINVAL;
590
  }
591

592
  if (setsockopt(handle->socket,
593
                 IPPROTO_IP,
594
                 optname,
595
                 (char*) &mreq,
596
                 sizeof mreq) == SOCKET_ERROR) {
597
    return uv_translate_sys_error(WSAGetLastError());
598
  }
599

600
  return 0;
601
}
602

603

604
int uv__udp_set_membership6(uv_udp_t* handle,
605
                            const struct sockaddr_in6* multicast_addr,
606
                            const char* interface_addr,
607
                            uv_membership membership) {
608
  int optname;
609
  int err;
610
  struct ipv6_mreq mreq;
611
  struct sockaddr_in6 addr6;
612

613
  if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
614
    return UV_EINVAL;
615

616
  err = uv__udp_maybe_bind(handle,
617
                           (const struct sockaddr*) &uv_addr_ip6_any_,
618
                           sizeof(uv_addr_ip6_any_),
619
                           UV_UDP_REUSEADDR);
620

621
  if (err)
622
    return uv_translate_sys_error(err);
623

624
  memset(&mreq, 0, sizeof(mreq));
625

626
  if (interface_addr) {
627
    if (uv_ip6_addr(interface_addr, 0, &addr6))
628
      return UV_EINVAL;
629
    mreq.ipv6mr_interface = addr6.sin6_scope_id;
630
  } else {
631
    mreq.ipv6mr_interface = 0;
632
  }
633

634
  mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr;
635

636
  switch (membership) {
637
  case UV_JOIN_GROUP:
638
    optname = IPV6_ADD_MEMBERSHIP;
639
    break;
640
  case UV_LEAVE_GROUP:
641
    optname = IPV6_DROP_MEMBERSHIP;
642
    break;
643
  default:
644
    return UV_EINVAL;
645
  }
646

647
  if (setsockopt(handle->socket,
648
                 IPPROTO_IPV6,
649
                 optname,
650
                 (char*) &mreq,
651
                 sizeof mreq) == SOCKET_ERROR) {
652
    return uv_translate_sys_error(WSAGetLastError());
653
  }
654

655
  return 0;
656
}
657

658

659
static int uv__udp_set_source_membership4(uv_udp_t* handle,
660
                                          const struct sockaddr_in* multicast_addr,
661
                                          const char* interface_addr,
662
                                          const struct sockaddr_in* source_addr,
663
                                          uv_membership membership) {
664
  struct ip_mreq_source mreq;
665
  int optname;
666
  int err;
667

668
  if (handle->flags & UV_HANDLE_IPV6)
669
    return UV_EINVAL;
670

671
  /* If the socket is unbound, bind to inaddr_any. */
672
  err = uv__udp_maybe_bind(handle,
673
                           (const struct sockaddr*) &uv_addr_ip4_any_,
674
                           sizeof(uv_addr_ip4_any_),
675
                           UV_UDP_REUSEADDR);
676
  if (err)
677
    return uv_translate_sys_error(err);
678

679
  memset(&mreq, 0, sizeof(mreq));
680

681
  if (interface_addr != NULL) {
682
    err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
683
    if (err)
684
      return err;
685
  } else {
686
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
687
  }
688

689
  mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
690
  mreq.imr_sourceaddr.s_addr = source_addr->sin_addr.s_addr;
691

692
  if (membership == UV_JOIN_GROUP)
693
    optname = IP_ADD_SOURCE_MEMBERSHIP;
694
  else if (membership == UV_LEAVE_GROUP)
695
    optname = IP_DROP_SOURCE_MEMBERSHIP;
696
  else
697
    return UV_EINVAL;
698

699
  if (setsockopt(handle->socket,
700
                 IPPROTO_IP,
701
                 optname,
702
                 (char*) &mreq,
703
                 sizeof(mreq)) == SOCKET_ERROR) {
704
    return uv_translate_sys_error(WSAGetLastError());
705
  }
706

707
  return 0;
708
}
709

710

711
int uv__udp_set_source_membership6(uv_udp_t* handle,
712
                                   const struct sockaddr_in6* multicast_addr,
713
                                   const char* interface_addr,
714
                                   const struct sockaddr_in6* source_addr,
715
                                   uv_membership membership) {
716
  struct group_source_req mreq;
717
  struct sockaddr_in6 addr6;
718
  int optname;
719
  int err;
720

721
  STATIC_ASSERT(sizeof(mreq.gsr_group) >= sizeof(*multicast_addr));
722
  STATIC_ASSERT(sizeof(mreq.gsr_source) >= sizeof(*source_addr));
723

724
  if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
725
    return UV_EINVAL;
726

727
  err = uv__udp_maybe_bind(handle,
728
                           (const struct sockaddr*) &uv_addr_ip6_any_,
729
                           sizeof(uv_addr_ip6_any_),
730
                           UV_UDP_REUSEADDR);
731

732
  if (err)
733
    return uv_translate_sys_error(err);
734

735
  memset(&mreq, 0, sizeof(mreq));
736

737
  if (interface_addr != NULL) {
738
    err = uv_ip6_addr(interface_addr, 0, &addr6);
739
    if (err)
740
      return err;
741
    mreq.gsr_interface = addr6.sin6_scope_id;
742
  } else {
743
    mreq.gsr_interface = 0;
744
  }
745

746
  memcpy(&mreq.gsr_group, multicast_addr, sizeof(*multicast_addr));
747
  memcpy(&mreq.gsr_source, source_addr, sizeof(*source_addr));
748

749
  if (membership == UV_JOIN_GROUP)
750
    optname = MCAST_JOIN_SOURCE_GROUP;
751
  else if (membership == UV_LEAVE_GROUP)
752
    optname = MCAST_LEAVE_SOURCE_GROUP;
753
  else
754
    return UV_EINVAL;
755

756
  if (setsockopt(handle->socket,
757
                 IPPROTO_IPV6,
758
                 optname,
759
                 (char*) &mreq,
760
                 sizeof(mreq)) == SOCKET_ERROR) {
761
    return uv_translate_sys_error(WSAGetLastError());
762
  }
763

764
  return 0;
765
}
766

767

768
int uv_udp_set_membership(uv_udp_t* handle,
769
                          const char* multicast_addr,
770
                          const char* interface_addr,
771
                          uv_membership membership) {
772
  struct sockaddr_in addr4;
773
  struct sockaddr_in6 addr6;
774

775
  if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0)
776
    return uv__udp_set_membership4(handle, &addr4, interface_addr, membership);
777
  else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0)
778
    return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);
779
  else
780
    return UV_EINVAL;
781
}
782

783

784
int uv_udp_set_source_membership(uv_udp_t* handle,
785
                                 const char* multicast_addr,
786
                                 const char* interface_addr,
787
                                 const char* source_addr,
788
                                 uv_membership membership) {
789
  int err;
790
  struct sockaddr_storage mcast_addr;
791
  struct sockaddr_in* mcast_addr4;
792
  struct sockaddr_in6* mcast_addr6;
793
  struct sockaddr_storage src_addr;
794
  struct sockaddr_in* src_addr4;
795
  struct sockaddr_in6* src_addr6;
796

797
  mcast_addr4 = (struct sockaddr_in*)&mcast_addr;
798
  mcast_addr6 = (struct sockaddr_in6*)&mcast_addr;
799
  src_addr4 = (struct sockaddr_in*)&src_addr;
800
  src_addr6 = (struct sockaddr_in6*)&src_addr;
801

802
  err = uv_ip4_addr(multicast_addr, 0, mcast_addr4);
803
  if (err) {
804
    err = uv_ip6_addr(multicast_addr, 0, mcast_addr6);
805
    if (err)
806
      return err;
807
    err = uv_ip6_addr(source_addr, 0, src_addr6);
808
    if (err)
809
      return err;
810
    return uv__udp_set_source_membership6(handle,
811
                                          mcast_addr6,
812
                                          interface_addr,
813
                                          src_addr6,
814
                                          membership);
815
  }
816
  
817
  err = uv_ip4_addr(source_addr, 0, src_addr4);
818
  if (err)
819
    return err;
820
  return uv__udp_set_source_membership4(handle,
821
                                        mcast_addr4,
822
                                        interface_addr,
823
                                        src_addr4,
824
                                        membership);
825
}
826

827

828
int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
829
  struct sockaddr_storage addr_st;
830
  struct sockaddr_in* addr4;
831
  struct sockaddr_in6* addr6;
832

833
  addr4 = (struct sockaddr_in*) &addr_st;
834
  addr6 = (struct sockaddr_in6*) &addr_st;
835

836
  if (!interface_addr) {
837
    memset(&addr_st, 0, sizeof addr_st);
838
    if (handle->flags & UV_HANDLE_IPV6) {
839
      addr_st.ss_family = AF_INET6;
840
      addr6->sin6_scope_id = 0;
841
    } else {
842
      addr_st.ss_family = AF_INET;
843
      addr4->sin_addr.s_addr = htonl(INADDR_ANY);
844
    }
845
  } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) {
846
    /* nothing, address was parsed */
847
  } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {
848
    /* nothing, address was parsed */
849
  } else {
850
    return UV_EINVAL;
851
  }
852

853
  if (handle->socket == INVALID_SOCKET)
854
    return UV_EBADF;
855

856
  if (addr_st.ss_family == AF_INET) {
857
    if (setsockopt(handle->socket,
858
                   IPPROTO_IP,
859
                   IP_MULTICAST_IF,
860
                   (char*) &addr4->sin_addr,
861
                   sizeof(addr4->sin_addr)) == SOCKET_ERROR) {
862
      return uv_translate_sys_error(WSAGetLastError());
863
    }
864
  } else if (addr_st.ss_family == AF_INET6) {
865
    if (setsockopt(handle->socket,
866
                   IPPROTO_IPV6,
867
                   IPV6_MULTICAST_IF,
868
                   (char*) &addr6->sin6_scope_id,
869
                   sizeof(addr6->sin6_scope_id)) == SOCKET_ERROR) {
870
      return uv_translate_sys_error(WSAGetLastError());
871
    }
872
  } else {
873
    assert(0 && "unexpected address family");
874
    abort();
875
  }
876

877
  return 0;
878
}
879

880

881
int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
882
  BOOL optval = (BOOL) value;
883

884
  if (handle->socket == INVALID_SOCKET)
885
    return UV_EBADF;
886

887
  if (setsockopt(handle->socket,
888
                 SOL_SOCKET,
889
                 SO_BROADCAST,
890
                 (char*) &optval,
891
                 sizeof optval)) {
892
    return uv_translate_sys_error(WSAGetLastError());
893
  }
894

895
  return 0;
896
}
897

898

899
int uv__udp_is_bound(uv_udp_t* handle) {
900
  struct sockaddr_storage addr;
901
  int addrlen;
902

903
  addrlen = sizeof(addr);
904
  if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0)
905
    return 0;
906

907
  return addrlen > 0;
908
}
909

910

911
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
912
  WSAPROTOCOL_INFOW protocol_info;
913
  int opt_len;
914
  int err;
915

916
  /* Detect the address family of the socket. */
917
  opt_len = (int) sizeof protocol_info;
918
  if (getsockopt(sock,
919
                 SOL_SOCKET,
920
                 SO_PROTOCOL_INFOW,
921
                 (char*) &protocol_info,
922
                 &opt_len) == SOCKET_ERROR) {
923
    return uv_translate_sys_error(GetLastError());
924
  }
925

926
  err = uv__udp_set_socket(handle->loop,
927
                           handle,
928
                           sock,
929
                           protocol_info.iAddressFamily);
930
  if (err)
931
    return uv_translate_sys_error(err);
932

933
  if (uv__udp_is_bound(handle))
934
    handle->flags |= UV_HANDLE_BOUND;
935

936
  if (uv__udp_is_connected(handle))
937
    handle->flags |= UV_HANDLE_UDP_CONNECTED;
938

939
  return 0;
940
}
941

942

943
#define SOCKOPT_SETTER(name, option4, option6, validate)                      \
944
  int uv_udp_set_##name(uv_udp_t* handle, int value) {                        \
945
    DWORD optval = (DWORD) value;                                             \
946
                                                                              \
947
    if (!(validate(value))) {                                                 \
948
      return UV_EINVAL;                                                       \
949
    }                                                                         \
950
                                                                              \
951
    if (handle->socket == INVALID_SOCKET)                                     \
952
      return UV_EBADF;                                                        \
953
                                                                              \
954
    if (!(handle->flags & UV_HANDLE_IPV6)) {                                  \
955
      /* Set IPv4 socket option */                                            \
956
      if (setsockopt(handle->socket,                                          \
957
                     IPPROTO_IP,                                              \
958
                     option4,                                                 \
959
                     (char*) &optval,                                         \
960
                     sizeof optval)) {                                        \
961
        return uv_translate_sys_error(WSAGetLastError());                     \
962
      }                                                                       \
963
    } else {                                                                  \
964
      /* Set IPv6 socket option */                                            \
965
      if (setsockopt(handle->socket,                                          \
966
                     IPPROTO_IPV6,                                            \
967
                     option6,                                                 \
968
                     (char*) &optval,                                         \
969
                     sizeof optval)) {                                        \
970
        return uv_translate_sys_error(WSAGetLastError());                     \
971
      }                                                                       \
972
    }                                                                         \
973
    return 0;                                                                 \
974
  }
975

976
#define VALIDATE_TTL(value) ((value) >= 1 && (value) <= 255)
977
#define VALIDATE_MULTICAST_TTL(value) ((value) >= -1 && (value) <= 255)
978
#define VALIDATE_MULTICAST_LOOP(value) (1)
979

980
SOCKOPT_SETTER(ttl,
981
               IP_TTL,
982
               IPV6_HOPLIMIT,
983
               VALIDATE_TTL)
984
SOCKOPT_SETTER(multicast_ttl,
985
               IP_MULTICAST_TTL,
986
               IPV6_MULTICAST_HOPS,
987
               VALIDATE_MULTICAST_TTL)
988
SOCKOPT_SETTER(multicast_loop,
989
               IP_MULTICAST_LOOP,
990
               IPV6_MULTICAST_LOOP,
991
               VALIDATE_MULTICAST_LOOP)
992

993
#undef SOCKOPT_SETTER
994
#undef VALIDATE_TTL
995
#undef VALIDATE_MULTICAST_TTL
996
#undef VALIDATE_MULTICAST_LOOP
997

998

999
/* This function is an egress point, i.e. it returns libuv errors rather than
1000
 * system errors.
1001
 */
1002
int uv__udp_bind(uv_udp_t* handle,
1003
                 const struct sockaddr* addr,
1004
                 unsigned int addrlen,
1005
                 unsigned int flags) {
1006
  int err;
1007

1008
  err = uv__udp_maybe_bind(handle, addr, addrlen, flags);
1009
  if (err)
1010
    return uv_translate_sys_error(err);
1011

1012
  return 0;
1013
}
1014

1015

1016
int uv__udp_connect(uv_udp_t* handle,
1017
                    const struct sockaddr* addr,
1018
                    unsigned int addrlen) {
1019
  const struct sockaddr* bind_addr;
1020
  int err;
1021

1022
  if (!(handle->flags & UV_HANDLE_BOUND)) {
1023
    if (addrlen == sizeof(uv_addr_ip4_any_))
1024
      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
1025
    else if (addrlen == sizeof(uv_addr_ip6_any_))
1026
      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
1027
    else
1028
      return UV_EINVAL;
1029

1030
    err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
1031
    if (err)
1032
      return uv_translate_sys_error(err);
1033
  }
1034

1035
  err = connect(handle->socket, addr, addrlen);
1036
  if (err)
1037
    return uv_translate_sys_error(WSAGetLastError());
1038

1039
  handle->flags |= UV_HANDLE_UDP_CONNECTED;
1040

1041
  return 0;
1042
}
1043

1044

1045
int uv__udp_disconnect(uv_udp_t* handle) {
1046
    int err;
1047
    struct sockaddr_storage addr;
1048

1049
    memset(&addr, 0, sizeof(addr));
1050

1051
    err = connect(handle->socket, (struct sockaddr*) &addr, sizeof(addr));
1052
    if (err)
1053
      return uv_translate_sys_error(WSAGetLastError());
1054

1055
    handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
1056
    return 0;
1057
}
1058

1059

1060
/* This function is an egress point, i.e. it returns libuv errors rather than
1061
 * system errors.
1062
 */
1063
int uv__udp_send(uv_udp_send_t* req,
1064
                 uv_udp_t* handle,
1065
                 const uv_buf_t bufs[],
1066
                 unsigned int nbufs,
1067
                 const struct sockaddr* addr,
1068
                 unsigned int addrlen,
1069
                 uv_udp_send_cb send_cb) {
1070
  const struct sockaddr* bind_addr;
1071
  int err;
1072

1073
  if (!(handle->flags & UV_HANDLE_BOUND)) {
1074
    if (addrlen == sizeof(uv_addr_ip4_any_))
1075
      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
1076
    else if (addrlen == sizeof(uv_addr_ip6_any_))
1077
      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
1078
    else
1079
      return UV_EINVAL;
1080

1081
    err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
1082
    if (err)
1083
      return uv_translate_sys_error(err);
1084
  }
1085

1086
  err = uv__send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
1087
  if (err)
1088
    return uv_translate_sys_error(err);
1089

1090
  return 0;
1091
}
1092

1093

1094
int uv__udp_try_send(uv_udp_t* handle,
1095
                     const uv_buf_t bufs[],
1096
                     unsigned int nbufs,
1097
                     const struct sockaddr* addr,
1098
                     unsigned int addrlen) {
1099
  DWORD bytes;
1100
  const struct sockaddr* bind_addr;
1101
  struct sockaddr_storage converted;
1102
  int err;
1103

1104
  assert(nbufs > 0);
1105

1106
  if (addr != NULL) {
1107
    err = uv__convert_to_localhost_if_unspecified(addr, &converted);
1108
    if (err)
1109
      return err;
1110
    addr = (const struct sockaddr*) &converted;
1111
  }
1112

1113
  /* Already sending a message.*/
1114
  if (handle->send_queue_count != 0)
1115
    return UV_EAGAIN;
1116

1117
  if (!(handle->flags & UV_HANDLE_BOUND)) {
1118
    if (addrlen == sizeof(uv_addr_ip4_any_))
1119
      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
1120
    else if (addrlen == sizeof(uv_addr_ip6_any_))
1121
      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
1122
    else
1123
      return UV_EINVAL;
1124
    err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
1125
    if (err)
1126
      return uv_translate_sys_error(err);
1127
  }
1128

1129
  err = WSASendTo(handle->socket,
1130
                  (WSABUF*)bufs,
1131
                  nbufs,
1132
                  &bytes,
1133
                  0,
1134
                  addr,
1135
                  addrlen,
1136
                  NULL,
1137
                  NULL);
1138

1139
  if (err)
1140
    return uv_translate_sys_error(WSAGetLastError());
1141

1142
  return bytes;
1143
}
1144

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.