mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-11 02:38:09 +09:00
Improve channel_select().
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@708 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
@@ -1712,47 +1712,68 @@ static int count_ptrs(CHANNEL **ptrs) {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** the list of pointers are then actualized and will only contain pointers to
|
/**
|
||||||
* channels that are respectively readable, writable or have an exception to trap
|
* @brief Act like the standard select(2) on channels.
|
||||||
* \brief act as the standard select(2) for channels
|
*
|
||||||
* \param readchans a NULL pointer or an array of channel pointers, finished by a NULL
|
* The list of pointers are then actualized and will only contain pointers to
|
||||||
* \param writechans a NULL pointer or an array of channel pointers, finished by a NULL
|
* channels that are respectively readable, writable or have an exception to
|
||||||
* \param exceptchans a NULL pointer or an array of channel pointers, finished by a NULL
|
* trap.
|
||||||
* \param timeout timeout as defined by select(2)
|
*
|
||||||
* \return SSH_SUCCESS operation successful\n
|
* @param readchans A NULL pointer or an array of channel pointers,
|
||||||
|
* terminated by a NULL.
|
||||||
|
*
|
||||||
|
* @param writechans A NULL pointer or an array of channel pointers,
|
||||||
|
* terminated by a NULL.
|
||||||
|
*
|
||||||
|
* @param exceptchans A NULL pointer or an array of channel pointers,
|
||||||
|
* terminated by a NULL.
|
||||||
|
*
|
||||||
|
* @param timeout Timeout as defined by select(2).
|
||||||
|
*
|
||||||
|
* @return SSH_SUCCESS operation successful\n
|
||||||
* SSH_EINTR select(2) syscall was interrupted, relaunch the function
|
* SSH_EINTR select(2) syscall was interrupted, relaunch the function
|
||||||
*/
|
*/
|
||||||
int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptchans, struct
|
int channel_select(CHANNEL **readchans, CHANNEL **writechans,
|
||||||
timeval * timeout){
|
CHANNEL **exceptchans, struct timeval * timeout) {
|
||||||
|
CHANNEL **rchans, **wchans, **echans;
|
||||||
|
CHANNEL *dummy = NULL;
|
||||||
fd_set rset;
|
fd_set rset;
|
||||||
fd_set wset;
|
fd_set wset;
|
||||||
fd_set eset;
|
fd_set eset;
|
||||||
CHANNEL *dummy=NULL;
|
int fdmax = -1;
|
||||||
CHANNEL **rchans, **wchans, **echans;
|
int rc;
|
||||||
int fdmax=-1;
|
|
||||||
int i;
|
int i;
|
||||||
int r;
|
|
||||||
/* don't allow NULL pointers */
|
/* don't allow NULL pointers */
|
||||||
if(!readchans)
|
if (readchans == NULL) {
|
||||||
readchans=&dummy;
|
readchans = &dummy;
|
||||||
if(!writechans)
|
}
|
||||||
writechans=&dummy;
|
|
||||||
if(!exceptchans)
|
if (writechans == NULL) {
|
||||||
exceptchans=&dummy;
|
writechans = &dummy;
|
||||||
if(!readchans[0] && !writechans[0] && !exceptchans[0]){
|
}
|
||||||
/* no channel to poll ?? go away ! */
|
|
||||||
|
if (exceptchans == NULL) {
|
||||||
|
exceptchans = &dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readchans[0] == NULL && writechans[0] == NULL && exceptchans[0] == NULL) {
|
||||||
|
/* No channel to poll?? Go away! */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* prepare the outgoing temporary arrays */
|
|
||||||
|
/* Prepare the outgoing temporary arrays */
|
||||||
rchans = malloc(sizeof(CHANNEL *) * (count_ptrs(readchans) + 1));
|
rchans = malloc(sizeof(CHANNEL *) * (count_ptrs(readchans) + 1));
|
||||||
if (rchans == NULL) {
|
if (rchans == NULL) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
wchans = malloc(sizeof(CHANNEL *) * (count_ptrs(writechans) + 1));
|
wchans = malloc(sizeof(CHANNEL *) * (count_ptrs(writechans) + 1));
|
||||||
if (wchans == NULL) {
|
if (wchans == NULL) {
|
||||||
SAFE_FREE(rchans);
|
SAFE_FREE(rchans);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
echans = malloc(sizeof(CHANNEL *) * (count_ptrs(exceptchans) + 1));
|
echans = malloc(sizeof(CHANNEL *) * (count_ptrs(exceptchans) + 1));
|
||||||
if (echans == NULL) {
|
if (echans == NULL) {
|
||||||
SAFE_FREE(rchans);
|
SAFE_FREE(rchans);
|
||||||
@@ -1760,87 +1781,78 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first, try without doing network stuff */
|
/*
|
||||||
/* then, select and redo the networkless stuff */
|
* First, try without doing network stuff then, select and redo the
|
||||||
|
* networkless stuff
|
||||||
|
*/
|
||||||
do {
|
do {
|
||||||
channel_protocol_select(readchans,writechans,exceptchans,rchans,wchans,echans);
|
channel_protocol_select(readchans, writechans, exceptchans,
|
||||||
if(rchans[0]||wchans[0]||echans[0]){
|
rchans, wchans, echans);
|
||||||
/* we've got one without doing any select */
|
if (rchans[0] != NULL || wchans[0] != NULL || echans[0] != NULL) {
|
||||||
/* overwrite the begining arrays */
|
/* We've got one without doing any select overwrite the begining arrays */
|
||||||
memcpy(readchans,rchans, (count_ptrs(rchans)+1)*sizeof(CHANNEL *));
|
memcpy(readchans, rchans, (count_ptrs(rchans) + 1) * sizeof(CHANNEL *));
|
||||||
memcpy(writechans,wchans, (count_ptrs(wchans)+1)*sizeof(CHANNEL *));
|
memcpy(writechans, wchans, (count_ptrs(wchans) + 1) * sizeof(CHANNEL *));
|
||||||
memcpy(exceptchans,echans, (count_ptrs(echans)+1)*sizeof(CHANNEL *));
|
memcpy(exceptchans, echans, (count_ptrs(echans) + 1) * sizeof(CHANNEL *));
|
||||||
free(rchans);
|
SAFE_FREE(rchans);
|
||||||
free(wchans);
|
SAFE_FREE(wchans);
|
||||||
free(echans);
|
SAFE_FREE(echans);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* since we verified the invalid fd cases into the networkless select,
|
/*
|
||||||
we can be sure all fd are valid ones */
|
* Since we verified the invalid fd cases into the networkless select,
|
||||||
|
* we can be sure all fd are valid ones
|
||||||
|
*/
|
||||||
FD_ZERO(&rset);
|
FD_ZERO(&rset);
|
||||||
FD_ZERO(&wset);
|
FD_ZERO(&wset);
|
||||||
FD_ZERO(&eset);
|
FD_ZERO(&eset);
|
||||||
for(i=0;readchans[i];++i){
|
|
||||||
if(!ssh_socket_fd_isset(readchans[i]->session->socket,&rset))
|
for (i = 0; readchans[i] != NULL; i++) {
|
||||||
|
if (!ssh_socket_fd_isset(readchans[i]->session->socket, &rset)) {
|
||||||
ssh_socket_fd_set(readchans[i]->session->socket, &rset, &fdmax);
|
ssh_socket_fd_set(readchans[i]->session->socket, &rset, &fdmax);
|
||||||
}
|
}
|
||||||
for(i=0;writechans[i];++i){
|
|
||||||
if(!ssh_socket_fd_isset(writechans[i]->session->socket,&wset))
|
|
||||||
ssh_socket_fd_set(writechans[i]->session->socket,&wset, &fdmax);
|
|
||||||
}
|
|
||||||
for(i=0;exceptchans[i];++i){
|
|
||||||
if(!ssh_socket_fd_isset(exceptchans[i]->session->socket,&eset))
|
|
||||||
ssh_socket_fd_set(exceptchans[i]->session->socket,&eset,&fdmax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fd=readchans[i]->session->fd;
|
for (i = 0; writechans[i] != NULL; i++) {
|
||||||
if(!FD_ISSET(fd,&rset)){
|
if (!ssh_socket_fd_isset(writechans[i]->session->socket, &wset)) {
|
||||||
FD_SET(fd,&rset);
|
ssh_socket_fd_set(writechans[i]->session->socket, &wset, &fdmax);
|
||||||
if(fd>=fdmax)
|
|
||||||
fdmax=fd+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
for(i=0;writechans[i];++i){
|
|
||||||
fd=writechans[i]->session->fd;
|
|
||||||
if(!FD_ISSET(fd,&wset)){
|
|
||||||
FD_SET(fd,&wset);
|
|
||||||
if(fd>=fdmax)
|
|
||||||
fdmax=fd+1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0;exceptchans[i];++i){
|
for (i = 0; exceptchans[i] != NULL; i++) {
|
||||||
fd=exceptchans[i]->session->fd;
|
if (!ssh_socket_fd_isset(exceptchans[i]->session->socket, &eset)) {
|
||||||
if(!FD_ISSET(fd,&eset)){
|
ssh_socket_fd_set(exceptchans[i]->session->socket, &eset, &fdmax);
|
||||||
FD_SET(fd,&eset);
|
|
||||||
if(fd>=fdmax)
|
|
||||||
fdmax=fd+1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
/* here we go */
|
/* Here we go */
|
||||||
r=select(fdmax,&rset,&wset,&eset,timeout);
|
rc = select(fdmax, &rset, &wset, &eset, timeout);
|
||||||
/* leave if select was interrupted */
|
/* Leave if select was interrupted */
|
||||||
if(r==EINTR){
|
if (rc == EINTR) {
|
||||||
free(rchans);
|
SAFE_FREE(rchans);
|
||||||
free(wchans);
|
SAFE_FREE(wchans);
|
||||||
free(echans);
|
SAFE_FREE(echans);
|
||||||
return SSH_EINTR;
|
return SSH_EINTR;
|
||||||
}
|
}
|
||||||
for(i=0;readchans[i];++i){
|
|
||||||
if(ssh_socket_fd_isset(readchans[i]->session->socket,&rset))
|
for (i = 0; readchans[i] != NULL; i++) {
|
||||||
|
if (ssh_socket_fd_isset(readchans[i]->session->socket, &rset)) {
|
||||||
ssh_socket_set_toread(readchans[i]->session->socket);
|
ssh_socket_set_toread(readchans[i]->session->socket);
|
||||||
}
|
}
|
||||||
for(i=0;writechans[i];++i){
|
}
|
||||||
if(ssh_socket_fd_isset(writechans[i]->session->socket,&wset))
|
|
||||||
|
for (i = 0; writechans[i] != NULL; i++) {
|
||||||
|
if (ssh_socket_fd_isset(writechans[i]->session->socket, &wset)) {
|
||||||
ssh_socket_set_towrite(writechans[i]->session->socket);
|
ssh_socket_set_towrite(writechans[i]->session->socket);
|
||||||
}
|
}
|
||||||
for(i=0;exceptchans[i];++i){
|
}
|
||||||
if(ssh_socket_fd_isset(exceptchans[i]->session->socket,&eset))
|
|
||||||
|
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);
|
ssh_socket_set_except(exceptchans[i]->session->socket);
|
||||||
}
|
}
|
||||||
} while(1); /* return to do loop */
|
}
|
||||||
|
} while(1); /* Return to do loop */
|
||||||
|
|
||||||
/* not reached */
|
/* not reached */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user