libuv-svace-build

Форк
0
/
test-udp-multicast-join6.c 
218 строк · 5.6 Кб
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 "task.h"
24

25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28

29

30
#define CHECK_HANDLE(handle) \
31
  ASSERT_NE((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client, 0)
32

33
#if defined(__APPLE__)          || \
34
    defined(_AIX)               || \
35
    defined(__MVS__)            || \
36
    defined(__NetBSD__)         || \
37
    defined(__OpenBSD__)
38
  #define MULTICAST_ADDR "ff02::1%lo0"
39
  #define INTERFACE_ADDR "::1%lo0"
40
#else
41
  #define MULTICAST_ADDR "ff02::1"
42
  #define INTERFACE_ADDR NULL
43
#endif
44

45
static uv_udp_t server;
46
static uv_udp_t client;
47
static uv_udp_send_t req;
48
static uv_udp_send_t req_ss;
49

50
static int cl_recv_cb_called;
51

52
static int sv_send_cb_called;
53

54
static int close_cb_called;
55

56
static void alloc_cb(uv_handle_t* handle,
57
                     size_t suggested_size,
58
                     uv_buf_t* buf) {
59
  static char slab[65536];
60
  CHECK_HANDLE(handle);
61
  ASSERT_LE(suggested_size, sizeof(slab));
62
  buf->base = slab;
63
  buf->len = sizeof(slab);
64
}
65

66

67
static void close_cb(uv_handle_t* handle) {
68
  CHECK_HANDLE(handle);
69
  close_cb_called++;
70
}
71

72

73
static void sv_send_cb(uv_udp_send_t* req, int status) {
74
  ASSERT_NOT_NULL(req);
75
  ASSERT_OK(status);
76
  CHECK_HANDLE(req->handle);
77

78
  sv_send_cb_called++;
79

80
  if (sv_send_cb_called == 2)
81
    uv_close((uv_handle_t*) req->handle, close_cb);
82
}
83

84

85
static int do_send(uv_udp_send_t* send_req) {
86
  uv_buf_t buf;
87
  struct sockaddr_in6 addr;
88
  
89
  buf = uv_buf_init("PING", 4);
90

91
  ASSERT_OK(uv_ip6_addr(MULTICAST_ADDR, TEST_PORT, &addr));
92

93
  /* client sends "PING" */
94
  return uv_udp_send(send_req,
95
                     &client,
96
                     &buf,
97
                     1,
98
                     (const struct sockaddr*) &addr,
99
                     sv_send_cb);
100
}
101

102

103
static void cl_recv_cb(uv_udp_t* handle,
104
                       ssize_t nread,
105
                       const uv_buf_t* buf,
106
                       const struct sockaddr* addr,
107
                       unsigned flags) {
108
  CHECK_HANDLE(handle);
109
  ASSERT_OK(flags);
110

111
  if (nread < 0) {
112
    ASSERT(0 && "unexpected error");
113
  }
114

115
  if (nread == 0) {
116
    /* Returning unused buffer. Don't count towards cl_recv_cb_called */
117
    ASSERT_NULL(addr);
118
    return;
119
  }
120

121
  ASSERT_NOT_NULL(addr);
122
  ASSERT_EQ(4, nread);
123
  ASSERT(!memcmp("PING", buf->base, nread));
124

125
  cl_recv_cb_called++;
126

127
  if (cl_recv_cb_called == 2) {
128
    /* we are done with the server handle, we can close it */
129
    uv_close((uv_handle_t*) &server, close_cb);
130
  } else {
131
    int r;
132
    char source_addr[64];
133

134
    r = uv_ip6_name((const struct sockaddr_in6*)addr, source_addr, sizeof(source_addr));
135
    ASSERT_OK(r);
136

137
    r = uv_udp_set_membership(&server, MULTICAST_ADDR, INTERFACE_ADDR, UV_LEAVE_GROUP);
138
    ASSERT_OK(r);
139

140
    r = uv_udp_set_source_membership(&server, MULTICAST_ADDR, INTERFACE_ADDR, source_addr, UV_JOIN_GROUP);
141
    ASSERT_OK(r);
142

143
    r = do_send(&req_ss);
144
    ASSERT_OK(r);
145
  }
146
}
147

148

149
static int can_ipv6_external(void) {
150
  uv_interface_address_t* addr;
151
  int supported;
152
  int count;
153
  int i;
154

155
  if (uv_interface_addresses(&addr, &count))
156
    return 0;  /* Assume no IPv6 support on failure. */
157

158
  supported = 0;
159
  for (i = 0; supported == 0 && i < count; i += 1)
160
    supported = (AF_INET6 == addr[i].address.address6.sin6_family &&
161
                 !addr[i].is_internal);
162

163
  uv_free_interface_addresses(addr, count);
164
  return supported;
165
}
166

167

168
TEST_IMPL(udp_multicast_join6) {
169
  int r;
170
  struct sockaddr_in6 addr;
171

172
  if (!can_ipv6_external())
173
    RETURN_SKIP("No external IPv6 interface available");
174

175
  ASSERT_OK(uv_ip6_addr("::", TEST_PORT, &addr));
176

177
  r = uv_udp_init(uv_default_loop(), &server);
178
  ASSERT_OK(r);
179

180
  r = uv_udp_init(uv_default_loop(), &client);
181
  ASSERT_OK(r);
182

183
  /* bind to the desired port */
184
  r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0);
185
  ASSERT_OK(r);
186

187
  r = uv_udp_set_membership(&server, MULTICAST_ADDR, INTERFACE_ADDR, UV_JOIN_GROUP);
188
  if (r == UV_ENODEV) {
189
    MAKE_VALGRIND_HAPPY(uv_default_loop());
190
    RETURN_SKIP("No ipv6 multicast route");
191
  }
192

193
  ASSERT_OK(r);
194

195
/* TODO(gengjiawen): Fix test on QEMU. */
196
#if defined(__QEMU__)
197
  RETURN_SKIP("Test does not currently work in QEMU");
198
#endif
199
  r = uv_udp_recv_start(&server, alloc_cb, cl_recv_cb);
200
  ASSERT_OK(r);
201
  
202
  r = do_send(&req);
203
  ASSERT_OK(r);
204

205
  ASSERT_OK(close_cb_called);
206
  ASSERT_OK(cl_recv_cb_called);
207
  ASSERT_OK(sv_send_cb_called);
208

209
  /* run the loop till all events are processed */
210
  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
211

212
  ASSERT_EQ(2, cl_recv_cb_called);
213
  ASSERT_EQ(2, sv_send_cb_called);
214
  ASSERT_EQ(2, close_cb_called);
215

216
  MAKE_VALGRIND_HAPPY(uv_default_loop());
217
  return 0;
218
}
219

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

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

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

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