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