From 952da7887f4feaba5c1ec1e81fc5531a9947c52a Mon Sep 17 00:00:00 2001 From: goodale Date: Thu, 25 May 2000 12:51:03 +0000 Subject: Socket thorn based on John Shalf's code git-svn-id: http://svn.cactuscode.org/arrangements/CactusConnect/Socket/trunk@2 9697cf00-7f2a-4e1b-af3c-314b8e4b499e --- README | 10 ++ interface.ccl | 4 + param.ccl | 2 + schedule.ccl | 2 + src/SocketUtils.h | 110 ++++++++++++++ src/Utils.c | 411 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/make.code.defn | 9 ++ 7 files changed, 548 insertions(+) create mode 100644 README create mode 100644 interface.ccl create mode 100644 param.ccl create mode 100644 schedule.ccl create mode 100644 src/SocketUtils.h create mode 100644 src/Utils.c create mode 100644 src/make.code.defn diff --git a/README b/README new file mode 100644 index 0000000..8f6c09a --- /dev/null +++ b/README @@ -0,0 +1,10 @@ +Cactus Code Thorn Socket +Authors : Tom Goodale, John Shalf +CVS info : $Header$ +-------------------------------------------------------------------------- + +Purpose of the thorn: + +This thorn provides platform-independent socket calls. + + diff --git a/interface.ccl b/interface.ccl new file mode 100644 index 0000000..e18d2d6 --- /dev/null +++ b/interface.ccl @@ -0,0 +1,4 @@ +# Interface definition for thorn Socket +# $Header$ + +implements: Socket \ No newline at end of file diff --git a/param.ccl b/param.ccl new file mode 100644 index 0000000..9f7d2d1 --- /dev/null +++ b/param.ccl @@ -0,0 +1,2 @@ +# Parameter definitions for thorn Socket +# $Header$ diff --git a/schedule.ccl b/schedule.ccl new file mode 100644 index 0000000..d706530 --- /dev/null +++ b/schedule.ccl @@ -0,0 +1,2 @@ +# Schedule definitions for thorn Socket +# $Header$ diff --git a/src/SocketUtils.h b/src/SocketUtils.h new file mode 100644 index 0000000..aa9fe82 --- /dev/null +++ b/src/SocketUtils.h @@ -0,0 +1,110 @@ + /*@@ + @header SocketUtils.h + @date 1991 + @author John Shalf + @desc + + @enddesc + @version $Header$ + @@*/ + +#ifndef _SOCKETUTILS_H_ +#define _SOCKETUTILS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* #if defined(ANSI) || defined(__STDC__) */ +#ifdef __STDC__ +/* + TCP utilities library (1991) + Last modification Dec 1995 +*/ +/*================================================================== +** name: OpenClientSockTCP +** purpose: Given the hostname of the server and the portnumber of the +** service to connect to, it opens a TCP socket to the host and returns +** the file descriptor of the socket. +** parameters: +** hostname: the name of the server host as a character string (not ip number) +** port: The port number for the server. +** returns: +** integer file descriptor for low level io. Can convert to FILE * +** using the fdopen() system call. +**=================================================================*/ +int Socket_TCPOpenClientSock(const char *hostname, int port); +int Socket_UDPOpenClientSock(const char *hostname, int port); + +/*================================================================== +** name: OpenServerSockTCP +** purpose: Opens a passive TCP connection on "port". After opening +** the socket, the server is automatically set to listen on that socket. +** The programmer need only call accept() to allow connections by clients. +** parameters: +** port: The port number for the server. +** returns: +** integer file descriptor for low level io. Needs to remain a file +** descriptor to accept() client connections. Can convert the client +** connection file descriptor to a FILE * using fdopen(); +**=================================================================*/ +int Socket_TCPOpenServerSock(int port); +int Socket_UDPOpenServerSock(int port); + +/*================================================================== +** name: TCPBlockingWrite +** purpose: Handles error conditions when writing to a file descriptor. +** If a buffer is too large to write in one block, this routine will +** divide the buffer into two segments and recursively call itself to +** send each of the halves. +** parameters: +** fd: file descriptor to write the buffer data to. +** buffer: an array of bytes write to the file stream. +** buflen: number of bytes in the buffer +** returns: +** either the number of characters written or constant describing +** why the write failed. +** notes: If you want the routine to print identifiable errors +** to stderr, define PERRORS. +**=================================================================*/ +int Socket_TCPBlockingWrite(int fd, char *buffer, int buflen); + +/*================================================================== +** name: TCPBlockingRead +** purpose: Handles error conditions when reading from a file descriptor. +** With TCP stream connections, the record size of the recieved stream +** may not coincide with the record written. This routine assembles +** a fragmented record into a single array by blocking until buflen +** characters are recieved, or write returns a premature EOF. +** parameters: +** fd: file descriptor to read the buffer data from. +** buffer: an array of bytes read from the file stream. +** buflen: number of bytes in the buffer +** returns: +** either the number of characters read into the buffer or constant describing +** why the read failed. +** notes: If you want the routine to print out identifiable errors +** to stderr, define PERRORS. +**=================================================================*/ +int Socket_TCPBlockingRead(int fd,char *buffer,int buflen); +#else +int Socket_TCPOpenClientSock(); +int Socket_TCPOpenServerSock(); +int Socket_TCPBlockingWrite(); +int Socket_TCPBlockingRead(); +#endif + +#define PERRORS +#ifndef __IN_HEADER +#include +#include +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _SOCKETUTILS_H */ + diff --git a/src/Utils.c b/src/Utils.c new file mode 100644 index 0000000..ceb4d0f --- /dev/null +++ b/src/Utils.c @@ -0,0 +1,411 @@ +/*@@ + @file Utils.c + @date 1991 + @author John Shalf + @desc + Socket stuff provided by John Shalf + @enddesc + @history + @hdate Thu May 25 13:45:29 2000 @hauthor Tom Goodale + @hdesc Moved this file into Cactus + @endhistory + @version $Header$ + @@*/ + +#include "cctk.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "SocketUtils.h" + +/* #if defined(ANSI) || defined(__STDC__) */ +#ifdef __STDC__ +/* +u_long htonl(u_long hostlong); +u_short htons(u_short hostshort); +u_long ntohl(u_long netlong); +u_short ntohs(u_short netshort); + +int inet_aton(const char *cp, struct in_addr *pin); +unsigned long inet_addr(const char *cp); +unsigned long inet_network(const char *cp); +char *inet_ntoa(struct in_addr in); +struct in_addr inet_makeaddr(int net, int lna); +unsigned long inet_lnaof(struct in_addr in); +unsigned long inet_netof(struct in_addr in); +*/ +#else +u_short htons(); +u_short ntohs(); +u_long inet_addr(); +#endif + +static char *rcsid = "$Header$"; + + +extern int errno; + + /*@@ + @routine Socket_TCPOpenClientSock + @date 1991 + @author John Shalf + @desc + + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Socket_TCPOpenClientSock(const char *hostname,int port) +{ + struct hostent *phe; + /* struct servent *pse; */ + struct protoent *ppe; + struct sockaddr_in sin; + int s /*,type*/; + + bzero((char *)&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr=INADDR_ANY; + sin.sin_port = htons((u_short)port); + + if(phe=gethostbyname(hostname)) + { + bcopy(phe->h_addr, (char *)&sin.sin_addr, phe->h_length); + } + else if((sin.sin_addr.s_addr = inet_addr(hostname)) == INADDR_NONE) + { + fprintf(stderr,"can\'t find host %s \n",hostname); + } + if((ppe=getprotobyname("tcp")) == 0) + { + perror("can\'t find tcp protocol\n"); + return -1; + } + s=socket(PF_INET,SOCK_STREAM,ppe->p_proto); + if(s<0) + { + perror(""); + fprintf(stderr,"couldn\'t allocate socket on host %s: port %u\n",hostname,port); + return s; + } + if(connect(s,(struct sockaddr *)&sin, sizeof(sin)) < 0) + { + perror(""); + fprintf(stderr,"couldn\'t connect to host %s: port %u\n",hostname,port); + return -1; + } + return s; +} + +/*@@ + @routine Socket_UDPOpenClientSock + @date 1991 + @author John Shalf + @desc + + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Socket_UDPOpenClientSock(const char *hostname,int port) +{ + struct hostent *phe; + /* struct servent *pse; */ + struct protoent *ppe; + struct sockaddr_in sin; + int sock/*,type*/; + + bzero((char *)&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr=INADDR_ANY; + sin.sin_port = htons((u_short)port); + + if(phe=gethostbyname(hostname)) + { + bcopy(phe->h_addr, (char *)&sin.sin_addr, phe->h_length); + } + else if((sin.sin_addr.s_addr = inet_addr(hostname)) == INADDR_NONE) + { + fprintf(stderr,"can\'t find host %s \n",hostname); + } + if((ppe=getprotobyname("udp")) == 0) + { + perror("can\'t find udp protocol\n"); + return -1; + } + sock=socket(PF_INET,SOCK_DGRAM,ppe->p_proto); + if(sock<0) + { + perror(""); + fprintf(stderr,"couldn\'t allocate socket on host %s: port %u\n",hostname,port); + return sock; + } + if(bind(sock,&sin,sizeof(sin)) <0) + { + close(sock); + perror("client: bind failed"); + return -1; + } + + + /* if(connect(s,(struct sockaddr *)&sin, sizeof(sin)) < 0) + {` + perror(""); + fprintf(stderr,"couldn\'t connect to host %s: port %u\n",hostname,port); + return -1; + } + */ + return sock; +} + +/*@@ + @routine Socket_TCPOpenServerSock + @date 1991 + @author John Shalf + @desc + + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Socket_TCPOpenServerSock(int port) +{ + /* struct servent *pse; */ + struct protoent *ppe; + struct sockaddr_in sin; + int s/*,type*/; + bzero((char *)&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_port = htons((u_short)port); + + if((ppe=getprotobyname("tcp")) == 0) + { + perror("can\'t find tcp protocol\n"); + return -1; + } + s=socket(PF_INET,SOCK_STREAM,ppe->p_proto); + if(s<0) + { + fprintf(stderr,"couldn\'t create socket on port %u\n",port); + return s; + } + if(bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0) + { + fprintf(stderr,"couldn\'t bind to port %u\n",port); + return s; + } + if(listen(s,5) < 0) /* note, server connection qlen fixed to 5 */ + { + fprintf(stderr,"couldn\'t listen on port %u\n",port); + } + return s; +} + +/*@@ + @routine Socket_UDPOpenServerSock + @date 1991 + @author John Shalf + @desc + + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Socket_UDPOpenServerSock(int port) +{ + /* struct servent *pse; */ + struct protoent *ppe; + struct sockaddr_in sin; + int s/*,type*/; + bzero((char *)&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_port = htons((u_short)port); + + if((ppe=getprotobyname("udp")) == 0) + { + perror("can\'t find udp protocol\n"); + return -1; + } + s=socket(PF_INET,SOCK_DGRAM,ppe->p_proto); + if(s<0) + { + fprintf(stderr,"couldn\'t create socket on port %u\n",port); + return s; + } + if(bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0) + { + fprintf(stderr,"couldn\'t bind to port %u\n",port); + return s; + } + return s; +} + +/*@@ + @routine Socket_TCPBlockingWrite + @date 1991 + @author John Shalf + @desc + + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Socket_TCPBlockingWrite(int fd,char *buffer, int buflen) +{ + register int n; + int nstore; + n=write(fd,buffer,buflen); + + if(n>=0) + { + return n; + } + else + { + switch(errno) /* note use of global variable errno */ + { + case EBADF: +#ifdef PERRORS + perror("invalid file descriptor"); +#endif + break; + case EPIPE: +#ifdef PERRORS + perror("attemped to write to an unconnected socket"); +#endif + break; + case EFBIG: +#ifdef PERRORS + perror("datasize too large to write."); + perror("will attempt recovery by sending in smaller pieces"); +#endif + /* subdivide buffer and call TCPBlockingWrite() recursively */ + nstore=n; /* preserve register variable */ + TCPBlockingWrite(fd,buffer,buflen>>1); + TCPBlockingWrite(fd,buffer+(buflen>>1),buflen-(buflen>>1)); + n=nstore; /* restore register variable */ + break; + case EFAULT: +#ifdef PERRORS + perror("invalid buffer address"); +#endif + break; + case EINVAL: +#ifdef PERRORS + perror("file descriptor points to unusable device."); +#endif + break; + case EIO: +#ifdef PERRORS + perror("an io error occured"); +#endif + break; + case EWOULDBLOCK: +#ifdef PERRORS + perror("Non-blocking I/O is specified by ioctl"); + perror("but socket has no data (would have blocked)."); +#endif + break; + } + } + return n; /* default, don't know what happened */ +} + +/*@@ + @routine Socket_TCPBlockingRead + @date 1991 + @author John Shalf + @desc + + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Socket_TCPBlockingRead(int fd,char *buffer, int buflen) +{ + /* do errno only if types.h has been included */ + /* how can I tell if this has been included ? */ + register int n,accum=0; + while((n=read(fd,buffer,buflen)) > 0) + { + if(n>=0) + { + buffer = buffer + n; + buflen -= n; + accum+=n; + } + } +#ifdef PERRORS + if(n<0) + { + switch(errno) /* note use of global variable errno */ + { + case EBADF: +#ifdef PERRORS + perror("invalid file descriptor"); +#endif + break; + case EFAULT: +#ifdef PERRORS + perror("invalid buffer address"); +#endif + break; + case EINTR: +#ifdef PERRORS + perror("operation interrupted by a signal"); + perror("disable signals and try again"); +#endif + break; + case EWOULDBLOCK: +#ifdef PERRORS + perror("Non-blocking I/O is specified by ioctl"); + perror("but socket has no data (would have blocked)."); +#endif + break; + } + } +#endif + + if(n<0) + { + return n; + } + else + { + return accum; + } +} diff --git a/src/make.code.defn b/src/make.code.defn new file mode 100644 index 0000000..b8eac84 --- /dev/null +++ b/src/make.code.defn @@ -0,0 +1,9 @@ +# Main make.code.defn file for thorn Socket +# $Header$ + +# Source files in this directory +SRCS = Utils.c + +# Subdirectories containing source files +SUBDIRS = + -- cgit v1.2.3