More configure and build tuning
[melted] / src / valerie / valerie_socket.c
1 /*
2 * valerie_socket.c -- Client Socket
3 * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 /* System header files */
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <netdb.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <netinet/in.h>
36
37 /* Application header files */
38 #include "valerie_socket.h"
39
40 /** Initialise the socket.
41 */
42
43 valerie_socket valerie_socket_init( char *server, int port )
44 {
45 valerie_socket socket = malloc( sizeof( valerie_socket_t ) );
46 if ( socket != NULL )
47 {
48 memset( socket, 0, sizeof( valerie_socket_t ) );
49 socket->fd = -1;
50 socket->server = strdup( server );
51 socket->port = port;
52 }
53 return socket;
54 }
55
56 /** Connect to the server.
57 */
58
59 int valerie_socket_connect( valerie_socket connection )
60 {
61 int ret = 0;
62 struct hostent *host;
63 struct sockaddr_in sock;
64
65 if ( connection->server != NULL )
66 {
67 host = gethostbyname( connection->server );
68
69 memset( &sock, 0, sizeof( struct sockaddr_in ) );
70 memcpy( &sock.sin_addr, host->h_addr, host->h_length );
71 sock.sin_family = host->h_addrtype;
72 sock.sin_port = htons( connection->port );
73
74 if ( ( connection->fd = socket( AF_INET, SOCK_STREAM, 0 ) ) != -1 )
75 ret = connect( connection->fd, (const struct sockaddr *)&sock, sizeof( struct sockaddr_in ) );
76 else
77 ret = -1;
78 }
79
80 return ret;
81 }
82
83 /** Convenience constructor for a connected file descriptor.
84 */
85
86 valerie_socket valerie_socket_init_fd( int fd )
87 {
88 valerie_socket socket = malloc( sizeof( valerie_socket_t ) );
89 if ( socket != NULL )
90 {
91 memset( socket, 0, sizeof( valerie_socket_t ) );
92 socket->fd = fd;
93 socket->no_close = 1;
94 }
95 return socket;
96 }
97
98 /** Read an arbitrarily formatted block of data from the server.
99 */
100
101 int valerie_socket_read_data( valerie_socket socket, char *data, int length )
102 {
103 struct timeval tv = { 1, 0 };
104 fd_set rfds;
105 int used = 0;
106
107 data[ 0 ] = '\0';
108
109 FD_ZERO( &rfds );
110 FD_SET( socket->fd, &rfds );
111
112 if ( select( socket->fd + 1, &rfds, NULL, NULL, &tv ) )
113 {
114 used = read( socket->fd, data, length - 1 );
115 if ( used > 0 )
116 data[ used ] = '\0';
117 else
118 used = -1;
119 }
120
121 return used;
122 }
123
124 /** Write an arbitrarily formatted block of data to the server.
125 */
126
127 int valerie_socket_write_data( valerie_socket socket, char *data, int length )
128 {
129 int used = 0;
130
131 while ( used >=0 && used < length )
132 {
133 struct timeval tv = { 1, 0 };
134 fd_set rfds;
135 fd_set wfds;
136 fd_set efds;
137
138 FD_ZERO( &rfds );
139 FD_SET( socket->fd, &rfds );
140 FD_ZERO( &wfds );
141 FD_SET( socket->fd, &wfds );
142 FD_ZERO( &efds );
143 FD_SET( socket->fd, &efds );
144
145 errno = 0;
146
147 if ( select( socket->fd + 1, &rfds, &wfds, &efds, &tv ) )
148 {
149 if ( errno != 0 || FD_ISSET( socket->fd, &efds ) || FD_ISSET( socket->fd, &rfds ) )
150 {
151 used = -1;
152 }
153 else if ( FD_ISSET( socket->fd, &wfds ) )
154 {
155 int inc = write( socket->fd, data + used, length - used );
156 if ( inc > 0 )
157 used += inc;
158 else
159 used = -1;
160 }
161 }
162 }
163
164 return used;
165 }
166
167 /** Close the socket.
168 */
169
170 void valerie_socket_close( valerie_socket socket )
171 {
172 if ( socket->fd > 0 && !socket->no_close )
173 close( socket->fd );
174 free( socket->server );
175 free( socket );
176 }