10e552da7Schristos /* Copyright (c) 2015 Saúl Ibarra Corretgé <saghul@gmail.com>.
20e552da7Schristos * All rights reserved.
30e552da7Schristos *
40e552da7Schristos * Permission is hereby granted, free of charge, to any person obtaining a copy
50e552da7Schristos * of this software and associated documentation files (the "Software"), to
60e552da7Schristos * deal in the Software without restriction, including without limitation the
70e552da7Schristos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
80e552da7Schristos * sell copies of the Software, and to permit persons to whom the Software is
90e552da7Schristos * furnished to do so, subject to the following conditions:
100e552da7Schristos *
110e552da7Schristos * The above copyright notice and this permission notice shall be included in
120e552da7Schristos * all copies or substantial portions of the Software.
130e552da7Schristos *
140e552da7Schristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
150e552da7Schristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
160e552da7Schristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
170e552da7Schristos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
180e552da7Schristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
190e552da7Schristos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
200e552da7Schristos * IN THE SOFTWARE.
210e552da7Schristos */
220e552da7Schristos
230e552da7Schristos #include "uv.h"
240e552da7Schristos #include "task.h"
250e552da7Schristos #include <string.h>
260e552da7Schristos
270e552da7Schristos #ifdef _WIN32
280e552da7Schristos # define INVALID_FD (INVALID_HANDLE_VALUE)
290e552da7Schristos #else
300e552da7Schristos # define INVALID_FD (-1)
310e552da7Schristos #endif
320e552da7Schristos
330e552da7Schristos
on_connect(uv_connect_t * req,int status)340e552da7Schristos static void on_connect(uv_connect_t* req, int status) {
350e552da7Schristos ASSERT(status == 0);
360e552da7Schristos uv_close((uv_handle_t*) req->handle, NULL);
370e552da7Schristos }
380e552da7Schristos
390e552da7Schristos
on_connection(uv_stream_t * server,int status)400e552da7Schristos static void on_connection(uv_stream_t* server, int status) {
410e552da7Schristos uv_tcp_t* handle;
420e552da7Schristos int r;
430e552da7Schristos
440e552da7Schristos ASSERT(status == 0);
450e552da7Schristos
460e552da7Schristos handle = malloc(sizeof(*handle));
47*5f2f4271Schristos ASSERT_NOT_NULL(handle);
480e552da7Schristos
490e552da7Schristos r = uv_tcp_init_ex(server->loop, handle, AF_INET);
500e552da7Schristos ASSERT(r == 0);
510e552da7Schristos
520e552da7Schristos r = uv_accept(server, (uv_stream_t*)handle);
530e552da7Schristos ASSERT(r == UV_EBUSY);
540e552da7Schristos
550e552da7Schristos uv_close((uv_handle_t*) server, NULL);
560e552da7Schristos uv_close((uv_handle_t*) handle, (uv_close_cb)free);
570e552da7Schristos }
580e552da7Schristos
590e552da7Schristos
tcp_listener(uv_loop_t * loop,uv_tcp_t * server)600e552da7Schristos static void tcp_listener(uv_loop_t* loop, uv_tcp_t* server) {
610e552da7Schristos struct sockaddr_in addr;
620e552da7Schristos int r;
630e552da7Schristos
640e552da7Schristos ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
650e552da7Schristos
660e552da7Schristos r = uv_tcp_init(loop, server);
670e552da7Schristos ASSERT(r == 0);
680e552da7Schristos
690e552da7Schristos r = uv_tcp_bind(server, (const struct sockaddr*) &addr, 0);
700e552da7Schristos ASSERT(r == 0);
710e552da7Schristos
720e552da7Schristos r = uv_listen((uv_stream_t*) server, 128, on_connection);
730e552da7Schristos ASSERT(r == 0);
740e552da7Schristos }
750e552da7Schristos
760e552da7Schristos
tcp_connector(uv_loop_t * loop,uv_tcp_t * client,uv_connect_t * req)770e552da7Schristos static void tcp_connector(uv_loop_t* loop, uv_tcp_t* client, uv_connect_t* req) {
780e552da7Schristos struct sockaddr_in server_addr;
790e552da7Schristos int r;
800e552da7Schristos
810e552da7Schristos ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr));
820e552da7Schristos
830e552da7Schristos r = uv_tcp_init(loop, client);
840e552da7Schristos ASSERT(r == 0);
850e552da7Schristos
860e552da7Schristos r = uv_tcp_connect(req,
870e552da7Schristos client,
880e552da7Schristos (const struct sockaddr*) &server_addr,
890e552da7Schristos on_connect);
900e552da7Schristos ASSERT(r == 0);
910e552da7Schristos }
920e552da7Schristos
930e552da7Schristos
TEST_IMPL(tcp_create_early)940e552da7Schristos TEST_IMPL(tcp_create_early) {
950e552da7Schristos struct sockaddr_in addr;
960e552da7Schristos struct sockaddr_in sockname;
970e552da7Schristos uv_tcp_t client;
980e552da7Schristos uv_os_fd_t fd;
990e552da7Schristos int r, namelen;
1000e552da7Schristos
1010e552da7Schristos ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
1020e552da7Schristos
1030e552da7Schristos r = uv_tcp_init_ex(uv_default_loop(), &client, AF_INET);
1040e552da7Schristos ASSERT(r == 0);
1050e552da7Schristos
1060e552da7Schristos r = uv_fileno((const uv_handle_t*) &client, &fd);
1070e552da7Schristos ASSERT(r == 0);
1080e552da7Schristos ASSERT(fd != INVALID_FD);
1090e552da7Schristos
1100e552da7Schristos /* Windows returns WSAEINVAL if the socket is not bound */
1110e552da7Schristos #ifndef _WIN32
1120e552da7Schristos namelen = sizeof sockname;
1130e552da7Schristos r = uv_tcp_getsockname(&client, (struct sockaddr*) &sockname, &namelen);
1140e552da7Schristos ASSERT(r == 0);
1150e552da7Schristos ASSERT(sockname.sin_family == AF_INET);
1160e552da7Schristos #endif
1170e552da7Schristos
1180e552da7Schristos r = uv_tcp_bind(&client, (const struct sockaddr*) &addr, 0);
1190e552da7Schristos ASSERT(r == 0);
1200e552da7Schristos
1210e552da7Schristos namelen = sizeof sockname;
1220e552da7Schristos r = uv_tcp_getsockname(&client, (struct sockaddr*) &sockname, &namelen);
1230e552da7Schristos ASSERT(r == 0);
1240e552da7Schristos ASSERT(memcmp(&addr.sin_addr,
1250e552da7Schristos &sockname.sin_addr,
1260e552da7Schristos sizeof(addr.sin_addr)) == 0);
1270e552da7Schristos
1280e552da7Schristos uv_close((uv_handle_t*) &client, NULL);
1290e552da7Schristos uv_run(uv_default_loop(), UV_RUN_DEFAULT);
1300e552da7Schristos
1310e552da7Schristos MAKE_VALGRIND_HAPPY();
1320e552da7Schristos return 0;
1330e552da7Schristos }
1340e552da7Schristos
1350e552da7Schristos
TEST_IMPL(tcp_create_early_bad_bind)1360e552da7Schristos TEST_IMPL(tcp_create_early_bad_bind) {
1370e552da7Schristos struct sockaddr_in addr;
1380e552da7Schristos uv_tcp_t client;
1390e552da7Schristos uv_os_fd_t fd;
1400e552da7Schristos int r;
1410e552da7Schristos
1420e552da7Schristos if (!can_ipv6())
1430e552da7Schristos RETURN_SKIP("IPv6 not supported");
1440e552da7Schristos
1450e552da7Schristos ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
1460e552da7Schristos
1470e552da7Schristos r = uv_tcp_init_ex(uv_default_loop(), &client, AF_INET6);
1480e552da7Schristos ASSERT(r == 0);
1490e552da7Schristos
1500e552da7Schristos r = uv_fileno((const uv_handle_t*) &client, &fd);
1510e552da7Schristos ASSERT(r == 0);
1520e552da7Schristos ASSERT(fd != INVALID_FD);
1530e552da7Schristos
1540e552da7Schristos /* Windows returns WSAEINVAL if the socket is not bound */
1550e552da7Schristos #ifndef _WIN32
1560e552da7Schristos {
1570e552da7Schristos int namelen;
1580e552da7Schristos struct sockaddr_in6 sockname;
1590e552da7Schristos namelen = sizeof sockname;
1600e552da7Schristos r = uv_tcp_getsockname(&client, (struct sockaddr*) &sockname, &namelen);
1610e552da7Schristos ASSERT(r == 0);
1620e552da7Schristos ASSERT(sockname.sin6_family == AF_INET6);
1630e552da7Schristos }
1640e552da7Schristos #endif
1650e552da7Schristos
1660e552da7Schristos r = uv_tcp_bind(&client, (const struct sockaddr*) &addr, 0);
1670e552da7Schristos #if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MSYS__)
1680e552da7Schristos ASSERT(r == UV_EINVAL);
1690e552da7Schristos #else
1700e552da7Schristos ASSERT(r == UV_EFAULT);
1710e552da7Schristos #endif
1720e552da7Schristos
1730e552da7Schristos uv_close((uv_handle_t*) &client, NULL);
1740e552da7Schristos uv_run(uv_default_loop(), UV_RUN_DEFAULT);
1750e552da7Schristos
1760e552da7Schristos MAKE_VALGRIND_HAPPY();
1770e552da7Schristos return 0;
1780e552da7Schristos }
1790e552da7Schristos
1800e552da7Schristos
TEST_IMPL(tcp_create_early_bad_domain)1810e552da7Schristos TEST_IMPL(tcp_create_early_bad_domain) {
1820e552da7Schristos uv_tcp_t client;
1830e552da7Schristos int r;
1840e552da7Schristos
1850e552da7Schristos r = uv_tcp_init_ex(uv_default_loop(), &client, 47);
1860e552da7Schristos ASSERT(r == UV_EINVAL);
1870e552da7Schristos
1880e552da7Schristos r = uv_tcp_init_ex(uv_default_loop(), &client, 1024);
1890e552da7Schristos ASSERT(r == UV_EINVAL);
1900e552da7Schristos
1910e552da7Schristos uv_run(uv_default_loop(), UV_RUN_DEFAULT);
1920e552da7Schristos
1930e552da7Schristos MAKE_VALGRIND_HAPPY();
1940e552da7Schristos return 0;
1950e552da7Schristos }
1960e552da7Schristos
1970e552da7Schristos
TEST_IMPL(tcp_create_early_accept)1980e552da7Schristos TEST_IMPL(tcp_create_early_accept) {
1990e552da7Schristos uv_tcp_t client, server;
2000e552da7Schristos uv_connect_t connect_req;
2010e552da7Schristos
2020e552da7Schristos tcp_listener(uv_default_loop(), &server);
2030e552da7Schristos tcp_connector(uv_default_loop(), &client, &connect_req);
2040e552da7Schristos
2050e552da7Schristos uv_run(uv_default_loop(), UV_RUN_DEFAULT);
2060e552da7Schristos
2070e552da7Schristos MAKE_VALGRIND_HAPPY();
2080e552da7Schristos return 0;
2090e552da7Schristos }
210