socket.c 6.63 KB
Newer Older
1
/* Module:			socket.c
2
 *
3 4
 * Description:		This module contains functions for low level socket
 *					operations (connecting/reading/writing to the backend)
5
 *
6
 * Classes:			SocketClass (Functions prefix: "SOCK_")
7
 *
8
 * API functions:	none
9
 *
10
 * Comments:		See "notice.txt" for copyright and license information.
11 12
 *
 */
13

Byron Nikolaidis's avatar
Byron Nikolaidis committed
14
#ifdef HAVE_CONFIG_H
15
#include "config.h"
Byron Nikolaidis's avatar
Byron Nikolaidis committed
16 17
#endif

18 19
#include "socket.h"

20
#ifndef WIN32
Byron Nikolaidis's avatar
Byron Nikolaidis committed
21
#include <stdlib.h>
22
#include <string.h>				/* for memset */
Byron Nikolaidis's avatar
Byron Nikolaidis committed
23 24
#endif

25 26
extern GLOBAL_VALUES globals;

Byron Nikolaidis's avatar
Byron Nikolaidis committed
27 28 29 30 31 32 33 34 35 36 37
#ifndef BOOL
#define BOOL	int
#endif
#ifndef TRUE
#define TRUE	(BOOL)1
#endif
#ifndef FALSE
#define FALSE	(BOOL)0
#endif


38
void
39
SOCK_clear_error(SocketClass * self)
40
{
41 42
	self->errornumber = 0;
	self->errormsg = NULL;
43 44
}

45
SocketClass *
46 47
SOCK_Constructor()
{
48
	SocketClass *rv;
49

50
	rv = (SocketClass *) malloc(sizeof(SocketClass));
51

52 53 54
	if (rv != NULL)
	{
		rv->socket = (SOCKETFD) - 1;
55 56 57 58 59
		rv->buffer_filled_in = 0;
		rv->buffer_filled_out = 0;
		rv->buffer_read_in = 0;

		rv->buffer_in = (unsigned char *) malloc(globals.socket_buffersize);
60
		if (!rv->buffer_in)
61 62 63
			return NULL;

		rv->buffer_out = (unsigned char *) malloc(globals.socket_buffersize);
64
		if (!rv->buffer_out)
65
			return NULL;
66 67 68

		rv->errormsg = NULL;
		rv->errornumber = 0;
69

70
		rv->reverse = FALSE;
71 72
	}
	return rv;
73 74 75 76

}

void
77
SOCK_Destructor(SocketClass * self)
78
{
79 80 81
	if (self->socket != -1)
	{
		if (!shutdown(self->socket, 2)) /* no sends or receives */
82 83 84
		{
			SOCK_put_char(self, 'X');
			SOCK_flush_output(self);
85
			closesocket(self->socket);
86
		}
87 88 89 90 91 92 93 94 95 96 97 98 99
	}

	if (self->buffer_in)
		free(self->buffer_in);

	if (self->buffer_out)
		free(self->buffer_out);

	free(self);

}


100 101
char
SOCK_connect_to(SocketClass * self, unsigned short port, char *hostname)
102
{
103 104 105
	struct hostent *host;
	struct sockaddr_in sadr;
	unsigned long iaddr;
106

107 108
	if (self->socket != -1)
	{
109 110 111 112 113
		self->errornumber = SOCKET_ALREADY_CONNECTED;
		self->errormsg = "Socket is already connected";
		return 0;
	}

114
	memset((char *) &sadr, 0, sizeof(sadr));
115

116 117 118
	/*
	 * If it is a valid IP address, use it. Otherwise use hostname lookup.
	 */
119
	iaddr = inet_addr(hostname);
120 121
	if (iaddr == INADDR_NONE)
	{
122
		host = gethostbyname(hostname);
123 124
		if (host == NULL)
		{
125 126 127 128 129
			self->errornumber = SOCKET_HOST_NOT_FOUND;
			self->errormsg = "Could not resolve hostname.";
			return 0;
		}
		memcpy(&(sadr.sin_addr), host->h_addr, host->h_length);
130
	}
131
	else
132
		memcpy(&(sadr.sin_addr), (struct in_addr *) & iaddr, sizeof(iaddr));
133 134 135 136 137

	sadr.sin_family = AF_INET;
	sadr.sin_port = htons(port);

	self->socket = socket(AF_INET, SOCK_STREAM, 0);
138 139
	if (self->socket == -1)
	{
140 141 142 143 144
		self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET;
		self->errormsg = "Could not create Socket.";
		return 0;
	}

145 146 147
	if (connect(self->socket, (struct sockaddr *) & (sadr),
				sizeof(sadr)) < 0)
	{
148 149 150 151

		self->errornumber = SOCKET_COULD_NOT_CONNECT;
		self->errormsg = "Could not connect to remote socket.";
		closesocket(self->socket);
152
		self->socket = (SOCKETFD) - 1;
153 154 155 156 157 158
		return 0;
	}
	return 1;
}


159 160
void
SOCK_get_n_char(SocketClass * self, char *buffer, int len)
161
{
162
	int			lf;
163

164 165
	if (!buffer)
	{
166 167 168 169 170
		self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
		self->errormsg = "get_n_char was called with NULL-Pointer";
		return;
	}

171
	for (lf = 0; lf < len; lf++)
172 173 174 175
		buffer[lf] = SOCK_get_next_byte(self);
}


176 177
void
SOCK_put_n_char(SocketClass * self, char *buffer, int len)
178
{
179
	int			lf;
180

181 182
	if (!buffer)
	{
183 184 185 186 187
		self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
		self->errormsg = "put_n_char was called with NULL-Pointer";
		return;
	}

188 189
	for (lf = 0; lf < len; lf++)
		SOCK_put_next_byte(self, (unsigned char) buffer[lf]);
190 191 192
}


193 194
/*	bufsize must include room for the null terminator
	will read at most bufsize-1 characters + null.
195
*/
196 197
void
SOCK_get_string(SocketClass * self, char *buffer, int bufsize)
198
{
199
	register int lf = 0;
200 201

	for (lf = 0; lf < bufsize; lf++)
202
		if (!(buffer[lf] = SOCK_get_next_byte(self)))
203
			return;
204 205

	buffer[bufsize - 1] = '\0';
206 207 208
}


209 210
void
SOCK_put_string(SocketClass * self, char *string)
211
{
212 213
	register int lf;
	int			len;
214

215
	len = strlen(string) + 1;
216

217 218
	for (lf = 0; lf < len; lf++)
		SOCK_put_next_byte(self, (unsigned char) string[lf]);
219 220 221
}


222 223
int
SOCK_get_int(SocketClass * self, short len)
224
{
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
	char		buf[4];

	switch (len)
	{
		case 2:
			SOCK_get_n_char(self, buf, len);
			if (self->reverse)
				return *((unsigned short *) buf);
			else
				return ntohs(*((unsigned short *) buf));

		case 4:
			SOCK_get_n_char(self, buf, len);
			if (self->reverse)
				return *((unsigned int *) buf);
			else
				return ntohl(*((unsigned int *) buf));

		default:
			self->errornumber = SOCKET_GET_INT_WRONG_LENGTH;
			self->errormsg = "Cannot read ints of that length";
			return 0;
247
	}
248
}
249 250


251 252
void
SOCK_put_int(SocketClass * self, int value, short len)
253
{
254
	unsigned int rv;
255

256 257 258 259 260 261
	switch (len)
	{
		case 2:
			rv = self->reverse ? value : htons((unsigned short) value);
			SOCK_put_n_char(self, (char *) &rv, 2);
			return;
262

263 264 265 266
		case 4:
			rv = self->reverse ? value : htonl((unsigned int) value);
			SOCK_put_n_char(self, (char *) &rv, 4);
			return;
267

268 269 270 271 272
		default:
			self->errornumber = SOCKET_PUT_INT_WRONG_LENGTH;
			self->errormsg = "Cannot write ints of that length";
			return;
	}
273 274 275
}


276 277
void
SOCK_flush_output(SocketClass * self)
278
{
279
	int			written;
280

281 282 283
	written = send(self->socket, (char *) self->buffer_out, self->buffer_filled_out, 0);
	if (written != self->buffer_filled_out)
	{
284 285 286 287 288 289
		self->errornumber = SOCKET_WRITE_ERROR;
		self->errormsg = "Could not flush socket buffer.";
	}
	self->buffer_filled_out = 0;
}

290 291
unsigned char
SOCK_get_next_byte(SocketClass * self)
292 293
{

294 295
	if (self->buffer_read_in >= self->buffer_filled_in)
	{
296
		/* there are no more bytes left in the buffer -> */
297
		/* reload the buffer */
298 299

		self->buffer_read_in = 0;
300
		self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, globals.socket_buffersize, 0);
301 302 303

		mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, globals.socket_buffersize);

304 305
		if (self->buffer_filled_in == -1)
		{
306 307 308 309
			self->errornumber = SOCKET_READ_ERROR;
			self->errormsg = "Error while reading from the socket.";
			self->buffer_filled_in = 0;
		}
310 311
		if (self->buffer_filled_in == 0)
		{
312 313 314 315 316 317 318 319 320
			self->errornumber = SOCKET_CLOSED;
			self->errormsg = "Socket has been closed.";
			self->buffer_filled_in = 0;
		}

	}
	return self->buffer_in[self->buffer_read_in++];
}

321 322
void
SOCK_put_next_byte(SocketClass * self, unsigned char next_byte)
323
{
324
	int			bytes_sent;
325 326 327

	self->buffer_out[self->buffer_filled_out++] = next_byte;

328 329
	if (self->buffer_filled_out == globals.socket_buffersize)
	{
330
		/* buffer is full, so write it out */
331 332 333
		bytes_sent = send(self->socket, (char *) self->buffer_out, globals.socket_buffersize, 0);
		if (bytes_sent != globals.socket_buffersize)
		{
334 335 336 337 338 339
			self->errornumber = SOCKET_WRITE_ERROR;
			self->errormsg = "Error while writing to the socket.";
		}
		self->buffer_filled_out = 0;
	}
}