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
Этот коммит содержится в:
родитель
9b5f893513
Коммит
077dd81fcc
@ -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
Обычный файл
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 */
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче
Block a user