Actual source code: sopen.c

  1: /* 
  2:   Usage: A = sopen(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
  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 petsc.h
 15:  #include petscsys.h

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

 26: #include <errno.h>
 27: #if defined(PETSC_HAVE_STDLIB_H)
 28: #include <stdlib.h>
 29: #endif
 30: #include <sys/types.h>
 31: #include <ctype.h>
 32: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
 33: #include <machine/endian.h>
 34: #endif
 35: #if defined(PETSC_HAVE_UNISTD_H)
 36: #include <unistd.h>
 37: #endif
 38: #if defined(PETSC_HAVE_SYS_SOCKET_H)
 39: #include <sys/socket.h>
 40: #endif
 41: #if defined(PETSC_HAVE_SYS_WAIT_H)
 42: #include <sys/wait.h>
 43: #endif
 44: #if defined(PETSC_HAVE_NETINET_IN_H)
 45: #include <netinet/in.h>
 46: #endif
 47: #if defined(PETSC_HAVE_NETDB_H)
 48: #include <netdb.h>
 49: #endif
 50: #if defined(PETSC_HAVE_FCNTL_H)
 51: #include <fcntl.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/viewer/impls/socket/socket.h
 72: #include "petscfix.h"
 73: #include "mex.h"

 75: #define PETSC_MEX_ERROR(a) {mexErrMsgTxt(a); return ;}

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

 99: /* open port*/
100:   listenport = establish((u_short) portnumber);
101:   if (listenport == -1) {
102:     PETSC_MEX_ERROR("RECEIVE: unable to establish port\n");
103:     return -1;
104:   }

106: /* wait for someone to try to connect */
107:   i = sizeof(struct sockaddr_in);
108:   if ((t = accept(listenport,(struct sockaddr *)&isa,(socklen_t *)&i)) < 0) {
109:     PETSC_MEX_ERROR("RECEIVE: error from accept\n");
110:     return(-1);
111:   }
112:   close(listenport);
113:   return(t);
114: }
115: /*-----------------------------------------------------------------*/
116: #define MAXHOSTNAME 100
119: PetscErrorCode establish(u_short portnum)
120: {
121:   char               myname[MAXHOSTNAME+1];
122:   int                s;
123:   PetscErrorCode     ierr;
124:   struct sockaddr_in sa;
125:   struct hostent     *hp;
126: #if defined(PETSC_HAVE_UNAME)
127:   struct utsname     utname;
128: #elif defined(PETSC_HAVE_GETCOMPUTERNAME)
129:   int                namelen=MAXHOSTNAME;
130: #endif

132:   /* Note we do not use gethostname since that is not POSIX */
133: #if defined(PETSC_HAVE_GETCOMPUTERNAME)
134:   GetComputerName((LPTSTR)myname,(LPDWORD)&namelen);
135: #elif defined(PETSC_HAVE_UNAME)
136:   uname(&utname);
137:   strncpy(myname,utname.nodename,MAXHOSTNAME);
138: #endif
139: #if defined(PETSC_HAVE_BZERO)
140:   bzero(&sa,sizeof(struct sockaddr_in));
141: #else
142:   memset(&sa,0,sizeof(struct sockaddr_in));
143: #endif
144:   hp = gethostbyname(myname);
145:   if (!hp) {
146:     PETSC_MEX_ERROR("RECEIVE: error from gethostbyname\n");
147:      return(-1);
148:   }

150:   sa.sin_family = hp->h_addrtype;
151:   sa.sin_port = htons(portnum);

153:   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
154:     PETSC_MEX_ERROR("RECEIVE: error from socket\n");
155:     return(-1);
156:   }
157:   {
158:   int optval = 1; /* Turn on the option */
159:   setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));
160:   }

162:   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
163: #if defined(PETSC_HAVE_WSAGETLASTERROR)
164:     WSAGetLastError();
165:     if (ierr != WSAEADDRINUSE) {
166: #else
167:     if (errno != EADDRINUSE) {
168: #endif
169:       close(s);
170:       PETSC_MEX_ERROR("RECEIVE: error from bind\n");
171:       return(-1);
172:     }
173:     close(listenport);
174:   }
175:   listen(s,0);
176:   return(s);
177: }

179: /*-----------------------------------------------------------------*/
180: /*                                                                 */
181: /*-----------------------------------------------------------------*/
184: void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
185: {
186:   int        t,portnumber;

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

191:   /* figure out portnumber user wants to use; default to 5005 */
192:   if (!nrhs) {
193:     char *str;
194:     str = getenv("PETSC_VIEWER_SOCKET_PORT");
195:     if (str) portnumber = atoi(str);
196:     else portnumber = DEFAULTPORT;
197:   } else {
198:     portnumber = (int)*mxGetPr(prhs[0]);
199:   }

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

204:   plhs[0]  = mxCreateDoubleMatrix(1,1,mxREAL);
205: 
206:   *mxGetPr(plhs[0]) = t;
207:   return;
208: }