Date: 2015-10-02T21:58:09+00:00

Actual source code: sopen.c
petsc-3.6.2 2015-10-02
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);
     78: int SOCKConnect_Private(int portnumber)
     79: {
     80:   struct sockaddr_in isa;
     81: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
     82:   size_t             i;
     83: #else
     84:   int                i;
     85: #endif
     86:   int                t;

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

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

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

    129:   sa.sin_family = hp->h_addrtype;
    130:   sa.sin_port   = htons(portnum);

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

    134:   {
    135:   int optval = 1; /* Turn on the option */
    136:   (void) setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));
    137:   }

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

    157: /*-----------------------------------------------------------------*/
    158: /*                                                                 */
    159: /*-----------------------------------------------------------------*/
    162: void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
    163: {
    164:   int t,portnumber;

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

    169:   /* figure out portnumber user wants to use; default to 5005 */
    170:   if (!nrhs) {
    171:     char *str;
    172:     str = getenv("PETSC_VIEWER_SOCKET_PORT");
    173:     if (str) portnumber = atoi(str);
    174:     else portnumber = PETSCSOCKETDEFAULTPORT;
    175:   } else portnumber = (int)*mxGetPr(prhs[0]);

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

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

    182:   *mxGetPr(plhs[0]) = t;
    183:   return;
    184: }