socket.c 6.6 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
Bruce Momjian's avatar
Bruce Momjian committed
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
}

void
Bruce Momjian's avatar
Bruce Momjian committed
76
SOCK_Destructor(SocketClass *self)
77
{
78 79
	if (self->socket != -1)
	{
80 81
		SOCK_put_char(self, 'X');
		SOCK_flush_output(self);
82
		if (!shutdown(self->socket, 2)) /* no sends or receives */
83 84 85 86 87 88 89
			closesocket(self->socket);
	}

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

	if (self->buffer_out)
Bruce Momjian's avatar
Bruce Momjian committed
90
		free(self->buffer_out);
91 92 93 94 95

	free(self);
}


96
char
Bruce Momjian's avatar
Bruce Momjian committed
97
SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
98
{
99 100 101
	struct hostent *host;
	struct sockaddr_in sadr;
	unsigned long iaddr;
102

103 104
	if (self->socket != -1)
	{
105 106 107 108 109
		self->errornumber = SOCKET_ALREADY_CONNECTED;
		self->errormsg = "Socket is already connected";
		return 0;
	}

110
	memset((char *) &sadr, 0, sizeof(sadr));
111

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

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

	self->socket = socket(AF_INET, SOCK_STREAM, 0);
134 135
	if (self->socket == -1)
	{
136 137 138 139 140
		self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET;
		self->errormsg = "Could not create Socket.";
		return 0;
	}

141 142 143
	if (connect(self->socket, (struct sockaddr *) & (sadr),
				sizeof(sadr)) < 0)
	{
144 145 146
		self->errornumber = SOCKET_COULD_NOT_CONNECT;
		self->errormsg = "Could not connect to remote socket.";
		closesocket(self->socket);
147
		self->socket = (SOCKETFD) - 1;
148 149 150 151 152 153
		return 0;
	}
	return 1;
}


154
void
Bruce Momjian's avatar
Bruce Momjian committed
155
SOCK_get_n_char(SocketClass *self, char *buffer, int len)
156
{
157
	int			lf;
158

159 160
	if (!buffer)
	{
161 162 163 164 165
		self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
		self->errormsg = "get_n_char was called with NULL-Pointer";
		return;
	}

166
	for (lf = 0; lf < len; lf++)
167 168 169 170
		buffer[lf] = SOCK_get_next_byte(self);
}


171
void
Bruce Momjian's avatar
Bruce Momjian committed
172
SOCK_put_n_char(SocketClass *self, char *buffer, int len)
173
{
174
	int			lf;
175

176 177
	if (!buffer)
	{
178 179 180 181 182
		self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
		self->errormsg = "put_n_char was called with NULL-Pointer";
		return;
	}

183 184
	for (lf = 0; lf < len; lf++)
		SOCK_put_next_byte(self, (unsigned char) buffer[lf]);
185 186 187
}


188 189
/*	bufsize must include room for the null terminator
	will read at most bufsize-1 characters + null.
190
*/
191
void
Bruce Momjian's avatar
Bruce Momjian committed
192
SOCK_get_string(SocketClass *self, char *buffer, int bufsize)
193
{
194
	register int lf = 0;
195 196

	for (lf = 0; lf < bufsize; lf++)
197
		if (!(buffer[lf] = SOCK_get_next_byte(self)))
198
			return;
199 200

	buffer[bufsize - 1] = '\0';
201 202 203
}


204
void
Bruce Momjian's avatar
Bruce Momjian committed
205
SOCK_put_string(SocketClass *self, char *string)
206
{
207 208
	register int lf;
	int			len;
209

210
	len = strlen(string) + 1;
211

212 213
	for (lf = 0; lf < len; lf++)
		SOCK_put_next_byte(self, (unsigned char) string[lf]);
214 215 216
}


217
int
Bruce Momjian's avatar
Bruce Momjian committed
218
SOCK_get_int(SocketClass *self, short len)
219
{
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
	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;
242
	}
243
}
244 245


246
void
Bruce Momjian's avatar
Bruce Momjian committed
247
SOCK_put_int(SocketClass *self, int value, short len)
248
{
249
	unsigned int rv;
250

251 252 253 254
	switch (len)
	{
		case 2:
			rv = self->reverse ? value : htons((unsigned short) value);
Bruce Momjian's avatar
Bruce Momjian committed
255
			SOCK_put_n_char(self, (char *) &rv, 2);
256
			return;
257

258 259 260 261
		case 4:
			rv = self->reverse ? value : htonl((unsigned int) value);
			SOCK_put_n_char(self, (char *) &rv, 4);
			return;
262

263 264 265 266 267
		default:
			self->errornumber = SOCKET_PUT_INT_WRONG_LENGTH;
			self->errormsg = "Cannot write ints of that length";
			return;
	}
268 269 270
}


271
void
Bruce Momjian's avatar
Bruce Momjian committed
272
SOCK_flush_output(SocketClass *self)
273
{
274
	int			written;
275

276 277 278
	written = send(self->socket, (char *) self->buffer_out, self->buffer_filled_out, 0);
	if (written != self->buffer_filled_out)
	{
279 280 281 282 283 284
		self->errornumber = SOCKET_WRITE_ERROR;
		self->errormsg = "Could not flush socket buffer.";
	}
	self->buffer_filled_out = 0;
}

285
unsigned char
Bruce Momjian's avatar
Bruce Momjian committed
286
SOCK_get_next_byte(SocketClass *self)
287
{
288 289
	if (self->buffer_read_in >= self->buffer_filled_in)
	{
290
		/* there are no more bytes left in the buffer -> */
291
		/* reload the buffer */
292 293

		self->buffer_read_in = 0;
294
		self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, globals.socket_buffersize, 0);
295 296 297

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

298 299
		if (self->buffer_filled_in == -1)
		{
300 301 302 303
			self->errornumber = SOCKET_READ_ERROR;
			self->errormsg = "Error while reading from the socket.";
			self->buffer_filled_in = 0;
		}
304 305
		if (self->buffer_filled_in == 0)
		{
306 307 308 309 310 311 312 313
			self->errornumber = SOCKET_CLOSED;
			self->errormsg = "Socket has been closed.";
			self->buffer_filled_in = 0;
		}
	}
	return self->buffer_in[self->buffer_read_in++];
}

314
void
Bruce Momjian's avatar
Bruce Momjian committed
315
SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
316
{
317
	int			bytes_sent;
318 319 320

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

321 322
	if (self->buffer_filled_out == globals.socket_buffersize)
	{
323
		/* buffer is full, so write it out */
324 325 326
		bytes_sent = send(self->socket, (char *) self->buffer_out, globals.socket_buffersize, 0);
		if (bytes_sent != globals.socket_buffersize)
		{
327 328 329 330 331 332
			self->errornumber = SOCKET_WRITE_ERROR;
			self->errormsg = "Error while writing to the socket.";
		}
		self->buffer_filled_out = 0;
	}
}