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