Actual source code: zope.c

  1: #include "zope.h"

  3: /*
  4:  * Opens a socket to the PETSc remote server
  5:  * returns a file descriptor for the socket
  6:  *
  7:  * Note: PETSC_HAVE_SYS_SOCKET_H is not defined on Windows
  8:  * and SO_REUSEADDR is not defined on BGL. In either case,
  9:  * this functionality gets disabled.  
 10:  */


 14: PetscErrorCode  PetscOpenSocket(char * hostname, int portnum, int * clientfd){
 15: #if defined(PETSC_HAVE_SYS_SOCKET_H) && defined(SO_REUSEADDR)
 16:     struct sockaddr_in sin;
 17:     typedef struct sockaddr SA;
 18:     struct hostent *host;

 22:     /* retrieve information of host */
 23:     host = gethostbyname(hostname);
 24:     if(!host){
 25:         SETERRQ(PETSC_ERR_ARG_CORRUPT, "unknown host");}
 26:     sin.sin_family = AF_INET;
 27:     PetscMemcpy((char *)&sin.sin_addr,host->h_addr, host->h_length);
 28:     sin.sin_port = htons(portnum);
 29:     /* active open */
 30:     if((*clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){
 31:         SETERRQ(PETSC_ERR_ARG_CORRUPT,"could not create new socket for client");}
 32:     if(connect(*clientfd, (SA*)&sin, sizeof(sin)) < 0){
 33:         SETERRQ(PETSC_ERR_ARG_CORRUPT,"could not create new connection for client");
 34:         close(*clientfd);}
 35:     return(0);
 36: #else
 37:   SETERRQ(PETSC_ERR_SUP,"Sockets not supported");
 38: #endif
 39: }

 41: /*
 42:  * Recieve function with error handeling
 43:  *
 44:  */
 45: PetscErrorCode  PetscFdRecv(int fd, void *buf, size_t len, int flags, unsigned int *size){
 46: #if defined(PETSC_HAVE_SYS_SOCKET_H) && defined(SO_REUSEADDR)
 47:   ssize_t recvLen;
 48: #endif

 51: #if defined(PETSC_HAVE_SYS_SOCKET_H) && defined(SO_REUSEADDR)
 52:   recvLen = recv(fd, buf, len, flags);
 53:   if(recvLen < 0) {SETERRQ(PETSC_ERR_ARG_CORRUPT,"Could not complete recv");}
 54:   *size = (unsigned int) recvLen;
 55: #else
 56:   SETERRQ(PETSC_ERR_SUP,"Sockets not supported");
 57: #endif
 58:   return(0);
 59: }

 61: /*
 62:  * Write function with error handeling
 63:  *
 64:  */
 65: PetscErrorCode  PetscFdWrite(int fd, void *buf, size_t len, unsigned int *size){
 66: #if defined(PETSC_HAVE_SYS_SOCKET_H) && defined(SO_REUSEADDR)
 67:   ssize_t sendLen;
 68: #endif

 71: #if defined(PETSC_HAVE_SYS_SOCKET_H) && defined(SO_REUSEADDR)
 72:   sendLen = write(fd, buf, len);
 73:   if(sendLen < 0) {SETERRQ(PETSC_ERR_ARG_CORRUPT, "Could not complete write: ");}
 74:   *size = (unsigned int) sendLen;
 75: #else
 76:   SETERRQ(PETSC_ERR_SUP,"Sockets not supported");
 77: #endif
 78:   return(0);
 79: }

 81: /*
 82:  * Opens a listening socket to allow for the PETSc remote to set options
 83:  *
 84:  */
 85: PetscErrorCode  PetscSocketListen(char * hostname, int portnum, int *listenfd){
 86:     const int MAX_BUF = 256;
 87:     int MAX_PENDING = 1;
 88:     int optval = 1;
 89:     char iname[256];
 90:     char value[256];
 91:     unsigned int len = 0;
 92:     unsigned int len2 = 0;
 93:     int newfd,flags;
 95: #if defined(PETSC_HAVE_SYS_SOCKET_H) && defined(SO_REUSEADDR)
 96:     struct sockaddr_in sin;
 97:     typedef struct sockaddr SA;
 98:     socklen_t sin_size, sout_size;
 99:     int PETSC_LISTEN_CHECK = 0;
100: #endif
101: 
103: #if defined(PETSC_HAVE_SYS_SOCKET_H) && defined(SO_REUSEADDR)
104:     sin.sin_family = AF_INET;
105:     sin.sin_addr.s_addr = INADDR_ANY;
106:     sin.sin_port = htons(portnum);
107:     /* passive open */
108:     if((*listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0){
109:         SETERRQ(PETSC_ERR_ARG_CORRUPT, "could not make a new socket for server");}

111:     /* Allow for non-blocking on the socket */
112:     if(!(flags = fcntl(*listenfd, F_GETFL, NULL)))
113:       SETERRQ(PETSC_ERR_ARG_CORRUPT,"flags error");
114:     flags = 0 | O_NONBLOCK;
115:     if(fcntl(*listenfd, F_SETFL, 0 | O_NONBLOCK))
116:       SETERRQ(PETSC_ERR_ARG_CORRUPT,"flags error");
117:     /* so it is possible to reuse port numbers */
118:     if(setsockopt(*listenfd, SOL_SOCKET, SO_REUSEADDR,
119:                 (const void *)&optval, sizeof(int)) < 0)
120:         SETERRQ(PETSC_ERR_ARG_CORRUPT,"Could not open a new socket");
121:     if((bind(*listenfd, (SA*)&sin, sizeof(sin))) < 0)
122:       SETERRQ(PETSC_ERR_ARG_CORRUPT,"Could not complete bind");
123:     listen(*listenfd, MAX_PENDING);
124:     /* Non-blocking busy loop waiting for a connnection */
125:     if(fork() == 0){
126:       /* PETSC_LISTEN_CHECK is set in PetscInitilize and PetscFinalize to
127:          tell the forked process when the program has finished */
128:       while(PETSC_LISTEN_CHECK){
129:         sin_size = sizeof(struct sockaddr_in);
130:         /* non-blocking listen */
131:         if((newfd = accept(*listenfd, (SA*)&sin, &sout_size)) < 0){
132:           if(errno == EAGAIN) break;
133:           SETERRQ(PETSC_ERR_ARG_CORRUPT,"Could not complete accept");}
134:         /* If a connection is found, fork off process to handle the connection */
135:         if(fork() == 0){
136:           close(*listenfd);
137:           PetscFdRecv(newfd, iname, MAX_BUF, 0, &len);
138:           iname[len] = '\0';
139:           printf("len = %d iname = %s\n",len, iname);
140:           PetscFdWrite(newfd, iname, MAX_BUF, &len2);
141:           PetscFdRecv(newfd, value, MAX_BUF, 0, &len);
142:           value[len] = '\0';
143:           printf("len = %d value = %s\n", len, value);
144:           PetscOptionsSetValue(iname, value);
145:           close(newfd);
146:           exit(0);}
147:         close(newfd);
148:         if(!PETSC_LISTEN_CHECK) exit(0);}
149:       exit(0);}
150: #else
151:   SETERRQ(PETSC_ERR_SUP,"Sockets not supported");
152: #endif
153:     return(0);}