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:  */


 11: PetscErrorCode  PetscOpenSocket(char * hostname, int portnum, int * clientfd){
 12:     struct sockaddr_in sin;
 13:     typedef struct sockaddr SA;
 14:     struct hostent *host;

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

 38: /*
 39:  * Recieve function with error handeling
 40:  *
 41:  */
 42: PetscErrorCode  PetscFdRecv(int fd, void *buf, size_t len, int flags, unsigned int *size){
 43: #ifdef PETSC_HAVE_SYS_SOCKET_H
 44:   ssize_t recvLen;
 45: #endif

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

 58: /*
 59:  * Write function with error handeling
 60:  *
 61:  */
 62: PetscErrorCode  PetscFdWrite(int fd, void *buf, size_t len, unsigned int *size){
 63: #ifdef PETSC_HAVE_SYS_SOCKET_H
 64:   ssize_t sendLen;
 65: #endif

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

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

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