Actual source code: sopen.c

      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) \
     64:   { \
     65:     mexErrMsgTxt(a); \
     66:     return; \
     67:   }
     68: #define PETSC_MEX_ERRORQ(a) \
     69:   { \
     70:     mexErrMsgTxt(a); \
     71:     return -1; \
     72:   }

     74: /* The listenport variable is an ugly hack. If the user hits a         */
     75: /* control c while we are listening then we stop listening         */
     76: /* but do not close the listen. Therefore if we try to bind again  */
     77: /* and get an address in use, close the listen which was left      */
     78: /* hanging; the problem is if the user uses several portnumbers    */
     79: /* and control c we may not be able to close the correct listener. */
     80: static int listenport;
     81: #define MAXHOSTNAME 255
     82: static int establish(u_short portnum)
     83: {
     84:   char               myname[MAXHOSTNAME + 1];
     85:   int                s;
     86:   struct sockaddr_in sa;
     87:   struct hostent    *hp;
     88: #if defined(PETSC_HAVE_UNAME)
     89:   struct utsname utname;
     90: #elif defined(PETSC_HAVE_GETCOMPUTERNAME)
     91:   int namelen = MAXHOSTNAME;
     92: #endif

     94:   /* Note we do not use gethostname since that is not POSIX */
     95: #if defined(PETSC_HAVE_GETCOMPUTERNAME)
     96:   GetComputerName((LPTSTR)myname, (LPDWORD)&namelen);
     97: #elif defined(PETSC_HAVE_UNAME)
     98:   uname(&utname);
     99:   strncpy(myname, utname.nodename, MAXHOSTNAME);
    100: #endif
    101: #if defined(PETSC_HAVE_BZERO)
    102:   bzero(&sa, sizeof(struct sockaddr_in));
    103: #else
    104:   memset(&sa, 0, sizeof(struct sockaddr_in));
    105: #endif
    106:   hp = gethostbyname(myname);
    107:   if (!hp) PETSC_MEX_ERRORQ("RECEIVE: error from gethostbyname\n");

    109:   sa.sin_family = (sa_family_t)hp->h_addrtype;
    110:   sa.sin_port   = htons(portnum);

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

    114:   {
    115:     int optval = 1; /* Turn on the option */
    116:     (void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
    117:   }

    119:   while (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
    120: #if defined(PETSC_HAVE_WSAGETLASTERROR)
    121:     PetscErrorCode ierr;
    122:     ierr = WSAGetLastError();
    123:     if (ierr != WSAEADDRINUSE) {
    124: #else
    125:     if (errno != EADDRINUSE) {
    126: #endif
    127:       close(s);
    128:       PETSC_MEX_ERRORQ("RECEIVE: error from bind\n");
    129:       return -1;
    130:     }
    131:     close(listenport);
    132:   }
    133:   listen(s, 0);
    134:   return s;
    135: }

    137: static int SOCKConnect_Private(int portnumber)
    138: {
    139:   struct sockaddr_in isa;
    140: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
    141:   size_t i;
    142: #else
    143:   int i;
    144: #endif
    145:   int t;

    147:   /* open port*/
    148:   listenport = establish((u_short)portnumber);
    149:   if (listenport == -1) PETSC_MEX_ERRORQ("RECEIVE: unable to establish port\n");

    151:   /* wait for someone to try to connect */
    152:   i = sizeof(struct sockaddr_in);
    153:   if ((t = accept(listenport, (struct sockaddr *)&isa, (socklen_t *)&i)) < 0) PETSC_MEX_ERRORQ("RECEIVE: error from accept\n");
    154:   close(listenport);
    155:   return t;
    156: }

    158: PETSC_EXTERN void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
    159: {
    160:   int t, portnumber;

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

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

    173:   /* open connection */
    174:   t = SOCKConnect_Private(portnumber);
    175:   if (t == -1) PETSC_MEX_ERROR("opening socket");

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

    179:   *mxGetPr(plhs[0]) = t;
    180:   return;
    181: }

    183: int main(int argc, char **argv)
    184: {
    185:   return 0;
    186: }