1
1

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
Этот коммит содержится в:
Aris Adamantiadis 2008-03-04 00:44:02 +00:00
родитель 9b5f893513
Коммит 077dd81fcc
9 изменённых файлов: 244 добавлений и 99 удалений

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

@ -285,7 +285,7 @@ struct error_struct {
struct ssh_session { struct ssh_session {
struct error_struct error; struct error_struct error;
int fd; struct socket *socket;
SSH_OPTIONS *options; SSH_OPTIONS *options;
char *serverbanner; char *serverbanner;
char *clientbanner; char *clientbanner;
@ -422,6 +422,21 @@ struct ssh_message {
struct ssh_channel_request channel_request; 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 */ /* session.c */
void ssh_cleanup(SSH_SESSION *session); void ssh_cleanup(SSH_SESSION *session);
@ -603,7 +618,7 @@ char *my_gcry_bn2dec(bignum bn);
#endif /* !HAVE_LIBGCRYPT */ #endif /* !HAVE_LIBGCRYPT */
#ifdef __cplusplus #ifdef __cplusplus
} ; }
#endif #endif
#endif /* _LIBSSH_PRIV_H */ #endif /* _LIBSSH_PRIV_H */

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

@ -6,7 +6,8 @@ libssh_la_SOURCES = auth1.c auth.c base64.c buffer.c \
gzip.c init.c kex.c keyfiles.c \ gzip.c init.c kex.c keyfiles.c \
keys.c messages.c misc.c options.c \ keys.c messages.c misc.c options.c \
packet.c server.c session.c sftp.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 libssh_la_CPPFLAGS = -I$(top_srcdir)/include

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

@ -905,7 +905,7 @@ static int channel_protocol_select(CHANNEL **rchans, CHANNEL **wchans, CHANNEL *
j=0; j=0;
for(i=0;echans[i];++i){ for(i=0;echans[i];++i){
chan=echans[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; eout[j]=chan;
++j; ++j;
} }
@ -940,7 +940,7 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch
CHANNEL *dummy=NULL; CHANNEL *dummy=NULL;
CHANNEL **rchans, **wchans, **echans; CHANNEL **rchans, **wchans, **echans;
int fdmax=-1; int fdmax=-1;
int i,fd; int i;
int r; int r;
/* don't allow NULL pointers */ /* don't allow NULL pointers */
if(!readchans) if(!readchans)
@ -980,12 +980,25 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch
FD_ZERO(&wset); FD_ZERO(&wset);
FD_ZERO(&eset); FD_ZERO(&eset);
for(i=0;readchans[i];++i){ 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)){ if(!FD_ISSET(fd,&rset)){
FD_SET(fd,&rset); FD_SET(fd,&rset);
if(fd>=fdmax) if(fd>=fdmax)
fdmax=fd+1; fdmax=fd+1;
} }
} }
for(i=0;writechans[i];++i){ for(i=0;writechans[i];++i){
fd=writechans[i]->session->fd; fd=writechans[i]->session->fd;
@ -995,6 +1008,7 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch
fdmax=fd+1; fdmax=fd+1;
} }
} }
for(i=0;exceptchans[i];++i){ for(i=0;exceptchans[i];++i){
fd=exceptchans[i]->session->fd; fd=exceptchans[i]->session->fd;
if(!FD_ISSET(fd,&eset)){ if(!FD_ISSET(fd,&eset)){
@ -1003,6 +1017,7 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch
fdmax=fd+1; fdmax=fd+1;
} }
} }
*/
/* here we go */ /* here we go */
r=select(fdmax,&rset,&wset,&eset,timeout); r=select(fdmax,&rset,&wset,&eset,timeout);
/* leave if select was interrupted */ /* leave if select was interrupted */
@ -1013,15 +1028,15 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch
return SSH_EINTR; return SSH_EINTR;
} }
for(i=0;readchans[i];++i){ 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; readchans[i]->session->data_to_read=1;
} }
for(i=0;writechans[i];++i){ 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; writechans[i]->session->data_to_write=1;
} }
for(i=0;exceptchans[i];++i){ 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; exceptchans[i]->session->data_except=1;
} }
} while(1); /* return to do loop */ } while(1); /* return to do loop */

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

@ -36,7 +36,7 @@ char *ssh_get_banner(SSH_SESSION *session){
char buffer[128]; char buffer[128];
int i = 0; int i = 0;
while (i < 127) { 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"); ssh_set_error(session,SSH_FATAL,"Remote host closed connection");
return NULL; return NULL;
} }
@ -98,7 +98,7 @@ int ssh_send_banner(SSH_SESSION *session,int server){
else else
session->clientbanner=strdup(banner); session->clientbanner=strdup(banner);
snprintf(buffer,128,"%s\r\n",banner); snprintf(buffer,128,"%s\r\n",banner);
write(session->fd,buffer,strlen(buffer)); ssh_socket_write(session->socket,buffer,strlen(buffer));
return 0; return 0;
} }
@ -247,12 +247,10 @@ int ssh_connect(SSH_SESSION *session){
if(fd<0) if(fd<0)
return -1; return -1;
set_status(options,0.2); set_status(options,0.2);
session->fd=fd; ssh_socket_set_fd(session->socket,fd);
session->alive=1; session->alive=1;
if(!(session->serverbanner=ssh_get_banner(session))){ if(!(session->serverbanner=ssh_get_banner(session))){
if(session->fd>=0) ssh_socket_close(session->socket);
close(session->fd);
session->fd=-1;
session->alive=0; session->alive=0;
return -1; return -1;
} }
@ -260,9 +258,7 @@ int ssh_connect(SSH_SESSION *session){
ssh_say(2,"banner : %s\n",session->serverbanner); ssh_say(2,"banner : %s\n",session->serverbanner);
/* here we analyse the different protocols the server allows */ /* here we analyse the different protocols the server allows */
if(ssh_analyze_banner(session,&ssh1,&ssh2)){ if(ssh_analyze_banner(session,&ssh1,&ssh2)){
if(session->fd>=0) ssh_socket_close(session->socket);
close(session->fd);
session->fd=-1;
session->alive=0; session->alive=0;
return -1; return -1;
} }
@ -275,8 +271,7 @@ int ssh_connect(SSH_SESSION *session){
ssh_set_error(session,SSH_FATAL, ssh_set_error(session,SSH_FATAL,
"no version of SSH protocol usable (banner: %s)", "no version of SSH protocol usable (banner: %s)",
session->serverbanner); session->serverbanner);
close(session->fd); ssh_socket_close(session->socket);
session->fd=-1;
session->alive=0; session->alive=0;
return -1; return -1;
} }
@ -285,27 +280,21 @@ int ssh_connect(SSH_SESSION *session){
switch(session->version){ switch(session->version){
case 2: case 2:
if(ssh_get_kex(session,0)){ if(ssh_get_kex(session,0)){
if(session->fd>=0) ssh_socket_close(session->socket);
close(session->fd);
session->fd=-1;
session->alive=0; session->alive=0;
return -1; return -1;
} }
set_status(options,0.6); set_status(options,0.6);
ssh_list_kex(&session->server_kex); ssh_list_kex(&session->server_kex);
if(set_kex(session)){ if(set_kex(session)){
if(session->fd>=0) ssh_socket_close(session->socket);
close(session->fd);
session->fd=-1;
session->alive=0; session->alive=0;
return -1; return -1;
} }
ssh_send_kex(session,0); ssh_send_kex(session,0);
set_status(options,0.8); set_status(options,0.8);
if(dh_handshake(session)){ if(dh_handshake(session)){
if(session->fd>=0) ssh_socket_close(session->socket);
close(session->fd);
session->fd=-1;
session->alive=0; session->alive=0;
return -1; return -1;
} }
@ -314,9 +303,7 @@ int ssh_connect(SSH_SESSION *session){
break; break;
case 1: case 1:
if(ssh_get_kex1(session)){ if(ssh_get_kex1(session)){
if(session->fd>=0) ssh_socket_close(session->socket);
close(session->fd);
session->fd=-1;
session->alive=0; session->alive=0;
return -1; return -1;
} }
@ -344,7 +331,7 @@ char *ssh_get_issue_banner(SSH_SESSION *session){
*/ */
void ssh_disconnect(SSH_SESSION *session){ void ssh_disconnect(SSH_SESSION *session){
STRING *str; STRING *str;
if(session->fd!= -1) { if(ssh_socket_is_open(session->socket)) {
packet_clear_out(session); packet_clear_out(session);
buffer_add_u8(session->out_buffer,SSH2_MSG_DISCONNECT); buffer_add_u8(session->out_buffer,SSH2_MSG_DISCONNECT);
buffer_add_u32(session->out_buffer,htonl(SSH2_DISCONNECT_BY_APPLICATION)); 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); buffer_add_ssh_string(session->out_buffer,str);
free(str); free(str);
packet_send(session); packet_send(session);
close(session->fd); ssh_socket_close(session->socket);
session->fd=-1;
} }
session->alive=0; session->alive=0;
ssh_cleanup(session); ssh_cleanup(session);
} }
const char *ssh_copyright(){ 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" " Distributed under the LGPL, please refer to COPYING file for informations"
" about your rights" ; " about your rights" ;
} }

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

@ -189,37 +189,38 @@ int ssh_fd_poll(SSH_SESSION *session, int *write, int *except){
fd_set rdes; // read set fd_set rdes; // read set
fd_set wdes; // writing set fd_set wdes; // writing set
fd_set edes; // exception set fd_set edes; // exception set
int fdmax=-1;
FD_ZERO(&rdes); FD_ZERO(&rdes);
FD_ZERO(&wdes); FD_ZERO(&wdes);
FD_ZERO(&edes); FD_ZERO(&edes);
if(!session->alive || session->fd<0){ if(!session->alive || !ssh_socket_is_open(session->socket)){
*except=1; *except=1;
*write=0; *write=0;
session->alive=0; session->alive=0;
return 0; return 0;
} }
if(!session->data_to_read) if(!session->data_to_read)
FD_SET(session->fd,&rdes); ssh_socket_fd_set(session->socket,&rdes,&fdmax);
if(!session->data_to_write) if(!session->data_to_write)
FD_SET(session->fd,&wdes); ssh_socket_fd_set(session->socket,&wdes,&fdmax);
FD_SET(session->fd,&edes); ssh_socket_fd_set(session->socket,&edes,&fdmax);
/* Set to return immediately (no blocking) */ /* Set to return immediately (no blocking) */
sometime.tv_sec = 0; sometime.tv_sec = 0;
sometime.tv_usec = 0; sometime.tv_usec = 0;
/* Make the call, and listen for errors */ /* 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)); ssh_set_error(NULL,SSH_FATAL, "select: %s", strerror(errno));
return -1; return -1;
} }
if(!session->data_to_read) 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) if(!session->data_to_write)
session->data_to_write=FD_ISSET(session->fd,&wdes); session->data_to_write=ssh_socket_fd_isset(session->socket,&wdes);
*except=FD_ISSET(session->fd,&edes); *except=ssh_socket_fd_isset(session->socket,&edes);
*write=session->data_to_write; *write=session->data_to_write;
return session->data_to_read; 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)); memcpy(&localset,readfds,sizeof(fd_set));
for(i=0;channels[i];i++){ for(i=0;channels[i];i++){
if(channels[i]->session->alive){ if(channels[i]->session->alive){
FD_SET(channels[i]->session->fd,&localset); ssh_socket_fd_set(channels[i]->session->socket,&localset,&maxfd);
if(channels[i]->session->fd>maxfd-1)
maxfd=channels[i]->session->fd+1;
} }
} }
rep=select(maxfd,&localset,NULL,NULL,timeout); 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 */ /* set the data_to_read flag on each session */
for(i=0;channels[i];i++) 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; channels[i]->session->data_to_read=1;
/* now, test each channel */ /* now, test each channel */
j=0; j=0;
for(i=0;channels[i];i++){ 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)){ if((channel_poll(channels[i],0)>0) || (channel_poll(channels[i],1)>0)){
outchannels[j]=channels[i]; outchannels[j]=channels[i];
j++; j++;

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

@ -34,25 +34,7 @@ MA 02111-1307, USA. */
/* XXX include selected mac size */ /* XXX include selected mac size */
static int macsize=SHA_DIGEST_LEN; 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 */ /* 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. */ /* 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; return SSH_OK;
if(session->blocking){ if(session->blocking){
buf=malloc(to_read); 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; session->data_to_read=0;
if(r==SSH_ERROR || r ==0){ if(r==SSH_ERROR || r ==0){
ssh_set_error(session,SSH_FATAL, ssh_set_error(session,SSH_FATAL,
(r==0)?"Connection closed by remote host" : "Error reading socket"); (r==0)?"Connection closed by remote host" : "Error reading socket");
close(session->fd); ssh_socket_close(session->socket);
session->fd=-1;
session->alive=0; session->alive=0;
session->data_except=1; session->data_except=1;
return SSH_ERROR; return SSH_ERROR;
@ -94,16 +75,14 @@ static int socket_read(SSH_SESSION *session,int len){
return SSH_AGAIN; return SSH_AGAIN;
session->data_to_read=0; session->data_to_read=0;
/* read as much as we can */ /* read as much as we can */
if(session->fd>0) if(ssh_socket_is_open(session->socket))
r=read(session->fd,buffer,sizeof(buffer)); r=ssh_socket_read(session->socket,buffer,sizeof(buffer));
else else
r=-1; r=-1;
if(r<=0){ if(r<=0){
ssh_set_error(session,SSH_FATAL, ssh_set_error(session,SSH_FATAL,
(r==0)?"Connection closed by remote host" : "Error reading socket"); (r==0)?"Connection closed by remote host" : "Error reading socket");
if(session->fd>=0) ssh_socket_close(session->socket);
close(session->fd);
session->fd=-1;
session->data_except=1; session->data_except=1;
session->alive=0; session->alive=0;
return SSH_ERROR; return SSH_ERROR;
@ -341,12 +320,13 @@ int packet_translate(SSH_SESSION *session){
return 0; 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; int written;
if(fd<0) if(!ssh_socket_is_open(s))
return SSH_ERROR; return SSH_ERROR;
while(len >0) { while(len >0) {
written=write(fd,buffer,len); written=ssh_socket_write(s,buffer,len);
if(written==0 || written==-1) if(written==0 || written==-1)
return SSH_ERROR; return SSH_ERROR;
len-=written; len-=written;
@ -361,14 +341,15 @@ static int packet_nonblocking_flush(SSH_SESSION *session){
int except, can_write; int except, can_write;
int w; int w;
ssh_fd_poll(session,&can_write,&except); /* internally sets data_to_write */ 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; 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)); ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s",strerror(errno));
return SSH_ERROR; return SSH_ERROR;
} }
while(session->data_to_write && buffer_get_rest_len(session->out_socket_buffer)>0){ while(session->data_to_write && buffer_get_rest_len(session->out_socket_buffer)>0){
if(session->fd>=0){ if(ssh_socket_is_open(session->socket)){
w=write(session->fd,buffer_get_rest(session->out_socket_buffer), w=ssh_socket_write(session->socket,buffer_get_rest(session->out_socket_buffer),
buffer_get_rest_len(session->out_socket_buffer)); buffer_get_rest_len(session->out_socket_buffer));
session->data_to_write=0; session->data_to_write=0;
} else } else
@ -377,8 +358,8 @@ static int packet_nonblocking_flush(SSH_SESSION *session){
session->data_to_write=0; session->data_to_write=0;
session->data_except=1; session->data_except=1;
session->alive=0; session->alive=0;
close(session->fd); ssh_socket_close(session->socket);
session->fd=-1; // FIXME use ssh_socket_get_errno()
ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s", ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s",
strerror(errno)); strerror(errno));
return SSH_ERROR; return SSH_ERROR;
@ -394,7 +375,7 @@ static int packet_nonblocking_flush(SSH_SESSION *session){
/* blocking packet flush */ /* blocking packet flush */
static int packet_blocking_flush(SSH_SESSION *session){ static int packet_blocking_flush(SSH_SESSION *session){
if(session->fd<0) { if(!ssh_socket_is_open(session->socket)) {
session->alive=0; session->alive=0;
return SSH_ERROR; return SSH_ERROR;
} }
@ -402,13 +383,13 @@ static int packet_blocking_flush(SSH_SESSION *session){
return SSH_ERROR; return SSH_ERROR;
if(buffer_get_rest(session->out_socket_buffer)==0) if(buffer_get_rest(session->out_socket_buffer)==0)
return SSH_OK; 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))){ buffer_get_rest_len(session->out_socket_buffer))){
session->data_to_write=0; session->data_to_write=0;
session->data_except=1; session->data_except=1;
session->alive=0; session->alive=0;
close(session->fd); ssh_socket_close(session->socket);
session->fd=-1; // FIXME use the proper errno
ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s", ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s",
strerror(errno)); strerror(errno));
return SSH_ERROR; return SSH_ERROR;
@ -545,8 +526,7 @@ void packet_parse(SSH_SESSION *session){
case SSH_MSG_DISCONNECT: case SSH_MSG_DISCONNECT:
ssh_say(2,"Received SSH_MSG_DISCONNECT\n"); ssh_say(2,"Received SSH_MSG_DISCONNECT\n");
ssh_set_error(session,SSH_FATAL,"Received SSH_MSG_DISCONNECT"); ssh_set_error(session,SSH_FATAL,"Received SSH_MSG_DISCONNECT");
close(session->fd); ssh_socket_close(session->socket);
session->fd=-1;
session->alive=0; session->alive=0;
return; return;
case SSH_SMSG_STDOUT_DATA: case SSH_SMSG_STDOUT_DATA:
@ -572,8 +552,7 @@ void packet_parse(SSH_SESSION *session){
free(error_s); free(error_s);
free(error); free(error);
} }
close(session->fd); ssh_socket_close(session->socket);
session->fd=-1;
session->alive=0; session->alive=0;
return; return;
case SSH2_MSG_CHANNEL_WINDOW_ADJUST: case SSH2_MSG_CHANNEL_WINDOW_ADJUST:

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

@ -148,7 +148,8 @@ SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind){
session=ssh_new(); session=ssh_new();
session->server=1; session->server=1;
session->version=2; 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->options=ssh_options_copy(ssh_bind->options);
session->dsa_key=dsa; session->dsa_key=dsa;
session->rsa_key=rsa; session->rsa_key=rsa;

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

@ -42,7 +42,7 @@ SSH_SESSION *ssh_new() {
memset(session,0,sizeof(SSH_SESSION)); memset(session,0,sizeof(SSH_SESSION));
session->next_crypto=crypto_new(); session->next_crypto=crypto_new();
session->maxchannel=FIRST_CHANNEL; session->maxchannel=FIRST_CHANNEL;
session->fd=-1; session->socket=ssh_socket_new();
session->alive=0; session->alive=0;
session->blocking=1; session->blocking=1;
return session; return session;
@ -70,7 +70,8 @@ void ssh_cleanup(SSH_SESSION *session){
crypto_free(session->current_crypto); crypto_free(session->current_crypto);
if(session->next_crypto) if(session->next_crypto)
crypto_free(session->next_crypto); crypto_free(session->next_crypto);
if(session->socket)
ssh_socket_free(session->socket);
// delete all channels // delete all channels
while(session->channels) while(session->channels)
channel_free(session->channels); channel_free(session->channels);
@ -101,10 +102,8 @@ void ssh_cleanup(SSH_SESSION *session){
* \param session current ssh session * \param session current ssh session
*/ */
void ssh_silent_disconnect(SSH_SESSION *session){ void ssh_silent_disconnect(SSH_SESSION *session){
if(session->fd>=0) ssh_socket_close(session->socket);
close(session->fd);
session->alive=0; session->alive=0;
session->fd=-1;
ssh_disconnect(session); ssh_disconnect(session);
} }
@ -135,7 +134,7 @@ void ssh_set_blocking(SSH_SESSION *session,int blocking){
* not connected * not connected
*/ */
int ssh_get_fd(SSH_SESSION *session){ 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 /** \brief say to the session it has data to read on the file descriptor without blocking

150
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 <unistd.h>
#include <errno.h>
#ifdef _WIN_32
#include <winsock2.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
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 */
}