connection.c revision 30f8ce46
1bbe1b32bSmrg/*
2bbe1b32bSmrg * handles connections
3bbe1b32bSmrg */
4bbe1b32bSmrg/*
5bbe1b32bSmrg
6bbe1b32bSmrgCopyright 1990, 1991, 1998  The Open Group
7bbe1b32bSmrg
8bbe1b32bSmrgPermission to use, copy, modify, distribute, and sell this software and its
9bbe1b32bSmrgdocumentation for any purpose is hereby granted without fee, provided that
10bbe1b32bSmrgthe above copyright notice appear in all copies and that both that
11bbe1b32bSmrgcopyright notice and this permission notice appear in supporting
12bbe1b32bSmrgdocumentation.
13bbe1b32bSmrg
14bbe1b32bSmrgThe above copyright notice and this permission notice shall be included in
15bbe1b32bSmrgall copies or substantial portions of the Software.
16bbe1b32bSmrg
17bbe1b32bSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18bbe1b32bSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19bbe1b32bSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20bbe1b32bSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21bbe1b32bSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22bbe1b32bSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23bbe1b32bSmrg
24bbe1b32bSmrgExcept as contained in this notice, the name of The Open Group shall not be
25bbe1b32bSmrgused in advertising or otherwise to promote the sale, use or other dealings
26bbe1b32bSmrgin this Software without prior written authorization from The Open Group.
27bbe1b32bSmrg
28bbe1b32bSmrg * Copyright 1990, 1991 Network Computing Devices;
29bbe1b32bSmrg * Portions Copyright 1987 by Digital Equipment Corporation
30bbe1b32bSmrg *
31bbe1b32bSmrg * Permission to use, copy, modify, distribute, and sell this software and
32bbe1b32bSmrg * its documentation for any purpose is hereby granted without fee, provided
33bbe1b32bSmrg * that the above copyright notice appear in all copies and that both that
34bbe1b32bSmrg * copyright notice and this permission notice appear in supporting
35bbe1b32bSmrg * documentation, and that the names of Network Computing Devices, or Digital
36bbe1b32bSmrg * not be used in advertising or publicity pertaining to distribution
37bbe1b32bSmrg * of the software without specific, written prior permission.
38bbe1b32bSmrg *
39bbe1b32bSmrg * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
40bbe1b32bSmrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
41bbe1b32bSmrg * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
42bbe1b32bSmrg * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
43bbe1b32bSmrg * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
44bbe1b32bSmrg * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
45bbe1b32bSmrg * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
46bbe1b32bSmrg * THIS SOFTWARE.
47bbe1b32bSmrg */
48bbe1b32bSmrg/*
49bbe1b32bSmrg * Copyright 1990, 1991 Network Computing Devices;
50bbe1b32bSmrg * Portions Copyright 1987 by Digital Equipment Corporation
51bbe1b32bSmrg *
52bbe1b32bSmrg * Permission to use, copy, modify, distribute, and sell this software and
53bbe1b32bSmrg * its documentation for any purpose is hereby granted without fee, provided
54bbe1b32bSmrg * that the above copyright notice appear in all copies and that both that
55bbe1b32bSmrg * copyright notice and this permission notice appear in supporting
56bbe1b32bSmrg * documentation, and that the names of Network Computing Devices, or Digital
57bbe1b32bSmrg * not be used in advertising or publicity pertaining to distribution
58bbe1b32bSmrg * of the software without specific, written prior permission.
59bbe1b32bSmrg *
60bbe1b32bSmrg * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
61bbe1b32bSmrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
62bbe1b32bSmrg * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
63bbe1b32bSmrg * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
64bbe1b32bSmrg * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
65bbe1b32bSmrg * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
66bbe1b32bSmrg * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
67bbe1b32bSmrg * THIS SOFTWARE.
68bbe1b32bSmrg */
69ce6676dbSmrg
70ce6676dbSmrg#include	"xfs-config.h"
71bbe1b32bSmrg
72bbe1b32bSmrg#include	<stdlib.h>
73bbe1b32bSmrg#include	<X11/Xtrans/Xtrans.h>
74bbe1b32bSmrg#include	<stdlib.h>
75bbe1b32bSmrg#include	"misc.h"
76bbe1b32bSmrg#include	<stdio.h>
77bbe1b32bSmrg#include	<errno.h>
78bbe1b32bSmrg#include	<X11/Xos.h>
79bbe1b32bSmrg#include	<sys/param.h>
80bbe1b32bSmrg#include	<sys/socket.h>
81bbe1b32bSmrg#ifndef __UNIXOS2__
82bbe1b32bSmrg#include	<sys/uio.h>
83bbe1b32bSmrg#endif
84bbe1b32bSmrg#include	<signal.h>
85bbe1b32bSmrg
86bbe1b32bSmrg#include	<X11/fonts/FS.h>
87bbe1b32bSmrg#include	<X11/fonts/FSproto.h>
88bbe1b32bSmrg#include	"clientstr.h"
89bbe1b32bSmrg#include	"X11/Xpoll.h"
90bbe1b32bSmrg#include	"osdep.h"
91bbe1b32bSmrg#include	"globals.h"
92bbe1b32bSmrg#include	"osstruct.h"
93bbe1b32bSmrg#include	"servermd.h"
94bbe1b32bSmrg#include	"dispatch.h"
95bbe1b32bSmrg#include	"fsevents.h"
96bbe1b32bSmrg
97bbe1b32bSmrg#ifdef __UNIXOS2__
98bbe1b32bSmrg#define _NFILE OPEN_MAX
99bbe1b32bSmrg#define select(n,r,w,x,t) os2PseudoSelect(n,r,w,x,t)
100bbe1b32bSmrg#endif
101bbe1b32bSmrg
102bbe1b32bSmrg
103bbe1b32bSmrgint         ListenPort = DEFAULT_FS_PORT;   /* port to listen on */
104bbe1b32bSmrgint         lastfdesc;
105bbe1b32bSmrg
106bbe1b32bSmrgfd_set      WellKnownConnections;
107bbe1b32bSmrgfd_set      AllSockets;
108bbe1b32bSmrgfd_set      AllClients;
109bbe1b32bSmrgfd_set      LastSelectMask;
110bbe1b32bSmrgfd_set      ClientsWithInput;
111bbe1b32bSmrgfd_set      ClientsWriteBlocked;
112bbe1b32bSmrgfd_set      OutputPending;
113bbe1b32bSmrglong        OutputBufferSize = BUFSIZE;
114bbe1b32bSmrg
115bbe1b32bSmrgBool        NewOutputPending;
116bbe1b32bSmrgBool        AnyClientsWriteBlocked;
117bbe1b32bSmrg
118bbe1b32bSmrgint         ConnectionTranslation[MAXSOCKS];
119bbe1b32bSmrg
120bbe1b32bSmrgXtransConnInfo 	*ListenTransConns = NULL;
121bbe1b32bSmrgint	       	*ListenTransFds = NULL;
122bbe1b32bSmrgint		ListenTransCount;
123bbe1b32bSmrg
124bbe1b32bSmrg
12530f8ce46Smrgextern int  xfd_ffs (fd_mask);
126bbe1b32bSmrgstatic void error_conn_max(XtransConnInfo trans_conn);
127bbe1b32bSmrgstatic void close_fd(OsCommPtr oc);
128bbe1b32bSmrg
129bbe1b32bSmrg
130bbe1b32bSmrgstatic XtransConnInfo
131bbe1b32bSmrglookup_trans_conn (int fd)
132bbe1b32bSmrg{
133bbe1b32bSmrg    if (ListenTransFds)
134bbe1b32bSmrg    {
135bbe1b32bSmrg	int i;
136bbe1b32bSmrg	for (i = 0; i < ListenTransCount; i++)
137bbe1b32bSmrg	    if (ListenTransFds[i] == fd)
138bbe1b32bSmrg		return ListenTransConns[i];
139bbe1b32bSmrg    }
140bbe1b32bSmrg
141bbe1b32bSmrg    return (NULL);
142bbe1b32bSmrg}
143bbe1b32bSmrg
144bbe1b32bSmrgvoid
145bbe1b32bSmrgStopListening(void)
146bbe1b32bSmrg{
147bbe1b32bSmrg    int i;
148bbe1b32bSmrg
149bbe1b32bSmrg    for (i = 0; i < ListenTransCount; i++)
150bbe1b32bSmrg    {
151bbe1b32bSmrg	FD_CLR (ListenTransFds[i], &AllSockets);
152bbe1b32bSmrg	_FontTransCloseForCloning (ListenTransConns[i]);
153bbe1b32bSmrg    }
154bbe1b32bSmrg
155bbe1b32bSmrg    free ((char *) ListenTransFds);
156bbe1b32bSmrg    free ((char *) ListenTransConns);
157bbe1b32bSmrg
158bbe1b32bSmrg    ListenTransFds = NULL;
159bbe1b32bSmrg    ListenTransConns = NULL;
160ce6676dbSmrg    ListenTransCount = 0;
161bbe1b32bSmrg}
162bbe1b32bSmrg
163bbe1b32bSmrg/*
164bbe1b32bSmrg * creates the sockets for listening to clients
165bbe1b32bSmrg *
166bbe1b32bSmrg * only called when server first started
167bbe1b32bSmrg */
168bbe1b32bSmrgvoid
169bbe1b32bSmrgCreateSockets(int old_listen_count, OldListenRec *old_listen)
170bbe1b32bSmrg{
171bbe1b32bSmrg    int	i;
172ce6676dbSmrg    struct sigaction act;
173bbe1b32bSmrg
174bbe1b32bSmrg    FD_ZERO(&AllSockets);
175bbe1b32bSmrg    FD_ZERO(&AllClients);
176bbe1b32bSmrg    FD_ZERO(&LastSelectMask);
177bbe1b32bSmrg    FD_ZERO(&ClientsWithInput);
178bbe1b32bSmrg    FD_ZERO(&WellKnownConnections);
179bbe1b32bSmrg
180bbe1b32bSmrg    for (i = 0; i < MAXSOCKS; i++)
181bbe1b32bSmrg	ConnectionTranslation[i] = 0;
182bbe1b32bSmrg
183bbe1b32bSmrg    lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
184bbe1b32bSmrg
185ce6676dbSmrg    if ((lastfdesc < 0) || (lastfdesc > MAXSOCKS)) {
186bbe1b32bSmrg	lastfdesc = MAXSOCKS;
187bbe1b32bSmrg    }
188bbe1b32bSmrg
189bbe1b32bSmrg    if (old_listen_count > 0) {
190bbe1b32bSmrg
191bbe1b32bSmrg	/*
192bbe1b32bSmrg	 * The font server cloned itself.  Re-use previously opened
193bbe1b32bSmrg	 * transports for listening.
194bbe1b32bSmrg	 */
195bbe1b32bSmrg
196bbe1b32bSmrg	ListenTransConns = (XtransConnInfo *) malloc (
197bbe1b32bSmrg	    old_listen_count * sizeof (XtransConnInfo));
198bbe1b32bSmrg
199bbe1b32bSmrg	ListenTransFds = (int *) malloc (old_listen_count * sizeof (int));
200bbe1b32bSmrg
201bbe1b32bSmrg	ListenTransCount = 0;
202bbe1b32bSmrg
203bbe1b32bSmrg	for (i = 0; i < old_listen_count; i++)
204bbe1b32bSmrg	{
205bbe1b32bSmrg	    char portnum[10];
206bbe1b32bSmrg
207bbe1b32bSmrg	    if (old_listen[i].portnum != ListenPort)
208bbe1b32bSmrg		continue;		/* this should never happen */
209bbe1b32bSmrg	    else
210bbe1b32bSmrg		sprintf (portnum, "%d", old_listen[i].portnum);
211bbe1b32bSmrg
212bbe1b32bSmrg	    if ((ListenTransConns[ListenTransCount] =
213bbe1b32bSmrg		_FontTransReopenCOTSServer (old_listen[i].trans_id,
214bbe1b32bSmrg		old_listen[i].fd, portnum)) != NULL)
215bbe1b32bSmrg	    {
216bbe1b32bSmrg		ListenTransFds[ListenTransCount] = old_listen[i].fd;
217bbe1b32bSmrg		FD_SET (old_listen[i].fd, &WellKnownConnections);
218bbe1b32bSmrg
219bbe1b32bSmrg		NoticeF("reusing existing file descriptor %d\n",
220bbe1b32bSmrg		    old_listen[i].fd);
221bbe1b32bSmrg
222bbe1b32bSmrg		ListenTransCount++;
223bbe1b32bSmrg	    }
224bbe1b32bSmrg	}
225bbe1b32bSmrg    } else {
226bbe1b32bSmrg	char port[20];
227bbe1b32bSmrg	int partial;
228bbe1b32bSmrg
229bbe1b32bSmrg	sprintf (port, "%d", ListenPort);
230bbe1b32bSmrg
231bbe1b32bSmrg	if ((_FontTransMakeAllCOTSServerListeners (port, &partial,
232bbe1b32bSmrg	    &ListenTransCount, &ListenTransConns) >= 0) &&
233bbe1b32bSmrg	    (ListenTransCount >= 1))
234bbe1b32bSmrg	{
235bbe1b32bSmrg	    ListenTransFds = (int *) malloc (ListenTransCount * sizeof (int));
236bbe1b32bSmrg
237bbe1b32bSmrg	    for (i = 0; i < ListenTransCount; i++)
238bbe1b32bSmrg	    {
239bbe1b32bSmrg		int fd = _FontTransGetConnectionNumber (ListenTransConns[i]);
240bbe1b32bSmrg
241bbe1b32bSmrg		ListenTransFds[i] = fd;
242bbe1b32bSmrg		FD_SET (fd, &WellKnownConnections);
243bbe1b32bSmrg	    }
244bbe1b32bSmrg	}
245bbe1b32bSmrg    }
246bbe1b32bSmrg
247bbe1b32bSmrg    if (! XFD_ANYSET(&WellKnownConnections))
248bbe1b32bSmrg	FatalError("cannot establish any listening sockets\n");
249bbe1b32bSmrg
250bbe1b32bSmrg    /* set up all the signal handlers */
251ce6676dbSmrg    sigemptyset(&act.sa_mask);
252ce6676dbSmrg    act.sa_flags = SA_RESTART;
253ce6676dbSmrg#define HANDLE_SIGNAL(s, h)	act.sa_handler = h; sigaction(s, &act, NULL)
254ce6676dbSmrg
255ce6676dbSmrg    HANDLE_SIGNAL(SIGPIPE, SIG_IGN);
256ce6676dbSmrg    HANDLE_SIGNAL(SIGHUP, AutoResetServer);
257ce6676dbSmrg    HANDLE_SIGNAL(SIGINT, GiveUp);
258ce6676dbSmrg    HANDLE_SIGNAL(SIGTERM, GiveUp);
259ce6676dbSmrg    HANDLE_SIGNAL(SIGUSR1, ServerReconfig);
260ce6676dbSmrg    HANDLE_SIGNAL(SIGUSR2, ServerCacheFlush);
261ce6676dbSmrg    HANDLE_SIGNAL(SIGCHLD, CleanupChild);
262bbe1b32bSmrg
263bbe1b32bSmrg    XFD_COPYSET (&WellKnownConnections, &AllSockets);
264bbe1b32bSmrg}
265bbe1b32bSmrg
266bbe1b32bSmrg/*
267bbe1b32bSmrg * called when server cycles
268bbe1b32bSmrg */
269bbe1b32bSmrgvoid
270bbe1b32bSmrgResetSockets(void)
271bbe1b32bSmrg{
272bbe1b32bSmrg}
273bbe1b32bSmrg
274bbe1b32bSmrgvoid
275bbe1b32bSmrgCloseSockets(void)
276bbe1b32bSmrg{
277bbe1b32bSmrg    int i;
278bbe1b32bSmrg
279bbe1b32bSmrg    for (i = 0; i < ListenTransCount; i++)
280bbe1b32bSmrg	_FontTransClose (ListenTransConns[i]);
281bbe1b32bSmrg}
282bbe1b32bSmrg
283bbe1b32bSmrg/*
284bbe1b32bSmrg * accepts new connections
285bbe1b32bSmrg */
286bbe1b32bSmrgvoid
287bbe1b32bSmrgMakeNewConnections(void)
288bbe1b32bSmrg{
289bbe1b32bSmrg    fd_mask     readyconnections;
290bbe1b32bSmrg    int         curconn;
291bbe1b32bSmrg    int         newconn;
292bbe1b32bSmrg    long        connect_time;
293bbe1b32bSmrg    int         i;
294bbe1b32bSmrg    ClientPtr   client;
295bbe1b32bSmrg    OsCommPtr   oc;
296bbe1b32bSmrg    fd_set	tmask;
297bbe1b32bSmrg
298bbe1b32bSmrg    XFD_ANDSET (&tmask, &LastSelectMask, &WellKnownConnections);
299bbe1b32bSmrg    readyconnections = tmask.fds_bits[0];
300bbe1b32bSmrg    if (!readyconnections)
301bbe1b32bSmrg	return;
302bbe1b32bSmrg    connect_time = GetTimeInMillis();
303bbe1b32bSmrg
304bbe1b32bSmrg    /* kill off stragglers */
305bbe1b32bSmrg    for (i = MINCLIENT; i < currentMaxClients; i++) {
306bbe1b32bSmrg	if ((client = clients[i]) != NullClient) {
307bbe1b32bSmrg	    oc = (OsCommPtr) client->osPrivate;
308bbe1b32bSmrg	    if ((oc && (oc->conn_time != 0) &&
309bbe1b32bSmrg		    (connect_time - oc->conn_time) >= TimeOutValue) ||
310bbe1b32bSmrg		     ((client->noClientException != FSSuccess) &&
311bbe1b32bSmrg		      (client->clientGone != CLIENT_GONE)))
312bbe1b32bSmrg		CloseDownClient(client);
313bbe1b32bSmrg	}
314bbe1b32bSmrg    }
315bbe1b32bSmrg
316bbe1b32bSmrg    while (readyconnections) {
317bbe1b32bSmrg	XtransConnInfo trans_conn, new_trans_conn;
318bbe1b32bSmrg	int status;
319bbe1b32bSmrg
32030f8ce46Smrg	curconn = xfd_ffs(readyconnections) - 1;
321bbe1b32bSmrg	readyconnections &= ~(1 << curconn);
322bbe1b32bSmrg
323bbe1b32bSmrg	if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
324bbe1b32bSmrg	    continue;
325bbe1b32bSmrg
326bbe1b32bSmrg	if ((new_trans_conn = _FontTransAccept (trans_conn, &status)) == NULL)
327bbe1b32bSmrg	    continue;
328bbe1b32bSmrg
329bbe1b32bSmrg	newconn = _FontTransGetConnectionNumber (new_trans_conn);
330bbe1b32bSmrg
331bbe1b32bSmrg	_FontTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
332bbe1b32bSmrg
333bbe1b32bSmrg	oc = (OsCommPtr) fsalloc(sizeof(OsCommRec));
334bbe1b32bSmrg	if (!oc) {
335bbe1b32bSmrg	    fsfree(oc);
336bbe1b32bSmrg	    error_conn_max(new_trans_conn);
337bbe1b32bSmrg	    _FontTransClose(new_trans_conn);
338bbe1b32bSmrg	    continue;
339bbe1b32bSmrg	}
340bbe1b32bSmrg	FD_SET(newconn, &AllClients);
341bbe1b32bSmrg	FD_SET(newconn, &AllSockets);
342bbe1b32bSmrg	oc->fd = newconn;
343bbe1b32bSmrg	oc->trans_conn = new_trans_conn;
344bbe1b32bSmrg	oc->input = (ConnectionInputPtr) NULL;
345bbe1b32bSmrg	oc->output = (ConnectionOutputPtr) NULL;
346bbe1b32bSmrg	oc->conn_time = connect_time;
347bbe1b32bSmrg
348bbe1b32bSmrg	if ((newconn < lastfdesc) &&
349bbe1b32bSmrg		(client = NextAvailableClient((pointer) oc))) {
350bbe1b32bSmrg	    ConnectionTranslation[newconn] = client->index;
351bbe1b32bSmrg	} else {
352bbe1b32bSmrg	    error_conn_max(new_trans_conn);
353bbe1b32bSmrg	    close_fd(oc);
354bbe1b32bSmrg	}
355bbe1b32bSmrg    }
356bbe1b32bSmrg}
357bbe1b32bSmrg
358bbe1b32bSmrg#define	NOROOM	"maximum number of clients reached"
359bbe1b32bSmrg
360bbe1b32bSmrgstatic void
361bbe1b32bSmrgerror_conn_max(XtransConnInfo trans_conn)
362bbe1b32bSmrg{
363bbe1b32bSmrg    int fd = _FontTransGetConnectionNumber (trans_conn);
364bbe1b32bSmrg    fsConnSetup conn;
365bbe1b32bSmrg    char        pad[3];
366bbe1b32bSmrg    char        byteOrder = 0;
367bbe1b32bSmrg    int         whichbyte = 1;
368bbe1b32bSmrg    struct timeval waittime;
369bbe1b32bSmrg    fd_set      mask;
370bbe1b32bSmrg
371bbe1b32bSmrg
372bbe1b32bSmrg    waittime.tv_usec = BOTIMEOUT / MILLI_PER_SECOND;
373bbe1b32bSmrg    waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
374bbe1b32bSmrg	(1000000 / MILLI_PER_SECOND);
375bbe1b32bSmrg    FD_ZERO(&mask);
376bbe1b32bSmrg    FD_SET(fd, &mask);
377bbe1b32bSmrg    (void) Select(fd + 1, &mask, NULL, NULL, &waittime);
378bbe1b32bSmrg    /* try to read the byteorder of the connection */
379bbe1b32bSmrg    (void) _FontTransRead(trans_conn, &byteOrder, 1);
380bbe1b32bSmrg    if ((byteOrder == 'l') || (byteOrder == 'B')) {
381bbe1b32bSmrg	int         num_alts;
382bbe1b32bSmrg	AlternateServerPtr altservers,
383bbe1b32bSmrg	            as;
384bbe1b32bSmrg	int         i,
385bbe1b32bSmrg	            altlen = 0;
386bbe1b32bSmrg
387bbe1b32bSmrg	num_alts = ListAlternateServers(&altservers);
388bbe1b32bSmrg	conn.status = AuthDenied;
389bbe1b32bSmrg	conn.major_version = FS_PROTOCOL;
390bbe1b32bSmrg	conn.minor_version = FS_PROTOCOL_MINOR;
391bbe1b32bSmrg	conn.num_alternates = num_alts;
392bbe1b32bSmrg	for (i = 0, as = altservers; i < num_alts; i++, as++) {
393bbe1b32bSmrg	    altlen += (2 + as->namelen + 3) >> 2;
394bbe1b32bSmrg	}
395bbe1b32bSmrg	conn.alternate_len = altlen;
396bbe1b32bSmrg	/* blow off the auth info */
397bbe1b32bSmrg	conn.auth_index = 0;
398bbe1b32bSmrg	conn.auth_len = 0;
399bbe1b32bSmrg
400bbe1b32bSmrg	if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
401bbe1b32bSmrg		(!(*(char *) &whichbyte) && (byteOrder == 'l'))) {
402bbe1b32bSmrg	    conn.status = lswaps(conn.status);
403bbe1b32bSmrg	    conn.major_version = lswaps(conn.major_version);
404bbe1b32bSmrg	    conn.minor_version = lswaps(conn.minor_version);
405bbe1b32bSmrg	    conn.alternate_len = lswaps(conn.alternate_len);
406bbe1b32bSmrg	}
407bbe1b32bSmrg	(void) _FontTransWrite(trans_conn,
408bbe1b32bSmrg	    (char *) &conn, SIZEOF(fsConnSetup));
409bbe1b32bSmrg	/* dump alternates */
410bbe1b32bSmrg	for (i = 0, as = altservers; i < num_alts; i++, as++) {
411bbe1b32bSmrg	    (void) _FontTransWrite(trans_conn,
412bbe1b32bSmrg		(char *) as, 2);  /* XXX */
413bbe1b32bSmrg	    (void) _FontTransWrite(trans_conn,
414bbe1b32bSmrg		(char *) as->name, as->namelen);
415bbe1b32bSmrg	    altlen = 2 + as->namelen;
416bbe1b32bSmrg	    /* pad it */
417bbe1b32bSmrg	    if (altlen & 3)
418bbe1b32bSmrg		(void) _FontTransWrite(trans_conn,
419bbe1b32bSmrg		(char *) pad, ((4 - (altlen & 3)) & 3));
420bbe1b32bSmrg	}
421bbe1b32bSmrg    }
422bbe1b32bSmrg}
423bbe1b32bSmrg
424bbe1b32bSmrgstatic void
425bbe1b32bSmrgclose_fd(OsCommPtr oc)
426bbe1b32bSmrg{
427bbe1b32bSmrg    int         fd = oc->fd;
428bbe1b32bSmrg
429bbe1b32bSmrg    if (oc->trans_conn)
430bbe1b32bSmrg	_FontTransClose(oc->trans_conn);
431bbe1b32bSmrg    FreeOsBuffers(oc);
432bbe1b32bSmrg    FD_CLR(fd, &AllSockets);
433bbe1b32bSmrg    FD_CLR(fd, &AllClients);
434bbe1b32bSmrg    FD_CLR(fd, &ClientsWithInput);
435bbe1b32bSmrg    FD_CLR(fd, &ClientsWriteBlocked);
436bbe1b32bSmrg    if (!XFD_ANYSET(&ClientsWriteBlocked))
437bbe1b32bSmrg	AnyClientsWriteBlocked = FALSE;
438bbe1b32bSmrg    FD_CLR(fd, &OutputPending);
439bbe1b32bSmrg    fsfree(oc);
440bbe1b32bSmrg}
441bbe1b32bSmrg
442bbe1b32bSmrgvoid
443bbe1b32bSmrgCheckConnections(void)
444bbe1b32bSmrg{
445bbe1b32bSmrg    fd_set      mask;
446bbe1b32bSmrg    fd_set      tmask;
447bbe1b32bSmrg    int         curclient;
448bbe1b32bSmrg    int         i;
449bbe1b32bSmrg    struct timeval notime;
450bbe1b32bSmrg    int         r;
451bbe1b32bSmrg
452bbe1b32bSmrg    notime.tv_sec = 0;
453bbe1b32bSmrg    notime.tv_usec = 0;
454bbe1b32bSmrg
455bbe1b32bSmrg    XFD_COPYSET(&AllClients, &mask);
456bbe1b32bSmrg    for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) {
457bbe1b32bSmrg	while (mask.fds_bits[i]) {
45830f8ce46Smrg	    curclient = xfd_ffs(mask.fds_bits[i]) - 1 + (i * (sizeof(fd_mask) * 8));
459bbe1b32bSmrg	    FD_ZERO(&tmask);
460bbe1b32bSmrg	    FD_SET(curclient, &tmask);
461bbe1b32bSmrg	    r = Select(curclient + 1, &tmask, NULL, NULL, &notime);
462bbe1b32bSmrg	    if (r < 0)
463bbe1b32bSmrg		CloseDownClient(clients[ConnectionTranslation[curclient]]);
464bbe1b32bSmrg	    FD_CLR(curclient, &mask);
465bbe1b32bSmrg	}
466bbe1b32bSmrg    }
467bbe1b32bSmrg}
468bbe1b32bSmrg
469bbe1b32bSmrgvoid
470bbe1b32bSmrgCloseDownConnection(ClientPtr client)
471bbe1b32bSmrg{
472bbe1b32bSmrg    OsCommPtr   oc = (OsCommPtr) client->osPrivate;
473bbe1b32bSmrg
474ce6676dbSmrg    if (oc == NULL)
475ce6676dbSmrg	return;
476ce6676dbSmrg
477bbe1b32bSmrg    if (oc->output && oc->output->count)
478bbe1b32bSmrg	FlushClient(client, oc, (char *) NULL, 0, 0);
479bbe1b32bSmrg    ConnectionTranslation[oc->fd] = 0;
480bbe1b32bSmrg    close_fd(oc);
481bbe1b32bSmrg    client->osPrivate = (pointer) NULL;
482bbe1b32bSmrg}
483bbe1b32bSmrg
484bbe1b32bSmrg
485bbe1b32bSmrg/****************
486bbe1b32bSmrg * IgnoreClient
487bbe1b32bSmrg *    Removes one client from input masks.
488bbe1b32bSmrg *    Must have cooresponding call to AttendClient.
489bbe1b32bSmrg ****************/
490bbe1b32bSmrg
491bbe1b32bSmrgstatic fd_set IgnoredClientsWithInput;
492bbe1b32bSmrg
493bbe1b32bSmrgvoid
494bbe1b32bSmrgIgnoreClient(ClientPtr client)
495bbe1b32bSmrg{
496bbe1b32bSmrg    OsCommPtr   oc = (OsCommPtr) client->osPrivate;
497bbe1b32bSmrg    int         connection = oc->fd;
498bbe1b32bSmrg
499bbe1b32bSmrg    if (FD_ISSET(connection, &ClientsWithInput))
500bbe1b32bSmrg	FD_SET(connection, &IgnoredClientsWithInput);
501bbe1b32bSmrg    else
502bbe1b32bSmrg	FD_CLR(connection, &IgnoredClientsWithInput);
503bbe1b32bSmrg    FD_CLR(connection, &ClientsWithInput);
504bbe1b32bSmrg    FD_CLR(connection, &AllSockets);
505bbe1b32bSmrg    FD_CLR(connection, &AllClients);
506bbe1b32bSmrg    FD_CLR(connection, &LastSelectMask);
507bbe1b32bSmrg    isItTimeToYield = TRUE;
508bbe1b32bSmrg}
509bbe1b32bSmrg
510bbe1b32bSmrg/****************
511bbe1b32bSmrg * AttendClient
512bbe1b32bSmrg *    Adds one client back into the input masks.
513bbe1b32bSmrg ****************/
514bbe1b32bSmrg
515bbe1b32bSmrgvoid
516bbe1b32bSmrgAttendClient(ClientPtr client)
517bbe1b32bSmrg{
518bbe1b32bSmrg    OsCommPtr   oc = (OsCommPtr) client->osPrivate;
519bbe1b32bSmrg    int         connection = oc->fd;
520bbe1b32bSmrg
521bbe1b32bSmrg    FD_SET(connection, &AllClients);
522bbe1b32bSmrg    FD_SET(connection, &AllSockets);
523bbe1b32bSmrg    FD_SET(connection, &LastSelectMask);
524bbe1b32bSmrg    if (FD_ISSET(connection, &IgnoredClientsWithInput))
525bbe1b32bSmrg	FD_SET(connection, &ClientsWithInput);
526bbe1b32bSmrg}
527bbe1b32bSmrg
528bbe1b32bSmrg/*
529bbe1b32bSmrg * figure out which clients need to be toasted
530bbe1b32bSmrg */
531bbe1b32bSmrgvoid
532bbe1b32bSmrgReapAnyOldClients(void)
533bbe1b32bSmrg{
534bbe1b32bSmrg    int         i;
535bbe1b32bSmrg    long        cur_time = GetTimeInMillis();
536bbe1b32bSmrg    ClientPtr   client;
537bbe1b32bSmrg
538bbe1b32bSmrg#ifdef DEBUG
539bbe1b32bSmrg    fprintf(stderr, "looking for clients to reap\n");
540bbe1b32bSmrg#endif
541bbe1b32bSmrg
542bbe1b32bSmrg    for (i = MINCLIENT; i < currentMaxClients; i++) {
543bbe1b32bSmrg	client = clients[i];
544bbe1b32bSmrg	if (client) {
545bbe1b32bSmrg	    if ((cur_time - client->last_request_time) >= ReapClientTime) {
546bbe1b32bSmrg		if (client->clientGone == CLIENT_AGED) {
547bbe1b32bSmrg		    client->clientGone = CLIENT_TIMED_OUT;
548bbe1b32bSmrg
549bbe1b32bSmrg#ifdef DEBUG
550bbe1b32bSmrg		    fprintf(stderr, "reaping client #%d\n", i);
551bbe1b32bSmrg#endif
552bbe1b32bSmrg
553bbe1b32bSmrg		    CloseDownClient(client);
554bbe1b32bSmrg		} else {
555bbe1b32bSmrg		    client->clientGone = CLIENT_AGED;
556bbe1b32bSmrg		    SendKeepAliveEvent(client);
557bbe1b32bSmrg		}
558bbe1b32bSmrg	    }
559bbe1b32bSmrg	}
560bbe1b32bSmrg    }
561bbe1b32bSmrg}
562