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.