4
* Description: This module contains functions for low level socket
5
* operations (connecting/reading/writing to the backend)
7
* Classes: SocketClass (Functions prefix: "SOCK_")
11
* Comments: See "notice.txt" for copyright and license information.
17
#include "connection.h"
21
#include <string.h> /* for memset */
24
extern GLOBAL_VALUES globals;
38
SOCK_clear_error(SocketClass *self)
40
self->errornumber = 0;
41
self->errormsg = NULL;
46
SOCK_Constructor(const ConnectionClass *conn)
50
rv = (SocketClass *) malloc(sizeof(SocketClass));
54
rv->socket = (SOCKETFD) - 1;
55
rv->buffer_filled_in = 0;
56
rv->buffer_filled_out = 0;
57
rv->buffer_read_in = 0;
60
rv->buffer_size = conn->connInfo.drivers.socket_buffersize;
62
rv->buffer_size = globals.socket_buffersize;
63
rv->buffer_in = (unsigned char *) malloc(rv->buffer_size);
70
rv->buffer_out = (unsigned char *) malloc(rv->buffer_size);
86
SOCK_Destructor(SocketClass *self)
88
mylog("SOCK_Destructor\n");
91
if (self->socket != -1)
93
SOCK_put_char(self, 'X');
94
SOCK_flush_output(self);
95
closesocket(self->socket);
99
free(self->buffer_in);
101
if (self->buffer_out)
102
free(self->buffer_out);
109
SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
111
#if defined (POSIX_MULTITHREAD_SUPPORT)
112
const int bufsz = 8192;
116
struct hostent* hp = &host;
122
if (self->socket != -1)
124
self->errornumber = SOCKET_ALREADY_CONNECTED;
125
self->errormsg = "Socket is already connected";
129
memset((char *) &(self->sadr), 0, sizeof(self->sadr));
132
* If it is a valid IP address, use it. Otherwise use hostname lookup.
134
iaddr = inet_addr(hostname);
135
if (iaddr == INADDR_NONE)
137
#if defined (POSIX_MULTITHREAD_SUPPORT)
138
#if defined (HAVE_GETIPNODEBYNAME) /* Free-BSD ? */
139
hp = getipnodebyname(hostname, AF_INET, 0, &error);
140
#elif defined (PGS_REENTRANT_API_1) /* solaris, irix */
141
hp = gethostbyname_r(hostname, hp, buf, bufsz, &error);
142
#elif defined (PGS_REENTRANT_API_2) /* linux */
144
result = gethostbyname_r(hostname, hp, buf, bufsz, &hp, &error);
148
hp = gethostbyname(hostname);
151
hp = gethostbyname(hostname);
155
self->errornumber = SOCKET_HOST_NOT_FOUND;
156
self->errormsg = "Could not resolve hostname.";
159
memcpy(&(self->sadr.sin_addr), hp->h_addr, hp->h_length);
162
memcpy(&(self->sadr.sin_addr), (struct in_addr *) & iaddr, sizeof(iaddr));
164
#if defined (HAVE_GETIPNODEBYNAME)
166
#endif /* HAVE_GETIPNODEBYNAME */
167
self->sadr.sin_family = AF_INET;
168
self->sadr.sin_port = htons(port);
170
self->socket = socket(AF_INET, SOCK_STREAM, 0);
171
if (self->socket == -1)
173
self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET;
174
self->errormsg = "Could not create Socket.";
178
if (connect(self->socket, (struct sockaddr *) & (self->sadr),
179
sizeof(self->sadr)) < 0)
181
self->errornumber = SOCKET_COULD_NOT_CONNECT;
182
self->errormsg = "Could not connect to remote socket.";
183
closesocket(self->socket);
184
self->socket = (SOCKETFD) - 1;
192
SOCK_get_n_char(SocketClass *self, char *buffer, int len)
200
self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
201
self->errormsg = "get_n_char was called with NULL-Pointer";
205
for (lf = 0; lf < len; lf++)
206
buffer[lf] = SOCK_get_next_byte(self);
211
SOCK_put_n_char(SocketClass *self, char *buffer, int len)
219
self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
220
self->errormsg = "put_n_char was called with NULL-Pointer";
224
for (lf = 0; lf < len; lf++)
225
SOCK_put_next_byte(self, (unsigned char) buffer[lf]);
230
* bufsize must include room for the null terminator
231
* will read at most bufsize-1 characters + null.
232
* returns TRUE if truncation occurs.
235
SOCK_get_string(SocketClass *self, char *buffer, int bufsize)
239
for (lf = 0; lf < bufsize - 1; lf++)
240
if (!(buffer[lf] = SOCK_get_next_byte(self)))
243
buffer[bufsize - 1] = '\0';
249
SOCK_put_string(SocketClass *self, char *string)
254
len = strlen(string) + 1;
256
for (lf = 0; lf < len; lf++)
257
SOCK_put_next_byte(self, (unsigned char) string[lf]);
262
SOCK_get_int(SocketClass *self, short len)
272
SOCK_get_n_char(self, (char *) &buf, len);
283
SOCK_get_n_char(self, (char *) &buf, len);
291
self->errornumber = SOCKET_GET_INT_WRONG_LENGTH;
292
self->errormsg = "Cannot read ints of that length";
299
SOCK_put_int(SocketClass *self, int value, short len)
308
rv = self->reverse ? value : htons((unsigned short) value);
309
SOCK_put_n_char(self, (char *) &rv, 2);
313
rv = self->reverse ? value : htonl((unsigned int) value);
314
SOCK_put_n_char(self, (char *) &rv, 4);
318
self->errornumber = SOCKET_PUT_INT_WRONG_LENGTH;
319
self->errormsg = "Cannot write ints of that length";
326
SOCK_flush_output(SocketClass *self)
332
written = send(self->socket, (char *) self->buffer_out, self->buffer_filled_out, 0);
333
if (written != self->buffer_filled_out)
335
self->errornumber = SOCKET_WRITE_ERROR;
336
self->errormsg = "Could not flush socket buffer.";
338
self->buffer_filled_out = 0;
343
SOCK_get_next_byte(SocketClass *self)
347
if (self->buffer_read_in >= self->buffer_filled_in)
350
* there are no more bytes left in the buffer so reload the buffer
352
self->buffer_read_in = 0;
353
self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, self->buffer_size, 0);
355
mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, self->buffer_size);
357
if (self->buffer_filled_in < 0)
359
self->errornumber = SOCKET_READ_ERROR;
360
self->errormsg = "Error while reading from the socket.";
361
self->buffer_filled_in = 0;
364
if (self->buffer_filled_in == 0)
366
self->errornumber = SOCKET_CLOSED;
367
self->errormsg = "Socket has been closed.";
368
self->buffer_filled_in = 0;
372
return self->buffer_in[self->buffer_read_in++];
377
SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
383
self->buffer_out[self->buffer_filled_out++] = next_byte;
385
if (self->buffer_filled_out == self->buffer_size)
387
/* buffer is full, so write it out */
388
bytes_sent = send(self->socket, (char *) self->buffer_out, self->buffer_size, 0);
389
if (bytes_sent != self->buffer_size)
391
self->errornumber = SOCKET_WRITE_ERROR;
392
self->errormsg = "Error while writing to the socket.";
394
self->buffer_filled_out = 0;