[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
How use ssh_select after fail in ssh_bind_accept?
[Thread Prev] | [Thread Next]
- Subject: How use ssh_select after fail in ssh_bind_accept?
- From: samail@xxxxx
- Reply-to: libssh@xxxxxxxxxx
- Date: Tue, 17 Mar 2015 12:10:51 +0300
- To: libssh@xxxxxxxxxx
Hello,
I have question about using of ssh_select.
It's required to wait events on several descriptors (ssh and not ssh). The system select or ssh_select can be used for this purpose.
But I have problem with error cases after ssh_bind_accept(). Common algorithm is:
while ( ssh_select( descrs) == SSH_OK)
{
if (ssh_listen_descr is set)
{
ssh_bind_accept()
// create session etc
}
else if ( other descr)
{
....
}
}
When ssh_bind_accept() returns error (for example: 'too many open files' or 'Can't open file'), then ssh_select() will return read event on listening ssh descriptor always. Event the client has stopped already.
How I can process an error of ssh_bind_accept() to avoid endless events in ssh_select() ?
Code example in attach. To reproduce problem try to connect to port=2222.
Note: example will create many files 'delmeXXX' in current dir.
Example of output:
Max open file count was reached: can't open file delme252 (253 files opened). errno=24, strerror: Too many open files
Wait for ssh_select
ssh_select result: 0
ssh_bind_accept failed: Error opening ./ssh_host_dsa_key: Too many open files
Can't accept connection
Wait for ssh_select
ssh_select result: 0
ssh_bind_accept failed: Error opening ./ssh_host_dsa_key: Too many open files
Can't accept connection
Wait for ssh_select
ssh_select result: 0
ssh_bind_accept failed: Error opening ./ssh_host_dsa_key: Too many open files
Can't accept connection
Wait for ssh_select
ssh_select result: 0
...
So, select have endless read event on litening FD.
--
Regards,
Andrey
/*
CC ./server.cc -I/home/shamanin/tmp/libssh/include -I/home/shamanin/tmp/libssh/openssl/inc /home/shamanin/tmp/libssh/libssh_static.a /home/shamanin/tmp/libssh/openssl/lib/libssl.a /home/shamanin/tmp/libssh/openssl/lib/libcrypto.a -lsocket -lz -lnsl -lresolv -lposix4 /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/libgcc.a
*/
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <stdio.h>
#include <sys/time.h>
#include <strings.h>
#include <errno.h>
const int bindPort = 2222;
const char* bindIp = "0.0.0.0";
const char* dsaKeyFile = "./ssh_host_dsa_key";
const char* rsaKeyFile = "./ssh_host_rsa_key";
int setKeys(ssh_bind bind)
{
if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_DSAKEY, dsaKeyFile) < 0)
{
printf("Cannot set DSA key file\n");
return -1;
}
if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_RSAKEY, rsaKeyFile) < 0)
{
printf("Cannot set RSA key file\n");
return -1;
}
return 0;
}
int accept_ssh_connection(ssh_bind bind, ssh_session &retSession)
{
if ((retSession = ssh_new()) == NULL)
{
printf("Can't create ssh session\n");
return -1;
}
int ret = ssh_bind_accept(bind, retSession); // this call should be failed in test
if (ret != SSH_OK)
{
ssh_disconnect(retSession);
ssh_free(retSession);
retSession = 0;
printf("ssh_bind_accept failed: %s\n", ssh_get_error(bind));
return -1;
}
return 0;
}
int select_loop(ssh_bind bind, ssh_session &retSession)
{
ssh_channel channels[1], outchannels[1];
fd_set fds;
int maxfd;
struct timeval timeout;
int listenFd = ssh_bind_get_fd(bind);
timeout.tv_sec=300000; // long time
timeout.tv_usec=0;
channels[0] = 0;
outchannels[0] = 0;
FD_ZERO(&fds);
FD_SET(listenFd,&fds); // in real application fds will contain additional descriptors of other sockets
maxfd = listenFd + 1;
int ret = SSH_OK;
while (ret == SSH_OK)
{
printf("Wait for ssh_select\n");
ret = ssh_select(channels,outchannels,maxfd,&fds,&timeout);
printf("ssh_select result: %d\n", ret);
if (ret == SSH_OK && FD_ISSET(listenFd, &fds)) // is event on SSH listening descriptor
{
if (accept_ssh_connection(bind, retSession) < 0)
{
printf("Can't accept connection\n");
{
char buf[32];
int rres = read(listenFd, buf, sizeof(buf));
printf("read %d bytes from failed socket\n", rres);
}
continue; // we can't accept incomming SSH connection for any reason, but we should listen descriptors for other events
// problem is: ssh_select returns event for listening descriptor always, after fail in ssh_bind_accept
//return -1;
}
else
{
printf("Connection was accepted\n");
}
}
}
return 0;
}
void openFiles()
{
for(int i=0; i<10000; ++i)
{
char fname[128];
snprintf(fname, sizeof(fname), "delme%d", i);
FILE* fp = fopen(fname, "w");
if (!fp)
{
int err = errno;
printf("Max open file count was reached: can't open file %s (%d files opened). errno=%d, strerror: %s\n", fname, i+1, err, strerror(err));
if (i < 10)
printf("++++ Few files were opened. May be test was reproducced incorrectly.\n");
return;
}
}
}
int main()
{
ssh_bind bind = 0;
ssh_session session = 0;
ssh_channel channel = 0;
if(ssh_init() != 0)
{
printf("Can't init libssh\n");
return -1;
}
if ((bind = ssh_bind_new()) == NULL)
{
printf("ssh_bind_new error: %s\n",ssh_get_error(bind));
return -1;
}
if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDADDR, bindIp) < 0 ||
ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT, (void*) &bindPort) < 0)
{
printf("ssh_bind_options_set error: %s\n",ssh_get_error(bind));
return -1;
}
if (setKeys(bind) < 0)
return -1;
if (ssh_bind_listen(bind) < 0)
{
printf("ssh_bind_listen error: %s\n",ssh_get_error(bind));
return -1;
}
openFiles();
select_loop(bind, session);
ssh_finalize();
return 0;
}
Archive administrator: postmaster@lists.cynapses.org