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 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 */

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

@ -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

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

@ -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 */

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

@ -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" ;
}

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

@ -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++;

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

@ -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:

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

@ -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;

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

@ -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

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 */
}