Actual source code: sopen.c
1: /*
2: Usage: A = sopen(portnumber); [ 5000 < portnumber < 5010 ]
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: #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>
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: }
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: 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;
94: /* open port*/
95: listenport = establish((u_short)portnumber);
96: if (listenport == -1) PETSC_MEX_ERRORQ("RECEIVE: unable to establish port\n");
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
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");
133: sa.sin_family = hp->h_addrtype;
134: sa.sin_port = htons(portnum);
136: if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) PETSC_MEX_ERRORQ("RECEIVE: error from socket\n");
138: {
139: int optval = 1; /* Turn on the option */
140: (void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
141: }
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: }
161: /*-----------------------------------------------------------------*/
162: /* */
163: /*-----------------------------------------------------------------*/
164: PETSC_EXTERN void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
165: {
166: int t, portnumber;
168: /* check output parameters */
169: if (nlhs != 1) PETSC_MEX_ERROR("Open requires one output argument.");
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]);
179: /* open connection */
180: t = SOCKConnect_Private(portnumber);
181: if (t == -1) PETSC_MEX_ERROR("opening socket");
183: plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
185: *mxGetPr(plhs[0]) = t;
186: return;
187: }
189: int main(int argc, char **argv)
190: {
191: return 0;
192: }