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_IO_H)
51: #include <io.h>
52: #endif
53: #if defined(PETSC_HAVE_SYS_UTSNAME_H)
54: #include <sys/utsname.h>
55: #endif
56: #if defined(PETSC_HAVE_STRINGS_H)
57: #include <strings.h>
58: #endif
59: #if defined(PETSC_HAVE_STRING_H)
60: #include <string.h>
61: #endif
62: #if defined(PETSC_HAVE_WINSOCK2_H)
63: #include <Winsock2.h>
64: #endif
65: #if defined(PETSC_HAVE_WS2TCPIP_H)
66: #include <Ws2tcpip.h>
67: #endif
68: #include src/sys/viewer/impls/socket/socket.h
69: #include "petscfix.h"
70: #include "mex.h"
72: EXTERN PetscErrorCode SOCKConnect_Private(int);
73: #define PETSC_MEX_ERROR(a) {fprintf(stdout,"OPENPORT: %s \n",a); return ;}
74: /*-----------------------------------------------------------------*/
75: /* */
76: /*-----------------------------------------------------------------*/
79: void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
80: {
81: int t,portnumber;
83: /* check output parameters */
84: if (nlhs != 1) PETSC_MEX_ERROR("Open requires one output argument.");
86: /* figure out portnumber user wants to use; default to 5005 */
87: if (!nrhs) {
88: char *str;
89: str = getenv("PETSC_VIEWER_SOCKET_PORT");
90: if (str) portnumber = atoi(str);
91: else portnumber = DEFAULTPORT;
92: } else {
93: portnumber = (int)*mxGetPr(prhs[0]);
94: }
96: /* open connection */
97: t = SOCKConnect_Private(portnumber); if (t == -1) PETSC_MEX_ERROR("opening socket");
99: plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
100:
101: *mxGetPr(plhs[0]) = t;
102: return;
103: }
105: /*-----------------------------------------------------------------*/
106: /* The listenport variable is an ugly hack. If the user hits a */
107: /* control c while we are listening then we stop listening */
108: /* but do not close the listen. Therefore if we try to bind again */
109: /* and get an address in use, close the listen which was left */
110: /* hanging; the problem is if the user uses several portnumbers */
111: /* and control c we may not be able to close the correct listener. */
112: static int listenport;
113: /*-----------------------------------------------------------------*/
117: PetscErrorCode SOCKConnect_Private(int portnumber)
118: {
119: struct sockaddr_in isa;
120: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
121: size_t i;
122: #else
123: int i;
124: #endif
125: int t;
127: /* open port*/
128: listenport = establish((u_short) portnumber);
129: if (listenport == -1) {
130: fprintf(stdout,"RECEIVE: unable to establish port\n");
131: return -1;
132: }
134: /* wait for someone to try to connect */
135: i = sizeof(struct sockaddr_in);
136: if ((t = accept(listenport,(struct sockaddr *)&isa,(socklen_t *)&i)) < 0) {
137: fprintf(stdout,"RECEIVE: error from accept\n");
138: return(-1);
139: }
140: close(listenport);
141: return(t);
142: }
143: /*-----------------------------------------------------------------*/
144: #define MAXHOSTNAME 100
147: PetscErrorCode establish(u_short portnum)
148: {
149: char myname[MAXHOSTNAME+1];
150: int s;
151: PetscErrorCode ierr;
152: struct sockaddr_in sa;
153: struct hostent *hp;
154: #if defined(PETSC_HAVE_UNAME)
155: struct utsname utname;
156: #elif defined(PETSC_HAVE_GETCOMPUTERNAME)
157: int namelen=MAXHOSTNAME;
158: #endif
160: /* Note we do not use gethostname since that is not POSIX */
161: #if defined(PETSC_HAVE_GETCOMPUTERNAME)
162: GetComputerName((LPTSTR)myname,(LPDWORD)&namelen);
163: #elif defined(PETSC_HAVE_UNAME)
164: uname(&utname);
165: strncpy(myname,utname.nodename,MAXHOSTNAME);
166: #endif
167: #if defined(PETSC_HAVE_BZERO)
168: bzero(&sa,sizeof(struct sockaddr_in));
169: #else
170: memset(&sa,0,sizeof(struct sockaddr_in));
171: #endif
172: hp = gethostbyname(myname);
173: if (!hp) {
174: fprintf(stdout,"RECEIVE: error from gethostbyname\n");
175: return(-1);
176: }
178: sa.sin_family = hp->h_addrtype;
179: sa.sin_port = htons(portnum);
181: if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
182: fprintf(stdout,"RECEIVE: error from socket\n");
183: return(-1);
184: }
185: {
186: int optval = 1; /* Turn on the option */
187: setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));
188: }
190: while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
191: #if defined(PETSC_HAVE_WSAGETLASTERROR)
192: WSAGetLastError();
193: if (ierr != WSAEADDRINUSE) {
194: #else
195: if (errno != EADDRINUSE) {
196: #endif
197: close(s);
198: fprintf(stdout,"RECEIVE: error from bind\n");
199: return(-1);
200: }
201: close(listenport);
202: }
203: listen(s,0);
204: return(s);
205: }