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