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