Actual source code: sopen.c

petsc-3.9.4 2018-09-11
Report Typos and Errors
  1: /*
  2:   Usage: A = sopen(portnumber);  [ 5000 < portnumber < 5010 ]

  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: #include <ctype.h>
 27: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
 28: #include <machine/endian.h>
 29: #endif
 30: #if defined(PETSC_HAVE_UNISTD_H)
 31: #include <unistd.h>
 32: #endif
 33: #if defined(PETSC_HAVE_SYS_SOCKET_H)
 34: #include <sys/socket.h>
 35: #endif
 36: #if defined(PETSC_HAVE_SYS_WAIT_H)
 37: #include <sys/wait.h>
 38: #endif
 39: #if defined(PETSC_HAVE_NETINET_IN_H)
 40: #include <netinet/in.h>
 41: #endif
 42: #if defined(PETSC_HAVE_NETDB_H)
 43: #include <netdb.h>
 44: #endif
 45: #if defined(PETSC_HAVE_FCNTL_H)
 46: #include <fcntl.h>
 47: #endif
 48: #if defined(PETSC_HAVE_IO_H)
 49: #include <io.h>
 50: #endif
 51: #if defined(PETSC_HAVE_SYS_UTSNAME_H)
 52: #include <sys/utsname.h>
 53: #endif
 54: #if defined(PETSC_HAVE_WINSOCK2_H)
 55: #include <Winsock2.h>
 56: #endif
 57: #if defined(PETSC_HAVE_WS2TCPIP_H)
 58: #include <Ws2tcpip.h>
 59: #endif
 60:  #include <../src/sys/classes/viewer/impls/socket/socket.h>
 61: #include <mex.h>

 63: #define PETSC_MEX_ERROR(a) {mexErrMsgTxt(a); return;}
 64: #define PETSC_MEX_ERRORQ(a) {mexErrMsgTxt(a); return -1;}

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

 86: /* open port*/
 87:   listenport = establish((u_short) portnumber);
 88:   if (listenport == -1) PETSC_MEX_ERRORQ("RECEIVE: unable to establish port\n");

 90: /* wait for someone to try to connect */
 91:   i = sizeof(struct sockaddr_in);
 92:   if ((t = accept(listenport,(struct sockaddr*)&isa,(socklen_t*)&i)) < 0) PETSC_MEX_ERRORQ("RECEIVE: error from accept\n");
 93:   close(listenport);
 94:   return(t);
 95: }
 96: /*-----------------------------------------------------------------*/
 97: #define MAXHOSTNAME 100
 98: int establish(u_short portnum)
 99: {
100:   char               myname[MAXHOSTNAME+1];
101:   int                s;
102:   struct sockaddr_in sa;
103:   struct hostent     *hp;
104: #if defined(PETSC_HAVE_UNAME)
105:   struct utsname     utname;
106: #elif defined(PETSC_HAVE_GETCOMPUTERNAME)
107:   int                namelen=MAXHOSTNAME;
108: #endif

110:   /* Note we do not use gethostname since that is not POSIX */
111: #if defined(PETSC_HAVE_GETCOMPUTERNAME)
112:   GetComputerName((LPTSTR)myname,(LPDWORD)&namelen);
113: #elif defined(PETSC_HAVE_UNAME)
114:   uname(&utname);
115:   strncpy(myname,utname.nodename,MAXHOSTNAME);
116: #endif
117: #if defined(PETSC_HAVE_BZERO)
118:   bzero(&sa,sizeof(struct sockaddr_in));
119: #else
120:   memset(&sa,0,sizeof(struct sockaddr_in));
121: #endif
122:   hp = gethostbyname(myname);
123:   if (!hp) PETSC_MEX_ERRORQ("RECEIVE: error from gethostbyname\n");

125:   sa.sin_family = hp->h_addrtype;
126:   sa.sin_port   = htons(portnum);

128:   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) PETSC_MEX_ERRORQ("RECEIVE: error from socket\n");

130:   {
131:   int optval = 1; /* Turn on the option */
132:   (void) setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));
133:   }

135:   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
136: #if defined(PETSC_HAVE_WSAGETLASTERROR)
137:     PetscErrorCode     ierr;
138:     WSAGetLastError();
139:     if (ierr != WSAEADDRINUSE) {
140: #else
141:     if (errno != EADDRINUSE) {
142: #endif
143:       close(s);
144:       PETSC_MEX_ERRORQ("RECEIVE: error from bind\n");
145:       return(-1);
146:     }
147:     close(listenport);
148:   }
149:   listen(s,0);
150:   return(s);
151: }

153: /*-----------------------------------------------------------------*/
154: /*                                                                 */
155: /*-----------------------------------------------------------------*/
156: PETSC_EXTERN void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
157: {
158:   int t,portnumber;

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

163:   /* figure out portnumber user wants to use; default to 5005 */
164:   if (!nrhs) {
165:     char *str;
166:     str = getenv("PETSC_VIEWER_SOCKET_PORT");
167:     if (str) portnumber = atoi(str);
168:     else portnumber = PETSCSOCKETDEFAULTPORT;
169:   } else portnumber = (int)*mxGetPr(prhs[0]);

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

174:   plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);

176:   *mxGetPr(plhs[0]) = t;
177:   return;
178: }