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