home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-12-22 | 62.5 KB | 1,740 lines |
- Newsgroups: comp.sources.unix
- From: pleierc@informatik.tu-muenchen.de (Christoph Pleier)
- Subject: v27i191: distributed-c-2.1 - Distributed C Development Environment, V2.1, Part17/18
- References: <1.756634932.28500@gw.home.vix.com>
- Sender: unix-sources-moderator@gw.home.vix.com
- Approved: vixie@gw.home.vix.com
-
- Submitted-By: pleierc@informatik.tu-muenchen.de (Christoph Pleier)
- Posting-Number: Volume 27, Issue 191
- Archive-Name: distributed-c-2.1/part17
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 17 (of 18)."
- # Contents: lib/ipc_socket.c
- # Wrapped by vixie@gw.home.vix.com on Thu Dec 23 00:12:07 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'lib/ipc_socket.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'lib/ipc_socket.c'\"
- else
- echo shar: Extracting \"'lib/ipc_socket.c'\" \(60451 characters\)
- sed "s/^X//" >'lib/ipc_socket.c' <<'END_OF_FILE'
- X/***************************************************************************
- X * *
- X * @@@@ @@@ @@@@@ @@@@@ @@@@@ @@@ @@@@ @ @ @@@@@ @@@@@ @@@@ @@@ *
- X * @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ *
- X * @ @ @ @@@@@ @ @@@@@ @ @@@@@ @ @ @ @@@@@ @ @ @ *
- X * @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ *
- X * @@@@ @@@ @@@@@ @ @ @ @@@ @@@@ @@@@@ @ @@@@@ @@@@ @@@ *
- X * *
- X * A compiler for distributed programming with C *
- X * *
- X * i p c _ s o c k e t . c *
- X * *
- X * Package : Runtime Library *
- X * Version : 1.1 *
- X * CreationDate : 10.07.90 *
- X * LastUpDate : 06.12.93 *
- X * *
- X * This file contains the hardware dependent routines building the message *
- X * passing layer based on stream sockets for use on operating system BSD *
- X * Unix Version 4.3 or other compatible operating systems like Sun Os 4.1, *
- X * ConvexOs, HP-UX, UNICOS, AIX or Ultrix. *
- X * *
- X * Copyright (C) 1990-1994 by Christoph Pleier *
- X * All rights reserved! *
- X ***************************************************************************/
- X
- X/*
- X * This file is part of the Distributed C Development Environment (DCDE).
- X * DCDE is free software; you can redistribute it and/or modify
- X * it under the terms written in the README-file.
- X * DCDE is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- X * See the file README for more details.
- X */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#ifdef UNICOS
- X# include <sys/param.h>
- X#endif
- X#include <sys/time.h>
- X#include <netinet/in.h>
- X#ifdef HPUX
- X# include <codelibs/nap.h>
- X#endif
- X#ifdef AIX
- X# include <sys/select.h>
- X# include <isode/isoaddrs.h>
- X# include <isode/manifest.h>
- X#endif
- X#include <netdb.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include "ipc_socket.h"
- X#include "run_Errno.h"
- X
- X#define DEBUG_IPC /**/
- X
- X/* To avoid that processes whose connection attempt is refused several times
- X * (e.g. if the called process tries itself to connect to the calling process)
- X * let grow the load of the computer nodes because of the busy waiting
- X * character, we raise each time a connection attempt is refused the delay
- X * until the connecting process is allowed to retry the attempt.
- X * The delay starts at MCON_RETRY_DELAY_MIN and is raised in steps of
- X * MCON_RETRY_DELAY_STEP until MCON_RETRY_DELAY_MAX. After the connection
- X * attempt succeeded or the operation is timed out the delay is reset to the
- X * minimal value.
- X *
- X * Note: the values specify different unities on different machines!
- X */
- X#ifdef SPARC
- X /* the values specify microseconds */
- X# define MCON_RETRY_DELAY_MIN 5000
- X# define MCON_RETRY_DELAY_MAX 100000
- X# define MCON_RETRY_DELAY_STEP 5000
- X#else
- X# ifdef HPUX
- X /* the values specify milliseconds */
- X# define MCON_RETRY_DELAY_MIN 10
- X# define MCON_RETRY_DELAY_MAX 1000
- X# define MCON_RETRY_DELAY_STEP 50
- X# else
- X /* the values specify seconds */
- X# define MCON_RETRY_DELAY_MIN 0
- X# define MCON_RETRY_DELAY_MAX 5
- X# define MCON_RETRY_DELAY_STEP 1
- X# endif /* HPUX /**/
- X#endif /* SPARC /**/
- X
- X#ifdef SYSTEM_V
- X# define bzero(s, n) memset((char *)(s), 0, (n))
- X# define bcopy(src, dst, num) memcpy((dst), (src), (num))
- X#endif /* SYSTEM_V /**/
- X
- X/* this variable is used to store the actual retry delay */
- Xint mcon_retry_delay = MCON_RETRY_DELAY_MIN;
- X
- X/* the array _con_socks is used to store all established TCP/IP connections. */
- Xint _con_num = 0;
- Xstruct _con *_con_socks_first = NULL, *_con_socks_last = NULL;
- X/* struct _con _con_socks[FD_SETSIZE]; */
- X
- X/* the used external global variables */
- Xextern int errno, /* system error code */
- X Errno, /* function error code */
- X _debugflush; /* flush debug messages or not */
- Xextern char *sys_errlist[], /* system error messages */
- X *_programname, /* name of program */
- X *_processname, /* name of process */
- X _processprefix[]; /* process specifying string */
- Xextern FILE *_debugout; /* where to write the debug messages */
- Xextern PORTDESCR _own_port; /* own port */
- X
- X#ifdef DEBUG_IPC
- X/* the flag to control the debug messages output */
- Xint _debug_ipc = 0;
- X#endif /* DEBUG_IPC /**/
- X
- X/* the timeout flag */
- Xstatic int timeout;
- X
- X/* caught signal SIGPIPE or not */
- Xstatic int sigpipe;
- X
- X/* set timer, if time equals 0 clear timer */
- X#ifdef BSD
- X# define SETTIMER(time) timeout = FALSE; \
- X { \
- X struct sigvec vec; \
- X \
- X vec.sv_handler = timeout_proc; \
- X vec.sv_mask = SIGALRM; \
- X vec.sv_flags = SV_INTERRUPT; \
- X sigvec(SIGALRM,&vec,(struct sigvec *) NULL);\
- X } \
- X (void) alarm(time);
- X# define CATCHSIGPIPE sigpipe = FALSE; \
- X { \
- X struct sigvec vec; \
- X \
- X vec.sv_handler = catch_SIGPIPE; \
- X vec.sv_mask = SIGPIPE; \
- X vec.sv_flags = SV_INTERRUPT; \
- X sigvec(SIGPIPE,&vec,(struct sigvec *) NULL);\
- X }
- X#else /* SYSTEM_V */
- X# define SETTIMER(time) timeout = FALSE; \
- X signal(SIGALRM, timeout_proc);\
- X (void) alarm(time);
- X# define CATCHSIGPIPE sigpipe = FALSE; \
- X signal(SIGPIPE, catch_SIGPIPE);
- X#endif /* BSD /**/
- X
- X/* if timeout is set, return ERROR */
- X#define RETURN_IF_TIMEOUT if (timeout) { \
- X Errno = ETIMEOUT; \
- X return(ERROR); \
- X }
- X
- X#ifdef DEBUG_IPC
- X# define DEBUGPUTS(msg) if (_debug_ipc) { \
- X fprintf(_debugout, "[ipc] %s %s\n", \
- X _processprefix, msg); \
- X if (_debugflush) \
- X fflush(_debugout); \
- X }
- X#else
- X# define DEBUGPUTS(msg) { /* nothing */ }
- X#endif
- X
- X/* The parameter types for the select() system call are different
- X * on HPUX systems. We handle this problem by a special cast macro.
- X */
- X#ifdef HPUX
- X#define SELECT_CAST (int *)
- X#else
- X#define SELECT_CAST (fd_set *)
- X#endif
- X
- X/******************************************************************************
- X * print_system_error() *
- X * *
- X * Writes a message of the last error consisting of a the appropriate system *
- X * error string and the appropriate error name to the file specified by 'fd'. *
- X * *
- X * Return values: none! *
- X ******************************************************************************/
- Xstatic int
- Xprint_system_error(fd)
- XFILE *fd;
- X{
- X register char *tmpptr;
- X
- X switch(errno) {
- X case EADDRINUSE:
- X tmpptr = "EADDRINUSE";
- X break;
- X case EADDRNOTAVAIL:
- X tmpptr = "EADDRNOTAVAIL";
- X break;
- X case EAFNOSUPPORT:
- X tmpptr = "EAFNOSUPPORT";
- X break;
- X case EALREADY:
- X tmpptr = "EALREADY";
- X break;
- X case EBADF:
- X tmpptr = "EBADF";
- X break;
- X case ECONNREFUSED:
- X tmpptr = "ECONNREFUSED";
- X break;
- X case EFAULT:
- X tmpptr = "EFAULT";
- X break;
- X case EINPROGRESS:
- X tmpptr = "EINPROGRESS";
- X break;
- X case EINTR:
- X tmpptr = "EINTR";
- X break;
- X case EINVAL:
- X tmpptr = "EINVAL";
- X break;
- X case EISCONN:
- X tmpptr = "EISCONN";
- X break;
- X case EMSGSIZE:
- X tmpptr = "EMSGSIZE";
- X break;
- X case ENETUNREACH:
- X tmpptr = "ENETUNREACH";
- X break;
- X case ENOBUFS:
- X tmpptr = "ENOBUFS";
- X break;
- X case ENOTSOCK:
- X tmpptr = "ENOTSOCK";
- X break;
- X case EOPNOTSUPP:
- X tmpptr = "EOPNOTSUPP";
- X break;
- X case ETIMEDOUT:
- X tmpptr = "ETIMEDOUT";
- X break;
- X case EWOULDBLOCK:
- X tmpptr = "EWOULDBLOCK";
- X break;
- X default:
- X tmpptr = NULL;
- X } /* switch */
- X if (tmpptr)
- X fprintf(fd, "Reason: %s (%s)\n", sys_errlist[errno], tmpptr);
- X else
- X fprintf(fd, "Reason: %s\n", sys_errlist[errno]);
- X fflush(fd);
- X} /* print_system_error */
- X
- X/******************************************************************************
- X * ipc_error() *
- X * *
- X * Writes a error message indicating the last error occured in the communica- *
- X * tion primitives to stderr. *
- X * *
- X * Return values: none! *
- X ******************************************************************************/
- Xstatic int
- Xipc_error(msg)
- Xchar *msg;
- X{
- X fprintf(stderr, "***** ERROR IN COMMUNICATION PRIMITIVES *****\n");
- X fprintf(stderr, "PROGRAM: %s, PROCESS: %s, HOST: %s, PID: %d\n",
- X _programname, _processname, _own_port.hostname, getpid());
- X fprintf(stderr, "Error: %s\n", msg);
- X if (errno != 0)
- X print_system_error(stderr);
- X fflush(stderr);
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "***** ERROR IN COMMUNICATION PRIMITIVES *****\n");
- X fprintf(_debugout, "PROGRAM: %s, PROCESS: %s, HOST: %s, PID: %d\n",
- X _programname, _processname, _own_port.hostname, getpid());
- X fprintf(_debugout, "Error: %s\n", msg);
- X if (errno != 0)
- X print_system_error(_debugout);
- X if (_debugflush)
- X fflush(_debugout);
- X }
- X#endif /* DEBUG_IPC /**/
- X} /* ipc_error */
- X
- X/******************************************************************************
- X * ipc_fatal_error() *
- X * *
- X * Writes a error message indicating the last error occured in the communica- *
- X * tion primitives to stderr and forces the termination of the program with *
- X * a core dump. *
- X * *
- X * Return values: this function returns never! *
- X ******************************************************************************/
- Xstatic int
- Xipc_fatal_error(loc, msg)
- Xchar *loc, *msg;
- X{
- X fprintf(stderr, "***** FATAL ERROR IN COMMUNICATION PRIMITIVES *****\n");
- X fprintf(stderr, "PROGRAM: %s, PROCESS: %s, HOST: %s, PID: %d\n",
- X _programname, _processname, _own_port.hostname, getpid());
- X fprintf(stderr, "Function: %s Error: %s\n", loc, msg);
- X if (errno != 0)
- X print_system_error(stderr);
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "***** FATAL ERROR IN COMMUNICATION PRIMITIVES *****\n");
- X fprintf(_debugout, "PROGRAM: %s, PROCESS: %s, HOST: %s, PID: %d\n",
- X _programname, _processname, _own_port.hostname, getpid());
- X fprintf(_debugout, "Function: %s Error: %s\n", loc, msg);
- X if (errno != 0)
- X print_system_error(_debugout);
- X if (_debugflush)
- X fflush(_debugout);
- X }
- X#endif /* DEBUG_IPC /**/
- X signal(SIGIOT, SIG_DFL);
- X abort();
- X} /* ipc_fatal_error */
- X
- X/******************************************************************************
- X * display_connection_list() *
- X * *
- X * Displays the list of established TCP/IP connections. **
- X * *
- X * Return values: none! *
- X ******************************************************************************/
- Xstatic int
- Xdisplay_connection_list()
- X{
- X int i;
- X register struct _con *_con_socks;
- X
- X#ifdef DEBUG_IPC
- X if (!_debug_ipc)
- X return;
- X fprintf(_debugout, "[ipc] %s connection list:\n", _processprefix);
- X for(_con_socks = _con_socks_first, i = 0; _con_socks; _con_socks = _con_socks->next, i++) {
- X fprintf(_debugout, "[ipc] %s entry %d:\n", _processprefix, i);
- X fprintf(_debugout, "[ipc] %s con_sock = %d\n",
- X _processprefix, _con_socks->con_sock);
- X fprintf(_debugout, "[ipc] %s port1:\n", _processprefix);
- X fprintf(_debugout, "[ipc] %s portnum = %d\n",
- X _processprefix, _con_socks->own_port.portnum);
- X fprintf(_debugout, "[ipc] %s hostname = %s\n",
- X _processprefix, _con_socks->own_port.hostname);
- X fprintf(_debugout, "[ipc] %s port2:\n", _processprefix);
- X fprintf(_debugout, "[ipc] %s portnum = %d\n",
- X _processprefix, _con_socks->other_port.portnum);
- X fprintf(_debugout, "[ipc] %s hostname = %s\n",
- X _processprefix, _con_socks->other_port.hostname);
- X } /* for */
- X#endif /* DEBUG_IPC /**/
- X} /* display_connection_list */
- X
- X/******************************************************************************
- X * store_connection_in_list() *
- X * *
- X * Stores the connection specified by the socket 'con_sock' in the list of *
- X * established TCP/IP connections. *
- X * *
- X * Return values: OK upon success / ERROR upon error *
- X ******************************************************************************/
- Xstatic int
- Xstore_connection_in_list(con_sock, own_port, other_port)
- Xint con_sock;
- XPORTDESCR own_port, other_port;
- X{
- X register struct _con *ptr;
- X#ifdef CONVEX
- X int close_connections();
- X#else
- X static int close_connections();
- X#endif
- X
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s storing connection in list:\n", _processprefix);
- X fflush(_debugout);
- X fprintf(_debugout, "[ipc] %s con_sock = %d\n",
- X _processprefix, con_sock);
- X fprintf(_debugout, "[ipc] %s port1:\n", _processprefix);
- X fprintf(_debugout, "[ipc] %s portnum = %d\n",
- X _processprefix, own_port.portnum);
- X fprintf(_debugout, "[ipc] %s hostname = %s\n",
- X _processprefix, own_port.hostname);
- X fprintf(_debugout, "[ipc] %s port2:\n", _processprefix);
- X fprintf(_debugout, "[ipc] %s portnum = %d\n",
- X _processprefix, other_port.portnum);
- X fprintf(_debugout, "[ipc] %s hostname = %s\n",
- X _processprefix, other_port.hostname);
- X if (_debugflush)
- X fflush(_debugout);
- X }
- X#endif /* DEBUG_IPC /**/
- X if (!(ptr = (struct _con *) malloc(sizeof(struct _con))))
- X ipc_fatal_error("store_connection_in_list", "out of heap space");
- X ptr->con_sock = con_sock;
- X ptr->own_port = own_port;
- X ptr->other_port = other_port;
- X ptr->next = NULL;
- X if (!_con_socks_first)
- X _con_socks_first = _con_socks_last = ptr;
- X else {
- X _con_socks_last->next = ptr;
- X _con_socks_last = ptr;
- X }
- X /* check if too many connections are open */
- X if (++_con_num > MAXOPENCONS)
- X close_connections(con_sock);
- X return(OK);
- X} /* store_connection_in_list */
- X
- X/******************************************************************************
- X * delete_connection_from_list() *
- X * *
- X * Deletes the connection specified by the socket 'con_sock' from the list of *
- X * established TCP/IP connections. *
- X * *
- X * Return values: OK upon success *
- X ******************************************************************************/
- Xstatic int
- Xdelete_connection_from_list(con_sock)
- Xint con_sock;
- X{
- X register struct _con *_con_socks, *last;
- X
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s deleting connection:\n",
- X _processprefix);
- X fprintf(_debugout, "[ipc] %s con_sock = %d\n",
- X _processprefix, _con_socks->con_sock);
- X fprintf(_debugout, "[ipc] %s port1:\n", _processprefix);
- X fprintf(_debugout, "[ipc] %s portnum = %d\n",
- X _processprefix, _con_socks->own_port.portnum);
- X fprintf(_debugout, "[ipc] %s hostname = %s\n",
- X _processprefix, _con_socks->own_port.hostname);
- X fprintf(_debugout, "[ipc] %s port2:\n", _processprefix);
- X fprintf(_debugout, "[ipc] %s portnum = %d\n",
- X _processprefix, _con_socks->other_port.portnum);
- X fprintf(_debugout, "[ipc] %s hostname = %s\n",
- X _processprefix, _con_socks->other_port.hostname);
- X if (_debugflush)
- X fflush(_debugout);
- X }
- X#endif /* DEBUG_IPC /**/
- X last = NULL;
- X for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
- X if (_con_socks->con_sock == con_sock) {
- X if (!last) {
- X _con_socks_first = _con_socks->next;
- X free(_con_socks);
- X } else {
- X last->next = _con_socks->next;
- X free(_con_socks);
- X }
- X _con_num--;
- X return(OK);
- X }
- X last = _con_socks;
- X } /* for */
- X ipc_fatal_error("delete_connection_from_list", "connection not found in list");
- X} /* delete_connection_from_list */
- X
- X/******************************************************************************
- X * close_connections() *
- X * *
- X * Closes CLOSECONNUM stored connections from the list of established TCP/IP *
- X * connections except the connection specified by 'con_sock'. *
- X * *
- X * Return values: OK upon success *
- X ******************************************************************************/
- Xstatic int
- Xclose_connections(con_sock)
- Xint con_sock;
- X{
- X register struct _con *_con_socks, *next;
- X int num, act_con_sock;
- X
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s closing %d connections\n",
- X _processprefix, CLOSECONNUM);
- X if (_debugflush)
- X fflush(_debugout);
- X }
- X#endif /* DEBUG_IPC /**/
- X num = CLOSECONNUM;
- X _con_socks = _con_socks_first;
- X while(_con_socks && num) {
- X act_con_sock = _con_socks->con_sock;
- X next = _con_socks->next;
- X if (_con_socks->con_sock != con_sock) {
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s deleting and closing socket %d\n",
- X _processprefix, act_con_sock);
- X if (_debugflush)
- X fflush(_debugout);
- X }
- X#endif /* DEBUG_IPC /**/
- X (void) close(act_con_sock);
- X delete_connection_from_list(act_con_sock);
- X num--;
- X }
- X _con_socks = next;
- X } /* while */
- X DEBUGPUTS("connections closed");
- X display_connection_list();
- X return(OK);
- X} /* close_connections */
- X
- X/******************************************************************************
- X * timeout_proc() *
- X * *
- X * Sets the timeout flag 'timeout' to indicate a timeout error. *
- X * *
- X * Return values: none! *
- X ******************************************************************************/
- X#ifdef UNICOS
- Xstatic void
- Xtimeout_proc(sig)
- Xint sig;
- X#else
- Xstatic void
- Xtimeout_proc(sig, code, scp)
- Xint sig, code;
- Xstruct sigcontext *scp;
- X#endif
- X{
- X DEBUGPUTS("***** timeout_proc():");
- X timeout = TRUE;
- X#ifdef HPUX
- X scp->sc_syscall_action = SIG_RETURN; /* abort interrupted system call! */
- X#endif
- X} /* timeout_proc */
- X
- X/******************************************************************************
- X * catch_SIGPIPE() *
- X * *
- X * Catches the signal SIGPIPE and stores TRUE in 'sigpipe'. *
- X * *
- X * Return values: none! *
- X ******************************************************************************/
- X#ifdef UNICOS
- Xstatic void
- Xcatch_SIGPIPE(sig)
- Xint sig;
- X#else
- Xstatic void
- Xcatch_SIGPIPE(sig, code, scp)
- Xint sig, code;
- Xstruct sigcontext *scp;
- X#endif
- X{
- X DEBUGPUTS("***** catch_SIGPIPE():");
- Xputs("SIGPIPE"); fflush(stdout);
- X sigpipe = TRUE;
- X#ifdef HPUX
- X scp->sc_syscall_action = SIG_RETURN; /* abort interrupted system call! */
- X#endif
- X} /* catch_SIGPIPE */
- X
- X/******************************************************************************
- X * _create_port() *
- X * *
- X * Creates a new communication endpoint. *
- X * *
- X * Return values: OK = success / ERROR = error *
- X ******************************************************************************/
- Xint
- X_create_port(port)
- XPORTDESCR *port;
- X{
- X int sock,
- X res;
- X u_short portnum;
- X struct sockaddr_in so_addr;
- X
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s ***** _create_port():\n", _processprefix);
- X fprintf(_debugout, "[ipc] %s &port = %d\n", _processprefix, port);
- X }
- X#endif /* DEBUG_IPC /**/
- X /* set Errno */
- X Errno = ECREATEPORT;
- X /* create a TCP socket */
- X if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- X ipc_error("system call: socket()");
- X return(ERROR);
- X }
- X /* initialize components of internet address */
- X bzero(&so_addr, sizeof(so_addr));
- X so_addr.sin_family = AF_INET;
- X so_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- X /* bind socket to an unused address (port number) */
- X for (portnum = STARTPORT; portnum <= ENDPORT; portnum++) {
- X#ifdef DEBUG_IPC
- X if (_debug_ipc)
- X fprintf(_debugout,"[ipc] %s trying to bind socket to portnum %d\n",
- X _processprefix, htons(portnum));
- X#endif /* DEBUG_IPC /**/
- X so_addr.sin_port = portnum;
- X if (!(res = bind(sock, (struct sockaddr *) &so_addr, sizeof(so_addr)))){
- X if (listen(sock, 1)) {
- X ipc_error("system call: listen()");
- X return(ERROR);
- X }
- X /*
- X * Initialize port and return
- X */
- X bzero((char *) port, sizeof(PORTDESCR));
- X port->state = CONNECTIONLESS;
- X port->acc_sock = sock;
- X port->portnum = portnum;
- X if (gethostname(port->hostname, MAXHOSTNAMELEN)) {
- X ipc_error("gethostname()");
- X return(ERROR);
- X }
- X port->con_sock = 0;
- X DEBUGPUTS("port successfully created");
- X /* clear Errno and return */
- X Errno = OK;
- X return(OK);
- X }
- X if ((res < 0) && (errno == EACCES)) {
- X ipc_error("can't access socket");
- X return (ERROR);
- X }
- X if (portnum > ENDPORT)
- X portnum = STARTPORT;
- X } /* for */
- X ipc_fatal_error("_create_port()", "no portnum found");
- X} /* _create_port */
- X
- X/******************************************************************************
- X * _delete_port() *
- X * *
- X * Deletes the communication endpoint specified by 'port'. *
- X * *
- X * Return values: OK = success / ERROR = error *
- X ******************************************************************************/
- Xint
- X_delete_port(port)
- XPORTDESCR *port;
- X{
- X register struct _con *_con_socks;
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s ***** _delete_port():\n", _processprefix);
- X _display_port_info("[ipc]", "port", *port);
- X }
- X#endif /* DEBUG_IPC /**/
- X /* set Errno */
- X Errno = EDELETEPORT;
- X /* check port state */
- X if (port->state != CONNECTIONLESS)
- X ipc_fatal_error("_delete_port()", "port state is not CONNECTIONLESS");
- X /* close connection if there's any */
- X if (port->con_sock)
- X (void) close(port->con_sock);
- X /* close socket */
- X if (close(port->acc_sock)) {
- X ipc_error("system call: close()");
- X return(ERROR);
- X }
- X /* shut down all open connections */
- X for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
- X (void) close(_con_socks->con_sock);
- X }
- X /* clear Errno and return */
- X Errno = OK;
- X return(OK);
- X} /* _delete_port */
- X
- X/******************************************************************************
- X * _accept_connection() *
- X * *
- X * Communication endpoint 'port' waits 'time' real time seconds for a *
- X * connection request (if 'time' equals 0 then the operation is unlimited). *
- X * *
- X * Return values: OK = success / ERROR = error *
- X ******************************************************************************/
- Xint
- X_accept_connection(con_port, port, time)
- XCONNECTIONDESCR *con_port;
- XPORTDESCR *port;
- Xunsigned time;
- X{
- X static int i,
- X num,
- X con_sock,
- X con_addr_len,
- X connector_portnum,
- X newconnection,
- X setsoptarg;
- X char connector_hostname[MAXHOSTNAMELEN],
- X address[MAXHOSTNAMELEN+20],
- X buffer[CON_MSGLEN+5];
- X PORTDESCR other_port;
- X register struct _con *_con_socks;
- X struct timeval timevalarg;
- X static fd_set readfds;
- X static struct sockaddr_in con_addr;
- X
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s ***** _accept_connection():\n",
- X _processprefix);
- X fprintf(_debugout, "[ipc] %s &con_port = %d\n", _processprefix,
- X con_port);
- X _display_port_info("[ipc]", "port", *port);
- X fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time);
- Xdisplay_connection_list();
- X }
- X#endif /* DEBUG_IPC /**/
- X /* set Errno */
- X Errno = EACPTCON;
- X /* set timer, if time equals 0 clear timer */
- X SETTIMER(time);
- X while(!timeout) {
- X /* check port state */
- X if (port->state != CONNECTIONLESS)
- X ipc_fatal_error("_accept_connection()", "port state is not CONNECTIONLESS");
- X DEBUGPUTS("state: CONNECTIONLESS");
- Xdisplay_connection_list();
- X /* initialize readfds */
- X FD_ZERO(&readfds);
- X FD_SET(port->acc_sock, &readfds);
- X for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
- X FD_SET(_con_socks->con_sock, &readfds);
- X }
- X /* First we wait until one or more process(es) want(s) to connect to us
- X * (connect() to port->acc_sock) or one or more process(es) want(s) to
- X * send some data to us using an existing connection.
- X */
- X port->state = SELECTING;
- X DEBUGPUTS("state: SELECTING");
- X if (select(FD_SETSIZE, SELECT_CAST &readfds, SELECT_CAST NULL, SELECT_CAST NULL,
- X (struct timeval *) NULL) < 0) {
- X if (errno == EINTR && timeout) {
- X /* return TIMEOUT error to caller */
- X continue;
- X }
- X switch(errno) {
- X case EBADF:
- X case EFAULT:
- X /* remove connections that have been closed */
- X timevalarg.tv_sec = 0;
- X timevalarg.tv_usec = 1;
- X for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
- X FD_ZERO(&readfds);
- X FD_SET(_con_socks->con_sock, &readfds);
- X if (select(FD_SETSIZE, SELECT_CAST &readfds, SELECT_CAST NULL, SELECT_CAST NULL,
- X &timevalarg) < 0) {
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s closed connection found! socket is %d\n",
- X _processprefix, _con_socks->con_sock);
- X if (_debugflush)
- X fflush(_debugout);
- X }
- X#endif /* DEBUG_IPC /**/
- X delete_connection_from_list(_con_socks->con_sock);
- X }
- X } /* for */
- X break;
- X default:
- X ipc_error("system call: select()");
- X return(ERROR);
- X } /* switch */
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X (void) close(con_sock);
- X continue;
- X }
- X /* Upon completion of select(), we look first if one or more process
- X * want(s) to establish a new connection (CASE 1) (Note: new connections
- X * are prefered!) Otherwise we choose one of the process(es) that
- X * want(s) to send data to us (CASE 2)!
- X */
- X /* clear connection descriptor */
- X con_sock = 0;
- X /* clear new connection flag */
- X newconnection = 0;
- X /* set connection descriptor */
- X if (FD_ISSET(port->acc_sock, &readfds)) {
- X /* CASE 1: accept a new connection */
- X port->state = ACCEPTING;
- X DEBUGPUTS("state: ACCEPTING");
- X con_addr_len = sizeof(con_addr);
- X if ((con_sock = accept(port->acc_sock, (struct sockaddr *) &con_addr,
- X &con_addr_len)) < 0) {
- X switch(errno) {
- X case EMFILE:
- X /* ipc_fatal_error("accept()", "too many open connections or files"); */
- X fprintf(stderr, "%s too many connections open\n", _processprefix);
- X fprintf(stderr, "%s closing %d connections\n", _processprefix, CLOSECONNUM);
- X fflush(stderr);
- X close_connections(0);
- X fprintf(stderr, "%s sleeping 15 seconds to get connections closed\n", _processprefix);
- X fflush(stderr);
- X sleep(15);
- X fprintf(stderr, "%s ok - trying again\n", _processprefix);
- X fflush(stderr);
- X break;
- X case ECONNRESET:
- X DEBUGPUTS("connection reset by peer");
- X break;
- X default:
- X ipc_error("system call: accept()");
- X return(ERROR);
- X } /* switch */
- X DEBUGPUTS("trying again");
- X (void) close(con_sock);
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X newconnection = 1;
- X } else {
- X /* CASE 2: reuse old, already existing connection */
- X for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
- X if (FD_ISSET(_con_socks->con_sock, &readfds)) {
- X DEBUGPUTS("reusing old connection");
- X con_sock = _con_socks->con_sock;
- X break;
- X }
- X }
- X }
- X /* If con_port equals zero at this point, select() returned indicating
- X * an ending connection. Unfortunately we don't know which connection
- X * it was! So we can't delete it from the list at this point.
- X */
- X if (!con_sock) {
- X DEBUGPUTS("a connection was closed (1)");
- X DEBUGPUTS("trying again");
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X /* Well! We have a correct connection, specified by con_sock.
- X * A request message of length zero indicates again the ending of
- X * a connection. We consider this aspect.
- X * Now let's look for a correct request message.
- X */
- X port->state = RECV_REQ;
- X DEBUGPUTS("state: RECV_REQ");
- X if ((num = read(con_sock, buffer, CON_MSGLEN + 5)) < 0) {
- X if (errno == EINTR && timeout) {
- X /* return TIMEOUT error to caller */
- X continue;
- X }
- X switch(errno) {
- X case EBADF:
- X DEBUGPUTS("bad file number, trying again");
- X break;
- X case ECONNRESET:
- X DEBUGPUTS("connection reset by peer, trying again");
- X break;
- X default:
- X ipc_error("system call: read() - 1");
- X return(ERROR);
- X } /* switch */
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X (void) close(con_sock);
- X continue;
- X }
- X if (num == 0) {
- X DEBUGPUTS("a connection was closed (2)");
- X DEBUGPUTS("trying again");
- X (void) close(con_sock);
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X if (num != CON_MSGLEN || strcmp(buffer, CON_REQUEST)) {
- X DEBUGPUTS("bad request message received");
- X DEBUGPUTS("trying again");
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X /* The request message was o.k. as well. Therefore we send back
- X * the reply message.
- X */
- X port->state = SEND_REP;
- X DEBUGPUTS("state: SEND_REP");
- X CATCHSIGPIPE;
- X if ((num = write(con_sock, CON_ACCEPTED, CON_MSGLEN)) < 0) {
- X if (errno == EINTR && timeout) {
- X /* return TIMEOUT error to caller */
- X continue;
- X }
- X if (sigpipe) {
- X /* connection was closed by foreign host */
- X errno = EPIPE;
- X sigpipe = FALSE;
- X }
- X switch(errno) {
- X case EBADF:
- X DEBUGPUTS("bad file number, trying again");
- X break;
- X case EPIPE:
- X DEBUGPUTS("broken pipe, trying again");
- X break;
- X case ECONNRESET:
- X DEBUGPUTS("connection reset by peer, trying again");
- X break;
- X default:
- X ipc_error("system call: write() - 1");
- X return(ERROR);
- X } /* switch */
- X (void) close(con_sock);
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X if (num != CON_MSGLEN) {
- X errno = 0;
- X ipc_error("sending reply message");
- X return(ERROR);
- X }
- X /* After correct handshaking of request and reply, we receive
- X * the address of the process connecting to us.
- X * We also check if the TCP/IP connection was ending!
- X */
- X port->state = RECV_ADDR;
- X DEBUGPUTS("state: RECV_ADDR");
- X if ((num = read(con_sock, address, sizeof(address))) < 0) {
- X if (errno == EINTR && timeout) {
- X /* return TIMEOUT error to caller */
- X continue;
- X }
- X switch(errno) {
- X case EBADF:
- X DEBUGPUTS("bad file number, trying again");
- X break;
- X case ECONNRESET:
- X DEBUGPUTS("connection reset by peer, trying again");
- X break;
- X default:
- X ipc_error("system call: read() - 2");
- X return(ERROR);
- X } /* switch */
- X (void) close(con_sock);
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X if (num == 0) {
- X DEBUGPUTS("connection was closed");
- X if (!newconnection)
- X delete_connection_from_list(con_sock);
- X DEBUGPUTS("trying again");
- X (void) close(con_sock);
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X if (num != sizeof(address)) {
- X DEBUGPUTS("bad address received");
- X DEBUGPUTS("trying again");
- X (void) close(con_sock);
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X sscanf(address, "%d|%s", &connector_portnum, connector_hostname);
- X /* Connection establishment completed!
- X * Initialize variables and return to calling program.
- X */
- X port->state = CONNECTED;
- X DEBUGPUTS("state: CONNECTED");
- X /* Initialize connection port */
- X con_port->state = CONNECTED;
- X con_port->con_sock = con_sock;
- X con_port->own_port = port;
- X con_port->other_port = NULL;
- X /* If we have accepted a new TCP/IP connection, we store it
- X * in the connection list.
- X */
- X if (newconnection) {
- X other_port.state = -1;
- X other_port.acc_sock = -1;;
- X other_port.con_sock = -1;;
- X other_port.portnum = connector_portnum;
- X strcpy(other_port.hostname, connector_hostname);
- X store_connection_in_list(con_sock, *port, other_port);
- X }
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s address of connector:\n",
- X _processprefix);
- X fprintf(_debugout, "[ipc] %s portnum = %d\n",
- X _processprefix, connector_portnum);
- X fprintf(_debugout, "[ipc] %s hostname = %s\n",
- X _processprefix, connector_hostname);
- X display_connection_list();
- X }
- X#endif /* DEBUG_IPC /**/
- X /* check periodically if connection is still alive */
- X setsoptarg = 1;
- X if (setsockopt(con_sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &setsoptarg, sizeof(int)) < 0) {
- X ipc_error("system_call: setsockopt(SO_KEEPALIVE)");
- X return(ERROR);
- X }
- X /* clear timer and return */
- X (void) alarm(0);
- X DEBUGPUTS("connection accepted");
- X Errno = OK;
- X return(OK);
- X } /* while */
- X DEBUGPUTS("TIMEOUT");
- X port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X Errno = ETIMEOUT;
- X return(ERROR);
- X} /* _accept_connection */
- X
- X/******************************************************************************
- X * _make_connection() *
- X * *
- X * Communication enpoint 'port1' tries 'time' real time seconds to connect *
- X * to 'port2' (if 'time' equals 0 then the operation is unlimited). *
- X * *
- X * Return values: OK = success / ERROR = error *
- X ******************************************************************************/
- Xint
- X_make_connection(con_port, port1, port2, time)
- XCONNECTIONDESCR *con_port;
- XPORTDESCR *port1;
- XPORTDESCR *port2;
- Xunsigned time;
- X{
- X int i,
- X num,
- X con_sock,
- X con_addr_len,
- X setsoptarg;
- X char buffer[CON_MSGLEN+5],
- X address[MAXHOSTNAMELEN+20];
- X static struct sockaddr_in con_addr;
- X static struct hostent *hostinfo;
- X register struct _con *_con_socks;
- X struct timeval timevalarg;
- X static fd_set writefds;
- X
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s ***** _make_connection():\n",
- X _processprefix);
- X fprintf(_debugout, "[ipc] %s &con_port = %d\n", _processprefix,
- X con_port);
- X _display_port_info("[ipc]", "port1", *port1);
- X _display_port_info("[ipc]", "port2", *port2);
- X fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time);
- Xdisplay_connection_list();
- X }
- X#endif /* DEBUG_IPC /**/
- X /* set Errno */
- X Errno = EMAKECON;
- X /* set timer, if time equals 0 clear timer */
- X SETTIMER(time);
- X while(!timeout) {
- X /* check port state */
- X if (port1->state != CONNECTIONLESS)
- X ipc_fatal_error("_make_connection()", "port state is not CONNECTIONLESS");
- X /* clear connection descriptor */
- X con_sock = 0;
- X /* If there's already an existing TCP/IP connection we use it (CASE 1).
- X * Otherwise we try to connect to the other port (CASE 2).
- X */
- X if (port2->con_sock) {
- X /* CASE 1a: connection exists! */
- X con_sock = port2->con_sock;
- X } else {
- X /* look if connection was already accepted! */
- X DEBUGPUTS("searching in connection list");
- X for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
- X if (port2->portnum == _con_socks->other_port.portnum
- X && !strcmp(port2->hostname, _con_socks->other_port.hostname)) {
- X /* CASE 1b: connection exists! */
- X DEBUGPUTS("using old connection");
- X con_sock = _con_socks->con_sock;
- X /* check if connection is still alive! */
- X FD_ZERO(&writefds);
- X FD_SET(con_sock, &writefds);
- X if (select(FD_SETSIZE, SELECT_CAST NULL, SELECT_CAST &writefds,
- X SELECT_CAST NULL, &timevalarg) < 0) {
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s closed connection found! socket is %d\n",
- X _processprefix, _con_socks->con_sock);
- X if (_debugflush)
- X fflush(_debugout);
- X#endif /* DEBUG_IPC /**/
- X delete_connection_from_list(_con_socks->con_sock);
- X con_sock = 0;
- X }
- X }
- X break;
- X }
- X } /* for */
- X /* If con_sock equals zero, there was no connection found in
- X * the array storing established TCP/IP connections.
- X * Because of that, we establish a new connection
- X */
- X if (con_sock == 0) {
- X /* CASE 2: establish a new TCP/IP connection! */
- X port1->state = CONNECTING;
- X DEBUGPUTS("state: CONNECTING");
- X /* create a new TCP socket
- X * NOTE: a new socket is used instead of port1
- X */
- X if ((con_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- X ipc_error("system call: socket()");
- X return(ERROR);
- X }
- X /* clear calling address */
- X bzero(&con_addr, sizeof(con_addr));
- X /* set address family of called host */
- X con_addr.sin_family = AF_INET;
- X /* get host information of called host */
- X hostinfo = NULL;
- X while(!timeout && !hostinfo)
- X hostinfo = gethostbyname(port2->hostname);
- X if (errno == EINTR && timeout) {
- X /* return TIMEOUT error to caller */
- X fputs("timeout caused by gethostbyname()!\n", stderr);
- X Errno = ETIMEOUT;
- X return(ERROR);
- X }
- X /* set address of called host */
- X bcopy(hostinfo->h_addr, &con_addr.sin_addr, hostinfo->h_length);
- X /* set portnum of called host */
- X con_addr.sin_port = port2->portnum;
- X /* try to connect */
- X if (connect(con_sock, (struct sockaddr *) &con_addr, sizeof(con_addr)) < 0){
- X switch(errno) {
- X case ETIMEDOUT:
- X DEBUGPUTS("attempt timed out by system, trying again");
- X break;
- X case EISCONN:
- X DEBUGPUTS("port is connected, trying again");
- X break;
- X case ECONNREFUSED:
- X DEBUGPUTS("connection refused, trying again");
- X break;
- X default:
- X ipc_error("system call: connect()");
- X } /* switch */
- X port1->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X (void) close(con_sock);
- X continue;
- X }
- X /* TCP/IP connection established! Store connection information
- X * in connection list.
- X */
- X store_connection_in_list(con_sock, *port1, *port2);
- X#ifdef DEBUG_IPC
- X if (_debug_ipc)
- X display_connection_list();
- X#endif /* DEBUG_IPC /**/
- X }
- X }
- X /* At this point, con_sock specifies a network connection to the called
- X * port. If the stored connection was closed at the other side we will
- X * get an EBADF, EPIPE or ECONNRESET error or receive signal SIGPIPE.
- X * In this case we delete the stored connection and try it again.
- X * Now we send a request message.
- X */
- X port1->state = SEND_REQ;
- X DEBUGPUTS("state: SEND_REQ");
- X CATCHSIGPIPE;
- X if ((num = write(con_sock, CON_REQUEST, CON_MSGLEN)) < 0) {
- X if (errno == EINTR && timeout) {
- X /* return TIMEOUT error to caller */
- X continue;
- X }
- X if (sigpipe) {
- X /* connection was closed by foreign host */
- X errno = EPIPE;
- X sigpipe = FALSE;
- X }
- X switch(errno) {
- X case EBADF:
- X DEBUGPUTS("bad file number, trying again");
- X break;
- X case EPIPE:
- X DEBUGPUTS("broken pipe, trying again");
- X break;
- X case ECONNRESET:
- X DEBUGPUTS("connection reset by peer, trying again");
- X break;
- X default:
- X ipc_error("system call: write() - 2");
- X return(ERROR);
- X } /* switch */
- X DEBUGPUTS("stored connection not longer valid");
- X delete_connection_from_list(con_sock);
- X (void) close(con_sock);
- X port1->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X if (num != CON_MSGLEN) {
- X errno = 0;
- X ipc_error("sending request");
- X return(ERROR);
- X }
- X /* Well! The request message was successfully sent to the called
- X * process. Now receive the reply message. We must also take care
- X * if the connection is ending during our handshaking!
- X */
- X port1->state = RECV_REP;
- X DEBUGPUTS("state: RECV_REP");
- X if ((num = read(con_sock, buffer, CON_MSGLEN + 5)) < 0) {
- X if (errno == EINTR && timeout) {
- X /* return TIMEOUT error to caller */
- X continue;
- X }
- X switch(errno) {
- X case EBADF:
- X DEBUGPUTS("bad file number, trying again");
- X break;
- X case ECONNRESET:
- X DEBUGPUTS("connection reset by peer, trying again");
- X break;
- X default:
- X ipc_error("system call: read() - 3");
- X return(ERROR);
- X } /* switch */
- X DEBUGPUTS("stored connection not longer valid");
- X delete_connection_from_list(con_sock);
- X (void) close(con_sock);
- X port1->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X if (num == 0) {
- X DEBUGPUTS("connection was closed");
- X delete_connection_from_list(con_sock);
- X DEBUGPUTS("trying again");
- X (void) close(con_sock);
- X port1->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X if (num != CON_MSGLEN) {
- X DEBUGPUTS("bad reply message received");
- X DEBUGPUTS("trying again");
- X port1->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X /* After correct handshaking of request and reply, send the own
- X * address to the called process, initialize the variables and
- X * return to the calling program.
- X */
- X if (!strcmp(buffer, CON_ACCEPTED)) {
- X port1->state = SEND_ADDR;
- X DEBUGPUTS("state: SEND_ADDR");
- X /* send address */
- X sprintf(address, "%d|%s", port1->portnum, port1->hostname);
- X CATCHSIGPIPE;
- X if ((num = write(con_sock, address, sizeof(address))) < 0) {
- X if (errno == EINTR && timeout) {
- X /* return TIMEOUT error to caller */
- X continue;
- X }
- X if (sigpipe) {
- X /* connection was closed by foreign host */
- X errno = EPIPE;
- X sigpipe = FALSE;
- X }
- X switch(errno) {
- X case EBADF:
- X DEBUGPUTS("bad file number, trying again");
- X break;
- X case EPIPE:
- X DEBUGPUTS("broken pipe, trying again");
- X break;
- X case ECONNRESET:
- X DEBUGPUTS("connection reset by peer, trying again");
- X break;
- X default:
- X ipc_error("system call: write() - 3");
- X return(ERROR);
- X } /* switch */
- X DEBUGPUTS("stored connection not longer valid");
- X delete_connection_from_list(con_sock);
- X port1->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X (void) close(con_sock);
- X continue;
- X }
- X if (num != sizeof(address)) {
- X errno = 0;
- X ipc_error("sending adress");
- X return(ERROR);
- X }
- X port1->state = CONNECTED;
- X DEBUGPUTS("state: CONNECTED");
- X /* Initialize connection port */
- X con_port->state = CONNECTED;
- X con_port->con_sock = con_sock;
- X con_port->own_port = port1;
- X con_port->other_port = port2;
- X /* clear timer and return */
- X (void) alarm(0);
- X DEBUGPUTS("connection established!");
- X mcon_retry_delay = MCON_RETRY_DELAY_MIN;
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s retry delay now %d\n",
- X _processprefix, mcon_retry_delay);
- X if (_debugflush)
- X fflush(_debugout);
- X }
- X#endif /* DEBUG_IPC /**/
- X /* check periodically if connection is still alive */
- X setsoptarg = 1;
- X if (setsockopt(con_sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &setsoptarg,
- X sizeof(int)) < 0) {
- X ipc_error("system_call: setsockopt(SO_KEEPALIVE)");
- X return(ERROR);
- X }
- X return(OK);
- X } else {
- X /* If two processes have already an established TCP/IP connection
- X * and try to make a connection using _make_connection() at the
- X * same time, each process receives as reply message the request
- X * message of the other process! In this case we try it again!
- X */
- X DEBUGPUTS("wrong reply message");
- X#ifdef SPARC
- X usleep(mcon_retry_delay);
- X#else
- X# ifdef HPUX
- X nap(mcon_retry_delay);
- X# else
- X sleep(mcon_retry_delay);
- X# endif /* HPUX /**/
- X#endif /* SPARC /**/
- X if (mcon_retry_delay < MCON_RETRY_DELAY_MAX)
- X mcon_retry_delay += MCON_RETRY_DELAY_STEP;
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s retry delay now %d\n",
- X _processprefix, mcon_retry_delay);
- X if (_debugflush)
- X fflush(_debugout);
- X }
- X#endif /* DEBUG_IPC /**/
- X DEBUGPUTS("trying again");
- X port1->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X continue;
- X }
- X } /* while */
- X DEBUGPUTS("TIMEOUT");
- X port1->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s retry delay now %d\n",
- X _processprefix, mcon_retry_delay);
- X if (_debugflush)
- X fflush(_debugout);
- X }
- X#endif /* DEBUG_IPC /**/
- X Errno = ETIMEOUT;
- X return(ERROR);
- X} /* _make_connection */
- X
- X/******************************************************************************
- X * _close_connection() *
- X * *
- X * The connection associated to connection port 'con_port' is closed. *
- X * *
- X * Return values: OK = success / ERROR = error *
- X ******************************************************************************/
- Xint
- X_close_connection(con_port)
- XCONNECTIONDESCR *con_port;
- X{
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s ***** _close_connection():\n",
- X _processprefix);
- X _display_connection_port_info("[ipc]", "con_port", *con_port);
- X }
- X#endif /* DEBUG_IPC /**/
- X /* set Errno */
- X Errno = ECLOSECON;
- X /* check port state */
- X if (con_port->state != CONNECTED)
- X ipc_fatal_error("_close_connection()", "con_port state is not CONNECTED");
- X con_port->own_port->state = CLOSING;
- X DEBUGPUTS("state: CLOSING");
- X con_port->own_port->state = CONNECTIONLESS;
- X con_port->state = CONNECTIONLESS;
- X DEBUGPUTS("state: CONNECTIONLESS");
- X return(OK);
- X} /* _close_connection */
- X
- X
- X/******************************************************************************
- X * *
- X * 'number' bytes are received from connection port 'con_port' and stored *
- X * into 'buffer'. 'time' is the maximum real time in seconds to wait for a *
- X * message to arrive (if 'time' equals 0 the waiting is unlimited). *
- X * *
- X * Return values: number of received bytes upon success / ERROR = error *
- X ******************************************************************************/
- Xint
- X_recv_data(con_port, buffer, number, time)
- XCONNECTIONDESCR *con_port;
- Xchar *buffer;
- Xint number;
- Xunsigned time;
- X{
- X int num, nleft, nread;
- X
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s ***** _recv_data():\n", _processprefix);
- X _display_connection_port_info("[ipc]", "con_port", *con_port);
- X fprintf(_debugout, "[ipc] %s buffer = %d, number = %d\n",
- X _processprefix, buffer, number);
- X fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time);
- X }
- X#endif /* DEBUG_IPC /**/
- X /* set Errno */
- X Errno = ERECVDATA;
- X /* check connection port state */
- X if (con_port->state != CONNECTED)
- X ipc_fatal_error("_recv_data()", "con_port state is not CONNECTED");
- X /* check port state */
- X if (con_port->own_port->state != CONNECTED)
- X ipc_fatal_error("_recv_data()", "port state is not CONNECTED");
- X /* set timer, if time equals 0 clear timer */
- X SETTIMER(time);
- X con_port->state = con_port->own_port->state = RECEIVING;
- X DEBUGPUTS("state: RECEIVING");
- X nleft = number;
- X while(nleft > 0) {
- X nread = read(con_port->con_sock, buffer, nleft);
- X if (nread < 0) {
- X /* ERROR! */
- X if (errno == EINTR && timeout) {
- X /* return TIMEOUT error to caller */
- X Errno = ETIMEOUT;
- X } else
- X ipc_error("system call: read() - 4");
- X con_port->state = con_port->own_port->state = CONNECTED;
- X DEBUGPUTS("state: CONNECTED");
- X return(ERROR);
- X } else if (nread == 0) {
- X /* EOF! */
- X break;
- X }
- X nleft -= nread;
- X buffer += nread;
- X } /* while */
- X con_port->state = con_port->own_port->state = CONNECTED;
- X DEBUGPUTS("state: CONNECTED");
- X /* clear timer and return */
- X (void) alarm(0);
- X return(number - nleft);
- X} /* _recv_data */
- X
- X/******************************************************************************
- X * _send_data() *
- X * *
- X * 'number' bytes, stored in 'buffer', are send to connection port 'con_port'.*
- X * 'time' is the maximum real time in seconds to retry sending upon error (if *
- X * 'time' equals 0 the waiting is unlimited). *
- X * *
- X * Return values: number of sent bytes upon success / ERROR = error *
- X ******************************************************************************/
- Xint
- X_send_data(con_port, buffer, number, time)
- XCONNECTIONDESCR *con_port;
- Xchar *buffer;
- Xint number;
- Xunsigned time;
- X{
- X int num, nleft, nwritten;
- X
- X#ifdef DEBUG_IPC
- X if (_debug_ipc) {
- X fprintf(_debugout, "[ipc] %s ***** _send_data():\n", _processprefix);
- X _display_connection_port_info("[ipc]", "con_port", *con_port);
- X fprintf(_debugout, "[ipc] %s buffer = %d, number = %d\n",
- X _processprefix, buffer, number);
- X fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time);
- X }
- X#endif /* DEBUG_IPC /**/
- X /* set Errno */
- X Errno = ESENDDATA;
- X /* check connection port state */
- X if (con_port->state != CONNECTED)
- X ipc_fatal_error("_send_data()", "con_port state is not CONNECTED");
- X /* check port state */
- X if (con_port->own_port->state != CONNECTED)
- X ipc_fatal_error("_send_data()", "port state is not CONNECTED");
- X /* set timer, if time equals 0 clear timer */
- X SETTIMER(time);
- X con_port->state = con_port->own_port->state = SENDING;
- X DEBUGPUTS("state: SENDING");
- X nleft = number;
- X while(nleft > 0) {
- X nwritten = write(con_port->con_sock, buffer, nleft);
- X if (nwritten <= 0) {
- X /* ERROR! */
- X if (errno == EINTR && timeout) {
- X /* return TIMEOUT error to caller */
- X Errno = ETIMEOUT;
- X } else
- X ipc_error("system call: write() - 4");
- X con_port->state = con_port->own_port->state = CONNECTED;
- X DEBUGPUTS("state: CONNECTED");
- X return(ERROR);
- X }
- X nleft -= nwritten;
- X buffer += nwritten;
- X } /* while */
- X con_port->state = con_port->own_port->state = CONNECTED;
- X DEBUGPUTS("state: CONNECTED");
- X /* clear timer and return */
- X (void) alarm(0);
- X return(number - nleft);
- X} /* _send_data */
- X
- X/* ============================ DEBUG Routines ============================== */
- X
- X/******************************************************************************
- X * _display_port_info() *
- X * *
- X * Displays the components of the structure PORTDESCR specified by 'port'. *
- X * *
- X * Return values: always OK for success *
- X ******************************************************************************/
- Xint
- X_display_port_info(prefix, msg, port)
- Xchar *prefix, *msg;
- XPORTDESCR port;
- X{
- X char *tmpptr;
- X
- X switch(port.state) {
- X case CONNECTIONLESS:
- X tmpptr = "CONNECTIONLESS";
- X break;
- X case CONNECTED:
- X tmpptr = "CONNECTED";
- X break;
- X case SELECTING:
- X tmpptr = "SELECTING";
- X break;
- X case ACCEPTING:
- X tmpptr = "ACCEPTING";
- X break;
- X case CONNECTING:
- X tmpptr = "CONNECTING";
- X break;
- X case SEND_REQ:
- X tmpptr = "SEND_REQ";
- X break;
- X case RECV_REQ:
- X tmpptr = "RECV_REQ";
- X break;
- X case SEND_REP:
- X tmpptr = "SEND_REP";
- X break;
- X case RECV_REP:
- X tmpptr = "RECV_REP";
- X break;
- X case SEND_ADDR:
- X tmpptr = "SEND_ADDR";
- X break;
- X case RECV_ADDR:
- X tmpptr = "RECV_ADDR";
- X break;
- X case SENDING:
- X tmpptr = "SENDING";
- X break;
- X case RECEIVING:
- X tmpptr = "RECEIVING";
- X break;
- X default:
- X tmpptr = "UNKNOWN";
- X } /* switch */
- X fprintf(_debugout, "%s %s %s: port information:\n", prefix,
- X _processprefix, msg);
- X fprintf(_debugout, "%s %s state: %s\n", prefix, _processprefix,
- X tmpptr);
- X fprintf(_debugout, "%s %s acc_sock = %d\n", prefix, _processprefix,
- X port.acc_sock);
- X fprintf(_debugout, "%s %s portnum = %d\n", prefix, _processprefix,
- X ntohs(port.portnum));
- X fprintf(_debugout, "%s %s hostname = %s\n", prefix, _processprefix,
- X port.hostname);
- X fprintf(_debugout, "%s %s con_sock = %d\n", prefix, _processprefix,
- X port.con_sock);
- X if (_debugflush)
- X fflush(_debugout);
- X return(OK);
- X} /* _display_port_info */
- X
- X/******************************************************************************
- X * _display_connection_port_info() *
- X * *
- X * Displays the components of the structure CONNECTIONDESCR specified by *
- X * 'con_port'. *
- X * *
- X * Return values: always OK for success *
- X ******************************************************************************/
- Xint
- X_display_connection_port_info(prefix, msg, con_port)
- Xchar *prefix, *msg;
- XCONNECTIONDESCR con_port;
- X{
- X char *tmpptr;
- X
- X switch(con_port.state) {
- X case CONNECTIONLESS:
- X tmpptr = "CONNECTIONLESS";
- X break;
- X case CONNECTED:
- X tmpptr = "CONNECTED";
- X break;
- X case SENDING:
- X tmpptr = "SENDING";
- X break;
- X case RECEIVING:
- X tmpptr = "RECEIVING";
- X break;
- X default:
- X tmpptr = "UNKNOWN";
- X } /* switch */
- X fprintf(_debugout, "%s %s %s: connection port info:\n", prefix,
- X _processprefix, msg);
- X fprintf(_debugout, "%s %s state: %s\n", prefix, _processprefix,
- X tmpptr);
- X fprintf(_debugout, "%s %s con_sock = %d\n", prefix, _processprefix,
- X con_port.con_sock);
- X if (_debugflush)
- X fflush(_debugout);
- X return(OK);
- X} /* _display_connection_port_info */
- X
- X/******************************************************************************
- X * _input_port_info() *
- X * *
- X * Input the port information for 'port'. *
- X * *
- X * Return values: none *
- X ******************************************************************************/
- Xint
- X_input_port_info(port)
- XPORTDESCR *port;
- X{
- X int dummy;
- X u_short dummy2;
- X
- X bzero((char *) port, sizeof(PORTDESCR));
- X printf("socket = ");
- X scanf("%d", &(port->acc_sock));
- X printf("portnum = ");
- X scanf("%d", &dummy);
- X dummy2 = (u_short) dummy;
- X port->portnum = htons(dummy2);
- X printf("hostname = ");
- X scanf("%s", port->hostname);
- X} /* _input_port_info */
- END_OF_FILE
- if test 60451 -ne `wc -c <'lib/ipc_socket.c'`; then
- echo shar: \"'lib/ipc_socket.c'\" unpacked with wrong size!
- fi
- # end of 'lib/ipc_socket.c'
- fi
- echo shar: End of archive 17 \(of 18\).
- cp /dev/null ark17isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 18 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-