Peter Eisentraut 968d7733a1 Rename config.h to pg_config.h and os.h to pg_config_os.h, fix a number of
places that were including the wrong files.
2001-08-24 14:07:50 +00:00

350 lines
6.7 KiB
C

/*-------
* Module: socket.c
*
* Description: This module contains functions for low level socket
* operations (connecting/reading/writing to the backend)
*
* Classes: SocketClass (Functions prefix: "SOCK_")
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*-------
*/
#include "socket.h"
#ifndef WIN32
#include <stdlib.h>
#include <string.h> /* for memset */
#endif
extern GLOBAL_VALUES globals;
#ifndef BOOL
#define BOOL int
#endif
#ifndef TRUE
#define TRUE (BOOL)1
#endif
#ifndef FALSE
#define FALSE (BOOL)0
#endif
void
SOCK_clear_error(SocketClass *self)
{
self->errornumber = 0;
self->errormsg = NULL;
}
SocketClass *
SOCK_Constructor()
{
SocketClass *rv;
rv = (SocketClass *) malloc(sizeof(SocketClass));
if (rv != NULL)
{
rv->socket = (SOCKETFD) - 1;
rv->buffer_filled_in = 0;
rv->buffer_filled_out = 0;
rv->buffer_read_in = 0;
rv->buffer_in = (unsigned char *) malloc(globals.socket_buffersize);
if (!rv->buffer_in)
{
free(rv);
return NULL;
}
rv->buffer_out = (unsigned char *) malloc(globals.socket_buffersize);
if (!rv->buffer_out)
{
free(rv->buffer_in);
free(rv);
return NULL;
}
rv->errormsg = NULL;
rv->errornumber = 0;
rv->reverse = FALSE;
}
return rv;
}
void
SOCK_Destructor(SocketClass *self)
{
if (self->socket != -1)
{
SOCK_put_char(self, 'X');
SOCK_flush_output(self);
closesocket(self->socket);
}
if (self->buffer_in)
free(self->buffer_in);
if (self->buffer_out)
free(self->buffer_out);
free(self);
}
char
SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
{
struct hostent *host;
struct sockaddr_in sadr;
unsigned long iaddr;
if (self->socket != -1)
{
self->errornumber = SOCKET_ALREADY_CONNECTED;
self->errormsg = "Socket is already connected";
return 0;
}
memset((char *) &sadr, 0, sizeof(sadr));
/*
* If it is a valid IP address, use it. Otherwise use hostname lookup.
*/
iaddr = inet_addr(hostname);
if (iaddr == INADDR_NONE)
{
host = gethostbyname(hostname);
if (host == NULL)
{
self->errornumber = SOCKET_HOST_NOT_FOUND;
self->errormsg = "Could not resolve hostname.";
return 0;
}
memcpy(&(sadr.sin_addr), host->h_addr, host->h_length);
}
else
memcpy(&(sadr.sin_addr), (struct in_addr *) & iaddr, sizeof(iaddr));
sadr.sin_family = AF_INET;
sadr.sin_port = htons(port);
self->socket = socket(AF_INET, SOCK_STREAM, 0);
if (self->socket == -1)
{
self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET;
self->errormsg = "Could not create Socket.";
return 0;
}
if (connect(self->socket, (struct sockaddr *) & (sadr),
sizeof(sadr)) < 0)
{
self->errornumber = SOCKET_COULD_NOT_CONNECT;
self->errormsg = "Could not connect to remote socket.";
closesocket(self->socket);
self->socket = (SOCKETFD) - 1;
return 0;
}
return 1;
}
void
SOCK_get_n_char(SocketClass *self, char *buffer, int len)
{
int lf;
if (!buffer)
{
self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
self->errormsg = "get_n_char was called with NULL-Pointer";
return;
}
for (lf = 0; lf < len; lf++)
buffer[lf] = SOCK_get_next_byte(self);
}
void
SOCK_put_n_char(SocketClass *self, char *buffer, int len)
{
int lf;
if (!buffer)
{
self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
self->errormsg = "put_n_char was called with NULL-Pointer";
return;
}
for (lf = 0; lf < len; lf++)
SOCK_put_next_byte(self, (unsigned char) buffer[lf]);
}
/*
* bufsize must include room for the null terminator
* will read at most bufsize-1 characters + null.
* returns TRUE if truncation occurs.
*/
BOOL
SOCK_get_string(SocketClass *self, char *buffer, int bufsize)
{
register int lf = 0;
for (lf = 0; lf < bufsize - 1; lf++)
if (!(buffer[lf] = SOCK_get_next_byte(self)))
return FALSE;
buffer[bufsize - 1] = '\0';
return TRUE;
}
void
SOCK_put_string(SocketClass *self, char *string)
{
register int lf;
int len;
len = strlen(string) + 1;
for (lf = 0; lf < len; lf++)
SOCK_put_next_byte(self, (unsigned char) string[lf]);
}
int
SOCK_get_int(SocketClass *self, short len)
{
switch (len)
{
case 2:
{
unsigned short buf;
SOCK_get_n_char(self, (char *) &buf, len);
if (self->reverse)
return buf;
else
return ntohs(buf);
}
case 4:
{
unsigned int buf;
SOCK_get_n_char(self, (char *) &buf, len);
if (self->reverse)
return buf;
else
return ntohl(buf);
}
default:
self->errornumber = SOCKET_GET_INT_WRONG_LENGTH;
self->errormsg = "Cannot read ints of that length";
return 0;
}
}
void
SOCK_put_int(SocketClass *self, int value, short len)
{
unsigned int rv;
switch (len)
{
case 2:
rv = self->reverse ? value : htons((unsigned short) value);
SOCK_put_n_char(self, (char *) &rv, 2);
return;
case 4:
rv = self->reverse ? value : htonl((unsigned int) value);
SOCK_put_n_char(self, (char *) &rv, 4);
return;
default:
self->errornumber = SOCKET_PUT_INT_WRONG_LENGTH;
self->errormsg = "Cannot write ints of that length";
return;
}
}
void
SOCK_flush_output(SocketClass *self)
{
int written;
written = send(self->socket, (char *) self->buffer_out, self->buffer_filled_out, 0);
if (written != self->buffer_filled_out)
{
self->errornumber = SOCKET_WRITE_ERROR;
self->errormsg = "Could not flush socket buffer.";
}
self->buffer_filled_out = 0;
}
unsigned char
SOCK_get_next_byte(SocketClass *self)
{
if (self->buffer_read_in >= self->buffer_filled_in)
{
/*
* there are no more bytes left in the buffer so reload the buffer
*/
self->buffer_read_in = 0;
self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, globals.socket_buffersize, 0);
mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, globals.socket_buffersize);
if (self->buffer_filled_in < 0)
{
self->errornumber = SOCKET_READ_ERROR;
self->errormsg = "Error while reading from the socket.";
self->buffer_filled_in = 0;
return 0;
}
if (self->buffer_filled_in == 0)
{
self->errornumber = SOCKET_CLOSED;
self->errormsg = "Socket has been closed.";
self->buffer_filled_in = 0;
return 0;
}
}
return self->buffer_in[self->buffer_read_in++];
}
void
SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
{
int bytes_sent;
self->buffer_out[self->buffer_filled_out++] = next_byte;
if (self->buffer_filled_out == globals.socket_buffersize)
{
/* buffer is full, so write it out */
bytes_sent = send(self->socket, (char *) self->buffer_out, globals.socket_buffersize, 0);
if (bytes_sent != globals.socket_buffersize)
{
self->errornumber = SOCKET_WRITE_ERROR;
self->errormsg = "Error while writing to the socket.";
}
self->buffer_filled_out = 0;
}
}