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: /*-----------------------------------------------------------------*/
 75: /* The listenport variable is an ugly hack. If the user hits a         */
 76: /* control c while we are listening then we stop listening         */
 77: /* but do not close the listen. Therefore if we try to bind again  */
 78: /* and get an address in use, close the listen which was left      */
 79: /* hanging; the problem is if the user uses several portnumbers    */
 80: /* and control c we may not be able to close the correct listener. */
 81: static int listenport;
 82: /*-----------------------------------------------------------------*/
 83: extern int establish(u_short);
 84: static int SOCKConnect_Private(int portnumber)
 85: {
 86:   struct sockaddr_in isa;
 87: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
 88:   size_t i;
 89: #else
 90:   int i;
 91: #endif
 92:   int t;

 94:   /* open port*/
 95:   listenport = establish((u_short)portnumber);
 96:   if (listenport == -1) PETSC_MEX_ERRORQ("RECEIVE: unable to establish port\n");

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

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

133:   sa.sin_family = hp->h_addrtype;
134:   sa.sin_port   = htons(portnum);

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

138:   {
139:     int optval = 1; /* Turn on the option */
140:     (void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
141:   }

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

161: PETSC_EXTERN void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
162: {
163:   int t, portnumber;

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

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

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

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

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

186: int main(int argc, char **argv)
187: {
188:   return 0;
189: }