|
|
|
@ -236,65 +236,68 @@ finish: |
|
|
|
|
GRPC_CLOSURE_SCHED(closure, error); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void tcp_client_connect_impl(grpc_closure* closure, grpc_endpoint** ep, |
|
|
|
|
grpc_pollset_set* interested_parties, |
|
|
|
|
const grpc_channel_args* channel_args, |
|
|
|
|
const grpc_resolved_address* addr, |
|
|
|
|
grpc_millis deadline) { |
|
|
|
|
int fd; |
|
|
|
|
grpc_error* grpc_tcp_client_prepare_fd(const grpc_channel_args* channel_args, |
|
|
|
|
const grpc_resolved_address* addr, |
|
|
|
|
grpc_resolved_address* mapped_addr, |
|
|
|
|
grpc_fd** fdobj) { |
|
|
|
|
grpc_dualstack_mode dsmode; |
|
|
|
|
int err; |
|
|
|
|
async_connect* ac; |
|
|
|
|
grpc_resolved_address addr6_v4mapped; |
|
|
|
|
grpc_resolved_address addr4_copy; |
|
|
|
|
grpc_fd* fdobj; |
|
|
|
|
int fd; |
|
|
|
|
grpc_error* error; |
|
|
|
|
char* name; |
|
|
|
|
char* addr_str; |
|
|
|
|
grpc_error* error; |
|
|
|
|
|
|
|
|
|
*ep = nullptr; |
|
|
|
|
|
|
|
|
|
/* Use dualstack sockets where available. */ |
|
|
|
|
if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { |
|
|
|
|
addr = &addr6_v4mapped; |
|
|
|
|
*fdobj = nullptr; |
|
|
|
|
/* Use dualstack sockets where available. Set mapped to v6 or v4 mapped to
|
|
|
|
|
v6. */ |
|
|
|
|
if (!grpc_sockaddr_to_v4mapped(addr, mapped_addr)) { |
|
|
|
|
/* addr is v4 mapped to v6 or v6. */ |
|
|
|
|
memcpy(mapped_addr, addr, sizeof(*mapped_addr)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
error = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd); |
|
|
|
|
error = |
|
|
|
|
grpc_create_dualstack_socket(mapped_addr, SOCK_STREAM, 0, &dsmode, &fd); |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
GRPC_CLOSURE_SCHED(closure, error); |
|
|
|
|
return; |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
if (dsmode == GRPC_DSMODE_IPV4) { |
|
|
|
|
/* If we got an AF_INET socket, map the address back to IPv4. */ |
|
|
|
|
GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy)); |
|
|
|
|
addr = &addr4_copy; |
|
|
|
|
/* Original addr is either v4 or v4 mapped to v6. Set mapped_addr to v4. */ |
|
|
|
|
if (!grpc_sockaddr_is_v4mapped(addr, mapped_addr)) { |
|
|
|
|
memcpy(mapped_addr, addr, sizeof(*mapped_addr)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if ((error = prepare_socket(addr, fd, channel_args)) != GRPC_ERROR_NONE) { |
|
|
|
|
GRPC_CLOSURE_SCHED(closure, error); |
|
|
|
|
return; |
|
|
|
|
if ((error = prepare_socket(mapped_addr, fd, channel_args)) != |
|
|
|
|
GRPC_ERROR_NONE) { |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
addr_str = grpc_sockaddr_to_uri(mapped_addr); |
|
|
|
|
gpr_asprintf(&name, "tcp-client:%s", addr_str); |
|
|
|
|
*fdobj = grpc_fd_create(fd, name); |
|
|
|
|
gpr_free(name); |
|
|
|
|
gpr_free(addr_str); |
|
|
|
|
return GRPC_ERROR_NONE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_tcp_client_create_from_prepared_fd( |
|
|
|
|
grpc_pollset_set* interested_parties, grpc_closure* closure, grpc_fd* fdobj, |
|
|
|
|
const grpc_channel_args* channel_args, const grpc_resolved_address* addr, |
|
|
|
|
grpc_millis deadline, grpc_endpoint** ep) { |
|
|
|
|
const int fd = grpc_fd_wrapped_fd(fdobj); |
|
|
|
|
int err; |
|
|
|
|
async_connect* ac; |
|
|
|
|
do { |
|
|
|
|
GPR_ASSERT(addr->len < ~(socklen_t)0); |
|
|
|
|
err = connect(fd, (const struct sockaddr*)addr->addr, (socklen_t)addr->len); |
|
|
|
|
} while (err < 0 && errno == EINTR); |
|
|
|
|
|
|
|
|
|
addr_str = grpc_sockaddr_to_uri(addr); |
|
|
|
|
gpr_asprintf(&name, "tcp-client:%s", addr_str); |
|
|
|
|
|
|
|
|
|
fdobj = grpc_fd_create(fd, name); |
|
|
|
|
|
|
|
|
|
if (err >= 0) { |
|
|
|
|
char* addr_str = grpc_sockaddr_to_uri(addr); |
|
|
|
|
*ep = grpc_tcp_client_create_from_fd(fdobj, channel_args, addr_str); |
|
|
|
|
gpr_free(addr_str); |
|
|
|
|
GRPC_CLOSURE_SCHED(closure, GRPC_ERROR_NONE); |
|
|
|
|
goto done; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (errno != EWOULDBLOCK && errno != EINPROGRESS) { |
|
|
|
|
grpc_fd_orphan(fdobj, nullptr, nullptr, false /* already_closed */, |
|
|
|
|
"tcp_client_connect_error"); |
|
|
|
|
GRPC_CLOSURE_SCHED(closure, GRPC_OS_ERROR(errno, "connect")); |
|
|
|
|
goto done; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_pollset_set_add_fd(interested_parties, fdobj); |
|
|
|
@ -304,8 +307,7 @@ static void tcp_client_connect_impl(grpc_closure* closure, grpc_endpoint** ep, |
|
|
|
|
ac->ep = ep; |
|
|
|
|
ac->fd = fdobj; |
|
|
|
|
ac->interested_parties = interested_parties; |
|
|
|
|
ac->addr_str = addr_str; |
|
|
|
|
addr_str = nullptr; |
|
|
|
|
ac->addr_str = grpc_sockaddr_to_uri(addr); |
|
|
|
|
gpr_mu_init(&ac->mu); |
|
|
|
|
ac->refs = 2; |
|
|
|
|
GRPC_CLOSURE_INIT(&ac->write_closure, on_writable, ac, |
|
|
|
@ -322,10 +324,25 @@ static void tcp_client_connect_impl(grpc_closure* closure, grpc_endpoint** ep, |
|
|
|
|
grpc_timer_init(&ac->alarm, deadline, &ac->on_alarm); |
|
|
|
|
grpc_fd_notify_on_write(ac->fd, &ac->write_closure); |
|
|
|
|
gpr_mu_unlock(&ac->mu); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
done: |
|
|
|
|
gpr_free(name); |
|
|
|
|
gpr_free(addr_str); |
|
|
|
|
static void tcp_client_connect_impl(grpc_closure* closure, grpc_endpoint** ep, |
|
|
|
|
grpc_pollset_set* interested_parties, |
|
|
|
|
const grpc_channel_args* channel_args, |
|
|
|
|
const grpc_resolved_address* addr, |
|
|
|
|
grpc_millis deadline) { |
|
|
|
|
grpc_resolved_address mapped_addr; |
|
|
|
|
grpc_fd* fdobj = nullptr; |
|
|
|
|
grpc_error* error; |
|
|
|
|
*ep = nullptr; |
|
|
|
|
if ((error = grpc_tcp_client_prepare_fd(channel_args, addr, &mapped_addr, |
|
|
|
|
&fdobj)) != GRPC_ERROR_NONE) { |
|
|
|
|
GRPC_CLOSURE_SCHED(closure, error); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
grpc_tcp_client_create_from_prepared_fd(interested_parties, closure, fdobj, |
|
|
|
|
channel_args, &mapped_addr, deadline, |
|
|
|
|
ep); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// overridden by api_fuzzer.c
|
|
|
|
|