xref: /petsc/src/sys/classes/viewer/impls/socket/mex-scripts/sopen.c (revision 29d3d2f85b004f78dba4877067ddf368d9ccb527)
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 /*-----------------------------------------------------------------*/
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 static 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;
93 
94   /* open port*/
95   listenport = establish((u_short)portnumber);
96   if (listenport == -1) PETSC_MEX_ERRORQ("RECEIVE: unable to establish port\n");
97 
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
117 
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");
132 
133   sa.sin_family = (sa_family_t)hp->h_addrtype;
134   sa.sin_port   = htons(portnum);
135 
136   if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) PETSC_MEX_ERRORQ("RECEIVE: error from socket\n");
137 
138   {
139     int optval = 1; /* Turn on the option */
140     (void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
141   }
142 
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 }
160 
161 PETSC_EXTERN void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
162 {
163   int t, portnumber;
164 
165   /* check output parameters */
166   if (nlhs != 1) PETSC_MEX_ERROR("Open requires one output argument.");
167 
168   /* figure out portnumber user wants to use; default to 5005 */
169   if (!nrhs) {
170     char *str;
171     str = getenv("PETSC_VIEWER_SOCKET_PORT");
172     if (str) portnumber = atoi(str);
173     else portnumber = PETSCSOCKETDEFAULTPORT;
174   } else portnumber = (int)*mxGetPr(prhs[0]);
175 
176   /* open connection */
177   t = SOCKConnect_Private(portnumber);
178   if (t == -1) PETSC_MEX_ERROR("opening socket");
179 
180   plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
181 
182   *mxGetPr(plhs[0]) = t;
183   return;
184 }
185 
186 int main(int argc, char **argv)
187 {
188   return 0;
189 }
190