1a96d7823Smrg/*
2a96d7823Smrg * Copyright 1990 Network Computing Devices
3a96d7823Smrg *
4a96d7823Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5a96d7823Smrg * documentation for any purpose is hereby granted without fee, provided that
6a96d7823Smrg * the above copyright notice appear in all copies and that both that
7a96d7823Smrg * copyright notice and this permission notice appear in supporting
8a96d7823Smrg * documentation, and that the name of Network Computing Devices not be
9a96d7823Smrg * used in advertising or publicity pertaining to distribution of the
10a96d7823Smrg * software without specific, written prior permission.  Network Computing
11a96d7823Smrg * Devices makes no representations about the suitability of this software
12a96d7823Smrg * for any purpose.  It is provided "as is" without express or implied
13a96d7823Smrg * warranty.
14a96d7823Smrg *
15a96d7823Smrg * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16a96d7823Smrg * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
17a96d7823Smrg * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
18a96d7823Smrg * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19a96d7823Smrg * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
20a96d7823Smrg * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
21a96d7823Smrg * OR PERFORMANCE OF THIS SOFTWARE.
22a96d7823Smrg *
23a96d7823Smrg * Author:  	Dave Lemke, Network Computing Devices, Inc
24a96d7823Smrg */
25a96d7823Smrg/*
26a96d7823Smrg * font server i/o routines
27a96d7823Smrg */
28a96d7823Smrg
29a96d7823Smrg#ifdef HAVE_CONFIG_H
30a96d7823Smrg#include <config.h>
31a96d7823Smrg#endif
32a96d7823Smrg#include "libxfontint.h"
33a96d7823Smrg
34a96d7823Smrg#ifdef WIN32
35a96d7823Smrg#define _WILLWINSOCK_
36a96d7823Smrg#include	"X11/Xwindows.h"
37a96d7823Smrg#endif
38a96d7823Smrg
39a96d7823Smrg#define FONT_t
40a96d7823Smrg#define TRANS_CLIENT
41a96d7823Smrg#include 	"X11/Xtrans/Xtrans.h"
42a96d7823Smrg#include	"X11/Xpoll.h"
43a96d7823Smrg#include	<X11/fonts/FS.h>
44a96d7823Smrg#include	<X11/fonts/FSproto.h>
45a96d7823Smrg#include	<X11/fonts/fontmisc.h>
46a96d7823Smrg#include	<X11/fonts/fontstruct.h>
47a96d7823Smrg#include	"fservestr.h"
48a96d7823Smrg
49a96d7823Smrg#include	<stdio.h>
50a96d7823Smrg#include	<signal.h>
51a96d7823Smrg#include	<sys/types.h>
52a96d7823Smrg#if !defined(WIN32)
53a96d7823Smrg#include	<sys/socket.h>
54a96d7823Smrg#endif
55a96d7823Smrg#include	<errno.h>
56a96d7823Smrg#ifdef WIN32
57a96d7823Smrg#define EWOULDBLOCK WSAEWOULDBLOCK
58a96d7823Smrg#undef EINTR
59a96d7823Smrg#define EINTR WSAEINTR
60a96d7823Smrg#endif
61a96d7823Smrg
62a96d7823Smrg
63a96d7823Smrg
64a96d7823Smrgstatic int  padlength[4] = {0, 3, 2, 1};
65a96d7823Smrg
66a96d7823Smrgstatic int
67a96d7823Smrg_fs_resize (FSBufPtr buf, long size);
68a96d7823Smrg
69a96d7823Smrgstatic void
70a96d7823Smrg_fs_downsize (FSBufPtr buf, long size);
71a96d7823Smrg
72a96d7823Smrgint
73a96d7823Smrg_fs_poll_connect (XtransConnInfo trans_conn, int timeout)
74a96d7823Smrg{
75a96d7823Smrg    fd_set	    w_mask;
76a96d7823Smrg    struct timeval  tv;
77a96d7823Smrg    int		    fs_fd = _FontTransGetConnectionNumber (trans_conn);
78a96d7823Smrg    int		    ret;
79a96d7823Smrg
80a96d7823Smrg    do
81a96d7823Smrg    {
82a96d7823Smrg	tv.tv_usec = 0;
83a96d7823Smrg	tv.tv_sec = timeout;
84a96d7823Smrg	FD_ZERO (&w_mask);
85a96d7823Smrg	FD_SET (fs_fd, &w_mask);
86a96d7823Smrg	ret = Select (fs_fd + 1, NULL, &w_mask, NULL, &tv);
87a96d7823Smrg    } while (ret < 0 && ECHECK(EINTR));
88a96d7823Smrg    if (ret == 0)
89a96d7823Smrg	return FSIO_BLOCK;
90a96d7823Smrg    if (ret < 0)
91a96d7823Smrg	return FSIO_ERROR;
92a96d7823Smrg    return FSIO_READY;
93a96d7823Smrg}
94a96d7823Smrg
95a96d7823SmrgXtransConnInfo
96a96d7823Smrg_fs_connect(char *servername, int *err)
97a96d7823Smrg{
98a96d7823Smrg    XtransConnInfo  trans_conn;		/* transport connection object */
99a96d7823Smrg    int		    ret;
100a96d7823Smrg    int		    i = 0;
101a96d7823Smrg    int		    retries = 5;
102a96d7823Smrg
103a96d7823Smrg    /*
104a96d7823Smrg     * Open the network connection.
105a96d7823Smrg     */
106a96d7823Smrg    if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL )
107a96d7823Smrg    {
108a96d7823Smrg	*err = FSIO_ERROR;
109a96d7823Smrg	return 0;
110a96d7823Smrg    }
111a96d7823Smrg
112a96d7823Smrg    /*
113a96d7823Smrg     * Set the connection non-blocking since we use select() to block.
114a96d7823Smrg     */
115a96d7823Smrg
116a96d7823Smrg    _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1);
117a96d7823Smrg
118a96d7823Smrg    do {
119a96d7823Smrg	i = _FontTransConnect(trans_conn,servername);
120a96d7823Smrg    } while ((i == TRANS_TRY_CONNECT_AGAIN) && (retries-- > 0));
121a96d7823Smrg
122a96d7823Smrg    if (i < 0)
123a96d7823Smrg    {
124a96d7823Smrg	if (i == TRANS_IN_PROGRESS)
125a96d7823Smrg	    ret = FSIO_BLOCK;
126a96d7823Smrg	else
127a96d7823Smrg	    ret = FSIO_ERROR;
128a96d7823Smrg    }
129a96d7823Smrg    else
130a96d7823Smrg	ret = FSIO_READY;
131a96d7823Smrg
132a96d7823Smrg    if (ret == FSIO_ERROR)
133a96d7823Smrg    {
134a96d7823Smrg	_FontTransClose(trans_conn);
135a96d7823Smrg	trans_conn = 0;
136a96d7823Smrg    }
137a96d7823Smrg
138a96d7823Smrg    *err = ret;
139a96d7823Smrg    return trans_conn;
140a96d7823Smrg}
141a96d7823Smrg
142a96d7823Smrgstatic int
143a96d7823Smrg_fs_fill (FSFpePtr conn)
144a96d7823Smrg{
145a96d7823Smrg    long    avail;
146a96d7823Smrg    long    bytes_read;
147a96d7823Smrg    Bool    waited = FALSE;
148a96d7823Smrg
149a96d7823Smrg    if (_fs_flush (conn) < 0)
150a96d7823Smrg	return FSIO_ERROR;
151a96d7823Smrg    /*
152a96d7823Smrg     * Don't go overboard here; stop reading when we've
153a96d7823Smrg     * got enough to satisfy the pending request
154a96d7823Smrg     */
155a96d7823Smrg    while ((conn->inNeed - (conn->inBuf.insert - conn->inBuf.remove)) > 0)
156a96d7823Smrg    {
157a96d7823Smrg	avail = conn->inBuf.size - conn->inBuf.insert;
158a96d7823Smrg	/*
159a96d7823Smrg	 * For SVR4 with a unix-domain connection, ETEST() after selecting
160a96d7823Smrg	 * readable means the server has died.  To do this here, we look for
161a96d7823Smrg	 * two consecutive reads returning ETEST().
162a96d7823Smrg	 */
163a96d7823Smrg	ESET (0);
164a96d7823Smrg	bytes_read =_FontTransRead(conn->trans_conn,
165a96d7823Smrg				   conn->inBuf.buf + conn->inBuf.insert,
166a96d7823Smrg				   avail);
167a96d7823Smrg	if (bytes_read > 0) {
168a96d7823Smrg	    conn->inBuf.insert += bytes_read;
169a96d7823Smrg	    waited = FALSE;
170a96d7823Smrg	}
171a96d7823Smrg	else
172a96d7823Smrg	{
173a96d7823Smrg	    if (bytes_read == 0 || ETEST ())
174a96d7823Smrg	    {
175a96d7823Smrg		if (!waited)
176a96d7823Smrg		{
177a96d7823Smrg		    waited = TRUE;
178a96d7823Smrg		    if (_fs_wait_for_readable (conn, 0) == FSIO_BLOCK)
179a96d7823Smrg			return FSIO_BLOCK;
180a96d7823Smrg		    continue;
181a96d7823Smrg		}
182a96d7823Smrg	    }
183a96d7823Smrg	    if (!ECHECK(EINTR))
184a96d7823Smrg	    {
185a96d7823Smrg	        _fs_connection_died (conn);
186a96d7823Smrg	        return FSIO_ERROR;
187a96d7823Smrg	    }
188a96d7823Smrg	}
189a96d7823Smrg    }
190a96d7823Smrg    return FSIO_READY;
191a96d7823Smrg}
192a96d7823Smrg
193a96d7823Smrg/*
194a96d7823Smrg * Make space and return whether data have already arrived
195a96d7823Smrg */
196a96d7823Smrg
197a96d7823Smrgint
198a96d7823Smrg_fs_start_read (FSFpePtr conn, long size, char **buf)
199a96d7823Smrg{
200a96d7823Smrg    int	    ret;
201a96d7823Smrg
202a96d7823Smrg    conn->inNeed = size;
203a96d7823Smrg    if (fs_inqueued(conn) < size)
204a96d7823Smrg    {
205a96d7823Smrg	if (_fs_resize (&conn->inBuf, size) != FSIO_READY)
206a96d7823Smrg	{
207a96d7823Smrg	    _fs_connection_died (conn);
208a96d7823Smrg	    return FSIO_ERROR;
209a96d7823Smrg	}
210a96d7823Smrg	ret = _fs_fill (conn);
211a96d7823Smrg	if (ret == FSIO_ERROR)
212a96d7823Smrg	    return ret;
213a96d7823Smrg	if (ret == FSIO_BLOCK || fs_inqueued(conn) < size)
214a96d7823Smrg	    return FSIO_BLOCK;
215a96d7823Smrg    }
216a96d7823Smrg    if (buf)
217a96d7823Smrg	*buf = conn->inBuf.buf + conn->inBuf.remove;
218a96d7823Smrg    return FSIO_READY;
219a96d7823Smrg}
220a96d7823Smrg
221a96d7823Smrgvoid
222a96d7823Smrg_fs_done_read (FSFpePtr conn, long size)
223a96d7823Smrg{
224a96d7823Smrg    if (conn->inBuf.insert - conn->inBuf.remove < size)
225a96d7823Smrg    {
226a96d7823Smrg#ifdef DEBUG
227a96d7823Smrg	fprintf (stderr, "_fs_done_read skipping to many bytes\n");
228a96d7823Smrg#endif
229a96d7823Smrg	return;
230a96d7823Smrg    }
231a96d7823Smrg    conn->inBuf.remove += size;
232a96d7823Smrg    conn->inNeed -= size;
233a96d7823Smrg    _fs_downsize (&conn->inBuf, FS_BUF_MAX);
234a96d7823Smrg}
235a96d7823Smrg
236a96d7823Smrglong
237a96d7823Smrg_fs_pad_length (long len)
238a96d7823Smrg{
239a96d7823Smrg    return len + padlength[len&3];
240a96d7823Smrg}
241a96d7823Smrg
242a96d7823Smrgint
243a96d7823Smrg_fs_flush (FSFpePtr conn)
244a96d7823Smrg{
245a96d7823Smrg    long    bytes_written;
246a96d7823Smrg    long    remain;
247a96d7823Smrg
248a96d7823Smrg    /* XXX - hack.  The right fix is to remember that the font server
249a96d7823Smrg       has gone away when we first discovered it. */
250a96d7823Smrg    if (conn->fs_fd < 0)
251a96d7823Smrg	return FSIO_ERROR;
252a96d7823Smrg
253a96d7823Smrg    while ((remain = conn->outBuf.insert - conn->outBuf.remove) > 0)
254a96d7823Smrg    {
255a96d7823Smrg	bytes_written = _FontTransWrite(conn->trans_conn,
256a96d7823Smrg					conn->outBuf.buf + conn->outBuf.remove,
257a96d7823Smrg					(int) remain);
258a96d7823Smrg	if (bytes_written > 0)
259a96d7823Smrg	{
260a96d7823Smrg	    conn->outBuf.remove += bytes_written;
261a96d7823Smrg	}
262a96d7823Smrg	else
263a96d7823Smrg	{
264a96d7823Smrg	    if (bytes_written == 0 || ETEST ())
265a96d7823Smrg	    {
266a96d7823Smrg		conn->brokenWriteTime = GetTimeInMillis () + FS_FLUSH_POLL;
267a96d7823Smrg		_fs_mark_block (conn, FS_BROKEN_WRITE);
268a96d7823Smrg		break;
269a96d7823Smrg	    }
270a96d7823Smrg	    if (!ECHECK (EINTR))
271a96d7823Smrg	    {
272a96d7823Smrg		_fs_connection_died (conn);
273a96d7823Smrg		return FSIO_ERROR;
274a96d7823Smrg	    }
275a96d7823Smrg	}
276a96d7823Smrg    }
277a96d7823Smrg    if (conn->outBuf.remove == conn->outBuf.insert)
278a96d7823Smrg    {
279a96d7823Smrg	_fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE);
280a96d7823Smrg	if (conn->outBuf.size > FS_BUF_INC)
281a96d7823Smrg	    conn->outBuf.buf = realloc (conn->outBuf.buf, FS_BUF_INC);
282a96d7823Smrg	conn->outBuf.remove = conn->outBuf.insert = 0;
283a96d7823Smrg    }
284a96d7823Smrg    return FSIO_READY;
285a96d7823Smrg}
286a96d7823Smrg
287a96d7823Smrgstatic int
288a96d7823Smrg_fs_resize (FSBufPtr buf, long size)
289a96d7823Smrg{
290a96d7823Smrg    char    *new;
291a96d7823Smrg    long    new_size;
292a96d7823Smrg
293a96d7823Smrg    if (buf->remove)
294a96d7823Smrg    {
295a96d7823Smrg	if (buf->remove != buf->insert)
296a96d7823Smrg	{
297a96d7823Smrg	    memmove (buf->buf,
298a96d7823Smrg		     buf->buf + buf->remove,
299a96d7823Smrg		     buf->insert - buf->remove);
300a96d7823Smrg	}
301a96d7823Smrg	buf->insert -= buf->remove;
302a96d7823Smrg	buf->remove = 0;
303a96d7823Smrg    }
304a96d7823Smrg    if (buf->size - buf->remove < size)
305a96d7823Smrg    {
306a96d7823Smrg	new_size = ((buf->remove + size + FS_BUF_INC) / FS_BUF_INC) * FS_BUF_INC;
307a96d7823Smrg	new = realloc (buf->buf, new_size);
308a96d7823Smrg	if (!new)
309a96d7823Smrg	    return FSIO_ERROR;
310a96d7823Smrg	buf->buf = new;
311a96d7823Smrg	buf->size = new_size;
312a96d7823Smrg    }
313a96d7823Smrg    return FSIO_READY;
314a96d7823Smrg}
315a96d7823Smrg
316a96d7823Smrgstatic void
317a96d7823Smrg_fs_downsize (FSBufPtr buf, long size)
318a96d7823Smrg{
319a96d7823Smrg    if (buf->insert == buf->remove)
320a96d7823Smrg    {
321a96d7823Smrg	buf->insert = buf->remove = 0;
322a96d7823Smrg	if (buf->size > size)
323a96d7823Smrg	{
324a96d7823Smrg	    buf->buf = realloc (buf->buf, size);
325a96d7823Smrg	    buf->size = size;
326a96d7823Smrg	}
327a96d7823Smrg    }
328a96d7823Smrg}
329a96d7823Smrg
330a96d7823Smrgvoid
331a96d7823Smrg_fs_io_reinit (FSFpePtr conn)
332a96d7823Smrg{
333a96d7823Smrg    conn->outBuf.insert = conn->outBuf.remove = 0;
334a96d7823Smrg    _fs_downsize (&conn->outBuf, FS_BUF_INC);
335a96d7823Smrg    conn->inBuf.insert = conn->inBuf.remove = 0;
336a96d7823Smrg    _fs_downsize (&conn->inBuf, FS_BUF_MAX);
337a96d7823Smrg}
338a96d7823Smrg
339a96d7823SmrgBool
340a96d7823Smrg_fs_io_init (FSFpePtr conn)
341a96d7823Smrg{
342a96d7823Smrg    conn->outBuf.insert = conn->outBuf.remove = 0;
343a96d7823Smrg    conn->outBuf.buf = malloc (FS_BUF_INC);
344a96d7823Smrg    if (!conn->outBuf.buf)
345a96d7823Smrg	return FALSE;
346a96d7823Smrg    conn->outBuf.size = FS_BUF_INC;
347a96d7823Smrg
348a96d7823Smrg    conn->inBuf.insert = conn->inBuf.remove = 0;
349a96d7823Smrg    conn->inBuf.buf = malloc (FS_BUF_INC);
350a96d7823Smrg    if (!conn->inBuf.buf)
351a96d7823Smrg    {
352a96d7823Smrg	free (conn->outBuf.buf);
353a96d7823Smrg	conn->outBuf.buf = 0;
354a96d7823Smrg	return FALSE;
355a96d7823Smrg    }
356a96d7823Smrg    conn->inBuf.size = FS_BUF_INC;
357a96d7823Smrg
358a96d7823Smrg    return TRUE;
359a96d7823Smrg}
360a96d7823Smrg
361a96d7823Smrgvoid
362a96d7823Smrg_fs_io_fini (FSFpePtr conn)
363a96d7823Smrg{
364a96d7823Smrg    if (conn->outBuf.buf)
365a96d7823Smrg	free (conn->outBuf.buf);
366a96d7823Smrg    if (conn->inBuf.buf)
367a96d7823Smrg	free (conn->inBuf.buf);
368a96d7823Smrg}
369a96d7823Smrg
370a96d7823Smrgstatic int
371a96d7823Smrg_fs_do_write(FSFpePtr conn, const char *data, long len, long size)
372a96d7823Smrg{
373a96d7823Smrg    if (size == 0) {
374a96d7823Smrg#ifdef DEBUG
375a96d7823Smrg	fprintf(stderr, "tried to write 0 bytes \n");
376a96d7823Smrg#endif
377a96d7823Smrg	return FSIO_READY;
378a96d7823Smrg    }
379a96d7823Smrg
380a96d7823Smrg    if (conn->fs_fd == -1)
381a96d7823Smrg	return FSIO_ERROR;
382a96d7823Smrg
383a96d7823Smrg    while (conn->outBuf.insert + size > conn->outBuf.size)
384a96d7823Smrg    {
385a96d7823Smrg	if (_fs_flush (conn) < 0)
386a96d7823Smrg	    return FSIO_ERROR;
387a96d7823Smrg	if (_fs_resize (&conn->outBuf, size) < 0)
388a96d7823Smrg	{
389a96d7823Smrg	    _fs_connection_died (conn);
390a96d7823Smrg	    return FSIO_ERROR;
391a96d7823Smrg	}
392a96d7823Smrg    }
393a96d7823Smrg    memcpy (conn->outBuf.buf + conn->outBuf.insert, data, len);
394a96d7823Smrg    /* Clear pad data */
395a96d7823Smrg    memset (conn->outBuf.buf + conn->outBuf.insert + len, 0, size - len);
396a96d7823Smrg    conn->outBuf.insert += size;
397a96d7823Smrg    _fs_mark_block (conn, FS_PENDING_WRITE);
398a96d7823Smrg    return FSIO_READY;
399a96d7823Smrg}
400a96d7823Smrg
401a96d7823Smrg/*
402a96d7823Smrg * Write the indicated bytes
403a96d7823Smrg */
404a96d7823Smrgint
405a96d7823Smrg_fs_write (FSFpePtr conn, const char *data, long len)
406a96d7823Smrg{
407a96d7823Smrg    return _fs_do_write (conn, data, len, len);
408a96d7823Smrg}
409a96d7823Smrg
410a96d7823Smrg/*
411a96d7823Smrg * Write the indicated bytes adding any appropriate pad
412a96d7823Smrg */
413a96d7823Smrgint
414a96d7823Smrg_fs_write_pad(FSFpePtr conn, const char *data, long len)
415a96d7823Smrg{
416a96d7823Smrg    return _fs_do_write (conn, data, len, len + padlength[len & 3]);
417a96d7823Smrg}
418a96d7823Smrg
419a96d7823Smrgint
420a96d7823Smrg_fs_wait_for_readable(FSFpePtr conn, int ms)
421a96d7823Smrg{
422a96d7823Smrg    fd_set	r_mask;
423a96d7823Smrg    fd_set	e_mask;
424a96d7823Smrg    int         result;
425a96d7823Smrg    struct timeval  tv;
426a96d7823Smrg
427a96d7823Smrg    for (;;) {
428a96d7823Smrg	if (conn->fs_fd < 0)
429a96d7823Smrg	    return FSIO_ERROR;
430a96d7823Smrg	FD_ZERO(&r_mask);
431a96d7823Smrg	FD_ZERO(&e_mask);
432a96d7823Smrg	tv.tv_sec = ms / 1000;
433a96d7823Smrg	tv.tv_usec = (ms % 1000) * 1000;
434a96d7823Smrg	FD_SET(conn->fs_fd, &r_mask);
435a96d7823Smrg	FD_SET(conn->fs_fd, &e_mask);
436a96d7823Smrg	result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, &tv);
437a96d7823Smrg	if (result < 0)
438a96d7823Smrg	{
439a96d7823Smrg	    if (ECHECK(EINTR) || ECHECK(EAGAIN))
440a96d7823Smrg		continue;
441a96d7823Smrg	    else
442a96d7823Smrg		return FSIO_ERROR;
443a96d7823Smrg	}
444a96d7823Smrg	if (result == 0)
445a96d7823Smrg	    return FSIO_BLOCK;
446a96d7823Smrg	if (FD_ISSET(conn->fs_fd, &r_mask))
447a96d7823Smrg	    return FSIO_READY;
448a96d7823Smrg	return FSIO_ERROR;
449a96d7823Smrg    }
450a96d7823Smrg}
451