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);
SOCKConnect_Private(int portnumber)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
establish(u_short portnum)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