aboutsummaryrefslogtreecommitdiff
path: root/libssh/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'libssh/packet.c')
-rw-r--r--libssh/packet.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/libssh/packet.c b/libssh/packet.c
index 330b6908..b653bb63 100644
--- a/libssh/packet.c
+++ b/libssh/packet.c
@@ -335,19 +335,19 @@ int packet_translate(SSH_SESSION *session){
static int atomic_write(int fd, void *buffer, int len){
int written;
- do {
+ while(len >0) {
written=write(fd,buffer,len);
if(written==0 || written==-1)
- return -1;
+ return SSH_ERROR;
len-=written;
buffer+=written;
- } while (len > 0);
+ }
return SSH_OK;
}
/* when doing a nonblocking write, you should issue the packet_write only once, then
* do packet_nonblocking_flush() until you get a SSH_OK or a SSH_ERROR */
-int packet_nonblocking_flush(SSH_SESSION *session){
+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 */
@@ -375,7 +375,11 @@ int packet_nonblocking_flush(SSH_SESSION *session){
}
/* blocking packet flush */
-int packet_blocking_flush(SSH_SESSION *session){
+static int packet_blocking_flush(SSH_SESSION *session){
+ if(session->data_except)
+ 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),
buffer_get_rest_len(session->out_socket_buffer))){
session->data_to_write=0;
@@ -392,6 +396,16 @@ int packet_blocking_flush(SSH_SESSION *session){
return SSH_OK; // no data pending
}
+/* Write the the bufferized output. If the session is blocking, or enforce_blocking
+ * is set, the call may block. Otherwise, it won't block.
+ * return SSH°OK if everything has been sent, SSH_AGAIN if there are still things
+ * to send on buffer, SSH_ERROR if there is an error. */
+int packet_flush(SSH_SESSION *session, int enforce_blocking){
+ if(enforce_blocking || session->blocking)
+ return packet_blocking_flush(session);
+ return packet_nonblocking_flush(session);
+}
+
/* this function places the outgoing packet buffer into an outgoing socket buffer */
static int socket_write(SSH_SESSION *session){
if(!session->out_socket_buffer){
@@ -596,15 +610,17 @@ static int packet_wait1(SSH_SESSION *session,int type,int blocking){
}
#endif /* HAVE_SSH1 */
static int packet_wait2(SSH_SESSION *session,int type,int blocking){
+ int ret;
while(1){
- if(packet_read2(session))
- return -1;
+ ret=packet_read2(session);
+ if(ret != SSH_OK)
+ return ret;
if(packet_translate(session))
- return -1;
+ return SSH_ERROR;
switch(session->in_packet.type){
case SSH2_MSG_DISCONNECT:
packet_parse(session);
- return -1;
+ return SSH_ERROR;
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
case SSH2_MSG_CHANNEL_DATA:
case SSH2_MSG_CHANNEL_EXTENDED_DATA:
@@ -612,20 +628,20 @@ static int packet_wait2(SSH_SESSION *session,int type,int blocking){
case SSH2_MSG_CHANNEL_EOF:
case SSH2_MSG_CHANNEL_CLOSE:
packet_parse(session);
- break;;
+ break;
case SSH2_MSG_IGNORE:
break;
default:
if(type && (type != session->in_packet.type)){
ssh_set_error(session,SSH_FATAL,"waitpacket(): Received a %d type packet, was waiting for a %d\n",session->in_packet.type,type);
- return -1;
+ return SSH_ERROR;
}
- return 0;
+ return SSH_OK;
}
if(blocking==0)
- return 0;
+ return SSH_OK; //shouldn't it return SSH_AGAIN here ?
}
- return 0;
+ return SSH_OK;
}
int packet_wait(SSH_SESSION *session, int type, int block){
#ifdef HAVE_SSH1