home *** CD-ROM | disk | FTP | other *** search
- /* 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
-
- 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 <sys/types.h>
- #include <netinet/in.h>
- #include <errno.h>
- #include <string.h>
- #include "panic.h"
-
- #ifdef ultrix
- extern int errno;
- #endif
-
- #ifdef BSD
- extern int errno;
- #endif
-
- 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 */
- /*---------------------------------------------------------------------------*/
-
- 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 %d: (Address already in use).\n\
- waisserver is already running on this system", portnumber);
- 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;
-
- /* 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 (setsockopt(*fd,SOL_SOCKET,SO_REUSEADDR,&trueValue,sizeof(char)) != 0)
- { perror("reuse"); waislog("errno = %d\n",errno);panic("can't reuse the socket");}
- */
- if (setsockopt(*fd,SOL_SOCKET,SO_SNDBUF,&size,sizeof(long)) != 0)
- panic("can't set socket size");
- if (setsockopt(*fd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(long)) != 0)
- panic("can't set socket size");
-
- 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);
-
- #ifdef BSD
- addr_p.S_un.S_addr = source.sin_addr.s_addr;
- #endif /* BSD */
-
- if(source.sin_family == AF_INET) {
- #ifdef NOINETNTOA
- waislog(WLOG_MEDIUM, WLOG_CONNECT,
- "Accepted connection from: %d.%d.%d.%d",
- #ifdef BSD
- addr_p.S_un.S_un_b.s_b1,
- addr_p.S_un.S_un_b.s_b2,
- addr_p.S_un.S_un_b.s_b3,
- addr_p.S_un.S_un_b.s_b4
- #else
- source.sin_addr.S_un.S_un_b.s_b1,
- source.sin_addr.S_un.S_un_b.s_b2,
- source.sin_addr.S_un.S_un_b.s_b3,
- source.sin_addr.S_un.S_un_b.s_b4
- #endif /* BSD */
- );
- #else
- waislog(WLOG_MEDIUM, WLOG_CONNECT,
- "Accepted connection from: %s",
- inet_ntoa(source.sin_addr));
- #endif /* NOINETNTOA */
- }
- 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
-
- boolean
- fd_connect_to_server(host_name,port,fd)
- char* host_name;
- long port;
- long* fd;
- {
- char hostnamebuf[80];
- long rc;
- 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);
- rc = connect (*fd, &name, sizeof (name));
- if(-1 == rc){
- perror("Connect to socket did not work");
- return FALSE;
- }
- return TRUE;
- }
-
- /* 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");
- return NULL;
- }
-
- if ((file = fdopen(fd,"r+")) == NULL) {
- perror("Connect to socket did not work");
- return NULL;
- }
-
- return file;
- }
-
- void
- close_connection_to_server(file)
- FILE* file;
- {
- fclose(file);
- }
-
- /*---------------------------------------------------------------------------*/
-
- #endif /* there is TCPIP */
-