socket.c   socket.c 
skipping to change at line 24 skipping to change at line 24
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILI TY * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILI TY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details. * License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * 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 * along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA. * MA 02111-1307, USA.
*/ */
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
#else #else
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#endif #endif
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/socket.h"
#include "libssh/buffer.h"
#include "libssh/poll.h"
#include "libssh/session.h"
/** \defgroup ssh_socket SSH Sockets /** \defgroup ssh_socket SSH Sockets
* \addtogroup ssh_socket * \addtogroup ssh_socket
* @{ * @{
*/ */
struct socket { struct socket {
socket_t fd; socket_t fd;
int last_errno; int last_errno;
int data_to_read; /* reading now on socket will int data_to_read; /* reading now on socket will
not block */ not block */
int data_to_write; int data_to_write;
int data_except; int data_except;
BUFFER *out_buffer; ssh_buffer out_buffer;
BUFFER *in_buffer; ssh_buffer in_buffer;
SSH_SESSION *session; ssh_session session;
}; };
/* /*
* \internal * \internal
* \brief inits the socket system (windows specific) * \brief inits the socket system (windows specific)
*/ */
int ssh_socket_init(void) { int ssh_socket_init(void) {
#ifdef _WIN32 #ifdef _WIN32
struct WSAData wsaData; struct WSAData wsaData;
skipping to change at line 75 skipping to change at line 78
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return -1; return -1;
} }
#endif #endif
return 0; return 0;
} }
/* /*
* \internal * \internal
* \brief creates a new Socket object * \brief creates a new Socket object
*/ */
struct socket *ssh_socket_new(SSH_SESSION *session) { struct socket *ssh_socket_new(ssh_session session) {
struct socket *s; struct socket *s;
s = malloc(sizeof(struct socket)); s = malloc(sizeof(struct socket));
if (s == NULL) { if (s == NULL) {
return NULL; return NULL;
} }
s->fd = -1; s->fd = -1;
s->last_errno = -1; s->last_errno = -1;
s->session = session; s->session = session;
s->in_buffer = buffer_new(); s->in_buffer = buffer_new();
skipping to change at line 185 skipping to change at line 188
/* \internal /* \internal
* \brief returns nonzero if the socket is open * \brief returns nonzero if the socket is open
*/ */
int ssh_socket_is_open(struct socket *s) { int ssh_socket_is_open(struct socket *s) {
return s->fd != -1; return s->fd != -1;
} }
/* \internal /* \internal
* \brief read len bytes from socket into buffer * \brief read len bytes from socket into buffer
*/ */
static int ssh_socket_unbuffered_read(struct socket *s, void *buffer, u32 l en) { static int ssh_socket_unbuffered_read(struct socket *s, void *buffer, uint3 2_t len) {
int rc = -1; int rc = -1;
if (s->data_except) { if (s->data_except) {
return -1; return -1;
} }
rc = recv(s->fd,buffer, len, 0); rc = recv(s->fd,buffer, len, 0);
#ifdef _WIN32 #ifdef _WIN32
s->last_errno = WSAGetLastError(); s->last_errno = WSAGetLastError();
#else #else
skipping to change at line 211 skipping to change at line 214
s->data_except = 1; s->data_except = 1;
} }
return rc; return rc;
} }
/* \internal /* \internal
* \brief writes len bytes from buffer to socket * \brief writes len bytes from buffer to socket
*/ */
static int ssh_socket_unbuffered_write(struct socket *s, const void *buffer , static int ssh_socket_unbuffered_write(struct socket *s, const void *buffer ,
u32 len) { uint32_t len) {
int w = -1; int w = -1;
if (s->data_except) { if (s->data_except) {
return -1; return -1;
} }
w = send(s->fd,buffer, len, 0); w = send(s->fd,buffer, len, 0);
#ifdef _WIN32 #ifdef _WIN32
s->last_errno = WSAGetLastError(); s->last_errno = WSAGetLastError();
#else #else
skipping to change at line 259 skipping to change at line 262
return; return;
FD_SET(s->fd,set); FD_SET(s->fd,set);
if (s->fd >= *fd_max) { if (s->fd >= *fd_max) {
*fd_max = s->fd + 1; *fd_max = s->fd + 1;
} }
} }
/** \internal /** \internal
* \brief reads blocking until len bytes have been read * \brief reads blocking until len bytes have been read
*/ */
int ssh_socket_completeread(struct socket *s, void *buffer, u32 len) { int ssh_socket_completeread(struct socket *s, void *buffer, uint32_t len) {
int r = -1; int r = -1;
u32 total = 0; uint32_t total = 0;
u32 toread = len; uint32_t toread = len;
if(! ssh_socket_is_open(s)) { if(! ssh_socket_is_open(s)) {
return SSH_ERROR; return SSH_ERROR;
} }
while((r = ssh_socket_unbuffered_read(s, buffer + total, toread))) { while((r = ssh_socket_unbuffered_read(s, ((uint8_t*)buffer + total), tore ad))) {
if (r < 0) { if (r < 0) {
return SSH_ERROR; return SSH_ERROR;
} }
total += r; total += r;
toread -= r; toread -= r;
if (total == len) { if (total == len) {
return len; return len;
} }
if (r == 0) { if (r == 0) {
return 0; return 0;
} }
} }
/* connection closed */ /* connection closed */
return total; return total;
} }
/** \internal /** \internal
* \brief Blocking write of len bytes * \brief Blocking write of len bytes
*/ */
int ssh_socket_completewrite(struct socket *s, const void *buffer, u32 len) int ssh_socket_completewrite(struct socket *s, const void *buffer, uint32_t
{ len) {
SSH_SESSION *session = s->session; ssh_session session = s->session;
int written = -1; int written = -1;
enter_function(); enter_function();
if(! ssh_socket_is_open(s)) { if(! ssh_socket_is_open(s)) {
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
} }
while (len >0) { while (len >0) {
written = ssh_socket_unbuffered_write(s, buffer, len); written = ssh_socket_unbuffered_write(s, buffer, len);
if (written == 0 || written == -1) { if (written == 0 || written == -1) {
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
} }
len -= written; len -= written;
buffer += written; buffer = ((uint8_t*)buffer + written);
} }
leave_function(); leave_function();
return SSH_OK; return SSH_OK;
} }
/** \internal /** \internal
* \brief buffered read of data (complete) * \brief buffered read of data (complete)
* \returns SSH_OK or SSH_ERROR. * \returns SSH_OK or SSH_ERROR.
* \returns SSH_AGAIN in nonblocking mode * \returns SSH_AGAIN in nonblocking mode
*/ */
int ssh_socket_read(struct socket *s, void *buffer, int len){ int ssh_socket_read(struct socket *s, void *buffer, int len){
SSH_SESSION *session = s->session; ssh_session session = s->session;
int rc = SSH_ERROR; int rc = SSH_ERROR;
enter_function(); enter_function();
rc = ssh_socket_wait_for_data(s, s->session, len); rc = ssh_socket_wait_for_data(s, s->session, len);
if (rc != SSH_OK) { if (rc != SSH_OK) {
leave_function(); leave_function();
return rc; return rc;
} }
skipping to change at line 344 skipping to change at line 347
return SSH_OK; return SSH_OK;
} }
#define WRITE_BUFFERING_THRESHOLD 65536 #define WRITE_BUFFERING_THRESHOLD 65536
/** \internal /** \internal
* \brief buffered write of data * \brief buffered write of data
* \returns SSH_OK, or SSH_ERROR * \returns SSH_OK, or SSH_ERROR
* \warning has no effect on socket before a flush * \warning has no effect on socket before a flush
*/ */
int ssh_socket_write(struct socket *s, const void *buffer, int len) { int ssh_socket_write(struct socket *s, const void *buffer, int len) {
SSH_SESSION *session = s->session; ssh_session session = s->session;
int rc = SSH_ERROR; int rc = SSH_ERROR;
enter_function(); enter_function();
if (buffer_add_data(s->out_buffer, buffer, len) < 0) { if (buffer_add_data(s->out_buffer, buffer, len) < 0) {
return SSH_ERROR; return SSH_ERROR;
} }
if (buffer_get_rest_len(s->out_buffer) > WRITE_BUFFERING_THRESHOLD) { if (buffer_get_rest_len(s->out_buffer) > WRITE_BUFFERING_THRESHOLD) {
rc = ssh_socket_nonblocking_flush(s); rc = ssh_socket_nonblocking_flush(s);
skipping to change at line 372 skipping to change at line 375
/** \internal /** \internal
* \brief wait for data on socket * \brief wait for data on socket
* \param s socket * \param s socket
* \param session the ssh session * \param session the ssh session
* \param len number of bytes to be read * \param len number of bytes to be read
* \returns SSH_OK bytes are available on socket * \returns SSH_OK bytes are available on socket
* \returns SSH_AGAIN need to call later for data * \returns SSH_AGAIN need to call later for data
* \returns SSH_ERROR error happened * \returns SSH_ERROR error happened
*/ */
int ssh_socket_wait_for_data(struct socket *s, SSH_SESSION *session, u32 le n) { int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_ t len) {
char buffer[4096] = {0}; char buffer[4096] = {0};
char *buf = NULL; char *buf = NULL;
int except; int except;
int can_write; int can_write;
int to_read; int to_read;
int r; int r;
enter_function(); enter_function();
to_read = len - buffer_get_rest_len(s->in_buffer); to_read = len - buffer_get_rest_len(s->in_buffer);
skipping to change at line 448 skipping to change at line 451
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
(r == 0) ? "Connection closed by remote host" : (r == 0) ? "Connection closed by remote host" :
"Error reading socket"); "Error reading socket");
ssh_socket_close(session->socket); ssh_socket_close(session->socket);
session->alive = 0; session->alive = 0;
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
} }
if (buffer_add_data(s->in_buffer,buffer, (u32) r) < 0) { if (buffer_add_data(s->in_buffer,buffer, (uint32_t) r) < 0) {
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
} }
} while(buffer_get_rest_len(s->in_buffer) < len); } while(buffer_get_rest_len(s->in_buffer) < len);
leave_function(); leave_function();
return SSH_OK; return SSH_OK;
} }
/* ssh_socket_poll */ /* ssh_socket_poll */
int ssh_socket_poll(struct socket *s, int *writeable, int *except) { int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
SSH_SESSION *session = s->session; ssh_session session = s->session;
pollfd_t fd[1]; ssh_pollfd_t fd[1];
int rc = -1; int rc = -1;
enter_function(); enter_function();
if (!ssh_socket_is_open(s)) { if (!ssh_socket_is_open(s)) {
*except = 1; *except = 1;
*writeable = 0; *writeable = 0;
return 0; return 0;
} }
skipping to change at line 511 skipping to change at line 514
*writeable = s->data_to_write; *writeable = s->data_to_write;
leave_function(); leave_function();
return (s->data_to_read || (buffer_get_rest_len(s->in_buffer) > 0)); return (s->data_to_read || (buffer_get_rest_len(s->in_buffer) > 0));
} }
/** \internal /** \internal
* \brief nonblocking flush of the output buffer * \brief nonblocking flush of the output buffer
*/ */
int ssh_socket_nonblocking_flush(struct socket *s) { int ssh_socket_nonblocking_flush(struct socket *s) {
SSH_SESSION *session = s->session; ssh_session session = s->session;
int except; int except;
int can_write; int can_write;
int w; int w;
enter_function(); enter_function();
/* internally sets data_to_write */ /* internally sets data_to_write */
if (ssh_socket_poll(s, &can_write, &except) < 0) { if (ssh_socket_poll(s, &can_write, &except) < 0) {
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
skipping to change at line 579 skipping to change at line 582
/* all data written */ /* all data written */
leave_function(); leave_function();
return SSH_OK; return SSH_OK;
} }
/** \internal /** \internal
* \brief locking flush of the output packet buffer * \brief locking flush of the output packet buffer
*/ */
int ssh_socket_blocking_flush(struct socket *s) { int ssh_socket_blocking_flush(struct socket *s) {
SSH_SESSION *session = s->session; ssh_session session = s->session;
enter_function(); enter_function();
if (!ssh_socket_is_open(s)) { if (!ssh_socket_is_open(s)) {
session->alive = 0; session->alive = 0;
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
} }
 End of changes. 18 change blocks. 
23 lines changed or deleted 26 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/