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);}