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