libuv-svace-build
196 строк · 5.7 Кб
1/* Copyright libuv project and 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#define CHECK_HANDLE(handle) \30ASSERT_NE((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client, 0)31
32static uv_udp_t server;33static uv_udp_t client;34static uv_buf_t buf;35static struct sockaddr_in lo_addr;36
37static int cl_send_cb_called;38static int sv_recv_cb_called;39
40static int close_cb_called;41
42
43static void alloc_cb(uv_handle_t* handle,44size_t suggested_size,45uv_buf_t* buf) {46static char slab[65536];47CHECK_HANDLE(handle);48ASSERT_LE(suggested_size, sizeof(slab));49buf->base = slab;50buf->len = sizeof(slab);51}
52
53
54static void close_cb(uv_handle_t* handle) {55CHECK_HANDLE(handle);56ASSERT(uv_is_closing(handle));57close_cb_called++;58}
59
60
61static void cl_send_cb(uv_udp_send_t* req, int status) {62int r;63
64ASSERT_NOT_NULL(req);65ASSERT_OK(status);66CHECK_HANDLE(req->handle);67if (++cl_send_cb_called == 1) {68uv_udp_connect(&client, NULL);69r = uv_udp_send(req, &client, &buf, 1, NULL, cl_send_cb);70ASSERT_EQ(r, UV_EDESTADDRREQ);71r = uv_udp_send(req,72&client,73&buf,741,75(const struct sockaddr*) &lo_addr,76cl_send_cb);77ASSERT_OK(r);78}79
80}
81
82
83static void sv_recv_cb(uv_udp_t* handle,84ssize_t nread,85const uv_buf_t* rcvbuf,86const struct sockaddr* addr,87unsigned flags) {88if (nread > 0) {89ASSERT_EQ(4, nread);90ASSERT_NOT_NULL(addr);91ASSERT_OK(memcmp("EXIT", rcvbuf->base, nread));92if (++sv_recv_cb_called == 4) {93uv_close((uv_handle_t*) &server, close_cb);94uv_close((uv_handle_t*) &client, close_cb);95}96}97}
98
99
100TEST_IMPL(udp_connect) {101#if defined(__OpenBSD__)102RETURN_SKIP("Test does not currently work in OpenBSD");103#endif104uv_udp_send_t req;105struct sockaddr_in ext_addr;106struct sockaddr_in tmp_addr;107int r;108int addrlen;109
110ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &lo_addr));111
112r = uv_udp_init(uv_default_loop(), &server);113ASSERT_OK(r);114
115r = uv_udp_bind(&server, (const struct sockaddr*) &lo_addr, 0);116ASSERT_OK(r);117
118r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb);119ASSERT_OK(r);120
121r = uv_udp_init(uv_default_loop(), &client);122ASSERT_OK(r);123
124buf = uv_buf_init("EXIT", 4);125
126/* connect() to INADDR_ANY fails on Windows with WSAEADDRNOTAVAIL */127ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &tmp_addr));128r = uv_udp_connect(&client, (const struct sockaddr*) &tmp_addr);129#ifdef _WIN32130ASSERT_EQ(r, UV_EADDRNOTAVAIL);131#else132ASSERT_OK(r);133r = uv_udp_connect(&client, NULL);134ASSERT_OK(r);135#endif136
137ASSERT_OK(uv_ip4_addr("8.8.8.8", TEST_PORT, &ext_addr));138ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &lo_addr));139
140r = uv_udp_connect(&client, (const struct sockaddr*) &lo_addr);141ASSERT_OK(r);142r = uv_udp_connect(&client, (const struct sockaddr*) &ext_addr);143ASSERT_EQ(r, UV_EISCONN);144
145addrlen = sizeof(tmp_addr);146r = uv_udp_getpeername(&client, (struct sockaddr*) &tmp_addr, &addrlen);147ASSERT_OK(r);148
149/* To send messages in connected UDP sockets addr must be NULL */150r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &lo_addr);151ASSERT_EQ(r, UV_EISCONN);152r = uv_udp_try_send(&client, &buf, 1, NULL);153ASSERT_EQ(4, r);154r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &ext_addr);155ASSERT_EQ(r, UV_EISCONN);156
157r = uv_udp_connect(&client, NULL);158ASSERT_OK(r);159r = uv_udp_connect(&client, NULL);160ASSERT_EQ(r, UV_ENOTCONN);161
162addrlen = sizeof(tmp_addr);163r = uv_udp_getpeername(&client, (struct sockaddr*) &tmp_addr, &addrlen);164ASSERT_EQ(r, UV_ENOTCONN);165
166/* To send messages in disconnected UDP sockets addr must be set */167r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &lo_addr);168ASSERT_EQ(4, r);169r = uv_udp_try_send(&client, &buf, 1, NULL);170ASSERT_EQ(r, UV_EDESTADDRREQ);171
172
173r = uv_udp_connect(&client, (const struct sockaddr*) &lo_addr);174ASSERT_OK(r);175r = uv_udp_send(&req,176&client,177&buf,1781,179(const struct sockaddr*) &lo_addr,180cl_send_cb);181ASSERT_EQ(r, UV_EISCONN);182r = uv_udp_send(&req, &client, &buf, 1, NULL, cl_send_cb);183ASSERT_OK(r);184
185uv_run(uv_default_loop(), UV_RUN_DEFAULT);186
187ASSERT_EQ(2, close_cb_called);188ASSERT_EQ(4, sv_recv_cb_called);189ASSERT_EQ(2, cl_send_cb_called);190
191ASSERT_OK(client.send_queue_size);192ASSERT_OK(server.send_queue_size);193
194MAKE_VALGRIND_HAPPY(uv_default_loop());195return 0;196}
197