Actual source code: openport.c

      1: /*
      2:   Usage: A = openport(portnumber);  [ 5000 < portnumber < 5010 ]
      3:
      4:         Written by Barry Smith, bsmith@mcs.anl.gov 4/14/92
      5:          Updated by Ridhard Katz, katz@ldeo.columbia.edu 9/28/03

      7:    This code has not been tested on all machines, the function prototypes may not
      8: exist for certain systems. Only compiles as C code.
      9: */

     11:  #include petsc.h
     12:  #include petscsys.h

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

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

     75: EXTERN PetscErrorCode SOCKConnect_Private(int);
     76: #define PETSC_MEX_ERROR(a) {fprintf(stdout,"OPENPORT: %s \n",a); return ;}
     77: /*-----------------------------------------------------------------*/
     78: /*                                                                 */
     79: /*-----------------------------------------------------------------*/
     82: void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
     83: {
     84:   int t,portnumber;

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

     89:   /* figure out portnumber user wants to use; default to 5005 */
     90:   if (!nrhs) {
     91:     char *str;
     92:     str = getenv("PETSC_VIEWER_SOCKET_PORT");
     93:     if (str) portnumber = atoi(str);
     94:     else portnumber = DEFAULTPORT;
     95:   } else {
     96:     portnumber = (int)*mxGetPr(prhs[0]);
     97:   }

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

    102:   plhs[0]  = mxCreateDoubleMatrix(1,1,mxREAL);
    103:
    104:   *mxGetPr(plhs[0]) = t;
    105:   return;
    106: }

    108: /*-----------------------------------------------------------------*/
    109: /* The listenport variable is an ugly hack. If the user hits a         */
    110: /* control c while we are listening then we stop listening         */
    111: /* but do not close the listen. Therefore if we try to bind again  */
    112: /* and get an address in use, close the listen which was left      */
    113: /* hanging; the problem is if the user uses several portnumbers    */
    114: /* and control c we may not be able to close the correct listener. */
    115: static int listenport;
    116: /*-----------------------------------------------------------------*/
    120: PetscErrorCode SOCKConnect_Private(int portnumber)
    121: {
    122:   struct sockaddr_in isa;
    123: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
    124:   size_t             i;
    125: #else
    126:   int                i;
    127: #endif
    128:   int                t;

    130: /* open port*/
    131:   listenport = establish((u_short) portnumber);
    132:   if (listenport == -1) {
    133:        fprintf(stdout,"RECEIVE: unable to establish port\n");
    134:        return -1;
    135:   }

    137: /* wait for someone to try to connect */
    138:   i = sizeof(struct sockaddr_in);
    139:   if ((t = accept(listenport,(struct sockaddr *)&isa,(socklen_t *)&i)) < 0) {
    140:      fprintf(stdout,"RECEIVE: error from accept\n");
    141:      return(-1);
    142:   }
    143:   close(listenport);
    144:   return(t);
    145: }
    146: /*-----------------------------------------------------------------*/
    147: #define MAXHOSTNAME 100
    150: PetscErrorCode establish(u_short portnum)
    151: {
    152:   char               myname[MAXHOSTNAME+1];
    153:   int                s;
    154:   PetscErrorCode     ierr;
    155:   struct sockaddr_in sa;
    156:   struct hostent     *hp;
    157: #if defined(PETSC_HAVE_UNAME)
    158:   struct utsname     utname;
    159: #elif defined(PETSC_HAVE_GETCOMPUTERNAME)
    160:   int                namelen=MAXHOSTNAME;
    161: #endif

    163:   /* Note we do not use gethostname since that is not POSIX */
    164: #if defined(PETSC_HAVE_GETCOMPUTERNAME)
    165:   GetComputerName((LPTSTR)myname,(LPDWORD)&namelen);
    166: #elif defined(PETSC_HAVE_UNAME)
    167:   uname(&utname);
    168:   strncpy(myname,utname.nodename,MAXHOSTNAME);
    169: #endif
    170: #if defined(PETSC_HAVE_BZERO)
    171:   bzero(&sa,sizeof(struct sockaddr_in));
    172: #else
    173:   memset(&sa,0,sizeof(struct sockaddr_in));
    174: #endif
    175:   hp = gethostbyname(myname);
    176:   if (!hp) {
    177:      fprintf(stdout,"RECEIVE: error from gethostbyname\n");
    178:      return(-1);
    179:   }

    181:   sa.sin_family = hp->h_addrtype;
    182:   sa.sin_port = htons(portnum);

    184:   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
    185:      fprintf(stdout,"RECEIVE: error from socket\n");
    186:      return(-1);
    187:   }
    188:   {
    189:   int optval = 1; /* Turn on the option */
    190:   setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));
    191:   }

    193:   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
    194: #if defined(PETSC_HAVE_WSAGETLASTERROR)
    195:     WSAGetLastError();
    196:     if (ierr != WSAEADDRINUSE) {
    197: #else
    198:     if (errno != EADDRINUSE) {
    199: #endif
    200:       close(s);
    201:       fprintf(stdout,"RECEIVE: error from bind\n");
    202:       return(-1);
    203:     }
    204:     close(listenport);
    205:   }
    206:   listen(s,0);
    207:   return(s);
    208: }