ftp.nice.ch/pub/next/connectivity/infosystems/WAIStation.1.9.6.N.b.tar.gz#/WAIS/ir/sockets.c

This is sockets.c in view mode; [Download] [Up]

/* WIDE AREA INFORMATION SERVER SOFTWARE	
   No guarantees or restrictions.  See the readme file for the full standard 
   disclaimer.  
   5.29.90	Harry Morris, morris@think.com
*/

#ifndef lint
static char *RCSid = "$Header: /tmp_mnt/net/quake/proj/wais/wais-8-b5/ir/RCS/sockets.c,v 1.23 92/05/06 17:34:41 jonathan Exp $";
#endif

/* Change log:
 * $Log:	sockets.c,v $
 * Revision 1.23  92/05/06  17:34:41  jonathan
 * Added Mach to some compiler switches.
 * 
 * Revision 1.22  92/04/28  15:21:14  jonathan
 * Added decoding of IP address to DNS name in accept_client handler.
 * 
 * Revision 1.21  92/04/01  09:49:49  morris
 * declared clr_socket static to stop gcc from complaining
 * 
 * Revision 1.20  92/03/24  10:35:32  jonathan
 * Put a loop around connect in fd_connect_to_server to check if the connect
 * was interrupted by a system call (usually a timer).  Retries if errno is
 * EINTR.
 * 
 * Revision 1.19  92/02/16  12:38:22  jonathan
 * Changed bzero's to memset's.
 * 
 * Revision 1.18  92/02/16  12:34:11  jonathan
 * Removed code refering to NOINETNTOA, since we should use inet_ntoa.
 * 
 * Revision 1.17  92/02/12  13:48:21  jonathan
 * Added "$Log" so RCS will put the log message in the header
 * 
 * 
*/

/*
   Added code in fd_accept_client_connection to print source Inet address to
   stderr. 
   - Jonny G Fri Apr 12 1991

*/

#define sockets_c

#include "sockets.h"

#ifdef NOTCPIP /* we don't have TCPIP */

void open_server (port,socket,size) long port; long* socket; long size; {}
void accept_client_connection (socket,file) long socket; FILE** file; {}
void close_client_connection (file) FILE* file; {}
void close_server (socket) long socket; {}
FILE *connect_to_server (host_name,port) char* host_name; long port; 
                                  {return(NULL);}
void close_connection_to_server (file) FILE* file; {}

#else /* there is TCPIP */

#include <errno.h>
#include <string.h>
#include "panic.h"

#if (defined(ultrix) || defined(BSD) || defined(Mach))
extern int errno;
#endif /* ultrix BSD or Mach */

extern char *sys_errlist[];


/* XXX
still need:
 non-blocking modes
 special send/recieve functions? (there are now some in ui.c)
 asynchronous calls?
*/

/* define the number of queued connections allowable on each port */
#define QUEUE_SIZE 3

/*---------------------------------------------------------------------------*/
/* Server functions                                                          */
/*---------------------------------------------------------------------------*/

static boolean clr_socket _AP((struct sockaddr_in *address, long portnumber,
			long* sock));

static boolean clr_socket(address, portnumber, sock)
     struct sockaddr_in *address;
     long portnumber;
     long *sock;
{
  if (errno == EADDRINUSE) {
    /* Try connecting to it */
    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 {
      /* Connection failed; probably socket in FIN_WAIT */
      int one = 1;

      (void) close(*sock);
      if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	panic("Open socket failed in trying to clear the port.");
      /*printf("Error binding port %d: (address already in use).\n\
Attempting to clear stale socket...", portnumber);*/
      if ( setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, 
		      &one, sizeof (one)) < 0) {
	/*printf("Warning: Setsockopt SO_REUSEADDR failed.");*/
      }
      address->sin_family = AF_INET;
      address->sin_addr.s_addr = INADDR_ANY;
      address->sin_port = htons(portnumber);
      if (bind(*sock, address, sizeof(*address)) == 0) {
	/*printf("Successfully cleared stale EADDRINUSE error");*/
      }
    }
  }
  return(true);
}


void
open_server(port,fd,size)
long port;
long* fd;
long size;
{ struct sockaddr_in address;

  memset(&address, 0, sizeof(address));

  /* open the fd */
  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)
    clr_socket(&address, port, fd);

  if (listen(*fd,QUEUE_SIZE) < 0)
    panic("can't open server: %s", sys_errlist[errno]);
}



/* This is a lower level function provided for use by the lisp version of
 * this library 
 * XXX should support non-blocking mode
 */

#include <arpa/inet.h>

void
fd_accept_client_connection(socket,fd)
long socket;
long* fd;
{ /* accept an input connection, and open a file on it */
  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 /* BSD */

  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(&source.sin_addr, 4, AF_INET);

    waislog(WLOG_MEDIUM, WLOG_CONNECT,
	    "Accepted connection from: %s [%s]",
	    peer->h_name,
#if defined(sparc) && defined(__GNUC__)
	    inet_ntoa(&source.sin_addr)
#else
	    inet_ntoa(source.sin_addr)
#endif /* sparc */
	    );
  }
  if (*fd < 0)
    panic("can't accept connection");
}


/* This is the prefered C function for accepting client requests */
void
accept_client_connection(socket,file)
long socket;
FILE** file;
{ long fd; /* file descriptor actually used */
  fd_accept_client_connection(socket,&fd);
  if ((*file = fdopen(fd,"r+")) == NULL)
    panic("can't accept connection");
}

/* When a server wants to end the session with a client */
void
close_client_connection(file)
FILE* file;
{ 
  fclose(file);
}

/* when exiting the top level server process (not the forked
   server processes that come one per client).
   Maybe we need to do this once per client as well.
*/
void
close_server(socket)
long socket;
{
  close(socket);
}

/*---------------------------------------------------------------------------*/
/* Client functions                                                          */
/*---------------------------------------------------------------------------*/

/* This is a lower level function provided for use by the lisp version of
 * this library 
 * XXX should support non-blocking mode
 */

#define HOSTNAME_BUFFER_SIZE 120
#define MAX_RETRYS 10

boolean
fd_connect_to_server(host_name,port,fd)
char* host_name;
long port;
long* fd;
{
  char hostnamebuf[80];
  long rc, i;
  struct hostent *host;
  /* struct servent *service = NULL; not used */
  struct sockaddr_in name;

  memset((char *)&name, 0,sizeof (name));
  name.sin_addr.s_addr = inet_addr(host_name);
  if (name.sin_addr.s_addr != -1) {
    name.sin_family = AF_INET;
    (void) strcpy(hostnamebuf, host_name);
  }
  else {
    host = gethostbyname(host_name);

    if(NULL == host){
      return FALSE;
    }

    name.sin_family = host->h_addrtype;
#ifdef h_addr
    bcopy(host->h_addr_list[0],
	  (caddr_t)&name.sin_addr, host->h_length);
#endif
    (void) strcpy(hostnamebuf, host->h_name);
  }
  host_name = hostnamebuf;

  name.sin_port = htons(port);

  *fd = socket (AF_INET, SOCK_STREAM, 0);
  for(i = 0; i < MAX_RETRYS; i++) {
    rc = connect (*fd, &name, sizeof (name));
    if(rc == 0) return TRUE;
    else if(errno == EINTR){
      sleep(1);
    }
    else {
      perror("Connect to socket did not work (1)");
      return FALSE;
    }
  }
  return FALSE;
}

/* This is the prefered C function for initiating client requests */
FILE *
connect_to_server(host_name,port)
char* host_name;
long port;
{
  FILE* file;
  long fd;
  if(fd_connect_to_server(host_name,port,&fd) == FALSE) {
    perror("Connect to socket did not work (2)");
    return NULL;
  }

  if ((file = fdopen(fd,"r+")) == NULL) {
    perror("Connect to socket did not work (3)");
    return NULL;
  }

  return file;
}

void
close_connection_to_server(file)
FILE* file;
{
  fclose(file);
}

/*---------------------------------------------------------------------------*/

#endif /* there is TCPIP */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.