Actual source code: openport.c
1: /*
2: Usage: A = openport(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
7: This code has not been tested on all machines, the function prototypes may not
8: exist for certain systems. Only compiles as C code.
9: */
11: #include petsc.h
12: #include petscsys.h
14: #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
15: /* Some systems have inconsistent include files that use but don't
16: ensure that the following definitions are made */
17: typedef unsigned char u_char;
18: typedef unsigned short u_short;
19: typedef unsigned int u_int;
20: typedef unsigned long u_long;
21: #endif
23: #include <errno.h>
24: #if defined(PETSC_HAVE_STDLIB_H)
25: #include <stdlib.h>
26: #endif
27: #include <sys/types.h>
28: #include <ctype.h>
29: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
30: #include <machine/endian.h>
31: #endif
32: #if defined(PETSC_HAVE_UNISTD_H)
33: #include <unistd.h>
34: #endif
35: #if defined(PETSC_HAVE_SYS_SOCKET_H)
36: #include <sys/socket.h>
37: #endif
38: #if defined(PETSC_HAVE_SYS_WAIT_H)
39: #include <sys/wait.h>
40: #endif
41: #if defined(PETSC_HAVE_NETINET_IN_H)
42: #include <netinet/in.h>
43: #endif
44: #if defined(PETSC_HAVE_NETDB_H)
45: #include <netdb.h>
46: #endif
47: #if defined(PETSC_HAVE_FCNTL_H)
48: #include <fcntl.h>
49: #endif
50: #if defined(PETSC_HAVE_STROPTS_H)
51: #include <stropts.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: EXTERN PetscErrorCode SOCKConnect_Private(int);
76: #define PETSC_MEX_ERROR(a) {fprintf(stdout,"OPENPORT: %s \n",a); return ;}
77: /*-----------------------------------------------------------------*/
78: /* */
79: /*-----------------------------------------------------------------*/
82: void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
83: {
84: int t,portnumber;
86: /* check output parameters */
87: if (nlhs != 1) PETSC_MEX_ERROR("Open requires one output argument.");
89: /* figure out portnumber user wants to use; default to 5005 */
90: if (!nrhs) {
91: char *str;
92: str = getenv("PETSC_VIEWER_SOCKET_PORT");
93: if (str) portnumber = atoi(str);
94: else portnumber = DEFAULTPORT;
95: } else {
96: portnumber = (int)*mxGetPr(prhs[0]);
97: }
99: /* open connection */
100: t = SOCKConnect_Private(portnumber); if (t == -1) PETSC_MEX_ERROR("opening socket");
102: plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
103:
104: *mxGetPr(plhs[0]) = t;
105: return;
106: }
108: /*-----------------------------------------------------------------*/
109: /* The listenport variable is an ugly hack. If the user hits a */
110: /* control c while we are listening then we stop listening */
111: /* but do not close the listen. Therefore if we try to bind again */
112: /* and get an address in use, close the listen which was left */
113: /* hanging; the problem is if the user uses several portnumbers */
114: /* and control c we may not be able to close the correct listener. */
115: static int listenport;
116: /*-----------------------------------------------------------------*/
120: PetscErrorCode SOCKConnect_Private(int portnumber)
121: {
122: struct sockaddr_in isa;
123: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
124: size_t i;
125: #else
126: int i;
127: #endif
128: int t;
130: /* open port*/
131: listenport = establish((u_short) portnumber);
132: if (listenport == -1) {
133: fprintf(stdout,"RECEIVE: unable to establish port\n");
134: return -1;
135: }
137: /* wait for someone to try to connect */
138: i = sizeof(struct sockaddr_in);
139: if ((t = accept(listenport,(struct sockaddr *)&isa,(socklen_t *)&i)) < 0) {
140: fprintf(stdout,"RECEIVE: error from accept\n");
141: return(-1);
142: }
143: close(listenport);
144: return(t);
145: }
146: /*-----------------------------------------------------------------*/
147: #define MAXHOSTNAME 100
150: PetscErrorCode establish(u_short portnum)
151: {
152: char myname[MAXHOSTNAME+1];
153: int s;
154: PetscErrorCode ierr;
155: struct sockaddr_in sa;
156: struct hostent *hp;
157: #if defined(PETSC_HAVE_UNAME)
158: struct utsname utname;
159: #elif defined(PETSC_HAVE_GETCOMPUTERNAME)
160: int namelen=MAXHOSTNAME;
161: #endif
163: /* Note we do not use gethostname since that is not POSIX */
164: #if defined(PETSC_HAVE_GETCOMPUTERNAME)
165: GetComputerName((LPTSTR)myname,(LPDWORD)&namelen);
166: #elif defined(PETSC_HAVE_UNAME)
167: uname(&utname);
168: strncpy(myname,utname.nodename,MAXHOSTNAME);
169: #endif
170: #if defined(PETSC_HAVE_BZERO)
171: bzero(&sa,sizeof(struct sockaddr_in));
172: #else
173: memset(&sa,0,sizeof(struct sockaddr_in));
174: #endif
175: hp = gethostbyname(myname);
176: if (!hp) {
177: fprintf(stdout,"RECEIVE: error from gethostbyname\n");
178: return(-1);
179: }
181: sa.sin_family = hp->h_addrtype;
182: sa.sin_port = htons(portnum);
184: if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
185: fprintf(stdout,"RECEIVE: error from socket\n");
186: return(-1);
187: }
188: {
189: int optval = 1; /* Turn on the option */
190: setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));
191: }
193: while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
194: #if defined(PETSC_HAVE_WSAGETLASTERROR)
195: WSAGetLastError();
196: if (ierr != WSAEADDRINUSE) {
197: #else
198: if (errno != EADDRINUSE) {
199: #endif
200: close(s);
201: fprintf(stdout,"RECEIVE: error from bind\n");
202: return(-1);
203: }
204: close(listenport);
205: }
206: listen(s,0);
207: return(s);
208: }