diff options
Diffstat (limited to 'doc/nx-X11_vs_XOrg69_patches/XlibInt.c.NX.patch')
-rw-r--r-- | doc/nx-X11_vs_XOrg69_patches/XlibInt.c.NX.patch | 1165 |
1 files changed, 1165 insertions, 0 deletions
diff --git a/doc/nx-X11_vs_XOrg69_patches/XlibInt.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/XlibInt.c.NX.patch new file mode 100644 index 000000000..b76e169ee --- /dev/null +++ b/doc/nx-X11_vs_XOrg69_patches/XlibInt.c.NX.patch @@ -0,0 +1,1165 @@ +--- ./nx-X11/lib/X11/XlibInt.c.X.original 2015-02-13 14:03:44.624443872 +0100 ++++ ./nx-X11/lib/X11/XlibInt.c 2015-02-10 19:13:12.800723493 +0100 +@@ -26,6 +26,24 @@ + from The Open Group. + + */ ++ ++/**************************************************************************/ ++/* */ ++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */ ++/* */ ++/* NX-X11, NX protocol compression and NX extensions to this software */ ++/* are copyright of NoMachine. Redistribution and use of the present */ ++/* software is allowed according to terms specified in the file LICENSE */ ++/* which comes in the source distribution. */ ++/* */ ++/* Check http://www.nomachine.com/licensing.html for applicability. */ ++/* */ ++/* NX and NoMachine are trademarks of Medialogic S.p.A. */ ++/* */ ++/* All rights reserved. */ ++/* */ ++/**************************************************************************/ ++ + /* $XFree86: xc/lib/X11/XlibInt.c,v 3.38 2003/10/30 21:55:05 alanh Exp $ */ + + /* +@@ -100,6 +118,34 @@ + + #endif /* XTHREADS else */ + ++#include "NX.h" ++ ++#ifdef NX_TRANS_SOCKET ++ ++#include "NX.h" ++#include "NXvars.h" ++ ++static struct timeval retry; ++ ++/* ++ * From Xtranssock.c. Presently the congestion state ++ * is reported by the proxy to the application, by ++ * invoking the callback directly. The function will ++ * be possibly used in the future, to be able to track ++ * the bandwidth usage even when the NX transport is ++ * not running. Note that in this sample implementation ++ * the congestion state is checked very often and can ++ * be surely optimized. ++ */ ++ ++#ifdef NX_TRANS_CHANGE ++ ++extern int _X11TransSocketCongestionChange(XtransConnInfo, int *); ++ ++#endif ++ ++#endif /* #ifdef NX_TRANS_SOCKET */ ++ + /* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX + * systems are broken and return EWOULDBLOCK when they should return EAGAIN + */ +@@ -219,6 +265,100 @@ + 0, 0, 0 + }; + ++#ifdef NX_TRANS_SOCKET ++ ++/* ++ * Replace the standard Select with a version giving NX a ++ * chance to check its own descriptors. This doesn't cover ++ * the cases where the system is using poll or when system- ++ * specific defines override the Select definition (OS/2). ++ */ ++ ++int _XSelect(int maxfds, fd_set *readfds, fd_set *writefds, ++ fd_set *exceptfds, struct timeval *timeout) ++{ ++#ifdef NX_TRANS_TEST ++ fprintf(stderr, "_XSelect: Called with [%d][%p][%p][%p][%p].\n", ++ maxfds, (void *) readfds, (void *) writefds, (void *) exceptfds, ++ (void *) timeout); ++#endif ++ ++ if (NXTransRunning(NX_FD_ANY)) ++ { ++ fd_set t_readfds, t_writefds; ++ struct timeval t_timeout; ++ ++ int n, r, e; ++ ++#ifdef NX_TRANS_TEST ++ ++ if (exceptfds != NULL) ++ { ++ fprintf(stderr, "_XSelect: WARNING! Can't handle exception fds in select.\n"); ++ } ++ ++#endif ++ ++ if (readfds == NULL) ++ { ++ FD_ZERO(&t_readfds); ++ ++ readfds = &t_readfds; ++ } ++ ++ if (writefds == NULL) ++ { ++ FD_ZERO(&t_writefds); ++ ++ writefds = &t_writefds; ++ } ++ ++ if (timeout == NULL) ++ { ++ t_timeout.tv_sec = 10; ++ t_timeout.tv_usec = 0; ++ ++ timeout = &t_timeout; ++ } ++ ++ n = maxfds; ++ ++ /* ++ * If the transport is gone avoid ++ * sleeping until the timeout. ++ */ ++ ++ if (NXTransPrepare(&n, readfds, writefds, timeout) != 0) ++ { ++ NXTransSelect(&r, &e, &n, readfds, writefds, timeout); ++ ++ NXTransExecute(&r, &e, &n, readfds, writefds, timeout); ++ ++ errno = e; ++ ++ return r; ++ } ++ else ++ { ++ return 0; ++ } ++ } ++ else ++ { ++ return select(maxfds, readfds, writefds, exceptfds, timeout); ++ } ++} ++ ++#else /* #ifdef NX_TRANS_SOCKET */ ++ ++int _XSelect(int maxfds, fd_set *readfds, fd_set *writefds, ++ fd_set *exceptfds, struct timeval *timeout) ++{ ++ return select(maxfds, readfds, writefds, exceptfds, timeout); ++} ++ ++#endif /* #ifdef NX_TRANS_SOCKET */ ++ + /* + * This is an OS dependent routine which: + * 1) returns as soon as the connection can be written on.... +@@ -242,6 +382,18 @@ + #endif + int nfound; + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) ++ int congestion; ++#endif ++ ++#ifdef NX_TRANS_SOCKET ++ ++ if (_XGetIOError(dpy)) { ++ return; ++ } ++ ++#endif ++ + #ifdef USE_POLL + filedes.fd = dpy->fd; + filedes.events = 0; +@@ -276,6 +428,8 @@ + (!dpy->lock->reply_awaiters || + dpy->lock->reply_awaiters->cv == cv))) + #endif ++ ++#ifndef NX_TRANS_SOCKET + #ifdef USE_POLL + filedes.events = POLLIN; + filedes.events |= POLLOUT; +@@ -283,17 +437,109 @@ + FD_SET(dpy->fd, &r_mask); + FD_SET(dpy->fd, &w_mask); + #endif ++#endif /* #ifndef NX_TRANS_SOCKET */ + + do { ++#ifdef NX_TRANS_SOCKET ++ /* ++ * Give a chance to the registered client to perform ++ * any needed operation before entering the select. ++ */ ++ ++#ifdef NX_TRANS_TEST ++ fprintf(stderr, "_XWaitForWritable: WAIT! Waiting for the display to become writable.\n"); ++#endif ++ NXTransFlush(dpy->fd); ++ ++ if (_NXDisplayBlockFunction != NULL) { ++ (*_NXDisplayBlockFunction)(dpy, NXBlockWrite); ++ } ++ ++ /* ++ * Need to set again the descriptors as we could have ++ * run multiple selects before having the possibility ++ * to read or write to the X connection. ++ */ ++ ++#ifdef USE_POLL ++ filedes.events = POLLIN; ++ filedes.events |= POLLOUT; ++#else ++ FD_SET(dpy->fd, &r_mask); ++ FD_SET(dpy->fd, &w_mask); ++#endif ++#endif /* #ifdef NX_TRANS_SOCKET */ ++ + UnlockDisplay(dpy); + #ifdef USE_POLL ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XWaitForWritable: Calling poll().\n"); ++#endif + nfound = poll (&filedes, 1, -1); + #else ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XWaitForWritable: Calling select() after [%ld] ms.\n", ++ NXTransTime()); ++#endif ++#ifdef NX_TRANS_SOCKET ++ /* ++ * Give a chance to the callback to detect ++ * the failure of the display even if we ++ * miss the interrupt inside the select. ++ */ ++ ++ if (_NXDisplayErrorFunction != NULL) { ++ retry.tv_sec = 5; ++ retry.tv_usec = 0; ++ nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, &retry); ++ } else { ++ nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL); ++ } ++#else + nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL); + #endif ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XWaitForWritable: Out of select() with [%d] after [%ld] ms.\n", ++ nfound, NXTransTime()); ++ ++ if (FD_ISSET(dpy->fd, &r_mask)) ++ { ++ BytesReadable_t pend; ++ ++ _X11TransBytesReadable(dpy->trans_conn, &pend); ++ ++ fprintf(stderr, "_XWaitForWritable: Descriptor [%d] is ready with [%ld] bytes to read.\n", ++ dpy->fd, pend); ++ } ++ ++ if (FD_ISSET(dpy->fd, &w_mask)) ++ { ++ fprintf(stderr, "_XWaitForWritable: Descriptor [%d] has become writable.\n\n", ++ dpy->fd); ++ } ++#endif ++#endif + InternalLockDisplay(dpy, cv != NULL); +- if (nfound < 0 && !ECHECK(EINTR)) ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) ++ if (_NXDisplayCongestionFunction != NULL && ++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { ++ (*_NXDisplayCongestionFunction)(dpy, congestion); ++ } ++#endif ++ ++#ifdef NX_TRANS_SOCKET ++ if (nfound <= 0) { ++ if ((nfound == -1 && !ECHECK(EINTR)) || ++ (_NXDisplayErrorFunction != NULL && ++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { ++ _XIOError(dpy); ++ return; ++ } ++ } ++#else ++ if (nfound < 0 && !ECHECK(EINTR)) + _XIOError(dpy); ++#endif + } while (nfound <= 0); + + if ( +@@ -311,7 +557,15 @@ + + /* find out how much data can be read */ + if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) ++#ifdef NX_TRANS_SOCKET ++ { ++ _XIOError(dpy); ++ ++ return; ++ } ++#else + _XIOError(dpy); ++#endif + len = pend; + + /* must read at least one xEvent; if none is pending, then +@@ -464,6 +718,15 @@ + int highest_fd = fd; + #endif + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) ++ int congestion; ++#endif ++#ifdef NX_TRANS_SOCKET ++ if (_XGetIOError(dpy)) { ++ return -1; ++ } ++#endif ++ + #ifdef USE_POLL + if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE + && !(dpy->flags & XlibDisplayProcConni)) { +@@ -495,16 +758,68 @@ + #endif + UnlockDisplay(dpy); + #ifdef USE_POLL ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XWaitForReadable: Calling poll().\n"); ++#endif + result = poll(filedes, + (dpy->flags & XlibDisplayProcConni) ? 1 : 1+dpy->im_fd_length, + -1); + #else ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XWaitForReadable: Calling select().\n"); ++#endif ++#ifdef NX_TRANS_SOCKET ++ /* ++ * Give a chance to the registered application ++ * to perform any needed operation. ++ */ ++ ++#ifdef NX_TRANS_TEST ++ fprintf(stderr, "_XWaitForReadable: WAIT! Waiting for the display to become readable.\n"); ++#endif ++ NXTransFlush(dpy->fd); ++ ++ if (_NXDisplayBlockFunction != NULL) { ++ (*_NXDisplayBlockFunction)(dpy, NXBlockRead); ++ } ++ ++ if (_NXDisplayErrorFunction != NULL) { ++ retry.tv_sec = 5; ++ retry.tv_usec = 0; ++ result = Select(highest_fd + 1, &r_mask, NULL, NULL, &retry); ++ } else { ++ result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL); ++ } ++#else + result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL); + #endif ++#endif ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XWaitForReadable: Out of select with result [%d] and errno [%d].\n", ++ result, (result < 0 ? errno : 0)); ++#endif + InternalLockDisplay(dpy, dpy->flags & XlibDisplayReply); ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) ++ if (_NXDisplayCongestionFunction != NULL && ++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { ++ (*_NXDisplayCongestionFunction)(dpy, congestion); ++ } ++#endif ++#ifdef NX_TRANS_SOCKET ++ if (result <= 0) { ++ if ((result == -1 && !ECHECK(EINTR)) || ++ (_NXDisplayErrorFunction != NULL && ++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { ++ _XIOError(dpy); ++ return -1; ++ } ++ continue; ++ } ++#else + if (result == -1 && !ECHECK(EINTR)) _XIOError(dpy); + if (result <= 0) + continue; ++#endif + #ifdef USE_POLL + if (filedes[0].revents & (POLLIN|POLLHUP|POLLERR)) + #else +@@ -562,6 +877,19 @@ + xGetInputFocusReply rep; + register xReq *req; + ++#ifdef NX_TRANS_SOCKET ++#ifdef NX_TRANS_DEBUG ++ fprintf(stderr, "_XSeqSyncFunction: Going to synchronize the display.\n"); ++#endif ++ if (dpy->flags & XlibDisplayIOError) ++ { ++#ifdef NX_TRANS_DEBUG ++ fprintf(stderr, "_XSeqSyncFunction: Returning 0 with I/O error detected.\n"); ++#endif ++ return 0; ++ } ++#endif ++ + LockDisplay(dpy); + if ((dpy->request - dpy->last_request_read) >= (BUFSIZE / SIZEOF(xReq))) { + GetEmptyReq(GetInputFocus, req); +@@ -611,7 +939,14 @@ + register int write_stat; + register char *bufindex; + _XExtension *ext; ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) ++ int congestion; ++#endif + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XFlushInt: Entering flush with [%d] bytes to write.\n", ++ (dpy->bufptr - dpy->buffer)); ++#endif + /* This fix resets the bufptr to the front of the buffer so + * additional appends to the bufptr will not corrupt memory. Since + * the server is down, these appends are no-op's anyway but +@@ -619,13 +954,23 @@ + */ + if (dpy->flags & XlibDisplayIOError) + { ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XFlushInt: Returning with I/O error detected.\n"); ++#endif + dpy->bufptr = dpy->buffer; + dpy->last_req = (char *)&_dummy_request; + return; + } + + #ifdef XTHREADS ++#ifdef NX_TRANS_SOCKET ++ while (dpy->flags & XlibDisplayWriting) { ++ if (_XGetIOError(dpy)) { ++ return; ++ } ++#else + while (dpy->flags & XlibDisplayWriting) { ++#endif + if (dpy->lock) { + ConditionWait(dpy, dpy->lock->writers); + } else { +@@ -653,6 +998,17 @@ + write_stat = _X11TransWrite(dpy->trans_conn, + bufindex, (int) todo); + if (write_stat >= 0) { ++#ifdef NX_TRANS_SOCKET ++ if (_NXDisplayWriteFunction != NULL) { ++ (*_NXDisplayWriteFunction)(dpy, write_stat); ++ } ++#ifdef NX_TRANS_CHANGE ++ if (_NXDisplayCongestionFunction != NULL && ++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { ++ (*_NXDisplayCongestionFunction)(dpy, congestion); ++ } ++#endif ++#endif + size -= write_stat; + todo = size; + bufindex += write_stat; +@@ -682,11 +1038,25 @@ + ); + } + #endif ++#ifdef NX_TRANS_SOCKET ++ } else if (!ECHECK(EINTR) || ++ (_NXDisplayErrorFunction != NULL && ++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { ++ _XIOError(dpy); ++ return; ++ } ++#else + } else if (!ECHECK(EINTR)) { + /* Write failed! */ + /* errno set by write system call. */ + _XIOError(dpy); + } ++#endif ++#ifdef NX_TRANS_SOCKET ++ if (_XGetIOError(dpy)) { ++ return; ++ } ++#endif + } + dpy->last_req = (char *)&_dummy_request; + if ((dpy->request - dpy->last_request_read) >= SEQLIMIT && +@@ -727,6 +1097,12 @@ + if (dpy->qlen) + return(dpy->qlen); + } ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ if (dpy->flags & XlibDisplayIOError) { ++ fprintf(stderr, "_XEventsQueued: Returning [%d] after display failure.\n", ++ dpy->qlen); ++ } ++#endif + if (dpy->flags & XlibDisplayIOError) return(dpy->qlen); + + #ifdef XTHREADS +@@ -767,8 +1143,19 @@ + } + #endif /* XTHREADS*/ + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XEventsQueued: Checking bytes readable.\n"); ++#endif + if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) ++#ifdef NX_TRANS_SOCKET ++ { ++ _XIOError(dpy); ++ ++ return (dpy->qlen); ++ } ++#else + _XIOError(dpy); ++#endif + #ifdef XCONN_CHECK_FREQ + /* This is a crock, required because FIONREAD or equivalent is + * not guaranteed to detect a broken connection. +@@ -785,10 +1172,16 @@ + + dpy->conn_checker = 0; + #ifdef USE_POLL ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XEventsQueued: Calling poll().\n"); ++#endif + filedes.fd = dpy->fd; + filedes.events = POLLIN; + if ((result = poll(&filedes, 1, 0))) + #else ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XEventsQueued: Calling select().\n"); ++#endif + FD_ZERO(&r_mask); + FD_SET(dpy->fd, &r_mask); + if ((result = Select(dpy->fd + 1, &r_mask, NULL, NULL, &zero_time))) +@@ -797,13 +1190,32 @@ + if (result > 0) + { + if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) ++#ifdef NX_TRANS_SOCKET ++ { ++ _XIOError(dpy); ++ ++ return (dpy->qlen); ++ } ++#else + _XIOError(dpy); ++#endif + /* we should not get zero, if we do, force a read */ + if (!pend) + pend = SIZEOF(xReply); + } ++#ifdef NX_TRANS_SOCKET ++ if (result <= 0) { ++ if ((result == -1 && !ECHECK(EINTR)) || ++ (_NXDisplayErrorFunction != NULL && ++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { ++ _XIOError(dpy); ++ return (dpy->qlen); ++ } ++ } ++#else + else if (result < 0 && !ECHECK(EINTR)) + _XIOError(dpy); ++#endif + } + } + #endif /* XCONN_CHECK_FREQ */ +@@ -815,6 +1227,10 @@ + { + UnlockNextEventReader(dpy); + } ++ ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XEventsQueued: Returning [%d].\n", dpy->qlen); ++#endif + return(dpy->qlen); + } + /* Force a read if there is not enough data. Otherwise, +@@ -847,6 +1263,11 @@ + + (void) _XRead (dpy, read_buf, (long) len); + ++#ifdef NX_TRANS_SOCKET ++ if (_XGetIOError(dpy)) { ++ return(dpy->qlen); ++ } ++#endif + #ifdef XTHREADS + /* what did we actually read: reply or event? */ + if (dpy->lock && dpy->lock->reply_awaiters) { +@@ -945,7 +1366,15 @@ + #endif /* XTHREADS */ + /* find out how much data can be read */ + if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) ++#ifdef NX_TRANS_SOCKET ++ { ++ _XIOError(dpy); ++ ++ return; ++ } ++#else + _XIOError(dpy); ++#endif + len = pend; + + /* must read at least one xEvent; if none is pending, then +@@ -995,6 +1424,15 @@ + dpy->flags |= XlibDisplayReadEvents; + i = _XRead (dpy, read_buf, (long) len); + dpy->flags &= ~XlibDisplayReadEvents; ++#ifdef NX_TRANS_SOCKET ++ if (dpy->flags & XlibDisplayIOError) ++ { ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XReadEvents: Returning with I/O error detected.\n"); ++#endif ++ return; ++ } ++#endif + if (i == -2) { + /* special flag from _XRead to say that internal connection has + done XPutBackEvent. Which we can use so we're done. */ +@@ -1065,12 +1503,33 @@ + #ifdef XTHREADS + int original_size = size; + #endif ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) ++ int congestion; ++#endif + + if ((dpy->flags & XlibDisplayIOError) || size == 0) + return 0; + ESET(0); ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) ++ while (1) { ++ /* ++ * Need to check the congestion state ++ * after the read so split the statement ++ * in multiple blocks. ++ */ ++ ++ bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size); ++ if (_NXDisplayCongestionFunction != NULL && ++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { ++ (*_NXDisplayCongestionFunction)(dpy, congestion); ++ } ++ if (bytes_read == size) { ++ break; ++ } ++#else + while ((bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size)) + != size) { ++#endif + + if (bytes_read > 0) { + size -= bytes_read; +@@ -1090,14 +1549,34 @@ + else if (bytes_read == 0) { + /* Read failed because of end of file! */ + ESET(EPIPE); ++#ifdef NX_TRANS_SOCKET ++ _XIOError(dpy); ++ ++ return -1; ++#else + _XIOError(dpy); ++#endif + } + + else /* bytes_read is less than 0; presumably -1 */ { + /* If it's a system call interrupt, it's not an error. */ ++#ifdef NX_TRANS_SOCKET ++ if (!ECHECK(EINTR) || ++ (_NXDisplayErrorFunction != NULL && ++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { ++ _XIOError(dpy); ++ return -1; ++ } ++#else + if (!ECHECK(EINTR)) + _XIOError(dpy); ++#endif + } ++#ifdef NX_TRANS_SOCKET ++ if (_XGetIOError(dpy)) { ++ return -1; ++ } ++#endif + } + #ifdef XTHREADS + if (dpy->lock && dpy->lock->reply_bytes_left > 0) +@@ -1268,6 +1747,9 @@ + #ifdef XTHREADS + int original_size; + #endif ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) ++ int congestion; ++#endif + + if ((dpy->flags & XlibDisplayIOError) || size == 0) return; + iov[0].iov_len = (int)size; +@@ -1285,7 +1767,19 @@ + original_size = size; + #endif + ESET(0); ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) ++ while (1) { ++ bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2); ++ if (_NXDisplayCongestionFunction != NULL && ++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { ++ (*_NXDisplayCongestionFunction)(dpy, congestion); ++ } ++ if (bytes_read == size) { ++ break; ++ } ++#else + while ((bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2)) != size) { ++#endif + + if (bytes_read > 0) { + size -= bytes_read; +@@ -1313,14 +1807,34 @@ + else if (bytes_read == 0) { + /* Read failed because of end of file! */ + ESET(EPIPE); ++#ifdef NX_TRANS_SOCKET ++ _XIOError(dpy); ++ ++ return; ++#else + _XIOError(dpy); ++#endif + } + + else /* bytes_read is less than 0; presumably -1 */ { + /* If it's a system call interrupt, it's not an error. */ ++#ifdef NX_TRANS_SOCKET ++ if (!ECHECK(EINTR) || ++ (_NXDisplayErrorFunction != NULL && ++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { ++ _XIOError(dpy); ++ return; ++ } ++#else + if (!ECHECK(EINTR)) + _XIOError(dpy); ++#endif + } ++#ifdef NX_TRANS_SOCKET ++ if (_XGetIOError(dpy)) { ++ return; ++ } ++#endif + } + #ifdef XTHREADS + if (dpy->lock && dpy->lock->reply_bytes_left > 0) +@@ -1351,8 +1865,31 @@ + + long skip, dbufsize, padsize, total, todo; + _XExtension *ext; ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) ++ int congestion; ++#endif ++ ++#ifdef NX_TRANS_SOCKET ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XSend: Sending data with [%d] bytes to write.\n", ++ (dpy->bufptr - dpy->buffer)); ++#endif ++ if (!size || (dpy->flags & XlibDisplayIOError)) ++ { ++ if (dpy->flags & XlibDisplayIOError) ++ { ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XSend: Returning with I/O error detected.\n"); ++#endif ++ dpy->bufptr = dpy->buffer; ++ dpy->last_req = (char *)&_dummy_request; ++ } + ++ return; ++ } ++#else + if (!size || (dpy->flags & XlibDisplayIOError)) return; ++#endif + dbufsize = dpy->bufptr - dpy->buffer; + #ifdef XTHREADS + dpy->flags |= XlibDisplayWriting; +@@ -1418,6 +1955,17 @@ + + ESET(0); + if ((len = _X11TransWritev(dpy->trans_conn, iov, i)) >= 0) { ++#ifdef NX_TRANS_SOCKET ++ if (_NXDisplayWriteFunction != NULL) { ++ (*_NXDisplayWriteFunction)(dpy, len); ++ } ++#ifdef NX_TRANS_CHANGE ++ if (_NXDisplayCongestionFunction != NULL && ++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { ++ (*_NXDisplayCongestionFunction)(dpy, congestion); ++ } ++#endif ++#endif + skip += len; + total -= len; + todo = total; +@@ -1447,9 +1995,23 @@ + ); + } + #endif ++#ifdef NX_TRANS_SOCKET ++ } else if (!ECHECK(EINTR) || ++ (_NXDisplayErrorFunction != NULL && ++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { ++ _XIOError(dpy); ++ return; ++ } ++#else + } else if (!ECHECK(EINTR)) { + _XIOError(dpy); + } ++#endif ++#ifdef NX_TRANS_SOCKET ++ if (_XGetIOError(dpy)) { ++ return; ++ } ++#endif + } + dpy->last_req = (char *) & _dummy_request; + if ((dpy->request - dpy->last_request_read) >= SEQLIMIT && +@@ -1640,10 +2202,31 @@ + if (newseq < lastseq) { + newseq += 0x10000; + if (newseq > dpy->request) { ++ ++#ifdef NX_TRANS_SOCKET ++ ++ if (_NXLostSequenceFunction != NULL) ++ { ++ (*_NXLostSequenceFunction)(dpy, newseq, dpy->request, ++ (unsigned int) rep->type); ++ } ++ else ++ { ++ (void) fprintf (stderr, ++ "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", ++ newseq, dpy->request, ++ (unsigned int) rep->type); ++ } ++ ++#else /* #ifdef NX_TRANS_SOCKET */ ++ + (void) fprintf (stderr, + "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", + newseq, dpy->request, + (unsigned int) rep->type); ++ ++#endif /* #ifdef NX_TRANS_SOCKET */ ++ + newseq -= 0x10000; + } + } +@@ -1671,9 +2254,22 @@ + #ifdef XTHREADS + struct _XCVList *cvl; + #endif ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XReply: Going to wait for an X reply.\n"); ++#endif + ++#ifdef NX_TRANS_SOCKET ++ if (dpy->flags & XlibDisplayIOError) ++ { ++#ifdef NX_TRANS_DEBUG ++ fprintf(stderr, "_XReply: Returning 0 with I/O error detected.\n"); ++#endif ++ return 0; ++ } ++#else + if (dpy->flags & XlibDisplayIOError) + return 0; ++#endif + + #ifdef XTHREADS + /* create our condition variable and append to list */ +@@ -1689,6 +2285,9 @@ + XThread_Self(), cvl); + #endif + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XReply: Going to flush the display buffer.\n"); ++#endif + _XFlushInt(dpy, cvl ? cvl->cv : NULL); + /* if it is not our turn to read a reply off the wire, + * wait til we're at head of list. if there is an event waiter, +@@ -1704,6 +2303,20 @@ + _XFlush(dpy); + #endif + ++#ifdef NX_TRANS_SOCKET ++ /* ++ * We are going to block waiting for the remote ++ * X server. Be sure that the proxy has flushed ++ * all the data. ++ */ ++ ++#ifdef NX_TRANS_TEST ++ fprintf(stderr, "_XReply: Requesting a flush of the NX transport.\n"); ++#endif ++ ++ NXTransFlush(dpy->fd); ++#endif ++ + for (;;) { + #ifdef XTHREADS + /* Did another thread's _XReadEvents get our reply by accident? */ +@@ -1767,6 +2380,12 @@ + ((long) rep->generic.length) << 2); + dpy->flags &= ~XlibDisplayReply; + UnlockNextReplyReader(dpy); ++#ifdef NX_TRANS_SOCKET ++ /* ++ * The original code has provision ++ * for returning already. ++ */ ++#endif + _XIOError (dpy); + return (0); + +@@ -1830,6 +2449,12 @@ + #endif + break; + } ++#ifdef NX_TRANS_SOCKET ++ if (_XGetIOError(dpy)) { ++ UnlockNextReplyReader(dpy); ++ return 0; ++ } ++#endif + } + } + +@@ -1849,6 +2474,14 @@ + (void) _XSetLastRequestRead(dpy, &rep->generic); + len = SIZEOF(xReply) + (rep->generic.length << 2); + if (len < SIZEOF(xReply)) { ++#ifdef NX_TRANS_SOCKET ++ ++ /* ++ * The original code has provision ++ * for returning already. ++ */ ++ ++#endif + _XIOError (dpy); + buf += *lenp; + *lenp = 0; +@@ -1876,6 +2509,14 @@ + } + if (len < SIZEOF(xReply)) + { ++#ifdef NX_TRANS_SOCKET ++ ++ /* ++ * The original code has provision ++ * for returning already. ++ */ ++ ++#endif + _XIOError (dpy); + buf += *lenp; + *lenp = 0; +@@ -1944,6 +2585,10 @@ + struct _XConnWatchInfo *watchers; + XPointer *wd; + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XRegisterInternalConnection: Got called.\n"); ++#endif ++ + new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo)); + if (!new_conni) + return 0; +@@ -1991,6 +2636,10 @@ + struct _XConnWatchInfo *watch; + XPointer *wd; + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XUnregisterInternalConnection: Got called.\n"); ++#endif ++ + for (prev = &dpy->im_fd_info; (info_list = *prev); + prev = &info_list->next) { + if (info_list->fd == fd) { +@@ -2030,6 +2679,10 @@ + struct _XConnectionInfo *info_list; + int *fd_list; + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "XInternalConnectionNumbers: Got called.\n"); ++#endif ++ + LockDisplay(dpy); + count = 0; + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) +@@ -2088,6 +2741,10 @@ + { + struct _XConnectionInfo *info_list; + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "XProcessInternalConnection: Got called.\n"); ++#endif ++ + LockDisplay(dpy); + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { + if (info_list->fd == fd) { +@@ -2116,6 +2773,10 @@ + struct _XConnectionInfo *info_list; + XPointer *wd_array; + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "XAddConnectionWatch: Got called.\n"); ++#endif ++ + LockDisplay(dpy); + + /* allocate new watch data */ +@@ -2172,6 +2833,10 @@ + struct _XConnectionInfo *conni; + int counter = 0; + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "XRemoveConnectionWatch: Got called.\n"); ++#endif ++ + LockDisplay(dpy); + for (watch=dpy->conn_watchers; watch; watch=watch->next) { + if (watch->fn == callback && watch->client_data == client_data) { +@@ -2209,6 +2874,10 @@ + #define SCRATCHSIZE 2048 + char buf[SCRATCHSIZE]; + ++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) ++ fprintf(stderr, "_XEatData: Going to eat [%ld] bytes of data from descriptor [%d].\n", ++ n, dpy->fd); ++#endif + while (n > 0) { + register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n; + (void) _XRead (dpy, buf, bytes_read); +@@ -2237,7 +2906,13 @@ + (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) { + /* Malloc call failed! */ + ESET(ENOMEM); ++#ifdef NX_TRANS_SOCKET ++ _XIOError(dpy); ++ ++ return; ++#else + _XIOError(dpy); ++#endif + } + qelt->next = NULL; + /* go call through display to find proper event reformatter */ +@@ -2710,7 +3385,29 @@ + QLength(dpy)); + + } +- exit(1); ++#ifdef NX_TRANS_SOCKET ++ if (_NXHandleDisplayError == 1) ++ { ++#ifdef NX_TRANS_TEST ++ fprintf(stderr, "_XDefaultIOError: Going to return from the error handler.\n"); ++#endif ++ return 0; ++ } ++ else ++ { ++#ifdef NX_TRANS_TEST ++ fprintf(stderr, "_XDefaultIOError: Going to exit from the program.\n"); ++#endif ++#ifdef NX_TRANS_EXIT ++ NXTransExit(1); ++#else ++ exit(1); ++#endif ++ } ++#else ++ exit(1); ++#endif /* #ifdef NX_TRANS_SOCKET */ ++ + return(0); /* dummy - function should never return */ + } + +@@ -2911,7 +3608,48 @@ + (*_XIOErrorFunction)(dpy); + else + _XDefaultIOError(dpy); ++#ifdef NX_TRANS_SOCKET ++ /* ++ * Check if we are supposed to return in the case ++ * of a display failure. The client which originated ++ * the X operation will have to check the value of ++ * the XlibDisplayIOError flag and handle appropria- ++ * tely the display disconnection. ++ */ ++ ++ if (_NXHandleDisplayError == 0) ++ { ++#ifdef NX_TRANS_EXIT ++ NXTransExit(1); ++#else ++ exit(1); ++#endif ++ } ++ ++ /* ++ * We are going to return. Reset the display ++ * buffers. Further writes will be discarded. ++ */ ++ ++#ifdef NX_TRANS_TEST ++ fprintf(stderr, "_XIOError: Resetting the display buffer.\n"); ++#endif ++ ++ dpy->bufptr = dpy->buffer; ++ dpy->last_req = (char *) &_dummy_request; ++ ++#ifdef NX_TRANS_TEST ++ fprintf(stderr, "_XIOError: Resetting the display flags.\n"); ++#endif ++ ++ dpy->flags &= ~XlibDisplayProcConni; ++ dpy->flags &= ~XlibDisplayPrivSync; ++ dpy->flags &= ~XlibDisplayReadEvents; ++ dpy->flags &= ~XlibDisplayWriting; ++ dpy->flags &= ~XlibDisplayReply; ++#else + exit (1); ++#endif + return 0; + } + |