FSConnServ.c revision ba6a1819
1/* $Xorg: FSConnServ.c,v 1.4 2001/02/09 02:03:25 xorgcvs Exp $ */
2
3/*
4 * Copyright 1990 Network Computing Devices;
5 * Portions Copyright 1987 by Digital Equipment Corporation
6 *
7 * Permission to use, copy, modify, distribute, and sell this software
8 * and its documentation for any purpose is hereby granted without fee,
9 * provided that the above copyright notice appear in all copies and
10 * that both that copyright notice and this permission notice appear
11 * in supporting documentation, and that the names of Network Computing
12 * Devices or Digital not be used in advertising or publicity pertaining
13 * to distribution of the software without specific, written prior
14 * permission. Network Computing Devices or Digital make no representations
15 * about the suitability of this software for any purpose.  It is provided
16 * "as is" without express or implied warranty.
17 *
18 * NETWORK COMPUTING DEVICES AND  DIGITAL DISCLAIM ALL WARRANTIES WITH
19 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES
21 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
22 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
25 * SOFTWARE.
26 */
27
28/*
29
30Copyright 1987, 1994, 1998  The Open Group
31
32Permission to use, copy, modify, distribute, and sell this software and its
33documentation for any purpose is hereby granted without fee, provided that
34the above copyright notice appear in all copies and that both that
35copyright notice and this permission notice appear in supporting
36documentation.
37
38The above copyright notice and this permission notice shall be included in
39all copies or substantial portions of the Software.
40
41THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
44OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
45AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
46CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
47
48Except as contained in this notice, the name of The Open Group shall not be
49used in advertising or otherwise to promote the sale, use or other dealings
50in this Software without prior written authorization from The Open Group.
51
52*/
53/* $XFree86: xc/lib/FS/FSConnServ.c,v 3.10 2001/10/28 03:32:27 tsi Exp $ */
54
55#ifdef HAVE_CONFIG_H
56#include <config.h>
57#endif
58#include	"FSlibint.h"
59#include	<stdio.h>
60#include	"X11/Xpoll.h"
61#ifdef NCD
62#include	<fcntl.h>
63#endif
64#ifdef WIN32
65#define ECHECK(err) (WSAGetLastError() == err)
66#else
67#ifdef ISC
68#define ECHECK(err) ((errno == err) || errno == EAGAIN || errno == EWOULDBLOCK)
69#else
70#define ECHECK(err) (errno == err)
71#endif
72#endif
73
74/*
75 * Attempts to connect to server, given server name. Returns transport
76 * connection object or NULL if connection fails.
77 */
78
79#define FS_CONNECTION_RETRIES 5
80
81XtransConnInfo
82_FSConnectServer(char *server_name)
83{
84    XtransConnInfo trans_conn = NULL;	/* transport connection object */
85    int retry, connect_stat;
86    int  madeConnection = 0;
87
88    /*
89     * Open the network connection.
90     */
91
92    for (retry = FS_CONNECTION_RETRIES; retry >= 0; retry--)
93    {
94	if ((trans_conn = _FSTransOpenCOTSClient(server_name)) == NULL)
95	{
96	    break;
97	}
98
99	if ((connect_stat = _FSTransConnect(trans_conn,server_name)) < 0)
100	{
101	    _FSTransClose(trans_conn);
102
103	    if (connect_stat == TRANS_TRY_CONNECT_AGAIN)
104	    {
105		sleep(1);
106		continue;
107	    }
108	    else
109		break;
110	}
111	else
112	{
113	    madeConnection = 1;
114	    break;
115	}
116    }
117
118    if (!madeConnection)
119	return (NULL);
120
121
122    /*
123     * set it non-blocking.  This is so we can read data when blocked for
124     * writing in the library.
125     */
126
127    _FSTransSetOption(trans_conn, TRANS_NONBLOCKING, 1);
128
129    return (trans_conn);
130}
131
132/*
133 * Disconnect from server.
134 */
135
136void
137_FSDisconnectServer(XtransConnInfo trans_conn)
138
139{
140    (void) _FSTransClose(trans_conn);
141}
142
143
144/*
145 * This is an OS dependent routine which:
146 * 1) returns as soon as the connection can be written on....
147 * 2) if the connection can be read, must enqueue events and handle errors,
148 * until the connection is writable.
149 */
150void _FSWaitForWritable(FSServer *svr)
151{
152    fd_set	r_mask;
153    fd_set	w_mask;
154    int         nfound;
155
156    FD_ZERO(&r_mask);
157    FD_ZERO(&w_mask);
158
159    while (1) {
160	FD_SET(svr->fd, &r_mask);
161	FD_SET(svr->fd, &w_mask);
162
163	do {
164	    nfound = Select(svr->fd + 1, &r_mask, &w_mask, NULL, NULL);
165	    if (nfound < 0 && !ECHECK(EINTR))
166		(*_FSIOErrorFunction) (svr);
167	} while (nfound <= 0);
168
169	if (XFD_ANYSET(&r_mask)) {
170	    char        buf[BUFSIZE];
171	    BytesReadable_t pend_not_register;
172	    register BytesReadable_t pend;
173	    register fsEvent *ev;
174
175	    /* find out how much data can be read */
176	    if (_FSTransBytesReadable(svr->trans_conn, &pend_not_register) < 0)
177		(*_FSIOErrorFunction) (svr);
178	    pend = pend_not_register;
179
180	    /*
181	     * must read at least one fsEvent; if none is pending, then we'll
182	     * just block waiting for it
183	     */
184	    if (pend < SIZEOF(fsEvent))
185		pend = SIZEOF(fsEvent);
186
187	    /* but we won't read more than the max buffer size */
188	    if (pend > BUFSIZE)
189		pend = BUFSIZE;
190
191	    /* round down to an integral number of FSReps */
192	    pend = (pend / SIZEOF(fsEvent)) * SIZEOF(fsEvent);
193
194	    _FSRead(svr, buf, pend);
195
196	    /* no space between comma and type or else macro will die */
197	    STARTITERATE(ev, fsEvent, buf, (pend > 0),
198			 (pend -= SIZEOF(fsEvent))) {
199		if (ev->type == FS_Error)
200		    _FSError(svr, (fsError *) ev);
201		else		/* it's an event packet; enqueue it */
202		    _FSEnq(svr, ev);
203	    }
204	    ENDITERATE
205	}
206	if (XFD_ANYSET(&w_mask))
207	    return;
208    }
209}
210
211
212void _FSWaitForReadable(FSServer *svr)
213{
214    fd_set	r_mask;
215    int         result;
216
217    FD_ZERO(&r_mask);
218    do {
219	FD_SET(svr->fd, &r_mask);
220	result = Select(svr->fd + 1, &r_mask, NULL, NULL, NULL);
221	if (result == -1 && !ECHECK(EINTR))
222	    (*_FSIOErrorFunction) (svr);
223    } while (result <= 0);
224}
225
226void _FSSendClientPrefix(
227    FSServer		*svr,
228    fsConnClientPrefix	*client)
229{
230    struct iovec iovarray[5],
231               *iov = iovarray;
232    int         niov = 0;
233
234#define add_to_iov(b,l) \
235	  { iov->iov_base = (b); iov->iov_len = (l); iov++, niov++; }
236
237    add_to_iov((caddr_t) client, SIZEOF(fsConnClientPrefix));
238
239#undef add_to_iov
240
241    (void) _FSTransWritev(svr->trans_conn, iovarray, niov);
242    return;
243}
244