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 Richard Katz, katz@ldeo.columbia.edu 9/28/03 6 Updated by Barry Smith, bsmith@mcs.anl.gov 8/11/06 7 8 Similar to MATLAB's sopen() only does not take file name, instead optional 9 port to listen at. 10 11 Only compiles as C code. 12 */ 13 14 #include <petscsys.h> 15 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 24 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> 62 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 } 73 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; 93 94 /* open port*/ 95 listenport = establish((u_short)portnumber); 96 if (listenport == -1) PETSC_MEX_ERRORQ("RECEIVE: unable to establish port\n"); 97 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 117 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"); 132 133 sa.sin_family = hp->h_addrtype; 134 sa.sin_port = htons(portnum); 135 136 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) PETSC_MEX_ERRORQ("RECEIVE: error from socket\n"); 137 138 { 139 int optval = 1; /* Turn on the option */ 140 (void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)); 141 } 142 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 } 160 161 /*-----------------------------------------------------------------*/ 162 /* */ 163 /*-----------------------------------------------------------------*/ 164 PETSC_EXTERN void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 165 { 166 int t, portnumber; 167 168 /* check output parameters */ 169 if (nlhs != 1) PETSC_MEX_ERROR("Open requires one output argument."); 170 171 /* figure out portnumber user wants to use; default to 5005 */ 172 if (!nrhs) { 173 char *str; 174 str = getenv("PETSC_VIEWER_SOCKET_PORT"); 175 if (str) portnumber = atoi(str); 176 else portnumber = PETSCSOCKETDEFAULTPORT; 177 } else portnumber = (int)*mxGetPr(prhs[0]); 178 179 /* open connection */ 180 t = SOCKConnect_Private(portnumber); 181 if (t == -1) PETSC_MEX_ERROR("opening socket"); 182 183 plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); 184 185 *mxGetPr(plhs[0]) = t; 186 return; 187 } 188 189 int main(int argc, char **argv) 190 { 191 return 0; 192 } 193