libuv-svace-build

Форк
0
/
test-tcp-bind-error.c 
317 строк · 8.4 Кб
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
#include <stdio.h>
25
#include <stdlib.h>
26

27

28
static int connect_cb_called = 0;
29
static int close_cb_called = 0;
30

31

32
static void close_cb(uv_handle_t* handle) {
33
  ASSERT_NOT_NULL(handle);
34
  close_cb_called++;
35
}
36

37

38
static void connect_cb(uv_connect_t* req, int status) {
39
  ASSERT_EQ(status, UV_EADDRINUSE);
40
  uv_close((uv_handle_t*) req->handle, close_cb);
41
  connect_cb_called++;
42
}
43

44

45
TEST_IMPL(tcp_bind_error_addrinuse_connect) {
46
  struct sockaddr_in addr;
47
  int addrlen;
48
  uv_connect_t req;
49
  uv_tcp_t conn;
50

51
  /* 127.0.0.1:<TEST_PORT> is already taken by tcp4_echo_server running in
52
   * another process. uv_tcp_bind() and uv_tcp_connect() should still succeed
53
   * (greatest common denominator across platforms) but the connect callback
54
   * should receive an UV_EADDRINUSE error.
55
   */
56
  ASSERT_OK(uv_tcp_init(uv_default_loop(), &conn));
57
  ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
58
  ASSERT_OK(uv_tcp_bind(&conn, (const struct sockaddr*) &addr, 0));
59

60
  ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT + 1, &addr));
61
  ASSERT_OK(uv_tcp_connect(&req,
62
                           &conn,
63
                           (const struct sockaddr*) &addr,
64
                           connect_cb));
65

66
  addrlen = sizeof(addr);
67
  ASSERT_EQ(UV_EADDRINUSE, uv_tcp_getsockname(&conn,
68
                                              (struct sockaddr*) &addr,
69
                                              &addrlen));
70

71
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
72
  ASSERT_EQ(1, connect_cb_called);
73
  ASSERT_EQ(1, close_cb_called);
74

75
  MAKE_VALGRIND_HAPPY(uv_default_loop());
76
  return 0;
77
}
78

79

80
TEST_IMPL(tcp_bind_error_addrinuse_listen) {
81
  struct sockaddr_in addr;
82
  uv_tcp_t server1, server2;
83
  int r;
84

85
  ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
86
  r = uv_tcp_init(uv_default_loop(), &server1);
87
  ASSERT_OK(r);
88
  r = uv_tcp_bind(&server1, (const struct sockaddr*) &addr, 0);
89
  ASSERT_OK(r);
90

91
  r = uv_tcp_init(uv_default_loop(), &server2);
92
  ASSERT_OK(r);
93
  r = uv_tcp_bind(&server2, (const struct sockaddr*) &addr, 0);
94
  ASSERT_OK(r);
95

96
  r = uv_listen((uv_stream_t*)&server1, 128, NULL);
97
  ASSERT_OK(r);
98
  r = uv_listen((uv_stream_t*)&server2, 128, NULL);
99
  ASSERT_EQ(r, UV_EADDRINUSE);
100

101
  uv_close((uv_handle_t*)&server1, close_cb);
102
  uv_close((uv_handle_t*)&server2, close_cb);
103

104
  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
105

106
  ASSERT_EQ(2, close_cb_called);
107

108
  MAKE_VALGRIND_HAPPY(uv_default_loop());
109
  return 0;
110
}
111

112

113
TEST_IMPL(tcp_bind_error_addrnotavail_1) {
114
  struct sockaddr_in addr;
115
  uv_tcp_t server;
116
  int r;
117

118
  ASSERT_OK(uv_ip4_addr("127.255.255.255", TEST_PORT, &addr));
119

120
  r = uv_tcp_init(uv_default_loop(), &server);
121
  ASSERT_OK(r);
122

123
  /* It seems that Linux is broken here - bind succeeds. */
124
  r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
125
  ASSERT(r == 0 || r == UV_EADDRNOTAVAIL);
126

127
  uv_close((uv_handle_t*)&server, close_cb);
128

129
  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
130

131
  ASSERT_EQ(1, close_cb_called);
132

133
  MAKE_VALGRIND_HAPPY(uv_default_loop());
134
  return 0;
135
}
136

137

138
TEST_IMPL(tcp_bind_error_addrnotavail_2) {
139
  struct sockaddr_in addr;
140
  uv_tcp_t server;
141
  int r;
142

143
  ASSERT_OK(uv_ip4_addr("4.4.4.4", TEST_PORT, &addr));
144

145
  r = uv_tcp_init(uv_default_loop(), &server);
146
  ASSERT_OK(r);
147
  r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
148
  ASSERT_EQ(r, UV_EADDRNOTAVAIL);
149

150
  uv_close((uv_handle_t*)&server, close_cb);
151

152
  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
153

154
  ASSERT_EQ(1, close_cb_called);
155

156
  MAKE_VALGRIND_HAPPY(uv_default_loop());
157
  return 0;
158
}
159

160

161
TEST_IMPL(tcp_bind_error_fault) {
162
  char garbage[] =
163
      "blah blah blah blah blah blah blah blah blah blah blah blah";
164
  struct sockaddr_in* garbage_addr;
165
  uv_tcp_t server;
166
  int r;
167

168
  garbage_addr = (struct sockaddr_in*) &garbage;
169

170
  r = uv_tcp_init(uv_default_loop(), &server);
171
  ASSERT_OK(r);
172
  r = uv_tcp_bind(&server, (const struct sockaddr*) garbage_addr, 0);
173
  ASSERT_EQ(r, UV_EINVAL);
174

175
  uv_close((uv_handle_t*)&server, close_cb);
176

177
  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
178

179
  ASSERT_EQ(1, close_cb_called);
180

181
  MAKE_VALGRIND_HAPPY(uv_default_loop());
182
  return 0;
183
}
184

185
/* Notes: On Linux uv_bind(server, NULL) will segfault the program.  */
186

187
TEST_IMPL(tcp_bind_error_inval) {
188
  struct sockaddr_in addr1;
189
  struct sockaddr_in addr2;
190
  uv_tcp_t server;
191
  int r;
192

193
  ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr1));
194
  ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT_2, &addr2));
195

196
  r = uv_tcp_init(uv_default_loop(), &server);
197
  ASSERT_OK(r);
198
  r = uv_tcp_bind(&server, (const struct sockaddr*) &addr1, 0);
199
  ASSERT_OK(r);
200
  r = uv_tcp_bind(&server, (const struct sockaddr*) &addr2, 0);
201
  ASSERT_EQ(r, UV_EINVAL);
202

203
  uv_close((uv_handle_t*)&server, close_cb);
204

205
  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
206

207
  ASSERT_EQ(1, close_cb_called);
208

209
  MAKE_VALGRIND_HAPPY(uv_default_loop());
210
  return 0;
211
}
212

213

214
TEST_IMPL(tcp_bind_localhost_ok) {
215
  struct sockaddr_in addr;
216
  uv_tcp_t server;
217
  int r;
218

219
  ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
220

221
  r = uv_tcp_init(uv_default_loop(), &server);
222
  ASSERT_OK(r);
223
  r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
224
  ASSERT_OK(r);
225

226
  MAKE_VALGRIND_HAPPY(uv_default_loop());
227
  return 0;
228
}
229

230

231
TEST_IMPL(tcp_bind_invalid_flags) {
232
  struct sockaddr_in addr;
233
  uv_tcp_t server;
234
  int r;
235

236
  ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
237

238
  r = uv_tcp_init(uv_default_loop(), &server);
239
  ASSERT_OK(r);
240
  r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, UV_TCP_IPV6ONLY);
241
  ASSERT_EQ(r, UV_EINVAL);
242

243
  MAKE_VALGRIND_HAPPY(uv_default_loop());
244
  return 0;
245
}
246

247

248
TEST_IMPL(tcp_listen_without_bind) {
249
  int r;
250
  uv_tcp_t server;
251

252
  r = uv_tcp_init(uv_default_loop(), &server);
253
  ASSERT_OK(r);
254
  r = uv_listen((uv_stream_t*)&server, 128, NULL);
255
  ASSERT_OK(r);
256

257
  MAKE_VALGRIND_HAPPY(uv_default_loop());
258
  return 0;
259
}
260

261

262
TEST_IMPL(tcp_bind_writable_flags) {
263
  struct sockaddr_in addr;
264
  uv_tcp_t server;
265
  uv_buf_t buf;
266
  uv_write_t write_req;
267
  uv_shutdown_t shutdown_req;
268
  int r;
269

270
  ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
271
  r = uv_tcp_init(uv_default_loop(), &server);
272
  ASSERT_OK(r);
273
  r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
274
  ASSERT_OK(r);
275
  r = uv_listen((uv_stream_t*)&server, 128, NULL);
276
  ASSERT_OK(r);
277

278
  ASSERT_OK(uv_is_writable((uv_stream_t*) &server));
279
  ASSERT_OK(uv_is_readable((uv_stream_t*) &server));
280

281
  buf = uv_buf_init("PING", 4);
282
  r = uv_write(&write_req, (uv_stream_t*) &server, &buf, 1, NULL);
283
  ASSERT_EQ(r, UV_EPIPE);
284
  r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL);
285
  ASSERT_EQ(r, UV_ENOTCONN);
286
  r = uv_read_start((uv_stream_t*) &server,
287
                    (uv_alloc_cb) abort,
288
                    (uv_read_cb) abort);
289
  ASSERT_EQ(r, UV_ENOTCONN);
290

291
  uv_close((uv_handle_t*)&server, close_cb);
292

293
  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
294

295
  ASSERT_EQ(1, close_cb_called);
296

297
  MAKE_VALGRIND_HAPPY(uv_default_loop());
298
  return 0;
299
}
300

301
TEST_IMPL(tcp_bind_or_listen_error_after_close) {
302
  uv_tcp_t tcp;
303
  struct sockaddr_in addr;
304

305
  memset(&addr, 0, sizeof(addr));
306
  addr.sin_addr.s_addr = htonl(INADDR_ANY);
307
  addr.sin_port = htons(9999);
308
  addr.sin_family = AF_INET;
309

310
  ASSERT_OK(uv_tcp_init(uv_default_loop(), &tcp));
311
  uv_close((uv_handle_t*) &tcp, NULL);
312
  ASSERT_EQ(uv_tcp_bind(&tcp, (struct sockaddr*) &addr, 0), UV_EINVAL);
313
  ASSERT_EQ(uv_listen((uv_stream_t*) &tcp, 5, NULL), UV_EINVAL);
314
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
315
  MAKE_VALGRIND_HAPPY(uv_default_loop());
316
  return 0;
317
}
318

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

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

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

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