--- ./nx-X11/lib/xtrans/Xtranssock.c.X.original 2015-02-13 14:03:44.672442927 +0100 +++ ./nx-X11/lib/xtrans/Xtranssock.c 2015-02-13 14:03:44.672442927 +0100 @@ -53,6 +53,35 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/**************************************************************************/ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ + +#ifdef NX_TRANS_SOCKET + +#ifdef NX_TRANS_DEBUG +#define XTRANSDEBUG 5 +#endif + +#ifndef PF_LOCAL +#define PF_LOCAL PF_UNIX +#endif + +#endif + #include #ifdef XTHREADS #include @@ -294,6 +323,560 @@ static int haveIPv6 = 1; #endif +#ifndef X11_t + +/* + * No NX changes if this is not + * compiled as a X11 transport. + */ + +#undef NX_TRANS_SOCKET + +#endif + +#ifdef NX_TRANS_SOCKET + +#ifdef TRANS_CLIENT + +#include "NX.h" + +typedef struct +{ + XtransConnInfo info; + int local; + int remote; + int congestion; + +} _NXProxyConnInfo; + +#define NX_PROXY_CONN_LIMIT 256 + +static _NXProxyConnInfo *_NXProxyConnInfoTab[NX_PROXY_CONN_LIMIT]; + +#endif /* #ifdef TRANS_CLIENT */ + +/* + * Override the UNIX_DIR and UNIX_PATH settings and + * make them configurable, based on the NX_TEMP or + * the TEMP environment. + * + * We must be careful as the same defines are used + * for different directories, based on the subsystem + * that is compiling this, while we want to override + * only the '/tmp/.X11-unix' and '/tmp/.X11-unix/X' + * settings. + */ + +static char _NXUnixDir[1024]; +static char _NXUnixPath[1024]; + +static char *_NXGetUnixDir(char *dir) +{ + const char *tempDir; + + PRMSG (3, "_NXGetUnixDir(%s)\n", dir, 0, 0); + + if (strcmp(dir, UNIX_DIR) != 0) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixDir: Returning other Unix directory [%s].\n", dir); +#endif + return dir; + } + + /* + * Check the environment only once. + */ + + if (*_NXUnixDir != '\0') + { + return _NXUnixDir; + } + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixDir: Trying with the NX_TEMP environment.\n"); +#endif + + tempDir = getenv("NX_TEMP"); + + if (tempDir == NULL || *tempDir == '\0') + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixDir: Trying with the TEMP environment.\n"); +#endif + + tempDir = getenv("TEMP"); + } + + if (tempDir != NULL && *tempDir != '\0') + { + if (strlen(tempDir) + strlen("/.X11-unix") + 1 > 1024) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixDir: WARNING! Maximum length of X11 Unix directory exceeded.\n"); +#endif + goto _NXGetUnixDirError; + } + + strcpy(_NXUnixDir, tempDir); + strcat(_NXUnixDir, "/.X11-unix"); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixDir: Using X11 Unix directory [%s].\n", _NXUnixDir); +#endif + + return _NXUnixDir; + } + +_NXGetUnixDirError: + + strcpy(_NXUnixDir, dir); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixDir: Returning default X11 Unix directory [%s].\n", _NXUnixDir); +#endif + + return _NXUnixDir; +} + +static char *_NXGetUnixPath(char *path) +{ + const char *unixDir; + + PRMSG (3, "_NXGetUnixPath(%s)\n", path, 0, 0); + + if (strcmp(path, UNIX_PATH) != 0) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixPath: Returning other X11 Unix path [%s].\n", path); +#endif + return path; + } + + /* + * Check the environment only once. + */ + + if (*_NXUnixPath != '\0') + { + return _NXUnixPath; + } + + unixDir = _NXGetUnixDir(UNIX_DIR); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixPath: Got X11 Unix directory [%s].\n", unixDir); +#endif + + if (strlen(unixDir) + strlen("/X") + 1 > 1024) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixPath: WARNING! Maximum length of X11 Unix path exceeded.\n"); +#endif + + goto _NXGetUnixPathError; + } + + strcpy(_NXUnixPath, unixDir); + strcat(_NXUnixPath, "/X"); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixPath: Returning X11 Unix path [%s].\n", _NXUnixPath); +#endif + + return _NXUnixPath; + +_NXGetUnixPathError: + + strcpy(_NXUnixPath, path); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetUnixPath: Returning default X11 Unix path [%s].\n", _NXUnixPath); +#endif + + return _NXUnixPath; +} + +#ifdef hpux + +static char *_NXGetOldUnixPath(char *path) +{ + PRMSG (3, "_NXGetOldUnixPath(%s)\n", path, 0, 0); + + if (strcmp(path, OLD_UNIX_PATH) == 0) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetOldUnixPath: Returning X11 Unix path [%s].\n", + _NXGetUnixPath(path)); +#endif + + return _NXGetUnixPath(path); + } + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetOldUnixPath: Returning other old X11 Unix path [%s].\n", path); +#endif + + return path; +} + +#endif /* #ifdef hpux */ + +/* + * Forcibly close any connection attempt on the + * listening socket. Need this to avoid loopback + * connections to the agent server. + */ + +#ifdef TRANS_SERVER + +void TRANS(SocketRejectConnection) (XtransConnInfo ciptr) +{ + size_t sa_l = sizeof(struct sockaddr); + struct sockaddr sa; + fd_set fs; + struct timeval t; + int f; + + PRMSG (3, "SocketRejectConnection(%x)\n", ciptr, 0, 0); + + FD_ZERO(&fs); + FD_SET(ciptr -> fd, &fs); + + t.tv_sec = 0; + t.tv_usec = 0; + + /* + * Check if there is an awaiting connection. + */ + + if (select(ciptr -> fd + 1, &fs, NULL, NULL, &t) == 1) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketRejectConnection: Accepting connection attempt on fd [%d].\n", + ciptr -> fd); +#endif + /* + * If there is one, close it. + */ + + if ((f = accept(ciptr -> fd, &sa, &sa_l)) >= 0) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketRejectConnection: Closing connection attempt on fd [%d].\n", + ciptr -> fd); +#endif + close(f); + } + } +} + +#endif /* #ifdef TRANS_SERVER */ + +#ifdef TRANS_CLIENT + +void *TRANS(SocketProxyConnInfo) (XtransConnInfo ciptr) +{ + if (_NXProxyConnInfoTab[ciptr->fd] != NULL) + { + return ciptr->priv; + } + + return NULL; +} + +static XtransConnInfo TRANS(SocketCreateConnInfo) () +{ + XtransConnInfo ciptr; + + int fds[2]; + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketCreateConnInfo: Going to create the NX connection info.\n"); +#endif + + if ((ciptr = (XtransConnInfo) calloc (1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "SocketCreateConnInfo: malloc failed\n", 0, 0, 0); + return NULL; + } + + /* + * Create a pair of sockets. We'll communicate with + * the NX proxy by reading and writing to our end. + */ + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketCreateConnInfo: Going to create the NX socketpair.\n"); +#endif + + if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0) + { + PRMSG (1, "SocketCreateConnInfo: socketpair() failed.\n", 0, 0, 0); + xfree ((char *) ciptr); + return NULL; + } + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketCreateConnInfo: X socket end is [%d] NX proxy end is [%d].\n", + fds[0], fds[1]); +#endif + + /* + * Save in _NXProxyConnInfoTab the local and remote end of + * the socketpair. The remote end will be used by the proxy. + * When the memory-to-memory transport is activated, the + * agent and the proxy don't read or write to the real des- + * criptors but the communication takes place by reading + * and writing to the proxy's buffers. + */ + + ciptr->fd = fds[0]; + + if (ciptr->fd >= NX_PROXY_CONN_LIMIT) + { + PRMSG (1, "SocketCreateConnInfo: No space for a new _NXProxyConnInfo for [%d].\n", + ciptr->fd, 0, 0); + xfree ((char *) ciptr); + return NULL; + } + else if (_NXProxyConnInfoTab[ciptr->fd] != NULL) + { + PRMSG (1, "SocketCreateConnInfo: _NXProxyConnInfo for [%d] is not NULL. Exiting.\n", + ciptr->fd, 0, 0); + exit(1); + } + + _NXProxyConnInfoTab[ciptr->fd] = (_NXProxyConnInfo *) xcalloc(1, sizeof(_NXProxyConnInfo)); + + if (_NXProxyConnInfoTab[ciptr->fd] == NULL) + { + PRMSG (1, "SocketCreateConnInfo: Alloc of _NXProxyConnInfo failed.\n", 0, 0, 0); + xfree ((char *) ciptr); + return NULL; + } + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketCreateConnInfo: Allocated new _NXProxyConnInfo for [%d].\n", + ciptr->fd); +#endif + + _NXProxyConnInfoTab[ciptr->fd]->info = ciptr; + _NXProxyConnInfoTab[ciptr->fd]->local = fds[0]; + _NXProxyConnInfoTab[ciptr->fd]->remote = fds[1]; + _NXProxyConnInfoTab[ciptr->fd]->congestion = 0; + + ciptr->priv = (char *) _NXProxyConnInfoTab[ciptr->fd]; + + return ciptr; +} + +static int TRANS(SocketConnectConnInfo) (XtransConnInfo ciptr, char *host, char *port) +{ + int fds[2]; + char display[1024]; + + _NXProxyConnInfo *proxy_conn; + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketConnectConnInfo: Going to connect NX fd [%d] to host [%s] port [%s].\n", + ciptr->fd, host, port); +#endif + + /* + * We should have already created the socket pair. + */ + + proxy_conn = (_NXProxyConnInfo *) ciptr->priv; + + if (proxy_conn == NULL) + { + PRMSG (1, "SocketConnectConnInfo: Pointer to _NXProxyConnInfo is NULL. Exiting.\n", 0, 0, 0); + + exit(1); + } + else if (_NXProxyConnInfoTab[ciptr->fd] != (_NXProxyConnInfo *) ciptr->priv) + { + PRMSG (1, "SocketConnectConnInfo: Can't find _NXProxyConnInfo in table. Exiting.\n", + 0, 0, 0); + + exit(1); + } + + if (strlen(host) + strlen(port) + 1 >= 1023) + { + PRMSG (1, "SocketConnectConnInfo: Length of NX display string '%s:%s' would exceed %d characters.\n", + host, port, 1023); + + return TRANS_CONNECT_FAILED; + } + + sprintf(display, "%s:%s", host, port); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketConnectConnInfo: Setting close-on-exec flag on local NX descriptor [%d].\n", + proxy_conn -> local); +#endif + +#ifdef F_SETFD +#ifdef FD_CLOEXEC + if (fcntl(proxy_conn -> local, F_SETFD, FD_CLOEXEC) != 0) +#else + if (fcntl(proxy_conn -> local, F_SETFD, 1) != 0) +#endif +#endif + { + PRMSG (1, "SocketConnectConnInfo: Cannot set close-on-exec on local NX descriptor [%d].\n", + proxy_conn -> local, 0, 0); + + return TRANS_CONNECT_FAILED; + } + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketConnectConnInfo: Creating the NX transport with display [%s].\n", + display); +#endif + + if (NXTransCreate(NX_FD_ANY, NX_MODE_CLIENT, display) < 0) + { + PRMSG (1, "SocketConnectConnInfo: Cannot create the NX transport.\n", + 0, 0, 0); + + return TRANS_CONNECT_FAILED; + } + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketConnectConnInfo: Starting the NX agent with descriptor [%d].\n", + proxy_conn -> remote); +#endif + + fds[0] = proxy_conn -> local; + fds[1] = proxy_conn -> remote; + + NXTransAgent(fds); + + return 0; +} + +static void TRANS(SocketCloseConnInfo) (XtransConnInfo ciptr) +{ + _NXProxyConnInfo *proxy_conn; + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketCloseConnInfo: Going to close the NX fd [%d].\n", ciptr->fd); +#endif + + proxy_conn = (_NXProxyConnInfo *) ciptr->priv; + + if (proxy_conn == NULL) + { + PRMSG (1, "SocketCloseConnInfo: Pointer to _NXProxyConnInfo is NULL. Exiting.\n", 0, 0, 0); + + exit(1); + } + else if (ciptr->fd >= NX_PROXY_CONN_LIMIT || + _NXProxyConnInfoTab[ciptr->fd] != (_NXProxyConnInfo *) ciptr->priv) + { + PRMSG (1, "SocketCloseConnInfo: Can't find _NXProxyConnInfo in table. Exiting.\n", + 0, 0, 0); + exit(1); + } + else if (_NXProxyConnInfoTab[ciptr->fd] -> info != ciptr || + _NXProxyConnInfoTab[ciptr->fd] -> local != ciptr->fd) + { + PRMSG (1, "SocketCloseConnInfo: Invalid _NXProxyConnInfo structure for [%d]. Exiting.\n", + ciptr->fd, 0, 0); + exit(1); + } + else if (proxy_conn->local < 0 || proxy_conn->remote < 0) + { + PRMSG (1, "SocketCloseConnInfo: Invalid socket pair in NX connection for [%d]. Exiting.\n", + ciptr->fd, 0, 0); + exit(1); + } + + NXTransClose(ciptr->fd); + + /* + * Get rid of the _NXProxyConnInfo structure. + */ + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketCloseConnInfo: Freeing _NXProxyConnInfo structure for [%d].\n", + ciptr->fd); +#endif + + xfree((char *) _NXProxyConnInfoTab[ciptr->fd]); + + _NXProxyConnInfoTab[ciptr->fd] = NULL; + + ciptr->priv = NULL; + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketCloseConnInfo: Should now close the local descriptor [%d].\n", + ciptr->fd); +#endif +} + +#endif /* #ifdef TRANS_CLIENT */ + +#if defined(TRANS_CLIENT) && defined(NX_TRANS_CHANGE) + +/* + * Check the congestion state of the NX transport + * and return 1 if there has been a change. This + * can be extended by adding a few counters track- + * ing the bandwidth usage of the X11 connection. + */ + +int TRANS(SocketCongestionChange) (XtransConnInfo ciptr, int *state) +{ + int congestion; + + _NXProxyConnInfo *proxy_conn; + + PRMSG (3, "SocketCongestionChange(%x)\n", ciptr, 0, 0); + + proxy_conn = (_NXProxyConnInfo *) ciptr->priv; + + if (proxy_conn == NULL) + { +#ifdef NX_TRANS_DEBUG + fprintf(stderr, "SocketCongestionChange: Descriptor [%d] doesn't appear to be a NX connection.\n", + ciptr->fd); +#endif + return 0; + } + +#ifdef NX_TRANS_DEBUG + fprintf(stderr, "SocketCongestionChange: Checking congestion on fd [%d] with old state [%d].\n", + ciptr->fd, proxy_conn->congestion); +#endif + + congestion = NXTransCongestion(ciptr->fd); + + if (congestion != proxy_conn->congestion) + { + proxy_conn->congestion = congestion; + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketCongestionChange: Change detected on fd [%d] with new state [%d].\n", + ciptr->fd, proxy_conn->congestion); +#endif + return 1; + } + +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketCongestionChange: No change on fd [%d] with current state [%d].\n", + ciptr->fd, congestion); +#endif + return 0; +} + +#endif /* #if defined(TRANS_CLIENT) && defined(NX_TRANS_CHANGE) */ + +#endif /* #ifdef NX_TRANS_SOCKET */ + /* * These are some utility function used by the real interface function below. */ @@ -562,6 +1145,29 @@ SocketInitOnce(); while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) { + +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + if ((!strcmp(protocol, "local") || !strcmp(protocol, "nx")) && + (!strcasecmp(host, "nx") || !strncasecmp(host, "nx,", 3))) + { + ciptr = TRANS(SocketCreateConnInfo) (); + + if (ciptr == NULL) + { + PRMSG (1, "SocketOpenCOTSClient: Unable to create the NX connection info for %s.\n", + transname, 0, 0); + + return NULL; + } + + ciptr->index = i; + + return ciptr; + } + +#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ + if ((ciptr = TRANS(SocketOpen) ( i, Sockettrans2devtab[i].devcotsname)) != NULL) break; @@ -576,6 +1182,12 @@ return NULL; } +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + ciptr->priv = NULL; + +#endif + /* Save the index for later use */ ciptr->index = i; @@ -677,6 +1289,29 @@ SocketInitOnce(); while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { + +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + if ((!strcmp(protocol, "local") || !strcmp(protocol, "nx")) && + (!strcasecmp(host, "nx") || !strncasecmp(host, "nx,", 3))) + { + ciptr = TRANS(SocketCreateConnInfo) (); + + if (ciptr == NULL) + { + PRMSG (1, "SocketOpenCLTSClient: Unable to create the NX connection info for %s.\n", + thistrans->TransName, 0, 0); + + return NULL; + } + + ciptr->index = i; + + return ciptr; + } + +#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ + if ((ciptr = TRANS(SocketOpen) ( i, Sockettrans2devtab[i].devcotsname)) != NULL) break; @@ -691,6 +1326,12 @@ return NULL; } +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + ciptr->priv = NULL; + +#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ + /* Save the index for later use */ ciptr->index = i; @@ -826,6 +1467,11 @@ { PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg); +#ifdef NX_TRANS_TEST + fprintf(stderr, "SocketSetOption: WARNING! Not setting option [%d] with value [%d] on descriptor [%d].\n", + option, arg, ciptr -> fd); +#endif + return -1; } @@ -875,6 +1521,11 @@ else retry = 0; +#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST) + fprintf(stderr, "SocketCreateListener: Creating listener for ciptr at [%p] on path [%s].\n", + (void *) ciptr, ((struct sockaddr_un *) sockname)->sun_family == AF_UNIX ? + ((struct sockaddr_un *) sockname)->sun_path : "TCP"); +#endif while (bind (fd, (struct sockaddr *) sockname, namelen) < 0) { if (errno == EADDRINUSE) { @@ -926,6 +1577,11 @@ ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS); +#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST) + fprintf(stderr, "SocketCreateListener: Set flags to [%d] for ciptr [%p].\n", + ciptr->flags, (void *) ciptr); +#endif + return 0; } @@ -1084,9 +1740,15 @@ #else mode = 0777; #endif +#ifdef NX_TRANS_SOCKET + if (trans_mkdir(_NXGetUnixDir(UNIX_DIR), mode) == -1) { + PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n", + _NXGetUnixDir(UNIX_DIR), errno, 0); +#else if (trans_mkdir(UNIX_DIR, mode) == -1) { PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n", UNIX_DIR, errno, 0); +#endif (void) umask (oldUmask); return TRANS_CREATE_LISTENER_FAILED; } @@ -1095,12 +1757,20 @@ sockname.sun_family = AF_UNIX; if (port && *port) { +#ifdef NX_TRANS_SOCKET + if (set_sun_path(port, _NXGetUnixPath(UNIX_PATH), sockname.sun_path) != 0) { +#else if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) { +#endif PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0); return TRANS_CREATE_LISTENER_FAILED; } } else { +#ifdef NX_TRANS_SOCKET + sprintf (sockname.sun_path, "%s%ld", _NXGetUnixPath(UNIX_PATH), (long)getpid()); +#else sprintf (sockname.sun_path, "%s%ld", UNIX_PATH, (long)getpid()); +#endif } #if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx) @@ -1110,6 +1780,10 @@ namelen = strlen(sockname.sun_path) + sizeof(sockname.sun_family); #endif +#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST) + fprintf(stderr, "SocketUNIXCreateListener: Unlinking path [%s] for ciptr at [%p].\n", + sockname.sun_path, (void *) ciptr); +#endif unlink (sockname.sun_path); if ((status = TRANS(SocketCreateListener) (ciptr, @@ -1181,9 +1855,15 @@ #else mode = 0777; #endif +#ifdef NX_TRANS_SOCKET + if (trans_mkdir(_NXGetUnixDir(UNIX_DIR), mode) == -1) { + PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n", + _NXGetUnixDir(UNIX_DIR), errno, 0); +#else if (trans_mkdir(UNIX_DIR, mode) == -1) { PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n", UNIX_DIR, errno, 0); +#endif (void) umask (oldUmask); return TRANS_RESET_FAILURE; } @@ -1962,7 +2642,12 @@ * we know for sure it will fail. */ +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + if (strcmp(host, "unix") != 0 && strcasecmp(host, "nx") != 0 && + strncasecmp(host, "nx,", 3) != 0 && !UnixHostReallyLocal (host)) +#else if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host)) +#endif { PRMSG (1, "SocketUNIXConnect: Cannot connect to non-local host %s\n", @@ -1988,7 +2673,11 @@ sockname.sun_family = AF_UNIX; +#ifdef NX_TRANS_SOCKET + if (set_sun_path(port, _NXGetUnixPath(UNIX_PATH), sockname.sun_path) != 0) { +#else if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) { +#endif PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0); return TRANS_CONNECT_FAILED; } @@ -2006,7 +2695,11 @@ * This is gross, but it was in Xlib */ old_sockname.sun_family = AF_UNIX; +#ifdef NX_TRANS_SOCKET + if (set_sun_path(port, _NXGetOldUnixPath(OLD_UNIX_PATH), old_sockname.sun_path) != 0) { +#else if (set_sun_path(port, OLD_UNIX_PATH, old_sockname.sun_path) != 0) { +#endif PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0); return TRANS_CONNECT_FAILED; } @@ -2014,6 +2707,19 @@ sizeof (old_sockname.sun_family); #endif +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + if (ciptr->priv != NULL) + { + if (TRANS(SocketConnectConnInfo) (ciptr, host, port) != 0) + { + return TRANS_CONNECT_FAILED; + } + + goto SocketUNIXConnectPost; + } + +#endif /* * Do the connect() @@ -2065,6 +2771,12 @@ } } +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + +SocketUNIXConnectPost: + +#endif + /* * Get the socket name and the peer name from the connect socket, * since this is unix domain. @@ -2099,6 +2811,58 @@ { PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n", ciptr, ciptr->fd, pend); + +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + if (ciptr->priv) + { + if (NXTransRunning(ciptr->fd) == 0) + { + /* + * Force the application to shut down the + * socket if the NX transport is gone. We + * may probably save this additional call. + */ + +#ifdef NX_TRANS_DEBUG + fprintf(stderr, "SocketBytesReadable: NX transport not running for descriptor [%d].\n", + ciptr->fd); +#endif + ESET(EPIPE); + + return -1; + } + else + { + /* + * Emulate BytesReadable. Some X applications may use the system + * select() in their main loop, instead of the _XSelect() that is + * replaced by NX. Still these applications use _XEventsQueued to + * poll events from the X connection, and _XEventsQueued uses the + * NX _XSelect(), so it is generally possible to let the client + * yield the control to NX and let it handle the I/O on the proxy + * descriptors even if the application is not explicitly designed + * to work as a NX agent. + */ + +#ifdef NX_TRANS_DEBUG + + int result; + + result = NXTransReadable(ciptr->fd, (int *) pend); + + fprintf(stderr, "SocketBytesReadable: Descriptor [%d] result [%d] readable [%ld].\n", + ciptr->fd, result, *pend); + + return result; +#else + return NXTransReadable(ciptr->fd, (int *) pend); +#endif + } + } + +#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ + #if defined(QNX4) *pend = 0L; /* FIONREAD only returns a short. Zero out upper bits */ #endif @@ -2128,6 +2892,41 @@ { PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + /* + * If we have a valid priv pointer then this + * is an internal connection to the proxy. + * In this case we should emulate the read. + */ + + if (ciptr->priv) + { + int result; + + result = NXTransRead(ciptr->fd, buf, size); + +#ifdef NX_TRANS_DEBUG + if (result < 0 && EGET() == EAGAIN) + { + fprintf(stderr, "SocketRead: Read from descriptor [%d] would block.\n", + ciptr->fd); + } + else + { + fprintf(stderr, "SocketRead: Read [%d] bytes from descriptor [%d].\n", + result, ciptr->fd); + } +#endif + return result; + } + else + { + return read (ciptr->fd, buf, size); + } + +#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ + #if defined(WIN32) || defined(__UNIXOS2__) { int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); @@ -2139,6 +2938,8 @@ #else return read (ciptr->fd, buf, size); #endif /* WIN32 */ + +#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ } @@ -2148,6 +2949,41 @@ { PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + /* + * If we have a valid priv pointer then this + * is an internal connection to the proxy. + * In this case we should emulate the write. + */ + + if (ciptr->priv) + { + int result; + + result = NXTransWrite(ciptr->fd, buf, size); + +#ifdef NX_TRANS_DEBUG + if (result < 0 && EGET() == EAGAIN) + { + fprintf(stderr, "SocketWrite: Write on descriptor [%d] would block.\n", + ciptr->fd); + } + else + { + fprintf(stderr, "SocketWrite: Written [%d] bytes on descriptor [%d].\n", + result, ciptr->fd); + } +#endif + return result; + } + else + { + return write (ciptr->fd, buf, size); + } + +#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ + #if defined(WIN32) || defined(__UNIXOS2__) { int ret = send ((SOCKET)ciptr->fd, buf, size, 0); @@ -2159,6 +2995,8 @@ #else return write (ciptr->fd, buf, size); #endif /* WIN32 */ + +#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ } @@ -2168,7 +3006,28 @@ { PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size); +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + /* + * If we have a valid priv pointer then this + * is an internal connection to the proxy. + * In this case we should emulate the readv. + */ + + if (ciptr->priv) + { + return NXTransReadVector(ciptr->fd, buf, size); + } + else + { + return READV (ciptr, buf, size); + } + +#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ + return READV (ciptr, buf, size); + +#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ } @@ -2178,7 +3037,28 @@ { PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size); +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + /* + * If we have a valid priv pointer then this + * is an internal connection to the proxy. + * In this case we should emulate the writev. + */ + + if (ciptr->priv) + { + return NXTransWriteVector(ciptr->fd, buf, size); + } + else + { + return WRITEV (ciptr, buf, size); + } + +#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ + return WRITEV (ciptr, buf, size); + +#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */ } @@ -2234,17 +3114,41 @@ struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr; int ret; - PRMSG (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd, 0); + PRMSG (2,"SocketUNIXClose(%x,%d)\n", ciptr, ciptr->fd, 0); + +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + if (ciptr->priv) + { + TRANS(SocketCloseConnInfo) (ciptr); + } + +#endif ret = close(ciptr->fd); +#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST) + fprintf(stderr, "SocketUNIXClose: Flags are [%d] for ciptr at [%p] check is [%d].\n", + ciptr->flags, (void *) ciptr, (ciptr->flags && sockname + && sockname->sun_family == AF_UNIX && sockname->sun_path[0])); +#endif + if (ciptr->flags && sockname && sockname->sun_family == AF_UNIX && sockname->sun_path[0]) { +#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST) + if (!(ciptr->flags & TRANS_NOUNLINK)) + { + fprintf(stderr, "SocketUNIXClose: Unlinking path [%s] for ciptr at [%p].\n", + sockname->sun_path, (void *) ciptr); + unlink (sockname->sun_path); + } +#else if (!(ciptr->flags & TRANS_NOUNLINK)) unlink (sockname->sun_path); +#endif } return ret; @@ -2263,6 +3167,15 @@ PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n", ciptr, ciptr->fd, 0); +#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) + + if (ciptr->priv) + { + TRANS(SocketCloseConnInfo) (ciptr); + } + +#endif + ret = close(ciptr->fd); return ret;