archie/prospero/lib/psrv/wais_gw/sockets.c
2024-05-27 16:13:40 +02:00

185 lines
4.4 KiB
C

/* WIDE AREA INFORMATION SERVER SOFTWARE:
Developed by Thinking Machines Corporation and put into the public
domain with no guarantees or restrictions.
*/
/*---------------------------------------------------------------------------*/
#define sockets_c
#include "sockets.h"
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <posix_signal.h>
#include "panic.h"
#include "waislog.h"
/* In theory this is defined in stdio.h, but its hosed on SOLARIS */
extern FILE *fdopen(const int fd, const char *opt);
extern char *sys_errlist[];
#define QUEUE_SIZE (3L)
#define HOSTNAME_BUFFER_SIZE (120L)
#define MAX_RETRYS (10L)
#define TIMEOUT_CONNECT 5
/*---------------------------------------------------------------------------*/
#if !defined(IN_RMG) && !defined(PFS_THREADS)
static boolean
clrSocket(struct sockaddr_in *address,long portnumber,long *sock)
{
if (errno == EADDRINUSE)
{ if (connect(*sock, address, sizeof (struct sockaddr_in)) == 0)
{ close(*sock);
waislog(WLOG_HIGH,WLOG_ERROR,
"cannot bind port %ld (address already in use)",
portnumber);
waislog(WLOG_HIGH,WLOG_ERROR,
"waisserver is already running on this system");
panic("Exiting");
}
else
{ int one = 1;
close(*sock);
if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
panic("Open socket failed in trying to clear the port.");
if (setsockopt(*sock,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one)) < 0)
; /* do nothing? */
address->sin_family = AF_INET;
address->sin_addr.s_addr = INADDR_ANY;
address->sin_port = htons(portnumber);
if (bind(*sock, address, sizeof(*address)) == 0)
; /* do nothing? */
}
}
return(true);
}
/*---------------------------------------------------------------------------*/
void
openServer(long port,long* fd,long size)
{
struct sockaddr_in address;
memset(&address, 0, sizeof(address));
if ((*fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{ panic("can't get file descriptor for socket: %s", sys_errlist[errno]);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_ANY);
address.sin_port = htons(port);
if (bind(*fd,(struct sockaddr*)&address,sizeof(struct sockaddr)) < 0)
clrSocket(&address, port, fd);
if (listen(*fd,QUEUE_SIZE) < 0)
panic("can't open server: %s", sys_errlist[errno]);
}
/*---------------------------------------------------------------------------*/
void
fdAcceptClientConnection(long socket,long* fd)
{
struct sockaddr_in source;
int sourcelen;
#ifdef BSD
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
u_long S_addr;
} S_un;
} addr_p;
#endif
sourcelen = sizeof(struct sockaddr_in);
do {
errno = 0;
*fd = accept(socket, &source, &sourcelen);
} while (*fd < 0 && errno == EINTR);
if (source.sin_family == AF_INET)
{ struct hostent *peer = NULL;
peer = gethostbyaddr((char*)&source.sin_addr, 4, AF_INET);
waislog(WLOG_MEDIUM,WLOG_CONNECT,"accepted connection from: %s [%s]",
(peer == NULL) ? "" : peer->h_name,
#if defined(sparc) && defined(__GNUC__) && !defined(__svr4__)
inet_ntoa(&source.sin_addr));
#else
inet_ntoa(source.sin_addr));
#endif /* sparc */
}
if (*fd < 0)
panic("can't accept connection");
}
/*---------------------------------------------------------------------------*/
void
acceptClientConnection(long socket,FILE** file)
{
long fd;
fdAcceptClientConnection(socket,&fd);
if ((*file = fdopen(fd,"r+")) == NULL)
panic("can't accept connection");
}
/*---------------------------------------------------------------------------*/
void
closeClientConnection(FILE* file)
{
fclose(file);
}
/*---------------------------------------------------------------------------*/
void
closeServer(long socket)
{
close(socket);
}
#endif /*!IN_RMG && !PFS_THREADS*/
/*---------------------------------------------------------------------------*/
FILE *
connectToServer(char* host_name,long port)
{
FILE* file;
int fd;
if ((fd = quick_open_tcp_stream(host_name, port, TIMEOUT_CONNECT)) == -1)
return(NULL);
if ((file = fdopen(fd,"r+")) == NULL)
{ perror("Connect to socket did not work, fdopen failure");
close(fd);
return(NULL);
}
return(file);
}
/*---------------------------------------------------------------------------*/
void
closeConnectionToServer(FILE* file)
{
fclose(file);
}
/*---------------------------------------------------------------------------*/