From 077dd81fcc9453613de18c6d037ef61f3a8e161c Mon Sep 17 00:00:00 2001 From: Aris Adamantiadis Date: Tue, 4 Mar 2008 00:44:02 +0000 Subject: [PATCH] added the socket class and created wrappers git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@137 7dcaeef0-15fb-0310-b436-a5af3365683c --- include/libssh/priv.h | 19 +++++- libssh/Makefile.am | 3 +- libssh/channels.c | 27 ++++++-- libssh/client.c | 40 ++++------- libssh/connect.c | 25 ++++--- libssh/packet.c | 65 +++++++----------- libssh/server.c | 3 +- libssh/session.c | 11 ++-- libssh/socket.c | 150 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 244 insertions(+), 99 deletions(-) create mode 100644 libssh/socket.c diff --git a/include/libssh/priv.h b/include/libssh/priv.h index b871e1f7..08f9744d 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -285,7 +285,7 @@ struct error_struct { struct ssh_session { struct error_struct error; - int fd; + struct socket *socket; SSH_OPTIONS *options; char *serverbanner; char *clientbanner; @@ -422,6 +422,21 @@ struct ssh_message { struct ssh_channel_request channel_request; }; +/* socketc.c */ + +struct socket; +struct socket *ssh_socket_new(); +void ssh_socket_free(struct socket *s); +void ssh_socket_set_fd(struct socket *s, int fd); +int ssh_socket_get_fd(struct socket *s); +void ssh_socket_close(struct socket *s); +int ssh_socket_read(struct socket *s, void *buffer, int len); +int ssh_socket_write(struct socket *s,const void *buffer, int len); +int ssh_socket_is_open(struct socket *s); +int ssh_socket_fd_isset(struct socket *s, fd_set *set); +void ssh_socket_fd_set(struct socket *s, fd_set *set, int *fd_max); +int ssh_socket_completeread(struct socket *s, void *buffer, int len); + /* session.c */ void ssh_cleanup(SSH_SESSION *session); @@ -603,7 +618,7 @@ char *my_gcry_bn2dec(bignum bn); #endif /* !HAVE_LIBGCRYPT */ #ifdef __cplusplus -} ; +} #endif #endif /* _LIBSSH_PRIV_H */ diff --git a/libssh/Makefile.am b/libssh/Makefile.am index 3804ac76..50367a4e 100644 --- a/libssh/Makefile.am +++ b/libssh/Makefile.am @@ -6,7 +6,8 @@ libssh_la_SOURCES = auth1.c auth.c base64.c buffer.c \ gzip.c init.c kex.c keyfiles.c \ keys.c messages.c misc.c options.c \ packet.c server.c session.c sftp.c \ - sftpserver.c string.c wrapper.c + sftpserver.c string.c wrapper.c \ + socket.c libssh_la_CPPFLAGS = -I$(top_srcdir)/include diff --git a/libssh/channels.c b/libssh/channels.c index b9f757df..65a2af3a 100644 --- a/libssh/channels.c +++ b/libssh/channels.c @@ -905,7 +905,7 @@ static int channel_protocol_select(CHANNEL **rchans, CHANNEL **wchans, CHANNEL * j=0; for(i=0;echans[i];++i){ chan=echans[i]; - if(chan->session->fd==-1 || !chan->open || chan->session->data_except){ + if(!ssh_socket_is_open(chan->session->socket) || !chan->open || chan->session->data_except){ eout[j]=chan; ++j; } @@ -940,7 +940,7 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch CHANNEL *dummy=NULL; CHANNEL **rchans, **wchans, **echans; int fdmax=-1; - int i,fd; + int i; int r; /* don't allow NULL pointers */ if(!readchans) @@ -980,12 +980,25 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch FD_ZERO(&wset); FD_ZERO(&eset); for(i=0;readchans[i];++i){ - fd=readchans[i]->session->fd; + if(!ssh_socket_fd_isset(readchans[i]->session->socket,&rset)) + 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; if(!FD_ISSET(fd,&rset)){ FD_SET(fd,&rset); if(fd>=fdmax) fdmax=fd+1; } + } for(i=0;writechans[i];++i){ fd=writechans[i]->session->fd; @@ -995,6 +1008,7 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch fdmax=fd+1; } } + for(i=0;exceptchans[i];++i){ fd=exceptchans[i]->session->fd; if(!FD_ISSET(fd,&eset)){ @@ -1003,6 +1017,7 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch fdmax=fd+1; } } +*/ /* here we go */ r=select(fdmax,&rset,&wset,&eset,timeout); /* leave if select was interrupted */ @@ -1013,15 +1028,15 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch return SSH_EINTR; } for(i=0;readchans[i];++i){ - if(FD_ISSET(readchans[i]->session->fd,&rset)) + if(ssh_socket_fd_isset(readchans[i]->session->socket,&rset)) readchans[i]->session->data_to_read=1; } for(i=0;writechans[i];++i){ - if(FD_ISSET(writechans[i]->session->fd,&wset)) + if(ssh_socket_fd_isset(writechans[i]->session->socket,&wset)) writechans[i]->session->data_to_write=1; } for(i=0;exceptchans[i];++i){ - if(FD_ISSET(exceptchans[i]->session->fd,&eset)) + if(ssh_socket_fd_isset(exceptchans[i]->session->socket,&eset)) exceptchans[i]->session->data_except=1; } } while(1); /* return to do loop */ diff --git a/libssh/client.c b/libssh/client.c index 9af4e627..c498a9ad 100644 --- a/libssh/client.c +++ b/libssh/client.c @@ -36,7 +36,7 @@ char *ssh_get_banner(SSH_SESSION *session){ char buffer[128]; int i = 0; while (i < 127) { - if(session->fd <0 || read(session->fd, &buffer[i], 1)<=0){ + if(!ssh_socket_is_open(session->socket) || ssh_socket_read(session->socket, &buffer[i], 1)<=0){ ssh_set_error(session,SSH_FATAL,"Remote host closed connection"); return NULL; } @@ -98,7 +98,7 @@ int ssh_send_banner(SSH_SESSION *session,int server){ else session->clientbanner=strdup(banner); snprintf(buffer,128,"%s\r\n",banner); - write(session->fd,buffer,strlen(buffer)); + ssh_socket_write(session->socket,buffer,strlen(buffer)); return 0; } @@ -247,12 +247,10 @@ int ssh_connect(SSH_SESSION *session){ if(fd<0) return -1; set_status(options,0.2); - session->fd=fd; + ssh_socket_set_fd(session->socket,fd); session->alive=1; if(!(session->serverbanner=ssh_get_banner(session))){ - if(session->fd>=0) - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->alive=0; return -1; } @@ -260,9 +258,7 @@ int ssh_connect(SSH_SESSION *session){ ssh_say(2,"banner : %s\n",session->serverbanner); /* here we analyse the different protocols the server allows */ if(ssh_analyze_banner(session,&ssh1,&ssh2)){ - if(session->fd>=0) - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->alive=0; return -1; } @@ -275,8 +271,7 @@ int ssh_connect(SSH_SESSION *session){ ssh_set_error(session,SSH_FATAL, "no version of SSH protocol usable (banner: %s)", session->serverbanner); - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->alive=0; return -1; } @@ -285,27 +280,21 @@ int ssh_connect(SSH_SESSION *session){ switch(session->version){ case 2: if(ssh_get_kex(session,0)){ - if(session->fd>=0) - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->alive=0; return -1; } set_status(options,0.6); ssh_list_kex(&session->server_kex); if(set_kex(session)){ - if(session->fd>=0) - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->alive=0; return -1; } ssh_send_kex(session,0); set_status(options,0.8); if(dh_handshake(session)){ - if(session->fd>=0) - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->alive=0; return -1; } @@ -314,9 +303,7 @@ int ssh_connect(SSH_SESSION *session){ break; case 1: if(ssh_get_kex1(session)){ - if(session->fd>=0) - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->alive=0; return -1; } @@ -344,7 +331,7 @@ char *ssh_get_issue_banner(SSH_SESSION *session){ */ void ssh_disconnect(SSH_SESSION *session){ STRING *str; - if(session->fd!= -1) { + if(ssh_socket_is_open(session->socket)) { packet_clear_out(session); buffer_add_u8(session->out_buffer,SSH2_MSG_DISCONNECT); buffer_add_u32(session->out_buffer,htonl(SSH2_DISCONNECT_BY_APPLICATION)); @@ -352,15 +339,14 @@ void ssh_disconnect(SSH_SESSION *session){ buffer_add_ssh_string(session->out_buffer,str); free(str); packet_send(session); - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); } session->alive=0; ssh_cleanup(session); } const char *ssh_copyright(){ - return LIBSSH_VERSION " (c) 2003-2006 Aris Adamantiadis (aris@0xbadc0de.be)" + return LIBSSH_VERSION " (c) 2003-2008 Aris Adamantiadis (aris@0xbadc0de.be)" " Distributed under the LGPL, please refer to COPYING file for informations" " about your rights" ; } diff --git a/libssh/connect.c b/libssh/connect.c index c797dc28..59760900 100644 --- a/libssh/connect.c +++ b/libssh/connect.c @@ -189,37 +189,38 @@ int ssh_fd_poll(SSH_SESSION *session, int *write, int *except){ fd_set rdes; // read set fd_set wdes; // writing set fd_set edes; // exception set + int fdmax=-1; FD_ZERO(&rdes); FD_ZERO(&wdes); FD_ZERO(&edes); - if(!session->alive || session->fd<0){ + if(!session->alive || !ssh_socket_is_open(session->socket)){ *except=1; *write=0; session->alive=0; return 0; } if(!session->data_to_read) - FD_SET(session->fd,&rdes); + ssh_socket_fd_set(session->socket,&rdes,&fdmax); if(!session->data_to_write) - FD_SET(session->fd,&wdes); - FD_SET(session->fd,&edes); + ssh_socket_fd_set(session->socket,&wdes,&fdmax); + ssh_socket_fd_set(session->socket,&edes,&fdmax); /* Set to return immediately (no blocking) */ sometime.tv_sec = 0; sometime.tv_usec = 0; /* Make the call, and listen for errors */ - if (select(session->fd + 1, &rdes,&wdes,&edes, &sometime) < 0) { + if (select(fdmax, &rdes,&wdes,&edes, &sometime) < 0) { ssh_set_error(NULL,SSH_FATAL, "select: %s", strerror(errno)); return -1; } if(!session->data_to_read) - session->data_to_read=FD_ISSET(session->fd,&rdes); + session->data_to_read=ssh_socket_fd_isset(session->socket,&rdes); if(!session->data_to_write) - session->data_to_write=FD_ISSET(session->fd,&wdes); - *except=FD_ISSET(session->fd,&edes); + session->data_to_write=ssh_socket_fd_isset(session->socket,&wdes); + *except=ssh_socket_fd_isset(session->socket,&edes); *write=session->data_to_write; return session->data_to_read; } @@ -285,9 +286,7 @@ int ssh_select(CHANNEL **channels,CHANNEL **outchannels, int maxfd, fd_set *read memcpy(&localset,readfds,sizeof(fd_set)); for(i=0;channels[i];i++){ if(channels[i]->session->alive){ - FD_SET(channels[i]->session->fd,&localset); - if(channels[i]->session->fd>maxfd-1) - maxfd=channels[i]->session->fd+1; + ssh_socket_fd_set(channels[i]->session->socket,&localset,&maxfd); } } rep=select(maxfd,&localset,NULL,NULL,timeout); @@ -301,13 +300,13 @@ int ssh_select(CHANNEL **channels,CHANNEL **outchannels, int maxfd, fd_set *read } /* set the data_to_read flag on each session */ for(i=0;channels[i];i++) - if(channels[i]->session->alive && FD_ISSET(channels[i]->session->fd,&localset)) + if(channels[i]->session->alive && ssh_socket_fd_isset(channels[i]->session->socket,&localset)) channels[i]->session->data_to_read=1; /* now, test each channel */ j=0; for(i=0;channels[i];i++){ - if(channels[i]->session->alive && FD_ISSET(channels[i]->session->fd,&localset)) + if(channels[i]->session->alive && ssh_socket_fd_isset(channels[i]->session->socket,&localset)) if((channel_poll(channels[i],0)>0) || (channel_poll(channels[i],1)>0)){ outchannels[j]=channels[i]; j++; diff --git a/libssh/packet.c b/libssh/packet.c index 00f87f8e..a4d07267 100644 --- a/libssh/packet.c +++ b/libssh/packet.c @@ -34,25 +34,7 @@ MA 02111-1307, USA. */ /* XXX include selected mac size */ static int macsize=SHA_DIGEST_LEN; -/* completeread will read blocking until len bytes have been read */ -static int completeread(int fd, void *buffer, int len){ - int r; - int total=0; - int toread=len; - if(fd<0) - return SSH_ERROR; - while((r=read(fd,buffer+total,toread))){ - if(r==-1) - return SSH_ERROR; - total += r; - toread-=r; - if(total==len) - return len; - if(r==0) - return 0; - } - return total ; /* connection closed */ -} + /* in nonblocking mode, socket_read will read as much as it can, and return */ /* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */ @@ -71,13 +53,12 @@ static int socket_read(SSH_SESSION *session,int len){ return SSH_OK; if(session->blocking){ buf=malloc(to_read); - r=completeread(session->fd,buf,to_read); + r=ssh_socket_completeread(session->socket,buf,to_read); session->data_to_read=0; if(r==SSH_ERROR || r ==0){ ssh_set_error(session,SSH_FATAL, (r==0)?"Connection closed by remote host" : "Error reading socket"); - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->alive=0; session->data_except=1; return SSH_ERROR; @@ -94,16 +75,14 @@ static int socket_read(SSH_SESSION *session,int len){ return SSH_AGAIN; session->data_to_read=0; /* read as much as we can */ - if(session->fd>0) - r=read(session->fd,buffer,sizeof(buffer)); + if(ssh_socket_is_open(session->socket)) + r=ssh_socket_read(session->socket,buffer,sizeof(buffer)); else r=-1; if(r<=0){ ssh_set_error(session,SSH_FATAL, (r==0)?"Connection closed by remote host" : "Error reading socket"); - if(session->fd>=0) - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->data_except=1; session->alive=0; return SSH_ERROR; @@ -341,12 +320,13 @@ int packet_translate(SSH_SESSION *session){ return 0; } -static int atomic_write(int fd, void *buffer, int len){ +// FIXME moves it in socket.c and rename it ssh_socket_completewrite() +static int atomic_write(struct socket *s, void *buffer, int len){ int written; - if(fd<0) + if(!ssh_socket_is_open(s)) return SSH_ERROR; while(len >0) { - written=write(fd,buffer,len); + written=ssh_socket_write(s,buffer,len); if(written==0 || written==-1) return SSH_ERROR; len-=written; @@ -361,14 +341,15 @@ static int packet_nonblocking_flush(SSH_SESSION *session){ int except, can_write; int w; ssh_fd_poll(session,&can_write,&except); /* internally sets data_to_write */ - if(session->fd<0){ + if(!ssh_socket_is_open(session->socket)){ session->alive=0; + // FIXME use ssh_socket_get_errno ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s",strerror(errno)); return SSH_ERROR; } while(session->data_to_write && buffer_get_rest_len(session->out_socket_buffer)>0){ - if(session->fd>=0){ - w=write(session->fd,buffer_get_rest(session->out_socket_buffer), + if(ssh_socket_is_open(session->socket)){ + w=ssh_socket_write(session->socket,buffer_get_rest(session->out_socket_buffer), buffer_get_rest_len(session->out_socket_buffer)); session->data_to_write=0; } else @@ -377,8 +358,8 @@ static int packet_nonblocking_flush(SSH_SESSION *session){ session->data_to_write=0; session->data_except=1; session->alive=0; - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); + // FIXME use ssh_socket_get_errno() ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s", strerror(errno)); return SSH_ERROR; @@ -394,7 +375,7 @@ static int packet_nonblocking_flush(SSH_SESSION *session){ /* blocking packet flush */ static int packet_blocking_flush(SSH_SESSION *session){ - if(session->fd<0) { + if(!ssh_socket_is_open(session->socket)) { session->alive=0; return SSH_ERROR; } @@ -402,13 +383,13 @@ static int packet_blocking_flush(SSH_SESSION *session){ return SSH_ERROR; if(buffer_get_rest(session->out_socket_buffer)==0) return SSH_OK; - if(atomic_write(session->fd,buffer_get_rest(session->out_socket_buffer), + if(atomic_write(session->socket,buffer_get_rest(session->out_socket_buffer), buffer_get_rest_len(session->out_socket_buffer))){ session->data_to_write=0; session->data_except=1; session->alive=0; - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); + // FIXME use the proper errno ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s", strerror(errno)); return SSH_ERROR; @@ -545,8 +526,7 @@ void packet_parse(SSH_SESSION *session){ case SSH_MSG_DISCONNECT: ssh_say(2,"Received SSH_MSG_DISCONNECT\n"); ssh_set_error(session,SSH_FATAL,"Received SSH_MSG_DISCONNECT"); - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->alive=0; return; case SSH_SMSG_STDOUT_DATA: @@ -572,8 +552,7 @@ void packet_parse(SSH_SESSION *session){ free(error_s); free(error); } - close(session->fd); - session->fd=-1; + ssh_socket_close(session->socket); session->alive=0; return; case SSH2_MSG_CHANNEL_WINDOW_ADJUST: diff --git a/libssh/server.c b/libssh/server.c index 4060c54c..06d5879f 100644 --- a/libssh/server.c +++ b/libssh/server.c @@ -148,7 +148,8 @@ SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind){ session=ssh_new(); session->server=1; session->version=2; - session->fd=fd; + session->socket=ssh_socket_new(); + ssh_socket_set_fd(session->socket,fd); session->options=ssh_options_copy(ssh_bind->options); session->dsa_key=dsa; session->rsa_key=rsa; diff --git a/libssh/session.c b/libssh/session.c index 1f19640d..06b31ab3 100644 --- a/libssh/session.c +++ b/libssh/session.c @@ -42,7 +42,7 @@ SSH_SESSION *ssh_new() { memset(session,0,sizeof(SSH_SESSION)); session->next_crypto=crypto_new(); session->maxchannel=FIRST_CHANNEL; - session->fd=-1; + session->socket=ssh_socket_new(); session->alive=0; session->blocking=1; return session; @@ -70,7 +70,8 @@ void ssh_cleanup(SSH_SESSION *session){ crypto_free(session->current_crypto); if(session->next_crypto) crypto_free(session->next_crypto); - + if(session->socket) + ssh_socket_free(session->socket); // delete all channels while(session->channels) channel_free(session->channels); @@ -101,10 +102,8 @@ void ssh_cleanup(SSH_SESSION *session){ * \param session current ssh session */ void ssh_silent_disconnect(SSH_SESSION *session){ - if(session->fd>=0) - close(session->fd); + ssh_socket_close(session->socket); session->alive=0; - session->fd=-1; ssh_disconnect(session); } @@ -135,7 +134,7 @@ void ssh_set_blocking(SSH_SESSION *session,int blocking){ * not connected */ int ssh_get_fd(SSH_SESSION *session){ - return session->fd; + return ssh_socket_get_fd(session->socket); } /** \brief say to the session it has data to read on the file descriptor without blocking diff --git a/libssh/socket.c b/libssh/socket.c new file mode 100644 index 00000000..c37fcaa9 --- /dev/null +++ b/libssh/socket.c @@ -0,0 +1,150 @@ +/* socket.c */ +/* the Socket class */ +/* + * Copyright 2008 Aris Adamantiadis + * + * This file is part of the SSH Library + * + * The SSH Library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the SSH Library; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. */ +#include "libssh/priv.h" +#include +#include +#ifdef _WIN_32 +#include +#endif +#include +#include + +struct socket { + int fd; + int last_errno; +}; + +/* + * \internal + * \brief creates a new Socket object + */ +struct socket *ssh_socket_new(){ + struct socket *s=malloc(sizeof(struct socket)); + s->fd=-1; + s->last_errno=-1; + return s; +} + +/* \internal + * \brief Deletes a socket object + */ +void ssh_socket_free(struct socket *s){ + free(s); +} + +/* \internal + * \brief closes a socket + */ +void ssh_socket_close(struct socket *s){ + if(ssh_socket_is_open(s)){ +#ifdef _WIN_32 + closesocket(s->fd); +#else + close(s->fd); +#endif + s->last_errno=errno; + s->fd=-1; + } +} + +/* \internal + * \brief sets the file descriptor of the socket + */ +void ssh_socket_set_fd(struct socket *s, int fd){ + s->fd=fd; +} + +/* \internal + * \brief returns the file descriptor of the socket + */ +int ssh_socket_get_fd(struct socket *s){ + return s->fd; +} + +/* \internal + * \brief returns nonzero if the socket is open + */ +int ssh_socket_is_open(struct socket *s){ + return s->fd != -1; +} + +/* \internal + * \brief read len bytes from socket into buffer + */ +int ssh_socket_read(struct socket *s, void *buffer, int len){ + int r=recv(s->fd,buffer,len,0); + s->last_errno=errno; + return r; +} + +/* \internal + * \brief writes len bytes from byffer to socket + */ +int ssh_socket_write(struct socket *s,const void *buffer, int len){ + int w=send(s->fd,buffer,len,0); + s->last_errno=errno; + return w; +} + +/* \internal + * \brief returns nonzero if the current socket is in the fd_set + */ +int ssh_socket_fd_isset(struct socket *s, fd_set *set){ + if(s->fd==-1) + return 0; + return FD_ISSET(s->fd,set); +} + +/* \internal + * \brief sets the current fd in a fd_set and updates the fd_max + */ + +void ssh_socket_fd_set(struct socket *s, fd_set *set, int *fd_max){ + if(s->fd==-1) + return; + FD_SET(s->fd,set); + if(s->fd>= *fd_max){ + *fd_max=s->fd+1; + } +} + +/* \internal + * \brief reads blocking until len bytes have been read + */ +int ssh_socket_completeread(struct socket *s, void *buffer, int len){ + int r; + int total=0; + int toread=len; + if(!ssh_socket_is_open(s)) + return SSH_ERROR; + while((r=ssh_socket_read(s,buffer+total,toread))){ + if(r==-1) + return SSH_ERROR; + total += r; + toread-=r; + if(total==len) + return len; + if(r==0) + return 0; + } + return total ; /* connection closed */ +}