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 /* The listenport variable is an ugly hack. If the user hits a */ 75 /* control c while we are listening then we stop listening */ 76 /* but do not close the listen. Therefore if we try to bind again */ 77 /* and get an address in use, close the listen which was left */ 78 /* hanging; the problem is if the user uses several portnumbers */ 79 /* and control c we may not be able to close the correct listener. */ 80 static int listenport; 81 extern int establish(u_short); 82 static int SOCKConnect_Private(int portnumber) 83 { 84 struct sockaddr_in isa; 85 #if defined(PETSC_HAVE_ACCEPT_SIZE_T) 86 size_t i; 87 #else 88 int i; 89 #endif 90 int t; 91 92 /* open port*/ 93 listenport = establish((u_short)portnumber); 94 if (listenport == -1) PETSC_MEX_ERRORQ("RECEIVE: unable to establish port\n"); 95 96 /* wait for someone to try to connect */ 97 i = sizeof(struct sockaddr_in); 98 if ((t = accept(listenport, (struct sockaddr *)&isa, (socklen_t *)&i)) < 0) PETSC_MEX_ERRORQ("RECEIVE: error from accept\n"); 99 close(listenport); 100 return t; 101 } 102 #define MAXHOSTNAME 100 103 int establish(u_short portnum) 104 { 105 char myname[MAXHOSTNAME + 1]; 106 int s; 107 struct sockaddr_in sa; 108 struct hostent *hp; 109 #if defined(PETSC_HAVE_UNAME) 110 struct utsname utname; 111 #elif defined(PETSC_HAVE_GETCOMPUTERNAME) 112 int namelen = MAXHOSTNAME; 113 #endif 114 115 /* Note we do not use gethostname since that is not POSIX */ 116 #if defined(PETSC_HAVE_GETCOMPUTERNAME) 117 GetComputerName((LPTSTR)myname, (LPDWORD)&namelen); 118 #elif defined(PETSC_HAVE_UNAME) 119 uname(&utname); 120 strncpy(myname, utname.nodename, MAXHOSTNAME); 121 #endif 122 #if defined(PETSC_HAVE_BZERO) 123 bzero(&sa, sizeof(struct sockaddr_in)); 124 #else 125 memset(&sa, 0, sizeof(struct sockaddr_in)); 126 #endif 127 hp = gethostbyname(myname); 128 if (!hp) PETSC_MEX_ERRORQ("RECEIVE: error from gethostbyname\n"); 129 130 sa.sin_family = (sa_family_t)hp->h_addrtype; 131 sa.sin_port = htons(portnum); 132 133 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) PETSC_MEX_ERRORQ("RECEIVE: error from socket\n"); 134 135 { 136 int optval = 1; /* Turn on the option */ 137 (void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)); 138 } 139 140 while (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 141 #if defined(PETSC_HAVE_WSAGETLASTERROR) 142 PetscErrorCode ierr; 143 ierr = WSAGetLastError(); 144 if (ierr != WSAEADDRINUSE) { 145 #else 146 if (errno != EADDRINUSE) { 147 #endif 148 close(s); 149 PETSC_MEX_ERRORQ("RECEIVE: error from bind\n"); 150 return -1; 151 } 152 close(listenport); 153 } 154 listen(s, 0); 155 return s; 156 } 157 158 PETSC_EXTERN void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 159 { 160 int t, portnumber; 161 162 /* check output parameters */ 163 if (nlhs != 1) PETSC_MEX_ERROR("Open requires one output argument."); 164 165 /* figure out portnumber user wants to use; default to 5005 */ 166 if (!nrhs) { 167 char *str; 168 str = getenv("PETSC_VIEWER_SOCKET_PORT"); 169 if (str) portnumber = atoi(str); 170 else portnumber = PETSCSOCKETDEFAULTPORT; 171 } else portnumber = (int)*mxGetPr(prhs[0]); 172 173 /* open connection */ 174 t = SOCKConnect_Private(portnumber); 175 if (t == -1) PETSC_MEX_ERROR("opening socket"); 176 177 plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); 178 179 *mxGetPr(plhs[0]) = t; 180 return; 181 } 182 183 int main(int argc, char **argv) 184 { 185 return 0; 186 } 187