aboutsummaryrefslogtreecommitdiff
path: root/libssh/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'libssh/socket.c')
-rw-r--r--libssh/socket.c92
1 files changed, 65 insertions, 27 deletions
diff --git a/libssh/socket.c b/libssh/socket.c
index 0aefa017..41a16a8d 100644
--- a/libssh/socket.c
+++ b/libssh/socket.c
@@ -39,6 +39,10 @@
struct socket {
socket_t fd;
int last_errno;
+ int data_to_read; /* reading now on socket will
+ not block */
+ int data_to_write;
+ int data_except;
BUFFER *out_buffer;
BUFFER *in_buffer;
SSH_SESSION *session;
@@ -121,12 +125,18 @@ int ssh_socket_is_open(struct socket *s){
* \brief read len bytes from socket into buffer
*/
int ssh_socket_unbuffered_read(struct socket *s, void *buffer, int len){
- int r=recv(s->fd,buffer,len,0);
+ int r;
+ if(s->data_except)
+ return -1;
+ r=recv(s->fd,buffer,len,0);
#ifndef _WIN32
s->last_errno=errno;
#else
s->last_errno=WSAGetLastError();
-#endif
+#endif
+ s->data_to_read=0;
+ if(r<0)
+ s->data_except=1;
return r;
}
@@ -134,13 +144,18 @@ int ssh_socket_unbuffered_read(struct socket *s, void *buffer, int len){
* \brief writes len bytes from buffer to socket
*/
int ssh_socket_unbuffered_write(struct socket *s,const void *buffer, int len){
- int w=send(s->fd,buffer,len,0);
+ int w;
+ if(s->data_except)
+ return -1;
+ w=send(s->fd,buffer,len,0);
#ifndef _WIN32
s->last_errno=errno;
#else
s->last_errno=WSAGetLastError();
#endif
-
+ s->data_to_write=0;
+ if(w<0)
+ s->data_except=1;
return w;
}
@@ -276,13 +291,12 @@ int ssh_socket_wait_for_data(struct socket *s, SSH_SESSION *session,int len){
if(session->blocking){
buf=malloc(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");
ssh_socket_close(session->socket);
session->alive=0;
- session->data_except=1;
+ free(buf);
leave_function();
return SSH_ERROR;
}
@@ -295,11 +309,11 @@ int ssh_socket_wait_for_data(struct socket *s, SSH_SESSION *session,int len){
/* nonblocking read */
do {
ssh_socket_poll(s,&can_write,&except); /* internally sets data_to_read */
- if(!session->data_to_read){
+ if(!s->data_to_read){
leave_function();
return SSH_AGAIN;
}
- session->data_to_read=0;
+
/* read as much as we can */
if(ssh_socket_is_open(session->socket))
r=ssh_socket_unbuffered_read(session->socket,buffer,sizeof(buffer));
@@ -309,7 +323,6 @@ int ssh_socket_wait_for_data(struct socket *s, SSH_SESSION *session,int len){
ssh_set_error(session,SSH_FATAL,
(r==0)?"Connection closed by remote host" : "Error reading socket");
ssh_socket_close(session->socket);
- session->data_except=1;
session->alive=0;
leave_function();
return SSH_ERROR;
@@ -343,9 +356,9 @@ int ssh_socket_poll(struct socket *s, int *write, int *except){
*write=0;
return 0;
}
- if(!session->data_to_read)
+ if(!s->data_to_read)
ssh_socket_fd_set(s,&rdes,&fdmax);
- if(!session->data_to_write)
+ if(!s->data_to_write)
ssh_socket_fd_set(s,&wdes,&fdmax);
ssh_socket_fd_set(s,&edes,&fdmax);
@@ -359,13 +372,15 @@ int ssh_socket_poll(struct socket *s, int *write, int *except){
leave_function();
return -1;
}
- if(!session->data_to_read)
- session->data_to_read=ssh_socket_fd_isset(session->socket,&rdes);
- if(!session->data_to_write)
- 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;
+ if(!s->data_to_read)
+ s->data_to_read=ssh_socket_fd_isset(s,&rdes);
+ if(!s->data_to_write)
+ s->data_to_write=ssh_socket_fd_isset(s,&wdes);
+ if(!s->data_except)
+ s->data_except=ssh_socket_fd_isset(s,&edes);
+ *except=s->data_except;
+ *write=s->data_to_write;
+ return s->data_to_read;
}
/** \internal
@@ -384,16 +399,13 @@ int ssh_socket_nonblocking_flush(struct socket *s){
leave_function();
return SSH_ERROR;
}
- while(session->data_to_write && buffer_get_rest_len(s->out_buffer)>0){
+ while(s->data_to_write && buffer_get_rest_len(s->out_buffer)>0){
if(ssh_socket_is_open(s)){
w=ssh_socket_unbuffered_write(s,buffer_get_rest(s->out_buffer),
buffer_get_rest_len(s->out_buffer));
- session->data_to_write=0;
} else
w=-1; /* write failed */
if(w<0){
- session->data_to_write=0;
- session->data_except=1;
session->alive=0;
ssh_socket_close(s);
// FIXME use ssh_socket_get_errno()
@@ -416,7 +428,7 @@ int ssh_socket_nonblocking_flush(struct socket *s){
/** \internal
- * \brief locking flush of the output buffer
+ * \brief locking flush of the output packet buffer
*/
int ssh_socket_blocking_flush(struct socket *s){
SSH_SESSION *session=s->session;
@@ -426,7 +438,7 @@ int ssh_socket_blocking_flush(struct socket *s){
leave_function();
return SSH_ERROR;
}
- if(session->data_except){
+ if(s->data_except){
leave_function();
return SSH_ERROR;
}
@@ -436,8 +448,6 @@ int ssh_socket_blocking_flush(struct socket *s){
}
if(ssh_socket_completewrite(s,buffer_get_rest(s->out_buffer),
buffer_get_rest_len(s->out_buffer))){
- session->data_to_write=0;
- session->data_except=1;
session->alive=0;
ssh_socket_close(s);
// FIXME use the proper errno
@@ -446,11 +456,39 @@ int ssh_socket_blocking_flush(struct socket *s){
leave_function();
return SSH_ERROR;
}
- session->data_to_write=0;
buffer_reinit(s->out_buffer);
leave_function();
return SSH_OK; // no data pending
}
+void ssh_socket_set_towrite(struct socket *s){
+ s->data_to_write=1;
+}
+
+void ssh_socket_set_toread(struct socket *s){
+ s->data_to_read=1;
+}
+
+void ssh_socket_set_except(struct socket *s){
+ s->data_except=1;
+}
+
+int ssh_socket_data_available(struct socket *s){
+ return s->data_to_read;
+}
+
+int ssh_socket_data_writable(struct socket *s){
+ return s->data_to_write;
+}
+
+int ssh_socket_get_status(struct socket *s){
+ int r=0;
+ if(s->data_to_read)
+ r |= SSH_READ_PENDING;
+ if(s->data_except)
+ r|= SSH_CLOSED_ERROR;
+ return r;
+}
+
/** @}
*/