mvcp compilation under mingw32 support added
[melted] / src / mvcp / mvcp_socket.c
1 /*
2 * mvcp_socket.c -- Client Socket
3 * Copyright (C) 2002-2009 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 #if !defined(__MINGW32__)
31 #include <netdb.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #else
35 #include <winsock2.h>
36 #endif
37 #include <sys/types.h>
38 #include <fcntl.h>
39 #include <errno.h>
40 #include <sys/time.h>
41
42 /* Application header files */
43 #include "mvcp_socket.h"
44
45 /** Initialise the socket.
46 */
47
48 mvcp_socket mvcp_socket_init( char *server, int port )
49 {
50 mvcp_socket socket = malloc( sizeof( mvcp_socket_t ) );
51 if ( socket != NULL )
52 {
53 memset( socket, 0, sizeof( mvcp_socket_t ) );
54 socket->fd = -1;
55 socket->server = strdup( server );
56 socket->port = port;
57 }
58 return socket;
59 }
60
61 /** Connect to the server.
62 */
63
64 int mvcp_socket_connect( mvcp_socket connection )
65 {
66 int ret = 0;
67 struct hostent *host;
68 struct sockaddr_in sock;
69
70 if ( connection->server != NULL )
71 {
72 host = gethostbyname( connection->server );
73
74 memset( &sock, 0, sizeof( struct sockaddr_in ) );
75 memcpy( &sock.sin_addr, host->h_addr, host->h_length );
76 sock.sin_family = host->h_addrtype;
77 sock.sin_port = htons( connection->port );
78
79 if ( ( connection->fd = socket( AF_INET, SOCK_STREAM, 0 ) ) != -1 )
80 ret = connect( connection->fd, (const struct sockaddr *)&sock, sizeof( struct sockaddr_in ) );
81 else
82 ret = -1;
83 }
84
85 return ret;
86 }
87
88 /** Convenience constructor for a connected file descriptor.
89 */
90
91 mvcp_socket mvcp_socket_init_fd( int fd )
92 {
93 mvcp_socket socket = malloc( sizeof( mvcp_socket_t ) );
94 if ( socket != NULL )
95 {
96 memset( socket, 0, sizeof( mvcp_socket_t ) );
97 socket->fd = fd;
98 socket->no_close = 1;
99 }
100 return socket;
101 }
102
103 /** Read an arbitrarily formatted block of data from the server.
104 */
105
106 int mvcp_socket_read_data( mvcp_socket socket, char *data, int length )
107 {
108 struct timeval tv = { 1, 0 };
109 fd_set rfds;
110 int used = 0;
111
112 data[ 0 ] = '\0';
113
114 FD_ZERO( &rfds );
115 FD_SET( socket->fd, &rfds );
116
117 if ( select( socket->fd + 1, &rfds, NULL, NULL, &tv ) )
118 {
119 used = read( socket->fd, data, length - 1 );
120 if ( used > 0 )
121 data[ used ] = '\0';
122 else
123 used = -1;
124 }
125
126 return used;
127 }
128
129 /** Write an arbitrarily formatted block of data to the server.
130 */
131
132 int mvcp_socket_write_data( mvcp_socket socket, const char *data, int length )
133 {
134 int used = 0;
135
136 while ( used >=0 && used < length )
137 {
138 struct timeval tv = { 1, 0 };
139 fd_set rfds;
140 fd_set wfds;
141 fd_set efds;
142
143 FD_ZERO( &rfds );
144 FD_SET( socket->fd, &rfds );
145 FD_ZERO( &wfds );
146 FD_SET( socket->fd, &wfds );
147 FD_ZERO( &efds );
148 FD_SET( socket->fd, &efds );
149
150 errno = 0;
151
152 if ( select( socket->fd + 1, &rfds, &wfds, &efds, &tv ) )
153 {
154 if ( errno != 0 || FD_ISSET( socket->fd, &efds ) || FD_ISSET( socket->fd, &rfds ) )
155 {
156 used = -1;
157 }
158 else if ( FD_ISSET( socket->fd, &wfds ) )
159 {
160 int inc = write( socket->fd, data + used, length - used );
161 if ( inc > 0 )
162 used += inc;
163 else
164 used = -1;
165 }
166 }
167 }
168
169 return used;
170 }
171
172 /** Close the socket.
173 */
174
175 void mvcp_socket_close( mvcp_socket socket )
176 {
177 if ( socket->fd > 0 && !socket->no_close )
178 close( socket->fd );
179 free( socket->server );
180 free( socket );
181 }