1b75c6efcSBarry Smith /* 2b75c6efcSBarry Smith Usage: A = sopen(portnumber); [ 5000 < portnumber < 5010 ] 3b75c6efcSBarry Smith 4b75c6efcSBarry Smith Written by Barry Smith, bsmith@mcs.anl.gov 4/14/92 5b75c6efcSBarry Smith Updated by Richard Katz, katz@ldeo.columbia.edu 9/28/03 6b75c6efcSBarry Smith Updated by Barry Smith, bsmith@mcs.anl.gov 8/11/06 7b75c6efcSBarry Smith 8b75c6efcSBarry Smith Similar to MATLAB's sopen() only does not take file name, instead optional 9b75c6efcSBarry Smith port to listen at. 10b75c6efcSBarry Smith 11b75c6efcSBarry Smith Only compiles as C code. 12b75c6efcSBarry Smith */ 13b75c6efcSBarry Smith 14b75c6efcSBarry Smith #include <petscsys.h> 15b75c6efcSBarry Smith 16b75c6efcSBarry Smith #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS) 17b75c6efcSBarry Smith /* Some systems have inconsistent include files that use but don't 18b75c6efcSBarry Smith ensure that the following definitions are made */ 19b75c6efcSBarry Smith typedef unsigned char u_char; 20b75c6efcSBarry Smith typedef unsigned short u_short; 21b75c6efcSBarry Smith typedef unsigned int u_int; 22b75c6efcSBarry Smith typedef unsigned long u_long; 23b75c6efcSBarry Smith #endif 24b75c6efcSBarry Smith 25b75c6efcSBarry Smith #include <errno.h> 26b75c6efcSBarry Smith #include <ctype.h> 27b75c6efcSBarry Smith #if defined(PETSC_HAVE_MACHINE_ENDIAN_H) 28b75c6efcSBarry Smith #include <machine/endian.h> 29b75c6efcSBarry Smith #endif 30b75c6efcSBarry Smith #if defined(PETSC_HAVE_UNISTD_H) 31b75c6efcSBarry Smith #include <unistd.h> 32b75c6efcSBarry Smith #endif 33b75c6efcSBarry Smith #if defined(PETSC_HAVE_SYS_SOCKET_H) 34b75c6efcSBarry Smith #include <sys/socket.h> 35b75c6efcSBarry Smith #endif 36b75c6efcSBarry Smith #if defined(PETSC_HAVE_SYS_WAIT_H) 37b75c6efcSBarry Smith #include <sys/wait.h> 38b75c6efcSBarry Smith #endif 39b75c6efcSBarry Smith #if defined(PETSC_HAVE_NETINET_IN_H) 40b75c6efcSBarry Smith #include <netinet/in.h> 41b75c6efcSBarry Smith #endif 42b75c6efcSBarry Smith #if defined(PETSC_HAVE_NETDB_H) 43b75c6efcSBarry Smith #include <netdb.h> 44b75c6efcSBarry Smith #endif 45b75c6efcSBarry Smith #if defined(PETSC_HAVE_FCNTL_H) 46b75c6efcSBarry Smith #include <fcntl.h> 47b75c6efcSBarry Smith #endif 48b75c6efcSBarry Smith #if defined(PETSC_HAVE_IO_H) 49b75c6efcSBarry Smith #include <io.h> 50b75c6efcSBarry Smith #endif 51b75c6efcSBarry Smith #if defined(PETSC_HAVE_SYS_UTSNAME_H) 52b75c6efcSBarry Smith #include <sys/utsname.h> 53b75c6efcSBarry Smith #endif 54b75c6efcSBarry Smith #if defined(PETSC_HAVE_WINSOCK2_H) 55b75c6efcSBarry Smith #include <Winsock2.h> 56b75c6efcSBarry Smith #endif 57b75c6efcSBarry Smith #if defined(PETSC_HAVE_WS2TCPIP_H) 58b75c6efcSBarry Smith #include <Ws2tcpip.h> 59b75c6efcSBarry Smith #endif 60b75c6efcSBarry Smith #include <../src/sys/classes/viewer/impls/socket/socket.h> 61b75c6efcSBarry Smith #include <mex.h> 62b75c6efcSBarry Smith 63b75c6efcSBarry Smith #define PETSC_MEX_ERROR(a) \ 64b75c6efcSBarry Smith { \ 65b75c6efcSBarry Smith mexErrMsgTxt(a); \ 66b75c6efcSBarry Smith return; \ 67b75c6efcSBarry Smith } 68b75c6efcSBarry Smith #define PETSC_MEX_ERRORQ(a) \ 69b75c6efcSBarry Smith { \ 70b75c6efcSBarry Smith mexErrMsgTxt(a); \ 71b75c6efcSBarry Smith return -1; \ 72b75c6efcSBarry Smith } 73b75c6efcSBarry Smith 74b75c6efcSBarry Smith /*-----------------------------------------------------------------*/ 75b75c6efcSBarry Smith /* The listenport variable is an ugly hack. If the user hits a */ 76b75c6efcSBarry Smith /* control c while we are listening then we stop listening */ 77b75c6efcSBarry Smith /* but do not close the listen. Therefore if we try to bind again */ 78b75c6efcSBarry Smith /* and get an address in use, close the listen which was left */ 79b75c6efcSBarry Smith /* hanging; the problem is if the user uses several portnumbers */ 80b75c6efcSBarry Smith /* and control c we may not be able to close the correct listener. */ 81b75c6efcSBarry Smith static int listenport; 82b75c6efcSBarry Smith /*-----------------------------------------------------------------*/ 83b75c6efcSBarry Smith extern int establish(u_short); 8466976f2fSJacob Faibussowitsch static int SOCKConnect_Private(int portnumber) 85b75c6efcSBarry Smith { 86b75c6efcSBarry Smith struct sockaddr_in isa; 87b75c6efcSBarry Smith #if defined(PETSC_HAVE_ACCEPT_SIZE_T) 88b75c6efcSBarry Smith size_t i; 89b75c6efcSBarry Smith #else 90b75c6efcSBarry Smith int i; 91b75c6efcSBarry Smith #endif 92b75c6efcSBarry Smith int t; 93b75c6efcSBarry Smith 94b75c6efcSBarry Smith /* open port*/ 95b75c6efcSBarry Smith listenport = establish((u_short)portnumber); 96b75c6efcSBarry Smith if (listenport == -1) PETSC_MEX_ERRORQ("RECEIVE: unable to establish port\n"); 97b75c6efcSBarry Smith 98b75c6efcSBarry Smith /* wait for someone to try to connect */ 99b75c6efcSBarry Smith i = sizeof(struct sockaddr_in); 100b75c6efcSBarry Smith if ((t = accept(listenport, (struct sockaddr *)&isa, (socklen_t *)&i)) < 0) PETSC_MEX_ERRORQ("RECEIVE: error from accept\n"); 101b75c6efcSBarry Smith close(listenport); 102*4ad8454bSPierre Jolivet return t; 103b75c6efcSBarry Smith } 104b75c6efcSBarry Smith /*-----------------------------------------------------------------*/ 105b75c6efcSBarry Smith #define MAXHOSTNAME 100 106b75c6efcSBarry Smith int establish(u_short portnum) 107b75c6efcSBarry Smith { 108b75c6efcSBarry Smith char myname[MAXHOSTNAME + 1]; 109b75c6efcSBarry Smith int s; 110b75c6efcSBarry Smith struct sockaddr_in sa; 111b75c6efcSBarry Smith struct hostent *hp; 112b75c6efcSBarry Smith #if defined(PETSC_HAVE_UNAME) 113b75c6efcSBarry Smith struct utsname utname; 114b75c6efcSBarry Smith #elif defined(PETSC_HAVE_GETCOMPUTERNAME) 115b75c6efcSBarry Smith int namelen = MAXHOSTNAME; 116b75c6efcSBarry Smith #endif 117b75c6efcSBarry Smith 118b75c6efcSBarry Smith /* Note we do not use gethostname since that is not POSIX */ 119b75c6efcSBarry Smith #if defined(PETSC_HAVE_GETCOMPUTERNAME) 120b75c6efcSBarry Smith GetComputerName((LPTSTR)myname, (LPDWORD)&namelen); 121b75c6efcSBarry Smith #elif defined(PETSC_HAVE_UNAME) 122b75c6efcSBarry Smith uname(&utname); 123b75c6efcSBarry Smith strncpy(myname, utname.nodename, MAXHOSTNAME); 124b75c6efcSBarry Smith #endif 125b75c6efcSBarry Smith #if defined(PETSC_HAVE_BZERO) 126b75c6efcSBarry Smith bzero(&sa, sizeof(struct sockaddr_in)); 127b75c6efcSBarry Smith #else 128b75c6efcSBarry Smith memset(&sa, 0, sizeof(struct sockaddr_in)); 129b75c6efcSBarry Smith #endif 130b75c6efcSBarry Smith hp = gethostbyname(myname); 131b75c6efcSBarry Smith if (!hp) PETSC_MEX_ERRORQ("RECEIVE: error from gethostbyname\n"); 132b75c6efcSBarry Smith 133b75c6efcSBarry Smith sa.sin_family = hp->h_addrtype; 134b75c6efcSBarry Smith sa.sin_port = htons(portnum); 135b75c6efcSBarry Smith 136b75c6efcSBarry Smith if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) PETSC_MEX_ERRORQ("RECEIVE: error from socket\n"); 137b75c6efcSBarry Smith 138b75c6efcSBarry Smith { 139b75c6efcSBarry Smith int optval = 1; /* Turn on the option */ 140b75c6efcSBarry Smith (void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)); 141b75c6efcSBarry Smith } 142b75c6efcSBarry Smith 143b75c6efcSBarry Smith while (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 144b75c6efcSBarry Smith #if defined(PETSC_HAVE_WSAGETLASTERROR) 145b75c6efcSBarry Smith PetscErrorCode ierr; 146b75c6efcSBarry Smith ierr = WSAGetLastError(); 147b75c6efcSBarry Smith if (ierr != WSAEADDRINUSE) { 148b75c6efcSBarry Smith #else 149b75c6efcSBarry Smith if (errno != EADDRINUSE) { 150b75c6efcSBarry Smith #endif 151b75c6efcSBarry Smith close(s); 152b75c6efcSBarry Smith PETSC_MEX_ERRORQ("RECEIVE: error from bind\n"); 153*4ad8454bSPierre Jolivet return -1; 154b75c6efcSBarry Smith } 155b75c6efcSBarry Smith close(listenport); 156b75c6efcSBarry Smith } 157b75c6efcSBarry Smith listen(s, 0); 158*4ad8454bSPierre Jolivet return s; 159b75c6efcSBarry Smith } 160b75c6efcSBarry Smith 161b75c6efcSBarry Smith /*-----------------------------------------------------------------*/ 162b75c6efcSBarry Smith /* */ 163b75c6efcSBarry Smith /*-----------------------------------------------------------------*/ 164b75c6efcSBarry Smith PETSC_EXTERN void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 165b75c6efcSBarry Smith { 166b75c6efcSBarry Smith int t, portnumber; 167b75c6efcSBarry Smith 168b75c6efcSBarry Smith /* check output parameters */ 169b75c6efcSBarry Smith if (nlhs != 1) PETSC_MEX_ERROR("Open requires one output argument."); 170b75c6efcSBarry Smith 171b75c6efcSBarry Smith /* figure out portnumber user wants to use; default to 5005 */ 172b75c6efcSBarry Smith if (!nrhs) { 173b75c6efcSBarry Smith char *str; 174b75c6efcSBarry Smith str = getenv("PETSC_VIEWER_SOCKET_PORT"); 175b75c6efcSBarry Smith if (str) portnumber = atoi(str); 176b75c6efcSBarry Smith else portnumber = PETSCSOCKETDEFAULTPORT; 177b75c6efcSBarry Smith } else portnumber = (int)*mxGetPr(prhs[0]); 178b75c6efcSBarry Smith 179b75c6efcSBarry Smith /* open connection */ 180b75c6efcSBarry Smith t = SOCKConnect_Private(portnumber); 181b75c6efcSBarry Smith if (t == -1) PETSC_MEX_ERROR("opening socket"); 182b75c6efcSBarry Smith 183b75c6efcSBarry Smith plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); 184b75c6efcSBarry Smith 185b75c6efcSBarry Smith *mxGetPr(plhs[0]) = t; 186b75c6efcSBarry Smith return; 187b75c6efcSBarry Smith } 188b75c6efcSBarry Smith 189b75c6efcSBarry Smith int main(int argc, char **argv) 190b75c6efcSBarry Smith { 191b75c6efcSBarry Smith return 0; 192b75c6efcSBarry Smith } 193