include: uv_tcp_connect{6} now takes sockaddr_in*

Passing or returning structs as values makes life hard for people that
work with libuv through a foreign function interface. Switch to a
pointer-based approach.

Fixes #684.
This commit is contained in:
Ben Noordhuis 2013-08-31 05:24:30 +02:00
parent daa229ace3
commit 255671da74
32 changed files with 119 additions and 147 deletions

View File

@ -773,10 +773,15 @@ UV_EXTERN int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name,
* initialized TCP handle and an uninitialized uv_connect_t*. The callback
* will be made when the connection is established.
*/
UV_EXTERN int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle,
struct sockaddr_in address, uv_connect_cb cb);
UV_EXTERN int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle,
struct sockaddr_in6 address, uv_connect_cb cb);
UV_EXTERN int uv_tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
const struct sockaddr_in* addr,
uv_connect_cb cb);
UV_EXTERN int uv_tcp_connect6(uv_connect_t* req,
uv_tcp_t* handle,
const struct sockaddr_in6* addr,
uv_connect_cb cb);
/* uv_connect_t is a subclass of uv_req_t */
struct uv_connect_s {

View File

@ -81,11 +81,11 @@ int uv__tcp_bind(uv_tcp_t* tcp,
}
static int uv__connect(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr* addr,
socklen_t addrlen,
uv_connect_cb cb) {
int uv__tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
const struct sockaddr* addr,
unsigned int addrlen,
uv_connect_cb cb) {
int err;
int r;
@ -217,22 +217,6 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
}
int uv__tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in addr,
uv_connect_cb cb) {
return uv__connect(req, handle, (struct sockaddr*) &addr, sizeof addr, cb);
}
int uv__tcp_connect6(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in6 addr,
uv_connect_cb cb) {
return uv__connect(req, handle, (struct sockaddr*) &addr, sizeof addr, cb);
}
int uv__tcp_nodelay(int fd, int on) {
return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
}

View File

@ -222,23 +222,31 @@ int uv_udp_bind6(uv_udp_t* handle,
int uv_tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in address,
const struct sockaddr_in* addr,
uv_connect_cb cb) {
if (handle->type != UV_TCP || address.sin_family != AF_INET)
return UV_EINVAL;
else
return uv__tcp_connect(req, handle, address, cb);
if (handle->type == UV_TCP && addr->sin_family == AF_INET) {
return uv__tcp_connect(req,
handle,
(const struct sockaddr*) addr,
sizeof(*addr),
cb);
}
return UV_EINVAL;
}
int uv_tcp_connect6(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in6 address,
const struct sockaddr_in6* addr,
uv_connect_cb cb) {
if (handle->type != UV_TCP || address.sin6_family != AF_INET6)
return UV_EINVAL;
else
return uv__tcp_connect6(req, handle, address, cb);
if (handle->type == UV_TCP && addr->sin6_family == AF_INET6) {
return uv__tcp_connect(req,
handle,
(const struct sockaddr*) addr,
sizeof(*addr),
cb);
}
return UV_EINVAL;
}

View File

@ -68,14 +68,10 @@ int uv__udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags);
int uv__tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in address,
const struct sockaddr* addr,
unsigned int addrlen,
uv_connect_cb cb);
int uv__tcp_connect6(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in6 address,
uv_connect_cb cb);
int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],

View File

@ -662,12 +662,13 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
}
int uv__tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in address,
uv_connect_cb cb) {
static int uv_tcp_try_connect(uv_connect_t* req,
uv_tcp_t* handle,
const struct sockaddr* addr,
unsigned int addrlen,
uv_connect_cb cb) {
uv_loop_t* loop = handle->loop;
int addrsize = sizeof(struct sockaddr_in);
const struct sockaddr* bind_addr;
BOOL success;
DWORD bytes;
int err;
@ -677,9 +678,14 @@ int uv__tcp_connect(uv_connect_t* req,
}
if (!(handle->flags & UV_HANDLE_BOUND)) {
err = uv_tcp_try_bind(handle,
(const struct sockaddr*) &uv_addr_ip4_any_,
sizeof(uv_addr_ip4_any_));
if (addrlen == sizeof(uv_addr_ip4_any_)) {
bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
} else if (addrlen == sizeof(uv_addr_ip6_any_)) {
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
} else {
abort();
}
err = uv_tcp_try_bind(handle, bind_addr, addrlen);
if (err)
return err;
}
@ -697,8 +703,8 @@ int uv__tcp_connect(uv_connect_t* req,
memset(&req->overlapped, 0, sizeof(req->overlapped));
success = handle->func_connectex(handle->socket,
(struct sockaddr*) &address,
addrsize,
addr,
addrlen,
NULL,
0,
&bytes,
@ -721,63 +727,6 @@ int uv__tcp_connect(uv_connect_t* req,
}
int uv__tcp_connect6(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in6 address,
uv_connect_cb cb) {
uv_loop_t* loop = handle->loop;
int addrsize = sizeof(struct sockaddr_in6);
BOOL success;
DWORD bytes;
int err;
if (handle->flags & UV_HANDLE_BIND_ERROR) {
return handle->bind_error;
}
if (!(handle->flags & UV_HANDLE_BOUND)) {
err = uv_tcp_try_bind(handle,
(const struct sockaddr*) &uv_addr_ip6_any_,
sizeof(uv_addr_ip6_any_));
if (err)
return err;
}
if (!handle->func_connectex) {
if (!uv_get_connectex_function(handle->socket, &handle->func_connectex)) {
return WSAEAFNOSUPPORT;
}
}
uv_req_init(loop, (uv_req_t*) req);
req->type = UV_CONNECT;
req->handle = (uv_stream_t*) handle;
req->cb = cb;
memset(&req->overlapped, 0, sizeof(req->overlapped));
success = handle->func_connectex(handle->socket,
(struct sockaddr*) &address,
addrsize,
NULL,
0,
&bytes,
&req->overlapped);
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
handle->reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
uv_insert_pending_req(loop, (uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
handle->reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
} else {
return WSAGetLastError();
}
return 0;
}
int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name,
int* namelen) {
int result;
@ -1422,3 +1371,21 @@ int uv__tcp_bind(uv_tcp_t* handle,
return 0;
}
/* This function is an egress point, i.e. it returns libuv errors rather than
* system errors.
*/
int uv__tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
const struct sockaddr* addr,
unsigned int addrlen,
uv_connect_cb cb) {
int err;
err = uv_tcp_try_connect(req, handle, addr, addrlen, cb);
if (err)
return uv_translate_sys_error(err);
return 0;
}

View File

@ -346,7 +346,7 @@ static void cl_close_cb(uv_handle_t* handle) {
ASSERT(0 == uv_tcp_init(handle->loop, (uv_tcp_t*) &ctx->client_handle));
ASSERT(0 == uv_tcp_connect(&ctx->connect_req,
(uv_tcp_t*) &ctx->client_handle,
listen_addr,
&listen_addr,
cl_connect_cb));
}
@ -387,7 +387,7 @@ static int test_tcp(unsigned int num_servers, unsigned int num_clients) {
ASSERT(0 == uv_tcp_init(loop, handle));
ASSERT(0 == uv_tcp_connect(&ctx->connect_req,
handle,
listen_addr,
&listen_addr,
cl_connect_cb));
ASSERT(0 == uv_idle_init(loop, &ctx->idle_handle));
}

View File

@ -193,7 +193,10 @@ static void pinger_new(void) {
uv_tcp_bind(&pinger->tcp, &client_addr);
r = uv_tcp_connect(&pinger->connect_req, &pinger->tcp, server_addr, pinger_connect_cb);
r = uv_tcp_connect(&pinger->connect_req,
&pinger->tcp,
&server_addr,
pinger_connect_cb);
ASSERT(!r);
}

View File

@ -194,14 +194,17 @@ static void pipe_do_setup(int num, void* arg) {
static void tcp_make_connect(conn_rec* p) {
struct sockaddr_in addr;
tcp_conn_rec* tp;
int r;
tp = (tcp_conn_rec*) p;
r = uv_tcp_init(loop, (uv_tcp_t*)&p->stream);
ASSERT(r == 0);
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
r = uv_tcp_connect(&((tcp_conn_rec*)p)->conn_req, (uv_tcp_t*)&p->stream, addr, connect_cb);
r = uv_tcp_connect(&tp->conn_req, (uv_tcp_t*) &p->stream, &addr, connect_cb);
if (r) {
fprintf(stderr, "uv_tcp_connect error %s\n", uv_err_name(r));
ASSERT(0);

View File

@ -240,7 +240,7 @@ static void maybe_connect_some(void) {
ASSERT(r == 0);
req = (uv_connect_t*) req_alloc();
r = uv_tcp_connect(req, tcp, connect_addr, connect_cb);
r = uv_tcp_connect(req, tcp, &connect_addr, connect_cb);
ASSERT(r == 0);
} else {
pipe = &pipe_write_handles[max_connect_socket++];

View File

@ -117,7 +117,7 @@ BENCHMARK_IMPL(tcp_write_batch) {
r = uv_tcp_init(loop, &tcp_client);
ASSERT(r == 0);
r = uv_tcp_connect(&connect_req, &tcp_client, addr, connect_cb);
r = uv_tcp_connect(&connect_req, &tcp_client, &addr, connect_cb);
ASSERT(r == 0);
start = uv_hrtime();

View File

@ -183,7 +183,7 @@ TEST_IMPL(callback_stack) {
nested++;
if (uv_tcp_connect(&connect_req, &client, addr, connect_cb)) {
if (uv_tcp_connect(&connect_req, &client, &addr, connect_cb)) {
FATAL("uv_tcp_connect failed");
}
nested--;

View File

@ -102,7 +102,7 @@ static void connection_fail(uv_connect_cb connect_cb) {
/* We are never doing multiple reads/connects at a time anyway. */
/* so these handles can be pre-initialized. */
uv_tcp_bind(&tcp, &client_addr);
r = uv_tcp_connect(&req, &tcp, server_addr, connect_cb);
r = uv_tcp_connect(&req, &tcp, &server_addr, connect_cb);
ASSERT(!r);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);

View File

@ -163,7 +163,7 @@ static void client_connect(void) {
r = uv_tcp_init(uv_default_loop(), client);
ASSERT(r == 0);
r = uv_tcp_connect(connect_req, client, addr, connect_cb);
r = uv_tcp_connect(connect_req, client, &addr, connect_cb);
ASSERT(r == 0);
}

View File

@ -219,7 +219,7 @@ static void tcp_connector(void) {
tcp.data = &connect_req;
ASSERT(!r);
r = uv_tcp_connect(&connect_req, &tcp, server_addr, on_connect);
r = uv_tcp_connect(&connect_req, &tcp, &server_addr, on_connect);
ASSERT(!r);
/* Fetch the actual port used by the connecting socket. */

View File

@ -129,7 +129,7 @@ static void make_many_connections(void) {
r = uv_tcp_connect(&conn->conn_req,
(uv_tcp_t*) &conn->conn,
addr,
&addr,
connect_cb);
ASSERT(r == 0);
@ -632,7 +632,7 @@ int ipc_helper_tcp_connection(void) {
r = uv_tcp_connect(&conn.conn_req,
(uv_tcp_t*) &conn.conn,
addr,
&addr,
connect_child_process_cb);
ASSERT(r == 0);

View File

@ -84,7 +84,7 @@ static void client_connect(void) {
r = uv_tcp_init(uv_default_loop(), &client);
ASSERT(r == 0);
r = uv_tcp_connect(connect_req, &client, addr, connect_cb);
r = uv_tcp_connect(connect_req, &client, &addr, connect_cb);
ASSERT(r == 0);
}

View File

@ -163,8 +163,10 @@ static void tcp_pinger_v6_new(void) {
/* We are never doing multiple reads/connects at a time anyway. */
/* so these handles can be pre-initialized. */
r = uv_tcp_connect6(&pinger->connect_req, &pinger->stream.tcp, server_addr,
pinger_on_connect);
r = uv_tcp_connect6(&pinger->connect_req,
&pinger->stream.tcp,
&server_addr,
pinger_on_connect);
ASSERT(!r);
/* Synchronous connect callbacks are not allowed. */
@ -189,8 +191,10 @@ static void tcp_pinger_new(void) {
/* We are never doing multiple reads/connects at a time anyway. */
/* so these handles can be pre-initialized. */
r = uv_tcp_connect(&pinger->connect_req, &pinger->stream.tcp, server_addr,
pinger_on_connect);
r = uv_tcp_connect(&pinger->connect_req,
&pinger->stream.tcp,
&server_addr,
pinger_on_connect);
ASSERT(!r);
/* Synchronous connect callbacks are not allowed. */

View File

@ -258,7 +258,7 @@ TEST_IMPL(tcp_ref3) {
uv_tcp_t h;
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
uv_tcp_init(uv_default_loop(), &h);
uv_tcp_connect(&connect_req, &h, addr, connect_and_shutdown);
uv_tcp_connect(&connect_req, &h, &addr, connect_and_shutdown);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(connect_cb_called == 1);
@ -274,7 +274,7 @@ TEST_IMPL(tcp_ref4) {
uv_tcp_t h;
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
uv_tcp_init(uv_default_loop(), &h);
uv_tcp_connect(&connect_req, &h, addr, connect_and_write);
uv_tcp_connect(&connect_req, &h, &addr, connect_and_write);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(connect_cb_called == 1);

View File

@ -72,7 +72,7 @@ TEST_IMPL(shutdown_close_tcp) {
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
r = uv_tcp_init(uv_default_loop(), &h);
ASSERT(r == 0);
r = uv_tcp_connect(&connect_req, &h, addr, connect_cb);
r = uv_tcp_connect(&connect_req, &h, &addr, connect_cb);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(r == 0);

View File

@ -160,7 +160,7 @@ TEST_IMPL(shutdown_eof) {
r = uv_tcp_init(uv_default_loop(), &tcp);
ASSERT(!r);
r = uv_tcp_connect(&connect_req, &tcp, server_addr, connect_cb);
r = uv_tcp_connect(&connect_req, &tcp, &server_addr, connect_cb);
ASSERT(!r);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);

View File

@ -63,7 +63,7 @@ TEST_IMPL(tcp_close_while_connecting) {
loop = uv_default_loop();
ASSERT(0 == uv_ip4_addr("1.2.3.4", TEST_PORT, &addr));
ASSERT(0 == uv_tcp_init(loop, &tcp_handle));
ASSERT(0 == uv_tcp_connect(&connect_req, &tcp_handle, addr, connect_cb));
ASSERT(0 == uv_tcp_connect(&connect_req, &tcp_handle, &addr, connect_cb));
ASSERT(0 == uv_timer_init(loop, &timer1_handle));
ASSERT(0 == uv_timer_start(&timer1_handle, timer1_cb, 50, 0));
ASSERT(0 == uv_timer_init(loop, &timer2_handle));

View File

@ -114,7 +114,7 @@ TEST_IMPL(tcp_close) {
r = uv_tcp_init(loop, &tcp_handle);
ASSERT(r == 0);
r = uv_tcp_connect(&connect_req, &tcp_handle, addr, connect_cb);
r = uv_tcp_connect(&connect_req, &tcp_handle, &addr, connect_cb);
ASSERT(r == 0);
ASSERT(write_cb_called == 0);

View File

@ -77,7 +77,7 @@ TEST_IMPL(tcp_connect_error_after_write) {
r = uv_write(&write_req, (uv_stream_t*)&conn, &buf, 1, write_cb);
ASSERT(r == UV_EBADF);
r = uv_tcp_connect(&connect_req, &conn, addr, connect_cb);
r = uv_tcp_connect(&connect_req, &conn, &addr, connect_cb);
ASSERT(r == 0);
r = uv_write(&write_req, (uv_stream_t*)&conn, &buf, 1, write_cb);

View File

@ -44,17 +44,18 @@ static void close_cb(uv_handle_t* handle) {
TEST_IMPL(tcp_connect_error_fault) {
char garbage[] = "blah blah blah blah blah blah blah blah blah blah blah blah";
struct sockaddr_in* garbage_addr;
const char garbage[] =
"blah blah blah blah blah blah blah blah blah blah blah blah";
const struct sockaddr_in* garbage_addr;
uv_tcp_t server;
int r;
uv_connect_t req;
garbage_addr = (struct sockaddr_in*) &garbage;
garbage_addr = (const struct sockaddr_in*) &garbage;
r = uv_tcp_init(uv_default_loop(), &server);
ASSERT(r == 0);
r = uv_tcp_connect(&req, &server, *garbage_addr, connect_cb);
r = uv_tcp_connect(&req, &server, garbage_addr, connect_cb);
ASSERT(r == UV_EINVAL);
uv_close((uv_handle_t*)&server, close_cb);

View File

@ -75,7 +75,7 @@ TEST_IMPL(tcp_connect_timeout) {
r = uv_tcp_init(uv_default_loop(), &conn);
ASSERT(r == 0);
r = uv_tcp_connect(&connect_req, &conn, addr, connect_cb);
r = uv_tcp_connect(&connect_req, &conn, &addr, connect_cb);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);

View File

@ -42,17 +42,18 @@ static void close_cb(uv_handle_t* handle) {
TEST_IMPL(tcp_connect6_error_fault) {
char garbage[] = "blah blah blah blah blah blah blah blah blah blah blah blah";
struct sockaddr_in6* garbage_addr;
const char garbage[] =
"blah blah blah blah blah blah blah blah blah blah blah blah";
const struct sockaddr_in6* garbage_addr;
uv_tcp_t server;
int r;
uv_connect_t req;
garbage_addr = (struct sockaddr_in6*) &garbage;
garbage_addr = (const struct sockaddr_in6*) &garbage;
r = uv_tcp_init(uv_default_loop(), &server);
ASSERT(r == 0);
r = uv_tcp_connect6(&req, &server, *garbage_addr, connect_cb);
r = uv_tcp_connect6(&req, &server, garbage_addr, connect_cb);
ASSERT(r == UV_EINVAL);
uv_close((uv_handle_t*)&server, close_cb);

View File

@ -164,7 +164,7 @@ TEST_IMPL(tcp_open) {
r = uv_tcp_open(&client, sock);
ASSERT(r == 0);
r = uv_tcp_connect(&connect_req, &client, addr, connect_cb);
r = uv_tcp_connect(&connect_req, &client, &addr, connect_cb);
ASSERT(r == 0);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);

View File

@ -65,7 +65,7 @@ TEST_IMPL(tcp_read_stop) {
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle));
ASSERT(0 == uv_tcp_init(uv_default_loop(), &tcp_handle));
ASSERT(0 == uv_tcp_connect(&connect_req, &tcp_handle, addr, connect_cb));
ASSERT(0 == uv_tcp_connect(&connect_req, &tcp_handle, &addr, connect_cb));
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
MAKE_VALGRIND_HAPPY();

View File

@ -118,7 +118,7 @@ TEST_IMPL(tcp_shutdown_after_write) {
r = uv_tcp_init(loop, &conn);
ASSERT(r == 0);
r = uv_tcp_connect(&connect_req, &conn, addr, connect_cb);
r = uv_tcp_connect(&connect_req, &conn, &addr, connect_cb);
ASSERT(r == 0);
r = uv_run(loop, UV_RUN_DEFAULT);

View File

@ -100,7 +100,7 @@ TEST_IMPL(tcp_unexpected_read) {
ASSERT(0 == uv_tcp_init(loop, &peer_handle));
ASSERT(0 == uv_tcp_bind(&server_handle, &addr));
ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 1, connection_cb));
ASSERT(0 == uv_tcp_connect(&connect_req, &client_handle, addr, connect_cb));
ASSERT(0 == uv_tcp_connect(&connect_req, &client_handle, &addr, connect_cb));
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
/* This is somewhat inexact but the idea is that the event loop should not

View File

@ -124,7 +124,7 @@ TEST_IMPL(tcp_write_to_half_open_connection) {
r = uv_tcp_init(loop, &tcp_client);
ASSERT(r == 0);
r = uv_tcp_connect(&connect_req, &tcp_client, addr, connect_cb);
r = uv_tcp_connect(&connect_req, &tcp_client, &addr, connect_cb);
ASSERT(r == 0);
r = uv_run(loop, UV_RUN_DEFAULT);

View File

@ -153,7 +153,7 @@ TEST_IMPL(tcp_writealot) {
r = uv_tcp_init(uv_default_loop(), &client);
ASSERT(r == 0);
r = uv_tcp_connect(&connect_req, &client, addr, connect_cb);
r = uv_tcp_connect(&connect_req, &client, &addr, connect_cb);
ASSERT(r == 0);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);