connect: Code style formatting

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit da50b12051)
This commit is contained in:
Anderson Toshiyuki Sasaki
2019-06-26 14:43:09 +02:00
committed by Andreas Schneider
parent 466ca07626
commit 3bc5f88f77

View File

@@ -90,53 +90,55 @@
#ifdef _WIN32 #ifdef _WIN32
#ifndef gai_strerror #ifndef gai_strerror
char WSAAPI *gai_strerrorA(int code) { char WSAAPI *gai_strerrorA(int code)
static char buf[256]; {
static char buf[256];
snprintf(buf, sizeof(buf), "Undetermined error code (%d)", code); snprintf(buf, sizeof(buf), "Undetermined error code (%d)", code);
return buf; return buf;
} }
#endif /* gai_strerror */ #endif /* gai_strerror */
#endif /* _WIN32 */ #endif /* _WIN32 */
static int ssh_connect_socket_close(socket_t s){ static int ssh_connect_socket_close(socket_t s)
{
#ifdef _WIN32 #ifdef _WIN32
return closesocket(s); return closesocket(s);
#else #else
return close(s); return close(s);
#endif #endif
} }
static int getai(const char *host, int port, struct addrinfo **ai)
{
const char *service = NULL;
struct addrinfo hints;
char s_port[10];
static int getai(const char *host, int port, struct addrinfo **ai) { ZERO_STRUCT(hints);
const char *service = NULL;
struct addrinfo hints;
char s_port[10];
ZERO_STRUCT(hints); hints.ai_protocol = IPPROTO_TCP;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; if (port == 0) {
hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM; } else {
snprintf(s_port, sizeof(s_port), "%hu", (unsigned short)port);
if (port == 0) { service = s_port;
hints.ai_flags = AI_PASSIVE;
} else {
snprintf(s_port, sizeof(s_port), "%hu", (unsigned short)port);
service = s_port;
#ifdef AI_NUMERICSERV #ifdef AI_NUMERICSERV
hints.ai_flags=AI_NUMERICSERV; hints.ai_flags = AI_NUMERICSERV;
#endif #endif
} }
if (ssh_is_ipaddr(host)) { if (ssh_is_ipaddr(host)) {
/* this is an IP address */ /* this is an IP address */
SSH_LOG(SSH_LOG_PACKET,"host %s matches an IP address",host); SSH_LOG(SSH_LOG_PACKET, "host %s matches an IP address", host);
hints.ai_flags |= AI_NUMERICHOST; hints.ai_flags |= AI_NUMERICHOST;
} }
return getaddrinfo(host, service, &hints, ai); return getaddrinfo(host, service, &hints, ai);
} }
static int set_tcp_nodelay(socket_t socket) static int set_tcp_nodelay(socket_t socket)
@@ -160,102 +162,109 @@ static int set_tcp_nodelay(socket_t socket)
* @warning very ugly !!! * @warning very ugly !!!
*/ */
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host, socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
const char *bind_addr, int port) { const char *bind_addr, int port)
socket_t s = -1; {
int rc; socket_t s = -1;
struct addrinfo *ai; int rc;
struct addrinfo *itr; struct addrinfo *ai = NULL;
struct addrinfo *itr = NULL;
rc = getai(host, port, &ai); rc = getai(host, port, &ai);
if (rc != 0) { if (rc != 0) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"Failed to resolve hostname %s (%s)", host, gai_strerror(rc)); "Failed to resolve hostname %s (%s)",
host, gai_strerror(rc));
return -1; return -1;
}
for (itr = ai; itr != NULL; itr = itr->ai_next){
/* create socket */
s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol);
if (s < 0) {
ssh_set_error(session, SSH_FATAL,
"Socket create failed: %s", strerror(errno));
continue;
} }
if (bind_addr) { for (itr = ai; itr != NULL; itr = itr->ai_next) {
struct addrinfo *bind_ai; /* create socket */
struct addrinfo *bind_itr; s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol);
if (s < 0) {
SSH_LOG(SSH_LOG_PACKET, "Resolving %s", bind_addr); ssh_set_error(session, SSH_FATAL,
"Socket create failed: %s", strerror(errno));
rc = getai(bind_addr, 0, &bind_ai); continue;
if (rc != 0) {
ssh_set_error(session, SSH_FATAL,
"Failed to resolve bind address %s (%s)",
bind_addr,
gai_strerror(rc));
ssh_connect_socket_close(s);
s=-1;
break;
}
for (bind_itr = bind_ai; bind_itr != NULL; bind_itr = bind_itr->ai_next) {
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
ssh_set_error(session, SSH_FATAL,
"Binding local address: %s", strerror(errno));
continue;
} else {
break;
} }
}
freeaddrinfo(bind_ai);
/* Cannot bind to any local addresses */ if (bind_addr) {
if (bind_itr == NULL) { struct addrinfo *bind_ai;
ssh_connect_socket_close(s); struct addrinfo *bind_itr;
s = -1;
continue;
}
}
rc = ssh_socket_set_nonblocking(s); SSH_LOG(SSH_LOG_PACKET, "Resolving %s", bind_addr);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL,
"Failed to set socket non-blocking for %s:%d", host, port);
ssh_connect_socket_close(s);
s = -1;
continue;
}
if (session->opts.nodelay) { rc = getai(bind_addr, 0, &bind_ai);
/* For winsock, socket options are only effective before connect */ if (rc != 0) {
rc = set_tcp_nodelay(s); ssh_set_error(session, SSH_FATAL,
"Failed to resolve bind address %s (%s)",
bind_addr,
gai_strerror(rc));
ssh_connect_socket_close(s);
s = -1;
break;
}
for (bind_itr = bind_ai;
bind_itr != NULL;
bind_itr = bind_itr->ai_next)
{
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
ssh_set_error(session, SSH_FATAL,
"Binding local address: %s", strerror(errno));
continue;
} else {
break;
}
}
freeaddrinfo(bind_ai);
/* Cannot bind to any local addresses */
if (bind_itr == NULL) {
ssh_connect_socket_close(s);
s = -1;
continue;
}
}
rc = ssh_socket_set_nonblocking(s);
if (rc < 0) { if (rc < 0) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"Failed to set TCP_NODELAY on socket: %s", strerror(errno)); "Failed to set socket non-blocking for %s:%d",
host, port);
ssh_connect_socket_close(s); ssh_connect_socket_close(s);
s = -1; s = -1;
continue; continue;
} }
if (session->opts.nodelay) {
/* For winsock, socket options are only effective before connect */
rc = set_tcp_nodelay(s);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL,
"Failed to set TCP_NODELAY on socket: %s",
strerror(errno));
ssh_connect_socket_close(s);
s = -1;
continue;
}
}
errno = 0;
rc = connect(s, itr->ai_addr, itr->ai_addrlen);
if (rc == -1 && (errno != 0) && (errno != EINPROGRESS)) {
ssh_set_error(session, SSH_FATAL,
"Failed to connect: %s", strerror(errno));
ssh_connect_socket_close(s);
s = -1;
continue;
}
break;
} }
errno = 0; freeaddrinfo(ai);
rc = connect(s, itr->ai_addr, itr->ai_addrlen);
if (rc == -1 && (errno != 0) && (errno != EINPROGRESS)) {
ssh_set_error(session, SSH_FATAL,
"Failed to connect: %s", strerror(errno));
ssh_connect_socket_close(s);
s = -1;
continue;
}
break; return s;
}
freeaddrinfo(ai);
return s;
} }
/** /**
@@ -264,11 +273,13 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
* @{ * @{
*/ */
static int ssh_select_cb (socket_t fd, int revents, void *userdata){ static int ssh_select_cb (socket_t fd, int revents, void *userdata)
fd_set *set = (fd_set *)userdata; {
if(revents & POLLIN) fd_set *set = (fd_set *)userdata;
FD_SET(fd, set); if (revents & POLLIN) {
return 0; FD_SET(fd, set);
}
return 0;
} }
/** /**
@@ -302,73 +313,84 @@ static int ssh_select_cb (socket_t fd, int revents, void *userdata){
* @see select(2) * @see select(2)
*/ */
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd, int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
fd_set *readfds, struct timeval *timeout) { fd_set *readfds, struct timeval *timeout)
fd_set origfds; {
socket_t fd; fd_set origfds;
size_t i, j; socket_t fd;
int rc; size_t i, j;
int base_tm, tm; int rc;
struct ssh_timestamp ts; int base_tm, tm;
ssh_event event = ssh_event_new(); struct ssh_timestamp ts;
int firstround=1; ssh_event event = ssh_event_new();
int firstround = 1;
base_tm = tm=timeout->tv_sec * 1000 + timeout->tv_usec/1000; base_tm = tm = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
for (i=0 ; channels[i] != NULL; ++i){ for (i = 0 ; channels[i] != NULL; ++i) {
ssh_event_add_session(event, channels[i]->session); ssh_event_add_session(event, channels[i]->session);
}
ZERO_STRUCT(origfds);
FD_ZERO(&origfds);
for (fd = 0; fd < maxfd ; fd++) {
if (FD_ISSET(fd, readfds)) {
ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
FD_SET(fd, &origfds);
}
}
outchannels[0] = NULL;
FD_ZERO(readfds);
ssh_timestamp_init(&ts);
do {
/* Poll every channel */
j = 0;
for (i = 0; channels[i]; i++) {
if(ssh_channel_poll(channels[i], 0) != 0) {
outchannels[j] = channels[i];
j++;
} else if(ssh_channel_poll(channels[i], 1) != 0) {
outchannels[j] = channels[i];
j++;
}
} }
outchannels[j] = NULL;
if(j != 0) ZERO_STRUCT(origfds);
break; FD_ZERO(&origfds);
/* watch if a user socket was triggered */ for (fd = 0; fd < maxfd ; fd++) {
for (fd = 0; fd < maxfd; fd++) {
if (FD_ISSET(fd, readfds)) { if (FD_ISSET(fd, readfds)) {
goto out; ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
FD_SET(fd, &origfds);
} }
} }
outchannels[0] = NULL;
FD_ZERO(readfds);
ssh_timestamp_init(&ts);
do {
/* Poll every channel */
j = 0;
for (i = 0; channels[i]; i++) {
rc = ssh_channel_poll(channels[i], 0);
if (rc != 0) {
outchannels[j] = channels[i];
j++;
} else {
rc = ssh_channel_poll(channels[i], 1);
if (rc != 0) {
outchannels[j] = channels[i];
j++;
}
}
}
/* If the timeout is elapsed, we should go out */ outchannels[j] = NULL;
if(!firstround && ssh_timeout_elapsed(&ts, base_tm)) if (j != 0) {
goto out; break;
/* since there's nothing, let's fire the polling */ }
rc = ssh_event_dopoll(event,tm);
if (rc == SSH_ERROR){ /* watch if a user socket was triggered */
goto out; for (fd = 0; fd < maxfd; fd++) {
} if (FD_ISSET(fd, readfds)) {
tm = ssh_timeout_update(&ts, base_tm); goto out;
firstround=0; }
} while (1); }
/* If the timeout is elapsed, we should go out */
if (!firstround && ssh_timeout_elapsed(&ts, base_tm)) {
goto out;
}
/* since there's nothing, let's fire the polling */
rc = ssh_event_dopoll(event,tm);
if (rc == SSH_ERROR) {
goto out;
}
tm = ssh_timeout_update(&ts, base_tm);
firstround = 0;
} while (1);
out: out:
for (fd = 0; fd < maxfd; fd++) { for (fd = 0; fd < maxfd; fd++) {
if (FD_ISSET(fd, &origfds)) { if (FD_ISSET(fd, &origfds)) {
ssh_event_remove_fd(event, fd); ssh_event_remove_fd(event, fd);
}
} }
} ssh_event_free(event);
ssh_event_free(event); return SSH_OK;
return SSH_OK;
} }
/** @} */ /** @} */