Actual source code: sopen.c
petsc-3.3-p7 2013-05-11
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
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 <petscsys.h>
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
25: #include <errno.h>
26: #if defined(PETSC_HAVE_STDLIB_H)
27: #include <stdlib.h>
28: #endif
29: #include <sys/types.h>
30: #include <ctype.h>
31: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
32: #include <machine/endian.h>
33: #endif
34: #if defined(PETSC_HAVE_UNISTD_H)
35: #include <unistd.h>
36: #endif
37: #if defined(PETSC_HAVE_SYS_SOCKET_H)
38: #include <sys/socket.h>
39: #endif
40: #if defined(PETSC_HAVE_SYS_WAIT_H)
41: #include <sys/wait.h>
42: #endif
43: #if defined(PETSC_HAVE_NETINET_IN_H)
44: #include <netinet/in.h>
45: #endif
46: #if defined(PETSC_HAVE_NETDB_H)
47: #include <netdb.h>
48: #endif
49: #if defined(PETSC_HAVE_FCNTL_H)
50: #include <fcntl.h>
51: #endif
52: #if defined (PETSC_HAVE_IO_H)
53: #include <io.h>
54: #endif
55: #if defined(PETSC_HAVE_SYS_UTSNAME_H)
56: #include <sys/utsname.h>
57: #endif
58: #if defined(PETSC_HAVE_STRINGS_H)
59: #include <strings.h>
60: #endif
61: #if defined(PETSC_HAVE_STRING_H)
62: #include <string.h>
63: #endif
64: #if defined(PETSC_HAVE_WINSOCK2_H)
65: #include <Winsock2.h>
66: #endif
67: #if defined(PETSC_HAVE_WS2TCPIP_H)
68: #include <Ws2tcpip.h>
69: #endif
70: #include <../src/sys/viewer/impls/socket/socket.h>
71: #include <mex.h>
73: #define PETSC_MEX_ERROR(a) {mexErrMsgTxt(a); return ;}
74: #define PETSC_MEX_ERRORQ(a) {mexErrMsgTxt(a); return -1;}
76: /*-----------------------------------------------------------------*/
77: /* The listenport variable is an ugly hack. If the user hits a */
78: /* control c while we are listening then we stop listening */
79: /* but do not close the listen. Therefore if we try to bind again */
80: /* and get an address in use, close the listen which was left */
81: /* hanging; the problem is if the user uses several portnumbers */
82: /* and control c we may not be able to close the correct listener. */
83: static int listenport;
84: /*-----------------------------------------------------------------*/
85: extern int establish(u_short);
88: int SOCKConnect_Private(int portnumber)
89: {
90: struct sockaddr_in isa;
91: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
92: size_t i;
93: #else
94: int i;
95: #endif
96: int t;
98: /* open port*/
99: listenport = establish((u_short) portnumber);
100: if (listenport == -1) {
101: PETSC_MEX_ERRORQ("RECEIVE: unable to establish port\n");
102: }
104: /* wait for someone to try to connect */
105: i = sizeof(struct sockaddr_in);
106: if ((t = accept(listenport,(struct sockaddr *)&isa,(socklen_t *)&i)) < 0) {
107: PETSC_MEX_ERRORQ("RECEIVE: error from accept\n");
108: }
109: close(listenport);
110: return(t);
111: }
112: /*-----------------------------------------------------------------*/
113: #define MAXHOSTNAME 100
116: int establish(u_short portnum)
117: {
118: char myname[MAXHOSTNAME+1];
119: int s;
120: PetscErrorCode ierr;
121: struct sockaddr_in sa;
122: struct hostent *hp;
123: #if defined(PETSC_HAVE_UNAME)
124: struct utsname utname;
125: #elif defined(PETSC_HAVE_GETCOMPUTERNAME)
126: int namelen=MAXHOSTNAME;
127: #endif
129: /* Note we do not use gethostname since that is not POSIX */
130: #if defined(PETSC_HAVE_GETCOMPUTERNAME)
131: GetComputerName((LPTSTR)myname,(LPDWORD)&namelen);
132: #elif defined(PETSC_HAVE_UNAME)
133: uname(&utname);
134: strncpy(myname,utname.nodename,MAXHOSTNAME);
135: #endif
136: #if defined(PETSC_HAVE_BZERO)
137: bzero(&sa,sizeof(struct sockaddr_in));
138: #else
139: memset(&sa,0,sizeof(struct sockaddr_in));
140: #endif
141: hp = gethostbyname(myname);
142: if (!hp) {
143: PETSC_MEX_ERRORQ("RECEIVE: error from gethostbyname\n");
144: }
146: sa.sin_family = hp->h_addrtype;
147: sa.sin_port = htons(portnum);
149: if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
150: PETSC_MEX_ERRORQ("RECEIVE: error from socket\n");
151: }
152: {
153: int optval = 1; /* Turn on the option */
154: setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));
155: }
157: while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
158: #if defined(PETSC_HAVE_WSAGETLASTERROR)
159: WSAGetLastError();
160: if (ierr != WSAEADDRINUSE) {
161: #else
162: if (errno != EADDRINUSE) {
163: #endif
164: close(s);
165: PETSC_MEX_ERRORQ("RECEIVE: error from bind\n");
166: return(-1);
167: }
168: close(listenport);
169: }
170: listen(s,0);
171: return(s);
172: }
174: /*-----------------------------------------------------------------*/
175: /* */
176: /*-----------------------------------------------------------------*/
179: void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
180: {
181: int t,portnumber;
183: /* check output parameters */
184: if (nlhs != 1) PETSC_MEX_ERROR("Open requires one output argument.");
186: /* figure out portnumber user wants to use; default to 5005 */
187: if (!nrhs) {
188: char *str;
189: str = getenv("PETSC_VIEWER_SOCKET_PORT");
190: if (str) portnumber = atoi(str);
191: else portnumber = PETSCSOCKETDEFAULTPORT;
192: } else {
193: portnumber = (int)*mxGetPr(prhs[0]);
194: }
196: /* open connection */
197: t = SOCKConnect_Private(portnumber); if (t == -1) PETSC_MEX_ERROR("opening socket");
199: plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
200:
201: *mxGetPr(plhs[0]) = t;
202: return;
203: }