/* * valerie_socket.c -- Client Socket * Copyright (C) 2002-2003 Ushodaya Enterprises Limited * Author: Charles Yates * * This 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. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include #endif /* System header files */ #include #include #include #include #include #include #include #include #include #include #include /* Application header files */ #include "valerie_socket.h" /** Initialise the socket. */ valerie_socket valerie_socket_init( char *server, int port ) { valerie_socket socket = malloc( sizeof( valerie_socket_t ) ); if ( socket != NULL ) { memset( socket, 0, sizeof( valerie_socket_t ) ); socket->fd = -1; socket->server = strdup( server ); socket->port = port; } return socket; } /** Connect to the server. */ int valerie_socket_connect( valerie_socket connection ) { int ret = 0; struct hostent *host; struct sockaddr_in sock; if ( connection->server != NULL ) { host = gethostbyname( connection->server ); memset( &sock, 0, sizeof( struct sockaddr_in ) ); memcpy( &sock.sin_addr, host->h_addr, host->h_length ); sock.sin_family = host->h_addrtype; sock.sin_port = htons( connection->port ); if ( ( connection->fd = socket( AF_INET, SOCK_STREAM, 0 ) ) != -1 ) ret = connect( connection->fd, (const struct sockaddr *)&sock, sizeof( struct sockaddr_in ) ); else ret = -1; } return ret; } /** Convenience constructor for a connected file descriptor. */ valerie_socket valerie_socket_init_fd( int fd ) { valerie_socket socket = malloc( sizeof( valerie_socket_t ) ); if ( socket != NULL ) { memset( socket, 0, sizeof( valerie_socket_t ) ); socket->fd = fd; socket->no_close = 1; } return socket; } /** Read an arbitrarily formatted block of data from the server. */ int valerie_socket_read_data( valerie_socket socket, char *data, int length ) { struct timeval tv = { 1, 0 }; fd_set rfds; int used = 0; data[ 0 ] = '\0'; FD_ZERO( &rfds ); FD_SET( socket->fd, &rfds ); if ( select( socket->fd + 1, &rfds, NULL, NULL, &tv ) ) { used = read( socket->fd, data, length - 1 ); if ( used > 0 ) data[ used ] = '\0'; else used = -1; } return used; } /** Write an arbitrarily formatted block of data to the server. */ int valerie_socket_write_data( valerie_socket socket, char *data, int length ) { int used = 0; while ( used >=0 && used < length ) { struct timeval tv = { 1, 0 }; fd_set rfds; fd_set wfds; fd_set efds; FD_ZERO( &rfds ); FD_SET( socket->fd, &rfds ); FD_ZERO( &wfds ); FD_SET( socket->fd, &wfds ); FD_ZERO( &efds ); FD_SET( socket->fd, &efds ); errno = 0; if ( select( socket->fd + 1, &rfds, &wfds, &efds, &tv ) ) { if ( errno != 0 || FD_ISSET( socket->fd, &efds ) || FD_ISSET( socket->fd, &rfds ) ) { used = -1; } else if ( FD_ISSET( socket->fd, &wfds ) ) { int inc = write( socket->fd, data + used, length - used ); if ( inc > 0 ) used += inc; else used = -1; } } } return used; } /** Close the socket. */ void valerie_socket_close( valerie_socket socket ) { if ( socket->fd > 0 && !socket->no_close ) close( socket->fd ); free( socket->server ); free( socket ); }