diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2009-11-27 20:42:43 +0100 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2009-11-27 20:42:43 +0100 |
commit | 91bb1b2de66a62723e0cbdda02e455f728522181 (patch) | |
tree | 2609d87fcf24107e3507237ec22a80da37994f7c /libssh/socket.c | |
parent | 810adadf2e8a5c68460b864994055ece6f1a3096 (diff) | |
download | libssh-91bb1b2de66a62723e0cbdda02e455f728522181.tar.gz libssh-91bb1b2de66a62723e0cbdda02e455f728522181.tar.xz libssh-91bb1b2de66a62723e0cbdda02e455f728522181.zip |
Squashed commit of the following:
commit 43fad8dfd977637c31fade76ace2905f6528c3bc
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Fri Nov 27 18:39:06 2009 +0100
adaptation to the new ssh_poll_handle object name
commit 1e5e6ac4605adf10d437d04f0fd4b7e66024853c
Merge: 3fd92a0... 810adad...
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Fri Nov 27 18:33:06 2009 +0100
Merge branch 'master' into badcode/libssh_async
commit 3fd92a08eb74b1447a9ff4ca4e1d137475c62cc6
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Mon Nov 2 14:25:46 2009 +0100
Compiles again
commit 8910d7b9692418c9ccea0234f6d49674d238dc16
Merge: e83f1b5... cce34a6...
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Mon Nov 2 12:47:34 2009 +0100
Merge branch 'master' into libssh_async
Very big merge !
Conflicts:
include/libssh/callbacks.h
include/libssh/priv.h
libssh/channels.c
libssh/messages.c
libssh/packet.c
libssh/server.c
libssh/session.c
libssh/socket.c
commit e83f1b593219e183082b015315f09bfe95a29cfc
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Mon Nov 2 12:07:01 2009 +0100
rename callback.h
commit dffa7b730e8f39e2198de18ab69a8e57bef95e58
Merge: 5a8b748... de8808c...
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Tue Sep 15 10:50:07 2009 +0200
Merge branch 'master' of git://git.libssh.org/projects/libssh/libssh into libssh_async
commit 5a8b7484f36599d28f2c0c14a23b76bfc7257638
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Sun Sep 13 12:55:18 2009 +0200
More updates to callback system
commit 18620c20d5e4e62107093f7fd330e553493253fa
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Sat Sep 12 22:26:52 2009 +0200
Same thing with channel_rcv_data
commit fc4a56f6726e409a5866272923f1cbebfc821af3
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Sat Sep 12 22:17:45 2009 +0200
added a few packet handlers for channels
commit 4b6bb4fd00b10cf1321a764126f277ab204bffe3
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Fri Sep 11 23:15:25 2009 +0300
sample packet handlers + bugfixes
commit 2784d09d6dec0a8f868912d14f90d860233b3f82
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Fri Sep 11 20:30:50 2009 +0300
Packet callbacks nearly finished
Need tests and implementation of some packet callbacks
commit cd3ea43f20c9ae2f54576ca98a0ea75c5d4299d3
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Thu Sep 10 12:46:02 2009 +0300
First step of async packet handling
The socket to packet handler is nearly done (needs testing)
I still need to define the interface for callbacks.
commit 487f4d2a900a5fe3b90ceda4460ab7d38d7ad722
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Tue Sep 8 23:24:09 2009 +0300
Almost complete socket callback system
Finished the callback function so it bufferizes data when
callee does not use it.
Flushes the buffer automaticaly after a ssh_socket_nonblocking_flush
commit 23571f22fac9e40c855dfa99569bba181a39648b
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Tue Sep 8 22:22:32 2009 +0300
First draft of a callback system
Diffstat (limited to 'libssh/socket.c')
-rw-r--r-- | libssh/socket.c | 139 |
1 files changed, 95 insertions, 44 deletions
diff --git a/libssh/socket.c b/libssh/socket.c index 933119f..cb96e8d 100644 --- a/libssh/socket.c +++ b/libssh/socket.c @@ -3,7 +3,7 @@ * * This file is part of the SSH Library * - * Copyright (c) 2008 by Aris Adamantiadis + * Copyright (c) 2008,2009 by Aris Adamantiadis * * 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 @@ -34,11 +34,11 @@ #include <sys/un.h> #endif #include "libssh/priv.h" +#include "libssh/callbacks.h" #include "libssh/socket.h" #include "libssh/buffer.h" #include "libssh/poll.h" #include "libssh/session.h" - /** \defgroup ssh_socket SSH Sockets * \addtogroup ssh_socket * @{ @@ -54,8 +54,14 @@ struct socket { ssh_buffer out_buffer; ssh_buffer in_buffer; ssh_session session; + ssh_socket_callbacks callbacks; + ssh_poll_handle poll; }; +static int ssh_socket_unbuffered_read(struct socket *s, void *buffer, uint32_t len); +static int ssh_socket_unbuffered_write(struct socket *s, const void *buffer, + uint32_t len); + /* * \internal * \brief inits the socket system (windows specific) @@ -103,7 +109,78 @@ struct socket *ssh_socket_new(ssh_session session) { return s; } -/* \internal +/** + * @internal + * @brief the socket callbacks, i.e. callbacks to be called + * upon a socket event + * @param callbacks a ssh_socket_callback object reference + */ + +void ssh_socket_set_callbacks(struct socket *s, ssh_socket_callbacks callbacks){ + s->callbacks=callbacks; +} + +int ssh_socket_pollcallback(ssh_poll_handle p, int fd, int revents, void *v_s){ + struct socket *s=(struct socket *)v_s; + char buffer[4096]; + int r,w; + (void)fd; + if(revents & POLLERR){ + s->data_except=1; + /* force a read to get an explanation */ + revents |= POLLIN; + } + if(revents & POLLIN){ + s->data_to_read=1; + r=ssh_socket_unbuffered_read(s,buffer,sizeof(buffer)); + if(r<0){ + ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN); + if(s->callbacks){ + s->callbacks->exception(s->callbacks->user, + SSH_SOCKET_EXCEPTION_ERROR, + s->last_errno); + } + } + if(r==0){ + ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN); + if(s->callbacks){ + s->callbacks->exception(s->callbacks->user, + SSH_SOCKET_EXCEPTION_EOF, + 0); + } + } + if(r>0){ + /* Bufferize the data and then call the callback */ + buffer_add_data(s->in_buffer,buffer,r); + if(s->callbacks){ + r= s->callbacks->data(s->callbacks->user, + buffer_get_rest(s->in_buffer), buffer_get_rest_len(s->in_buffer)); + buffer_pass_bytes(s->in_buffer,r); + } + } + } + if(revents & POLLOUT){ + s->data_to_write=1; + /* If buffered data is pending, write it */ + if(buffer_get_rest_len(s->out_buffer) > 0){ + w=ssh_socket_unbuffered_write(s, buffer_get_rest(s->out_buffer), + buffer_get_rest_len(s->out_buffer)); + } else if(s->callbacks){ + /* Otherwise advertise the upper level that write can be done */ + s->callbacks->controlflow(s->callbacks->user,SSH_SOCKET_FLOW_WRITEWONTBLOCK); + ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLOUT); + /* TODO: Find a way to put back POLLOUT when buffering occurs */ + } + } + return 0; +} + +void ssh_socket_register_pollcallback(struct socket *s, ssh_poll_handle p){ + ssh_poll_set_callback(p,ssh_socket_pollcallback,s); + s->poll=p; +} + +/** \internal * \brief Deletes a socket object */ void ssh_socket_free(struct socket *s){ @@ -225,7 +302,10 @@ static int ssh_socket_unbuffered_write(struct socket *s, const void *buffer, s->last_errno = errno; #endif s->data_to_write = 0; - + /* Reactive the POLLOUT detector in the poll multiplexer system */ + if(s->poll){ + ssh_poll_set_events(s->poll,ssh_poll_get_events(s->poll) | POLLOUT); + } if (w < 0) { s->data_except = 1; } @@ -337,7 +417,6 @@ int ssh_socket_read(struct socket *s, void *buffer, int len){ return SSH_OK; } -#define WRITE_BUFFERING_THRESHOLD 65536 /** \internal * \brief buffered write of data * \returns SSH_OK, or SSH_ERROR @@ -345,22 +424,12 @@ int ssh_socket_read(struct socket *s, void *buffer, int len){ */ int ssh_socket_write(struct socket *s, const void *buffer, int len) { ssh_session session = s->session; - int rc = SSH_ERROR; - enter_function(); - if (buffer_add_data(s->out_buffer, buffer, len) < 0) { return SSH_ERROR; } - - if (buffer_get_rest_len(s->out_buffer) > WRITE_BUFFERING_THRESHOLD) { - rc = ssh_socket_nonblocking_flush(s); - } else { - rc = len; - } - leave_function(); - return rc; + return len; } @@ -509,64 +578,46 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) { } /** \internal - * \brief nonblocking flush of the output buffer + * \brief starts a nonblocking flush of the output buffer + * */ int ssh_socket_nonblocking_flush(struct socket *s) { ssh_session session = s->session; - int except; - int can_write; int w; enter_function(); - /* internally sets data_to_write */ - if (ssh_socket_poll(s, &can_write, &except) < 0) { - leave_function(); - return SSH_ERROR; - } - if (!ssh_socket_is_open(s)) { 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)); + strerror(s->last_errno)); leave_function(); return SSH_ERROR; } - 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)); - } else { - /* write failed */ - w =- 1; - } - + if (s->data_to_write && buffer_get_rest_len(s->out_buffer) > 0) { + w = ssh_socket_unbuffered_write(s, buffer_get_rest(s->out_buffer), + buffer_get_rest_len(s->out_buffer)); if (w < 0) { session->alive = 0; ssh_socket_close(s); /* FIXME use ssh_socket_get_errno() */ ssh_set_error(session, SSH_FATAL, "Writing packet: error on socket (or connection closed): %s", - strerror(errno)); - + strerror(s->last_errno)); leave_function(); return SSH_ERROR; } - buffer_pass_bytes(s->out_buffer, w); - /* refresh the socket status */ - if (ssh_socket_poll(session->socket, &can_write, &except) < 0) { - leave_function(); - return SSH_ERROR; - } } /* Is there some data pending? */ - if (buffer_get_rest_len(s->out_buffer) > 0) { + if (buffer_get_rest_len(s->out_buffer) > 0 && s->poll) { + /* force the poll system to catch pollout events */ + ssh_poll_set_events(s->poll, ssh_poll_get_events(s->poll) |POLLOUT); leave_function(); return SSH_AGAIN; } |