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) {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: }

    180: int main(int argc, char **argv)
    181: {
    182:   return 0;
    183: }