Actual source code: sopen.c

petsc-3.3-p7 2013-05-11
  1: /* 
  2:   Usage: A = sopen(portnumber);  [ 5000 < portnumber < 5010 ]
  3:  
  4:         Written by Barry Smith, bsmith@mcs.anl.gov 4/14/92
  5:          Updated by Richard Katz, katz@ldeo.columbia.edu 9/28/03
  6:          Updated by Barry Smith, bsmith@mcs.anl.gov 8/11/06

  8:  Similar to MATLAB's sopen() only does not take file name, instead optional
  9:  port to listen at.

 11:  Only compiles as C code.
 12: */

 14: #include <petscsys.h>

 16: #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
 17: /* Some systems have inconsistent include files that use but don't
 18:    ensure that the following definitions are made */
 19: typedef unsigned char   u_char;
 20: typedef unsigned short  u_short;
 21: typedef unsigned int    u_int;
 22: typedef unsigned long   u_long;
 23: #endif

 25: #include <errno.h>
 26: #if defined(PETSC_HAVE_STDLIB_H)
 27: #include <stdlib.h>
 28: #endif
 29: #include <sys/types.h>
 30: #include <ctype.h>
 31: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
 32: #include <machine/endian.h>
 33: #endif
 34: #if defined(PETSC_HAVE_UNISTD_H)
 35: #include <unistd.h>
 36: #endif
 37: #if defined(PETSC_HAVE_SYS_SOCKET_H)
 38: #include <sys/socket.h>
 39: #endif
 40: #if defined(PETSC_HAVE_SYS_WAIT_H)
 41: #include <sys/wait.h>
 42: #endif
 43: #if defined(PETSC_HAVE_NETINET_IN_H)
 44: #include <netinet/in.h>
 45: #endif
 46: #if defined(PETSC_HAVE_NETDB_H)
 47: #include <netdb.h>
 48: #endif
 49: #if defined(PETSC_HAVE_FCNTL_H)
 50: #include <fcntl.h>
 51: #endif
 52: #if defined (PETSC_HAVE_IO_H)
 53: #include <io.h>
 54: #endif
 55: #if defined(PETSC_HAVE_SYS_UTSNAME_H)
 56: #include <sys/utsname.h>
 57: #endif
 58: #if defined(PETSC_HAVE_STRINGS_H)
 59: #include <strings.h>
 60: #endif
 61: #if defined(PETSC_HAVE_STRING_H)
 62: #include <string.h>
 63: #endif
 64: #if defined(PETSC_HAVE_WINSOCK2_H)
 65: #include <Winsock2.h>
 66: #endif
 67: #if defined(PETSC_HAVE_WS2TCPIP_H)
 68: #include <Ws2tcpip.h>
 69: #endif
 70: #include <../src/sys/viewer/impls/socket/socket.h>
 71: #include <mex.h>

 73: #define PETSC_MEX_ERROR(a) {mexErrMsgTxt(a); return ;}
 74: #define PETSC_MEX_ERRORQ(a) {mexErrMsgTxt(a); return -1;}

 76: /*-----------------------------------------------------------------*/
 77: /* The listenport variable is an ugly hack. If the user hits a         */
 78: /* control c while we are listening then we stop listening         */
 79: /* but do not close the listen. Therefore if we try to bind again  */
 80: /* and get an address in use, close the listen which was left      */
 81: /* hanging; the problem is if the user uses several portnumbers    */
 82: /* and control c we may not be able to close the correct listener. */
 83: static int listenport;
 84: /*-----------------------------------------------------------------*/
 85: extern int establish(u_short);
 88: int SOCKConnect_Private(int portnumber)
 89: {
 90:   struct sockaddr_in isa;
 91: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
 92:   size_t             i;
 93: #else
 94:   int                i;
 95: #endif
 96:   int                t;

 98: /* open port*/
 99:   listenport = establish((u_short) portnumber);
100:   if (listenport == -1) {
101:     PETSC_MEX_ERRORQ("RECEIVE: unable to establish port\n");
102:   }

104: /* wait for someone to try to connect */
105:   i = sizeof(struct sockaddr_in);
106:   if ((t = accept(listenport,(struct sockaddr *)&isa,(socklen_t *)&i)) < 0) {
107:     PETSC_MEX_ERRORQ("RECEIVE: error from accept\n");
108:   }
109:   close(listenport);
110:   return(t);
111: }
112: /*-----------------------------------------------------------------*/
113: #define MAXHOSTNAME 100
116: int establish(u_short portnum)
117: {
118:   char               myname[MAXHOSTNAME+1];
119:   int                s;
120:   PetscErrorCode     ierr;
121:   struct sockaddr_in sa;
122:   struct hostent     *hp;
123: #if defined(PETSC_HAVE_UNAME)
124:   struct utsname     utname;
125: #elif defined(PETSC_HAVE_GETCOMPUTERNAME)
126:   int                namelen=MAXHOSTNAME;
127: #endif

129:   /* Note we do not use gethostname since that is not POSIX */
130: #if defined(PETSC_HAVE_GETCOMPUTERNAME)
131:   GetComputerName((LPTSTR)myname,(LPDWORD)&namelen);
132: #elif defined(PETSC_HAVE_UNAME)
133:   uname(&utname);
134:   strncpy(myname,utname.nodename,MAXHOSTNAME);
135: #endif
136: #if defined(PETSC_HAVE_BZERO)
137:   bzero(&sa,sizeof(struct sockaddr_in));
138: #else
139:   memset(&sa,0,sizeof(struct sockaddr_in));
140: #endif
141:   hp = gethostbyname(myname);
142:   if (!hp) {
143:     PETSC_MEX_ERRORQ("RECEIVE: error from gethostbyname\n");
144:   }

146:   sa.sin_family = hp->h_addrtype;
147:   sa.sin_port = htons(portnum);

149:   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
150:     PETSC_MEX_ERRORQ("RECEIVE: error from socket\n");
151:   }
152:   {
153:   int optval = 1; /* Turn on the option */
154:   setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));
155:   }

157:   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
158: #if defined(PETSC_HAVE_WSAGETLASTERROR)
159:     WSAGetLastError();
160:     if (ierr != WSAEADDRINUSE) {
161: #else
162:     if (errno != EADDRINUSE) {
163: #endif
164:       close(s);
165:       PETSC_MEX_ERRORQ("RECEIVE: error from bind\n");
166:       return(-1);
167:     }
168:     close(listenport);
169:   }
170:   listen(s,0);
171:   return(s);
172: }

174: /*-----------------------------------------------------------------*/
175: /*                                                                 */
176: /*-----------------------------------------------------------------*/
179: void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
180: {
181:   int        t,portnumber;

183:   /* check output parameters */
184:   if (nlhs != 1) PETSC_MEX_ERROR("Open requires one output argument.");

186:   /* figure out portnumber user wants to use; default to 5005 */
187:   if (!nrhs) {
188:     char *str;
189:     str = getenv("PETSC_VIEWER_SOCKET_PORT");
190:     if (str) portnumber = atoi(str);
191:     else portnumber = PETSCSOCKETDEFAULTPORT;
192:   } else {
193:     portnumber = (int)*mxGetPr(prhs[0]);
194:   }

196:   /* open connection */
197:   t = SOCKConnect_Private(portnumber); if (t == -1)  PETSC_MEX_ERROR("opening socket");

199:   plhs[0]  = mxCreateDoubleMatrix(1,1,mxREAL);
200: 
201:   *mxGetPr(plhs[0]) = t;
202:   return;
203: }