connect: Code style formatting
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Этот коммит содержится в:
родитель
a82993b320
Коммит
da50b12051
366
src/connect.c
366
src/connect.c
@ -90,53 +90,55 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef gai_strerror
|
||||
char WSAAPI *gai_strerrorA(int code) {
|
||||
static char buf[256];
|
||||
char WSAAPI *gai_strerrorA(int code)
|
||||
{
|
||||
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 /* _WIN32 */
|
||||
|
||||
static int ssh_connect_socket_close(socket_t s){
|
||||
static int ssh_connect_socket_close(socket_t s)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return closesocket(s);
|
||||
return closesocket(s);
|
||||
#else
|
||||
return close(s);
|
||||
return close(s);
|
||||
#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) {
|
||||
const char *service = NULL;
|
||||
struct addrinfo hints;
|
||||
char s_port[10];
|
||||
ZERO_STRUCT(hints);
|
||||
|
||||
ZERO_STRUCT(hints);
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (port == 0) {
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
} else {
|
||||
snprintf(s_port, sizeof(s_port), "%hu", (unsigned short)port);
|
||||
service = s_port;
|
||||
if (port == 0) {
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
} else {
|
||||
snprintf(s_port, sizeof(s_port), "%hu", (unsigned short)port);
|
||||
service = s_port;
|
||||
#ifdef AI_NUMERICSERV
|
||||
hints.ai_flags=AI_NUMERICSERV;
|
||||
hints.ai_flags = AI_NUMERICSERV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_is_ipaddr(host)) {
|
||||
/* this is an IP address */
|
||||
SSH_LOG(SSH_LOG_PACKET,"host %s matches an IP address",host);
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
}
|
||||
if (ssh_is_ipaddr(host)) {
|
||||
/* this is an IP address */
|
||||
SSH_LOG(SSH_LOG_PACKET, "host %s matches an IP address", host);
|
||||
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)
|
||||
@ -160,102 +162,109 @@ static int set_tcp_nodelay(socket_t socket)
|
||||
* @warning very ugly !!!
|
||||
*/
|
||||
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
const char *bind_addr, int port) {
|
||||
socket_t s = -1;
|
||||
int rc;
|
||||
struct addrinfo *ai;
|
||||
struct addrinfo *itr;
|
||||
const char *bind_addr, int port)
|
||||
{
|
||||
socket_t s = -1;
|
||||
int rc;
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo *itr = NULL;
|
||||
|
||||
rc = getai(host, port, &ai);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to resolve hostname %s (%s)", host, gai_strerror(rc));
|
||||
rc = getai(host, port, &ai);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to resolve hostname %s (%s)",
|
||||
host, gai_strerror(rc));
|
||||
|
||||
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;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bind_addr) {
|
||||
struct addrinfo *bind_ai;
|
||||
struct addrinfo *bind_itr;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Resolving %s", bind_addr);
|
||||
|
||||
rc = getai(bind_addr, 0, &bind_ai);
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(bind_ai);
|
||||
|
||||
/* Cannot bind to any local addresses */
|
||||
if (bind_itr == NULL) {
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (bind_addr) {
|
||||
struct addrinfo *bind_ai;
|
||||
struct addrinfo *bind_itr;
|
||||
|
||||
rc = ssh_socket_set_nonblocking(s);
|
||||
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;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Resolving %s", bind_addr);
|
||||
|
||||
if (session->opts.nodelay) {
|
||||
/* For winsock, socket options are only effective before connect */
|
||||
rc = set_tcp_nodelay(s);
|
||||
rc = getai(bind_addr, 0, &bind_ai);
|
||||
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_itr == NULL) {
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_socket_set_nonblocking(s);
|
||||
if (rc < 0) {
|
||||
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);
|
||||
s = -1;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
freeaddrinfo(ai);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
|
||||
return s;
|
||||
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){
|
||||
fd_set *set = (fd_set *)userdata;
|
||||
if(revents & POLLIN)
|
||||
FD_SET(fd, set);
|
||||
return 0;
|
||||
static int ssh_select_cb (socket_t fd, int revents, void *userdata)
|
||||
{
|
||||
fd_set *set = (fd_set *)userdata;
|
||||
if (revents & POLLIN) {
|
||||
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)
|
||||
*/
|
||||
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
||||
fd_set *readfds, struct timeval *timeout) {
|
||||
fd_set origfds;
|
||||
socket_t fd;
|
||||
size_t i, j;
|
||||
int rc;
|
||||
int base_tm, tm;
|
||||
struct ssh_timestamp ts;
|
||||
ssh_event event = ssh_event_new();
|
||||
int firstround=1;
|
||||
fd_set *readfds, struct timeval *timeout)
|
||||
{
|
||||
fd_set origfds;
|
||||
socket_t fd;
|
||||
size_t i, j;
|
||||
int rc;
|
||||
int base_tm, tm;
|
||||
struct ssh_timestamp ts;
|
||||
ssh_event event = ssh_event_new();
|
||||
int firstround = 1;
|
||||
|
||||
base_tm = tm=timeout->tv_sec * 1000 + timeout->tv_usec/1000;
|
||||
for (i=0 ; channels[i] != NULL; ++i){
|
||||
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++;
|
||||
}
|
||||
base_tm = tm = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
|
||||
for (i = 0 ; channels[i] != NULL; ++i) {
|
||||
ssh_event_add_session(event, channels[i]->session);
|
||||
}
|
||||
outchannels[j] = NULL;
|
||||
if(j != 0)
|
||||
break;
|
||||
/* watch if a user socket was triggered */
|
||||
for (fd = 0; fd < maxfd; fd++) {
|
||||
|
||||
ZERO_STRUCT(origfds);
|
||||
FD_ZERO(&origfds);
|
||||
for (fd = 0; fd < maxfd ; fd++) {
|
||||
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 */
|
||||
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);
|
||||
outchannels[j] = NULL;
|
||||
if (j != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* watch if a user socket was triggered */
|
||||
for (fd = 0; fd < maxfd; fd++) {
|
||||
if (FD_ISSET(fd, readfds)) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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:
|
||||
for (fd = 0; fd < maxfd; fd++) {
|
||||
if (FD_ISSET(fd, &origfds)) {
|
||||
ssh_event_remove_fd(event, fd);
|
||||
for (fd = 0; fd < maxfd; fd++) {
|
||||
if (FD_ISSET(fd, &origfds)) {
|
||||
ssh_event_remove_fd(event, fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
ssh_event_free(event);
|
||||
return SSH_OK;
|
||||
ssh_event_free(event);
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user