1
1

channels: ssh_channel_select implemented with ssh_poll

Should fix #56
Этот коммит содержится в:
Aris Adamantiadis 2011-08-30 22:14:43 +03:00
родитель 7f5206b8ac
Коммит d1ebc4697a

Просмотреть файл

@ -2934,13 +2934,18 @@ int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans,
ssh_channel *exceptchans, struct timeval * timeout) { ssh_channel *exceptchans, struct timeval * timeout) {
ssh_channel *rchans, *wchans, *echans; ssh_channel *rchans, *wchans, *echans;
ssh_channel dummy = NULL; ssh_channel dummy = NULL;
fd_set rset; ssh_event event = NULL;
fd_set wset;
fd_set eset;
socket_t max_fd = SSH_INVALID_SOCKET;
int rc; int rc;
int i; int i;
int tm, tm_base;
struct ssh_timestamp ts;
if (timeout != NULL)
tm_base = timeout->tv_sec * 1000 + timeout->tv_usec/1000;
else
tm_base = SSH_TIMEOUT_INFINITE;
ssh_timestamp_init(&ts);
tm = tm_base;
/* don't allow NULL pointers */ /* don't allow NULL pointers */
if (readchans == NULL) { if (readchans == NULL) {
readchans = &dummy; readchans = &dummy;
@ -2979,75 +2984,54 @@ int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans,
} }
/* /*
* First, try without doing network stuff then, select and redo the * First, try without doing network stuff then, use the ssh_poll
* networkless stuff * infrastructure to poll on all sessions.
*/ */
do { do {
channel_protocol_select(readchans, writechans, exceptchans, channel_protocol_select(readchans, writechans, exceptchans,
rchans, wchans, echans); rchans, wchans, echans);
if (rchans[0] != NULL || wchans[0] != NULL || echans[0] != NULL) { if (rchans[0] != NULL || wchans[0] != NULL || echans[0] != NULL) {
/* We've got one without doing any select overwrite the beginning arrays */ /* At least one channel has an event */
memcpy(readchans, rchans, (count_ptrs(rchans) + 1) * sizeof(ssh_channel )); memcpy(readchans, rchans, (count_ptrs(rchans) + 1) * sizeof(ssh_channel ));
memcpy(writechans, wchans, (count_ptrs(wchans) + 1) * sizeof(ssh_channel )); memcpy(writechans, wchans, (count_ptrs(wchans) + 1) * sizeof(ssh_channel ));
memcpy(exceptchans, echans, (count_ptrs(echans) + 1) * sizeof(ssh_channel )); memcpy(exceptchans, echans, (count_ptrs(echans) + 1) * sizeof(ssh_channel ));
SAFE_FREE(rchans); SAFE_FREE(rchans);
SAFE_FREE(wchans); SAFE_FREE(wchans);
SAFE_FREE(echans); SAFE_FREE(echans);
if(event)
ssh_event_free(event);
return 0; return 0;
} }
/* /* Add all channels' sessions right into an event object */
* Since we verified the invalid fd cases into the networkless select, if (!event){
* we can be sure all fd are valid ones event = ssh_event_new();
*/ if(!event){
FD_ZERO(&rset); return SSH_ERROR;
FD_ZERO(&wset); }
FD_ZERO(&eset); for (i = 0; readchans[i] != NULL; i++) {
ssh_poll_get_default_ctx(readchans[i]->session);
for (i = 0; readchans[i] != NULL; i++) { ssh_event_add_session(event, readchans[i]->session);
if (!ssh_socket_fd_isset(readchans[i]->session->socket, &rset)) { }
ssh_socket_fd_set(readchans[i]->session->socket, &rset, &max_fd); for (i = 0; writechans[i] != NULL; i++) {
ssh_poll_get_default_ctx(writechans[i]->session);
ssh_event_add_session(event, writechans[i]->session);
}
for (i = 0; exceptchans[i] != NULL; i++) {
ssh_poll_get_default_ctx(exceptchans[i]->session);
ssh_event_add_session(event, exceptchans[i]->session);
} }
} }
for (i = 0; writechans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(writechans[i]->session->socket, &wset)) {
ssh_socket_fd_set(writechans[i]->session->socket, &wset, &max_fd);
}
}
for (i = 0; exceptchans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(exceptchans[i]->session->socket, &eset)) {
ssh_socket_fd_set(exceptchans[i]->session->socket, &eset, &max_fd);
}
}
/* Here we go */ /* Here we go */
rc = select(max_fd, &rset, &wset, &eset, timeout); rc = ssh_event_dopoll(event,tm);
/* Leave if select was interrupted */ if (rc != SSH_OK){
if (rc == EINTR) {
SAFE_FREE(rchans); SAFE_FREE(rchans);
SAFE_FREE(wchans); SAFE_FREE(wchans);
SAFE_FREE(echans); SAFE_FREE(echans);
return SSH_EINTR; ssh_event_free(event);
return rc;
} }
tm = ssh_timeout_update(&ts, tm_base);
for (i = 0; readchans[i] != NULL; i++) {
if (ssh_socket_fd_isset(readchans[i]->session->socket, &rset)) {
ssh_socket_set_read_wontblock(readchans[i]->session->socket);
}
}
for (i = 0; writechans[i] != NULL; i++) {
if (ssh_socket_fd_isset(writechans[i]->session->socket, &wset)) {
ssh_socket_set_write_wontblock(writechans[i]->session->socket);
}
}
for (i = 0; exceptchans[i] != NULL; i++) {
if (ssh_socket_fd_isset(exceptchans[i]->session->socket, &eset)) {
ssh_socket_set_except(exceptchans[i]->session->socket);
}
}
} while(1); /* Return to do loop */ } while(1); /* Return to do loop */
/* not reached */ /* not reached */