Unverified Commit 854f3fa4 authored by Mike Gabriel's avatar Mike Gabriel

Merge branch 'sunweaver-pr/proxy-to-proxy-over-unix-socket' into 3.6.x

Attributes GH PR #142: https://github.com/ArcticaProject/nx-libs/pull/142 Reviewed by: Salvador Fandino <sfandino@yahoo.com> -- Mon, 04 Jul 2016 16:31:00 +0200
parents e0edae04 5a22f2ec
#!/bin/bash
#/**************************************************************************/
#/* */
#/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
#/* Copyright (c) 2015-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
#/* */
#/* NXSCRIPTS, 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. */
#/* */
#/**************************************************************************/
#
# Uncomment this to enable echo.
#
#set -x
#
ulimit -c unlimited
NXPROXYBIN=nxproxy
NXAGENTBIN=nxagent
NX_PORT=7
NX_SYSTEM=${HOME}/.nx
NX_ROOT=${HOME}/.nx
#
# This should be randlomly generated.
#
#NX_COOKIE=`xauth list |grep "${HOSTNAME}/unix:\<${NX_PORT}\>" | grep MIT | cut -f 5 -d ' '`
NX_COOKIE=123efa980d2cba234ef6f73deac810ff
#
# Create the directories for the NX session.
#
rm -rf ${NX_ROOT}/C-${NX_PORT} || exit
mkdir -p ${NX_ROOT}/C-${NX_PORT} || exit
rm -rf ${HOME}/.nx/S-${NX_PORT} || exit
mkdir -p ${HOME}/.nx/S-${NX_PORT} || exit
#
# Set the path to libraries and NX executables.
#
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${HOME}/NX/nxcomp:${HOME}/NX/nxcompext:${HOME}/NX/nx-X11/exports/lib"
export LD_LIBRARY_PATH
PATH="${PATH}:${HOME}/NX/nxclient/nxclient:${HOME}/NX/nx-X11/programs/Xserver/"
export PATH
#
# Create the fake cookie for this display.
#
echo -ne "Creating the X authorization cookie.\n"
xauth add ${HOSTNAME}/unix:${NX_PORT} MIT-MAGIC-COOKIE-1 ${NX_COOKIE}
xauth add ${HOSTNAME}:${NX_PORT} MIT-MAGIC-COOKIE-1 ${NX_COOKIE}
function urlencode() {
echo "$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$1")"
}
#
# Options are written in a file 'options' in the session
# directory. The agent will use the DISPLAY settings, so
# we pass in the DISPLAY the name of the options file.
#
# cache=8M,images=32M,link=modem,type=unix-kde,cleanup=0,
# accept=62.98.198.1,cookie=$NX_COOKIE,
# id=giulietta.nomachine.com-1098-6A4649FD0FCA57FAC275AF3F1C45B10F,
# media=1:1098
#
NX_HOST=nx/nx,cache=8192k,link=modem,menu=1,keybd=1,samba=0,cups=0,limit=0,\
listen=$(urlencode "unix:${NX_SYSTEM}/C-${NX_PORT}/proxy.socket"),cookie=$NX_COOKIE,errors=${NX_ROOT}/C-${NX_PORT}/session
echo "${NX_HOST}:${NX_PORT}" >${NX_ROOT}/C-${NX_PORT}/options
#
# Run the agent. if you don't have a font server running,
# remove the argument "-fp unix/:7100"
#
NX_AGENT=:${NX_PORT}
echo -ne "Running the X client side NX agent.\n"
SAVED_DISPLAY=$DISPLAY
DISPLAY=nx/nx,options=${NX_ROOT}/C-${NX_PORT}/options:${NX_PORT}
export DISPLAY
#valgrind -v --num-callers=8 --error-limit=no --trace-children=no \
#valgrind --num-callers=8 --tool=memcheck --leak-check=yes --show-reachable=yes --track-fds=yes \
#ldd ${NXAGENTBIN}
${NXAGENTBIN} -name 'NX' -geometry 800x600+100+100 "$@" \
${NX_AGENT} 2>>${NX_ROOT}/C-${NX_PORT}/session &
#
# The X server side proxy will forward the connection
# to the original DISPLAY.
#
DISPLAY=$SAVED_DISPLAY
export DISPLAY
#
# These are the nxproxy options used to run a typical session.
#
# cookie=$NX_COOKIE,root=/home/pinzari/.nx,media=32824,
# session=kde_on_giulietta,id=giulietta.nomachine.com-1098-6A4649FD0FCA57FAC275AF3F1C45B10F,
# connect=giulietta.nomachine.com:1098
#
#NX_HOST=nx/nx,keybd=1,samba=1,cups=1,connect=localhost,cookie=$NX_COOKIE,errors=${NX_ROOT}/S-${NX_PORT}/session
NX_HOST=nx/nx,keybd=1,samba=0,cups=0,connect=$(urlencode "unix:${NX_SYSTEM}/C-${NX_PORT}/proxy.socket"),cookie=$NX_COOKIE,errors=${NX_ROOT}/S-${NX_PORT}/session
echo "${NX_HOST}:${NX_PORT}" >${NX_ROOT}/S-${NX_PORT}/options
echo -ne "Running the X server side NX proxy.\n"
#valgrind -v --num-callers=8 --error-limit=no --trace-children=no \
#valgrind --num-callers=8 --tool=memcheck --leak-check=yes --show-reachable=yes --track-fds=yes \
#ldd ${NXPROXYBIN}
${NXPROXYBIN} -S nx/nx,options=${NX_ROOT}/S-${NX_PORT}/options:${NX_PORT} \
2>>${HOME}/.nx/S-${NX_PORT}/session &
echo -ne "Session running on display :$NX_PORT.\n"
#!/bin/bash
set -ex
#/**************************************************************************/
#/* */
#/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
#/* Copyright (c) 2015-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
#/* */
#/* NXSCRIPTS, 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. */
#/* */
#/**************************************************************************/
#
# Uncomment this to enable echo.
#
# set -x
#
ulimit -c unlimited
NX_PORT=6
NX_SYSTEM=${HOME}/.nx
NX_ROOT=${HOME}/.nx
mkdir -p "${NX_ROOT}"
#
# This should be randlomly generated.
#
NX_COOKIE=`xauth -n list |grep "${HOSTNAME}/unix:${NX_PORT}" | grep MIT | cut -f 5 -d ' ' | head -n1`
if [ -z "$NX_COOKIE" ]; then
NX_COOKIE=`mcookie`
fi
#
# Create the directories for the NX session.
#
rm -rf ${NX_ROOT}/C-${NX_PORT} || exit
mkdir -p ${NX_ROOT}/C-${NX_PORT} || exit
rm -rf ${HOME}/.nx/S-${NX_PORT} || exit
mkdir -p ${HOME}/.nx/S-${NX_PORT} || exit
#
# Set the path to libraries and NX executables.
#
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${HOME}/NX/nxcomp:${HOME}/NX/nxcompext:${HOME}/NX/nx-X11/exports/lib"
export LD_LIBRARY_PATH
PATH="${PATH}:${HOME}/NX/nxclient/nxclient:${HOME}/NX/nx-X11/programs/Xserver/"
export PATH
#
# Create the fake cookie for this display.
#
echo -ne "Creating the X authorization cookie.\n"
xauth add ${HOSTNAME}/unix:${NX_PORT} MIT-MAGIC-COOKIE-1 ${NX_COOKIE}
xauth add ${HOSTNAME}:${NX_PORT} MIT-MAGIC-COOKIE-1 ${NX_COOKIE}
function urlencode() {
echo "$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$1")"
}
#
# Options are written in a file 'options' in the session
# directory. The agent will use the DISPLAY settings, so
# we pass in the DISPLAY the name of the options file.
#
# cache=8M,images=32M,link=modem,type=unix-kde,cleanup=0,
# accept=62.98.198.1,cookie=$NX_COOKIE,
# id=giulietta.nomachine.com-1098-6A4649FD0FCA57FAC275AF3F1C45B10F,
# media=1:1098
#
#NX_HOST=nx/nx,link=lan,pack=no-pack,keybd=1,samba=1,cups=1,limit=0,\
#accept=127.0.0.1,cookie=$NX_COOKIE,errors=${NX_ROOT}/C-${NX_PORT}/session
#NX_HOST=nx/nx,link=lan,pack=16m-jpeg-9,keybd=1,samba=1,cups=1,limit=0,\
#accept=127.0.0.1,cookie=$NX_COOKIE,errors=${NX_ROOT}/C-${NX_PORT}/session
#NX_HOST=nx/nx,cache=8192k,link=modem,keybd=1,samba=1,cups=1,limit=0,\
#connect=127.0.0.1,cookie=$NX_COOKIE,errors=${NX_ROOT}/C-${NX_PORT}/session
#NX_HOST=nx/nx,link=lan,pack=16m-jpeg-9,keybd=1,samba=1,cups=1,limit=0,\
#accept=127.0.0.1,cookie=$NX_COOKIE,errors=${NX_ROOT}/C-${NX_PORT}/session
NX_HOST=nx/nx,link=lan,pack=16m-jpeg-9,keybd=1,samba=1,cups=1,limit=0,\
listen=$(urlencode "unix:${NX_SYSTEM}/C-${NX_PORT}/proxy.socket"),cookie=$NX_COOKIE,errors=${NX_ROOT}/C-${NX_PORT}/session
echo "${NX_HOST}:${NX_PORT}" >${NX_ROOT}/C-${NX_PORT}/options
#
# Run the local proxy impersonating the X display.
#
echo -ne "Running the X client side NX proxy.\n"
#valgrind -v --num-callers=8 --error-limit=no --trace-children=no \
#valgrind --tool=memcheck --track-fds=yes \
nxproxy -C nx/nx,options=${NX_ROOT}/C-${NX_PORT}/options:${NX_PORT} \
2>>${HOME}/.nx/C-${NX_PORT}/session &
#
# The X server side proxy will forward the connection
# to the original DISPLAY.
#
#
# These are the nxproxy options used to run a typical session.
#
# cookie=$NX_COOKIE,root=/home/pinzari/.nx,media=32824,
# session=kde_on_giulietta,id=giulietta.nomachine.com-1098-6A4649FD0FCA57FAC275AF3F1C45B10F,
# connect=giulietta.nomachine.com:1098
#
NX_HOST=nx/nx,keybd=1,samba=1,cups=1,connect=$(urlencode "unix:${NX_SYSTEM}/C-${NX_PORT}/proxy.socket"),cookie=$NX_COOKIE,errors=${NX_ROOT}/S-${NX_PORT}/session
echo "${NX_HOST}:${NX_PORT}" >${NX_ROOT}/S-${NX_PORT}/options
echo -ne "Running the X server side NX proxy.\n"
#cachegrind -v --dumps=100000000 \
#cachegrind -v \
#valgrind -v --leak-check=yes --leak-resolution=high --show-reachable=yes \
# --show-reachable=yes --suppressions=nxproxy/nxproxy.supp \
# --weird-hacks=lax-ioctls --num-callers=8 --logfile-fd=2 \
nxproxy -S nx/nx,options=${NX_ROOT}/S-${NX_PORT}/options:${NX_PORT} \
2>>${HOME}/.nx/S-${NX_PORT}/session &
echo -ne "Session running on display :$NX_PORT.\n"
......@@ -24,6 +24,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include "ChannelEndPoint.h"
......@@ -31,8 +32,21 @@
ChannelEndPoint::ChannelEndPoint(const char *spec)
: defaultTCPPort_(0), defaultTCPInterface_(0),
defaultUnixPath_(NULL) {
spec_ = (spec ? strdup(spec) : NULL);
defaultUnixPath_(NULL), spec_(NULL) {
setSpec(spec);
}
ChannelEndPoint::~ChannelEndPoint()
{
char *unixPath = NULL;
if (getUnixPath(&unixPath))
{
struct stat st;
lstat(unixPath, &st);
if(S_ISSOCK(st.st_mode))
unlink(unixPath);
}
}
void
......@@ -40,21 +54,92 @@ ChannelEndPoint::setSpec(const char *spec) {
if (spec_) free(spec_);
if (spec && strlen(spec))
{
spec_ = strdup(spec);
isUnix_ = getUnixPath();
isTCP_ = getTCPHostAndPort();
}
else
{
spec_ = NULL;
isUnix_ = false;
isTCP_ = false;
}
}
void
ChannelEndPoint::setSpec(int port) {
ChannelEndPoint::setSpec(long port) {
if (port >= 0) {
char tmp[20];
sprintf(tmp, "%d", port);
sprintf(tmp, "%ld", port);
setSpec(tmp);
}
else {
disable();
}
}
void
ChannelEndPoint::setSpec(const char *hostName, long port) {
int length;
if (spec_) free(spec_);
isUnix_ = false;
isTCP_ = false;
if (hostName && strlen(hostName) && port >= 1)
{
length = snprintf(NULL, 0, "tcp:%s:%ld", hostName, port);
spec_ = (char *)calloc(length + 1, sizeof(char));
snprintf(spec_, length+1, "tcp:%s:%ld", hostName, port);
isTCP_ = true;
}
else setSpec((char*)NULL);
}
bool
ChannelEndPoint::getSpec(char **socketUri) const {
if (socketUri) *socketUri = NULL;
char *unixPath = NULL;
char *hostName = NULL;
long port = -1;
char *newSocketUri = NULL;
int length = -1;
if (getUnixPath(&unixPath))
{
length = snprintf(NULL, 0, "unix:%s", unixPath);
}
else if (getTCPHostAndPort(&hostName, &port))
{
length = snprintf(NULL, 0, "tcp:%s:%ld", hostName, port);
}
if (length > 0)
{
newSocketUri = (char *)calloc(length + 1, sizeof(char));
if (isUnixSocket())
snprintf(newSocketUri, length+1, "unix:%s", unixPath);
else
snprintf(newSocketUri, length+1, "tcp:%s:%ld", hostName, port);
if (socketUri)
*socketUri = strdup(newSocketUri);
}
free(newSocketUri);
free(unixPath);
free(hostName);
if (*socketUri != '\0')
return true;
return false;
}
void
ChannelEndPoint::setDefaultTCPPort(long port) {
defaultTCPPort_ = port;
......@@ -76,10 +161,12 @@ ChannelEndPoint::setDefaultUnixPath(char *path) {
}
void
ChannelEndPoint::disable() { setSpec("0"); }
ChannelEndPoint::disable() {
setSpec("0");
}
bool
ChannelEndPoint::specIsPort(long *port) const {
ChannelEndPoint::getPort(long *port) const {
if (port) *port = 0;
long p = -1;
if (spec_) {
......@@ -101,7 +188,7 @@ ChannelEndPoint::getUnixPath(char **unixPath) const {
long p;
char *path = NULL;
if (specIsPort(&p)) {
if (getPort(&p)) {
if (p != 1) return false;
}
else if (spec_ && (strncmp("unix:", spec_, 5) == 0)) {
......@@ -122,6 +209,11 @@ ChannelEndPoint::getUnixPath(char **unixPath) const {
return true;
}
bool
ChannelEndPoint::isUnixSocket() const {
return isUnix_;
}
// FIXME!!!
static const char *
getComputerName() {
......@@ -158,7 +250,7 @@ ChannelEndPoint::getTCPHostAndPort(char **host, long *port) const {
if (host) *host = NULL;
if (port) *port = 0;
if (specIsPort(&p)) {
if (getPort(&p)) {
h_len = 0;
}
else if (spec_ && (strncmp("tcp:", spec_, 4) == 0)) {
......@@ -194,8 +286,8 @@ ChannelEndPoint::getTCPHostAndPort(char **host, long *port) const {
}
bool
ChannelEndPoint::enabled() const {
return (getUnixPath() || getTCPHostAndPort());
ChannelEndPoint::isTCPSocket() const {
return isTCP_;
}
long ChannelEndPoint::getTCPPort() const {
......@@ -205,8 +297,15 @@ long ChannelEndPoint::getTCPPort() const {
}
bool
ChannelEndPoint::enabled() const {
return (isUnixSocket() || isTCPSocket());
}
bool
ChannelEndPoint::validateSpec() {
return (specIsPort() || getUnixPath() || getTCPHostAndPort());
isTCP_ = getTCPHostAndPort();
isUnix_ = getUnixPath();
return ( getPort() || isUnix_ || isTCP_ );
}
ChannelEndPoint &ChannelEndPoint::operator=(const ChannelEndPoint &other) {
......@@ -219,26 +318,24 @@ ChannelEndPoint &ChannelEndPoint::operator=(const ChannelEndPoint &other) {
old = spec_;
spec_ = (other.spec_ ? strdup(other.spec_) : NULL);
free(old);
isUnix_ = getUnixPath();
isTCP_ = getTCPHostAndPort();
return *this;
}
std::ostream& operator<<(std::ostream& os, const ChannelEndPoint& endPoint) {
if (endPoint.enabled()) {
char *unixPath, *host;
long port;
if (endPoint.getUnixPath(&unixPath)) {
os << "unix:" << unixPath;
free(unixPath);
}
else if (endPoint.getTCPHostAndPort(&host, &port)) {
os << "tcp:" << host << ":" << port;
free(host);
char* endPointSpec = NULL;
if (endPoint.getSpec(&endPointSpec))
{
os << endPointSpec;
free(endPointSpec);
}
else {
else
os << "(invalid)";
}
}
else {
else
{
os << "(disabled)";
}
return os;
......
......@@ -33,25 +33,32 @@ class ChannelEndPoint
int defaultTCPInterface_; // 0=localhost, otherwise IP of public interface.
char *defaultUnixPath_;
char *spec_;
bool isUnix_;
bool isTCP_;
bool specIsPort(long *port = NULL) const;
bool getPort(long *port = NULL) const;
public:
ChannelEndPoint(const char *spec = NULL);
~ChannelEndPoint();
ChannelEndPoint &operator=(const ChannelEndPoint &other);
bool enabled() const;
bool disabled() { return !enabled(); }
void disable();
void setSpec(const char *spec);
void setSpec(int port);
void setSpec(long port);
void setSpec(const char *hostName, long port);
bool getSpec(char **socketUri) const;
void setDefaultTCPPort(long port);
void setDefaultTCPInterface(int publicInterface);
void setDefaultUnixPath(char *path);
bool getUnixPath(char **path = NULL) const;
bool isUnixSocket() const;
bool getTCPHostAndPort(char **hostname = NULL, long *port = NULL) const;
long getTCPPort() const;
bool isTCPSocket() const;
bool validateSpec();
};
......
......@@ -239,7 +239,7 @@ struct sockaddr_un
// should connect to remote.
//
#define WE_INITIATE_CONNECTION (*connectHost != '\0')
#define WE_INITIATE_CONNECTION (connectSocket.enabled())
//
// Is true if we must provide our credentials
......@@ -255,7 +255,7 @@ struct sockaddr_un
//
#define WE_LISTEN_FORWARDER (control -> ProxyMode == proxy_server && \
listenPort != -1)
listenSocket.enabled())
//
// You must define FLUSH in Misc.h if
......@@ -440,7 +440,7 @@ static int SetupDisplaySocket(int &xServerAddrFamily, sockaddr *&xServerAddr,
static int ListenConnection(ChannelEndPoint &endPoint, const char *label);
static int ListenConnectionTCP(const char *host, long port, const char *label);
static int ListenConnectionUnix(const char *unixPath, const char *label);
static int ListenConnectionUnix(const char *path, const char *label);
static int ListenConnectionAny(sockaddr *addr, socklen_t addrlen, const char *label);
static int AcceptConnection(int fd, int domain, const char *label);
......@@ -448,8 +448,11 @@ static int AcceptConnection(int fd, int domain, const char *label);
// Other convenience functions.
//
static int WaitForRemote(int portNum);
static int ConnectToRemote(const char *const hostName, int portNum);
static int PrepareProxyConnectionTCP(char** hostName, long int* portNum, int* timeout, int* proxyFD, int* reason);
static int PrepareProxyConnectionUnix(char** path, int* timeout, int* proxyFD, int* reason);
static int WaitForRemote(ChannelEndPoint &socketAddress);
static int ConnectToRemote(ChannelEndPoint &socketAddress);
static int SendProxyOptions(int fd);
static int SendProxyCaches(int fd);
......@@ -514,7 +517,7 @@ static int ParsePackOption(const char *opt);
// given on the command line.
//
static int ParseHostOption(const char *opt, char *host, int &port);
static int ParseHostOption(const char *opt, char *host, long &port);
//
// Translate a font server port specification
......@@ -524,14 +527,6 @@ static int ParseHostOption(const char *opt, char *host, int &port);
static int ParseFontPath(char *path);
//
// Determine the interface where to listen for
// the remote proxy connection or the local
// forwarder.
//
static int ParseListenOption(int &interface);
//
// Translate a pack method id in a literal.
//
......@@ -952,9 +947,7 @@ static char unixSocketName[DEFAULT_STRING_LENGTH] = { 0 };
// Other parameters.
//
static char connectHost[DEFAULT_STRING_LENGTH] = { 0 };
static char acceptHost[DEFAULT_STRING_LENGTH] = { 0 };
static char listenHost[DEFAULT_STRING_LENGTH] = { 0 };
static char displayHost[DEFAULT_STRING_LENGTH] = { 0 };
static char authCookie[DEFAULT_STRING_LENGTH] = { 0 };
......@@ -972,13 +965,19 @@ static sockaddr *xServerAddr = NULL;
static unsigned int xServerAddrLength = 0;
//
// The port where the local proxy will await
// the peer connection or where the remote
// proxy will be contacted.
// The representation of a Unix socket path or
// a bind address, denoting where the local proxy
// will await the peer connection.
//
static ChannelEndPoint listenSocket;
//
// The TCP host and port or Unix file socket where
// the remote proxy will be contacted.
//
static int listenPort = -1;
static int connectPort = -1;
static ChannelEndPoint connectSocket;
//
// Helper channels are disabled by default.
......@@ -3364,46 +3363,75 @@ int InitBeforeNegotiation()
int SetupProxyConnection()
{
if (proxyFD == -1)
{
if (WE_INITIATE_CONNECTION)
{
if (connectPort < 0)
char *socketUri = NULL;
// Let's make sure, the default value for listenSocket is properly set. Doing this
// here, because we have to make sure that we call it after the connectSocket
// declaration is really really complete.
if (listenSocket.disabled() && connectSocket.disabled())
{
connectPort = DEFAULT_NX_PROXY_PORT_OFFSET + proxyPort;
char listenPortValue[20] = { 0 };
sprintf(listenPortValue, "%ld", (long)(proxyPort + DEFAULT_NX_PROXY_PORT_OFFSET));
SetAndValidateChannelEndPointArg("local", "listen", listenPortValue, listenSocket);
}
#ifdef TEST
*logofs << "Loop: Going to connect to " << connectHost
<< ":" << connectPort << ".\n" << logofs_flush;
connectSocket.getSpec(&socketUri);
*logofs << "Loop: connectSocket is "<< ( connectSocket.enabled() ? "enabled" : "disabled") << ". "
<< "The socket URI is '"<< ( socketUri != NULL ? socketUri : "<unset>") << "'.\n" << logofs_flush;
listenSocket.getSpec(&socketUri);
*logofs << "Loop: listenSocket is "<< ( listenSocket.enabled() ? "enabled" : "disabled") << ". "
<< "The socket URI is '"<< ( socketUri != NULL ? socketUri : "<unset>") << "'.\n" << logofs_flush;
free(socketUri);
socketUri = NULL;
#endif
proxyFD = ConnectToRemote(connectHost, connectPort);
if (WE_INITIATE_CONNECTION)
{
if (connectSocket.getSpec(&socketUri))
{
#ifdef TEST
*logofs << "Loop: Going to connect to '" << socketUri
<< "'.\n" << logofs_flush;
#endif
free(socketUri);
proxyFD = ConnectToRemote(connectSocket);
#ifdef TEST
*logofs << "Loop: Connected to remote proxy on FD#"
<< proxyFD << ".\n" << logofs_flush;
#endif
cerr << "Info" << ": Connection to remote proxy '" << connectHost
<< ":" << connectPort << "' established.\n";
cerr << "Info" << ": Connected to remote proxy on FD#"
<< proxyFD << ".\n";
}
}
else
{
if (listenPort < 0)
if (listenSocket.isTCPSocket() && (listenSocket.getTCPPort() < 0))
{
listenPort = DEFAULT_NX_PROXY_PORT_OFFSET + proxyPort;
listenSocket.setSpec(DEFAULT_NX_PROXY_PORT_OFFSET + proxyPort);
}
if (listenSocket.getSpec(&socketUri))
{
#ifdef TEST
*logofs << "Loop: Going to wait for connection on port "
<< listenPort << ".\n" << logofs_flush;
*logofs << "Loop: Going to wait for connection at '"
<< socketUri << "'.\n" << logofs_flush;
#endif
free(socketUri);
proxyFD = WaitForRemote(listenPort);
proxyFD = WaitForRemote(listenSocket);
#ifdef TEST
if (WE_LISTEN_FORWARDER)
{
*logofs << "Loop: Connected to remote forwarder on FD#"
......@@ -3414,8 +3442,9 @@ int SetupProxyConnection()
*logofs << "Loop: Connected to remote proxy on FD#"
<< proxyFD << ".\n" << logofs_flush;
}
#endif
}
}
}
#ifdef TEST
......@@ -3431,6 +3460,9 @@ int SetupProxyConnection()
// to reduce startup time. Option will
// later be disabled if needed.
//
// either listenSocket or connectSocket is used here...
if(listenSocket.isTCPSocket() || connectSocket.isTCPSocket())
SetNoDelay(proxyFD, 1);
......@@ -3945,72 +3977,7 @@ int SetupTcpSocket()
// Open TCP socket emulating local display.
//
tcpFD = socket(AF_INET, SOCK_STREAM, PF_UNSPEC);
if (tcpFD == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to socket failed for TCP socket"
<< ". Error is " << EGET() << " '" << ESTR() << "'.\n"
<< logofs_flush;
#endif
cerr << "Error" << ": Call to socket failed for TCP socket"
<< ". Error is " << EGET() << " '" << ESTR() << "'.\n";
HandleCleanup();
}
else if (SetReuseAddress(tcpFD) < 0)
{
HandleCleanup();
}
unsigned int proxyPortTCP = X_TCP_PORT + proxyPort;
sockaddr_in tcpAddr;
tcpAddr.sin_family = AF_INET;
tcpAddr.sin_port = htons(proxyPortTCP);
if ( loopbackBind )
{
tcpAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
else
{
tcpAddr.sin_addr.s_addr = htonl(INADDR_ANY);
}
if (bind(tcpFD, (sockaddr *) &tcpAddr, sizeof(tcpAddr)) == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to bind failed for TCP port "
<< proxyPortTCP << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to bind failed for TCP port "
<< proxyPortTCP << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n";
HandleCleanup();
}
if (listen(tcpFD, 8) == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to listen failed for TCP port "
<< proxyPortTCP << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to listen failed for TCP port "
<< proxyPortTCP << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n";
HandleCleanup();
}
return 1;
return ListenConnectionTCP((loopbackBind ? "localhost" : "*"), X_TCP_PORT + proxyPort, "X11");
}
int SetupUnixSocket()
......@@ -4019,90 +3986,40 @@ int SetupUnixSocket()
// Open UNIX domain socket for display.
//
unixFD = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC);
if (unixFD == -1)
{
if (!control->TempPath) {
#ifdef PANIC
*logofs << "Loop: PANIC! Call to socket failed for UNIX domain"
<< ". Error is " << EGET() << " '" << ESTR() << "'.\n"
<< logofs_flush;
*logofs << "Loop: PANIC! Temporal path is null.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to socket failed for UNIX domain"
<< ". Error is " << EGET() << " '" << ESTR() << "'.\n";
cerr << "Error" << ": Temporal path is null.\n";
HandleCleanup();
}
sockaddr_un unixAddr;
unixAddr.sun_family = AF_UNIX;
char dirName[DEFAULT_STRING_LENGTH];
unsigned int required = snprintf(unixSocketName, DEFAULT_STRING_LENGTH, "%s/.X11-unix", control->TempPath);
if (required < sizeof(unixSocketName)) {
snprintf(dirName, DEFAULT_STRING_LENGTH - 1, "%s/.X11-unix",
control -> TempPath);
*(dirName + DEFAULT_STRING_LENGTH - 1) = '\0';
// No need to execute the following actions conditionally
mkdir(unixSocketName, (0777 | S_ISVTX));
chmod(unixSocketName, (0777 | S_ISVTX));
struct stat dirStat;
required = snprintf(unixSocketName, DEFAULT_STRING_LENGTH, "%s/.X11-unix/X%d", control->TempPath, proxyPort);
if (required < sizeof(unixSocketName)) {
if ((stat(dirName, &dirStat) == -1) && (EGET() == ENOENT))
{
mkdir(dirName, (0777 | S_ISVTX));
chmod(dirName, (0777 | S_ISVTX));
unixFD = ListenConnectionUnix(unixSocketName, "x11");
if (unixFD >= 0)
chmod(unixSocketName, 0777);
return unixFD;
}
snprintf(unixSocketName, DEFAULT_STRING_LENGTH - 1, "%s/X%d",
dirName, proxyPort);
strncpy(unixAddr.sun_path, unixSocketName, 108);
#ifdef TEST
*logofs << "Loop: Assuming Unix socket with name '"
<< unixAddr.sun_path << "'.\n"
<< logofs_flush;
#endif
*(unixAddr.sun_path + 107) = '\0';
if (bind(unixFD, (sockaddr *) &unixAddr, sizeof(unixAddr)) == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to bind failed for UNIX domain socket "
<< unixSocketName << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to bind failed for UNIX domain socket "
<< unixSocketName << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n";
HandleCleanup();
}
if (listen(unixFD, 8) == -1)
{
unixSocketName[0] = '\0'; // Just in case!
#ifdef PANIC
*logofs << "Loop: PANIC! Call to listen failed for UNIX domain socket "
<< unixSocketName << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n" << logofs_flush;
*logofs << "Loop: PANIC! path for unix socket is too long.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to listen failed for UNIX domain socket "
<< unixSocketName << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n";
cerr << "Error" << ": path for Unix socket is too long.\n";
HandleCleanup();
}
//
// Let any local user to gain access to socket.
//
chmod(unixSocketName, 0777);
return 1;
}
//
......@@ -4528,6 +4445,8 @@ int ListenConnectionAny(sockaddr *addr, socklen_t addrlen, const char *label)
goto SetupSocketError;
}
if (addr->sa_family == AF_INET)
if (SetReuseAddress(newFD) < 0)
{
// SetReuseAddress already warns with an error
......@@ -4551,12 +4470,12 @@ int ListenConnectionAny(sockaddr *addr, socklen_t addrlen, const char *label)
if (listen(newFD, 8) == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to bind failed for " << label
*logofs << "Loop: PANIC! Call to listen failed for " << label
<< ". Error is " << EGET()
<< " '" << ESTR() << "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to bind failed for " << label
cerr << "Error" << ": Call to listen failed for " << label
<< ". Error is " << EGET()
<< " '" << ESTR() << "'.\n";
......@@ -5569,9 +5488,7 @@ void CleanupLocal()
*unixSocketName = '\0';
*connectHost = '\0';
*acceptHost = '\0';
*listenHost = '\0';
*displayHost = '\0';
*authCookie = '\0';
......@@ -5585,8 +5502,8 @@ void CleanupLocal()
xServerAddr = NULL;
listenPort = -1;
connectPort = -1;
listenSocket.disable();
connectSocket.disable();
cupsPort.disable();
auxPort.disable();
......@@ -6717,28 +6634,31 @@ void ResetTimer()
}
//
// Open TCP socket to listen for remote proxy and
// block until remote connects. If successful close
// the listening socket and return FD on which the
// other party is connected.
// Open TCP or UNIX file socket to listen for remote proxy
// and block until remote connects. If successful close
// the listening socket and return FD on which the other
// party is connected.
//
int WaitForRemote(int portNum)
int WaitForRemote(ChannelEndPoint &socketAddress)
{
char hostLabel[DEFAULT_STRING_LENGTH] = { 0 };
char *socketUri = NULL;
int retryAccept = -1;
int listenIPAddr = -1;
int proxyFD = -1;
int newFD = -1;
int acceptIPAddr = 0;
if (socketAddress.isTCPSocket())
{
//
// Get IP address of host to be awaited.
//
int acceptIPAddr = 0;
if (*acceptHost != '\0')
{
acceptIPAddr = GetHostAddress(acceptHost);
......@@ -6755,113 +6675,38 @@ int WaitForRemote(int portNum)
goto WaitForRemoteError;
}
}
proxyFD = socket(AF_INET, SOCK_STREAM, PF_UNSPEC);
if (proxyFD == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to socket failed for TCP socket. "
<< "Error is " << EGET() << " '" << ESTR() << "'.\n"
<< logofs_flush;
#endif
cerr << "Error" << ": Call to socket failed for TCP socket. "
<< "Error is " << EGET() << " '" << ESTR() << "'.\n";
goto WaitForRemoteError;
}
else if (SetReuseAddress(proxyFD) < 0)
{
goto WaitForRemoteError;
}
listenIPAddr = 0;
ParseListenOption(listenIPAddr);
sockaddr_in tcpAddr;
tcpAddr.sin_family = AF_INET;
tcpAddr.sin_port = htons(portNum);
//
// Quick patch to run on MacOS/X where inet_addr("127.0.0.1")
// alone seems to fail to return a valid interface. It probably
// just needs a htonl() or something like that.
//
// TODO: We have to give another look at inet_addr("127.0.0.1")
// on the Mac.
//
#ifdef __APPLE__
if ( loopbackBind )
{
tcpAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
strcpy(hostLabel, "any host");
}
else
{
tcpAddr.sin_addr.s_addr = htonl(INADDR_ANY);
}
#else
tcpAddr.sin_addr.s_addr = listenIPAddr;
#endif
if (bind(proxyFD, (sockaddr *) &tcpAddr, sizeof(tcpAddr)) == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to bind failed for TCP port "
<< portNum << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to bind failed for TCP port "
<< portNum << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n";
goto WaitForRemoteError;
snprintf(hostLabel, sizeof(hostLabel), "'%s'", acceptHost);
}
if (listen(proxyFD, 4) == -1)
if (loopbackBind)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to listen failed for TCP port "
<< portNum << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to listen failed for TCP port "
<< portNum << ". Error is " << EGET() << " '" << ESTR()
<< "'.\n";
goto WaitForRemoteError;
long bindPort;
if (socketAddress.getTCPHostAndPort(NULL, &bindPort))
socketAddress.setSpec("localhost", bindPort);
}
if (*acceptHost != '\0')
{
strcat(hostLabel, "'");
strcat(hostLabel, acceptHost);
strcat(hostLabel, "'");
}
else if (socketAddress.isUnixSocket())
strcpy(hostLabel, "this host");
else
{
strcpy(hostLabel, "any host");
}
strcpy(hostLabel, "unknown origin (something went wrong!!!)");
proxyFD = ListenConnection(socketAddress, "NX");
socketAddress.getSpec(&socketUri);
#ifdef TEST
*logofs << "Loop: Waiting for connection from "
<< hostLabel << " on port '" << portNum
<< hostLabel << " on socket '" << socketUri
<< "'.\n" << logofs_flush;
#endif
cerr << "Info" << ": Waiting for connection from "
<< hostLabel << " on port '" << portNum
<< hostLabel << " on socket '" << socketUri
<< "'.\n";
free(socketUri);
//
// How many times to loop waiting for connections
......@@ -6916,12 +6761,19 @@ int WaitForRemote(int portNum)
}
else if (result > 0 && FD_ISSET(proxyFD, &readSet))
{
sockaddr_in newAddr;
socklen_t addrLen = sizeof(sockaddr_in);
newFD = accept(proxyFD, (sockaddr *) &newAddr, &addrLen);
sockaddr_in newAddrINET;
if (socketAddress.isUnixSocket())
{
socklen_t addrLen = sizeof(sockaddr_un);
newFD = accept(proxyFD, NULL, &addrLen);
}
else if (socketAddress.isTCPSocket())
{
socklen_t addrLen = sizeof(sockaddr_in);
newFD = accept(proxyFD, (sockaddr *) &newAddrINET, &addrLen);
}
if (newFD == -1)
{
#ifdef PANIC
......@@ -6936,13 +6788,34 @@ int WaitForRemote(int portNum)
goto WaitForRemoteError;
}
char *connectedHost = inet_ntoa(newAddr.sin_addr);
if (socketAddress.isUnixSocket())
{
char * unixPath = NULL;
socketAddress.getUnixPath(&unixPath);
#ifdef TEST
*logofs << "Loop: Accepted connection from this host on Unix file socket '"
<< unixPath << "'.\n"
<< logofs_flush;
#endif
cerr << "Info" << ": Accepted connection from this host on Unix file socket '"
<< unixPath << "'.\n";
free(unixPath);
break;
}
else if (socketAddress.isTCPSocket())
{
char *connectedHost = inet_ntoa(newAddrINET.sin_addr);
if (*acceptHost == '\0' || (int) newAddr.sin_addr.s_addr == acceptIPAddr)
if (*acceptHost == '\0' || (int) newAddrINET.sin_addr.s_addr == acceptIPAddr)
{
#ifdef TEST
unsigned int connectedPort = ntohs(newAddr.sin_port);
unsigned int connectedPort = ntohs(newAddrINET.sin_port);
*logofs << "Loop: Accepted connection from '" << connectedHost
<< "' with port '" << connectedPort << "'.\n"
......@@ -6958,7 +6831,7 @@ int WaitForRemote(int portNum)
{
#ifdef PANIC
*logofs << "Loop: WARNING! Refusing connection from '" << connectedHost
<< "' on port '" << portNum << "'.\n" << logofs_flush;
<< "' on port '" << socketAddress.getTCPPort() << "'.\n" << logofs_flush;
#endif
cerr << "Warning" << ": Refusing connection from '"
......@@ -6972,11 +6845,25 @@ int WaitForRemote(int portNum)
sleep(5);
close(newFD);
}
}
if (--retryAccept == 0)
{
if (*acceptHost == '\0')
if (socketAddress.isUnixSocket())
{
#ifdef PANIC
*logofs << "Loop: PANIC! Connection via Unix file socket from this host "
<< "could not be established.\n"
<< logofs_flush;
#endif
cerr << "Error" << ": Connection via Unix file socket from this host "
<< "could not be established.\n";
}
else if (*acceptHost == '\0')
{
#ifdef PANIC
*logofs << "Loop: PANIC! Connection with remote host "
......@@ -7018,87 +6905,162 @@ WaitForRemoteError:
HandleCleanup();
}
//
// Connect to remote proxy. If successful
// return FD of connection, else return -1.
//
int ConnectToRemote(const char *const hostName, int portNum)
int PrepareProxyConnectionTCP(char** hostName, long int* portNum, int* timeout, int* proxyFD, int* reason)
{
int proxyFD = -1;
int remoteIPAddr = GetHostAddress(hostName);
if (!proxyFD)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Implementation error (PrepareProxyConnectionTCP). "
<< "'proxyFD' must not be a NULL pointer.\n" << logofs_flush;
#endif
cerr << "Error" << ": Implementation error (PrepareProxyConnectionTCP). "
<< "'proxyFD' must not be a NULL pointer.\n";
return -1;
}
if (!reason)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Implementation error (PrepareProxyConnectionTCP). "
<< "'reason' must not be a NULL pointer.\n" << logofs_flush;
#endif
cerr << "Error" << ": Implementation error (PrepareProxyConnectionTCP). "
<< "'reason' must not be a NULL pointer.\n";
return -1;
}
int remoteIPAddr = GetHostAddress(*hostName);
if (remoteIPAddr == 0)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Unknown remote host '"
<< hostName << "'.\n" << logofs_flush;
<< *hostName << "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Unknown remote host '"
<< hostName << "'.\n";
<< *hostName << "'.\n";
HandleCleanup();
}
#ifdef TEST
*logofs << "Loop: Connecting to remote host '"
<< hostName << ":" << portNum << "'.\n"
<< *hostName << ":" << *portNum << "'.\n"
<< logofs_flush;
#endif
cerr << "Info" << ": Connecting to remote host '"
<< hostName << ":" << portNum << "'.\n"
<< *hostName << ":" << *portNum << "'.\n"
<< logofs_flush;
//
// How many times we retry to connect to remote
// host in case of failure?
//
*proxyFD = -1;
*reason = -1;
int retryConnect = control -> OptionProxyRetryConnect;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(*portNum);
addr.sin_addr.s_addr = remoteIPAddr;
*proxyFD = socket(AF_INET, SOCK_STREAM, PF_UNSPEC);
*reason = EGET();
if (*proxyFD == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to socket failed. "
<< "Error is " << *reason << " '" << ESTR()
<< "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to socket failed. "
<< "Error is " << *reason << " '" << ESTR()
<< "'.\n";
return -1;
}
else if (SetReuseAddress(*proxyFD) < 0)
{
return -1;
}
//
// Show an alert after 20 seconds and use the
// same timeout to interrupt the connect. The
// retry timeout is incremental, starting from
// 100 miliseconds up to 1 second.
// Ensure operation is timed out
// if there is a network problem.
//
int alertTimeout = 20000;
int connectTimeout = 20000;
int retryTimeout = 100;
if (timeout)
SetTimer(*timeout);
else
SetTimer(20000);
T_timestamp lastRetry = getNewTimestamp();
int result = connect(*proxyFD, (sockaddr *) &addr, sizeof(sockaddr_in));
sockaddr_in addr;
*reason = EGET();
addr.sin_family = AF_INET;
addr.sin_port = htons(portNum);
addr.sin_addr.s_addr = remoteIPAddr;
ResetTimer();
for (;;)
return result;
}
int PrepareProxyConnectionUnix(char** path, int* timeout, int* proxyFD, int* reason)
{
if (!proxyFD)
{
proxyFD = socket(AF_INET, SOCK_STREAM, PF_UNSPEC);
#ifdef PANIC
*logofs << "Loop: PANIC! Implementation error (PrepareProxyConnectionUnix). "
<< "proxyFD must not be a NULL pointer.\n" << logofs_flush;
#endif
if (proxyFD == -1)
cerr << "Error" << ": Implementation error (PrepareProxyConnectionUnix). "
<< "proxyFD must not be a NULL pointer.\n";
return -1;
}
if (!reason)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Implementation error (PrepareProxyConnectionUnix). "
<< "'reason' must not be a NULL pointer.\n" << logofs_flush;
#endif
cerr << "Error" << ": Implementation error (PrepareProxyConnectionUnix). "
<< "'reason' must not be a NULL pointer.\n";
return -1;
}
/* FIXME: Add socket file existence and permission checks */
*proxyFD = -1;
*reason = -1;
sockaddr_un addr;
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, *path, 108 - 1);
*proxyFD = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC);
*reason = EGET();
if (*proxyFD == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to socket failed. "
<< "Error is " << EGET() << " '" << ESTR()
<< "Error is " << *reason << " '" << ESTR()
<< "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to socket failed. "
<< "Error is " << EGET() << " '" << ESTR()
<< "Error is " << *reason << " '" << ESTR()
<< "'.\n";
goto ConnectToRemoteError;
}
else if (SetReuseAddress(proxyFD) < 0)
{
goto ConnectToRemoteError;
return -1;
}
//
......@@ -7106,6 +7068,59 @@ int ConnectToRemote(const char *const hostName, int portNum)
// if there is a network problem.
//
if (timeout)
SetTimer(*timeout);
else
SetTimer(20000);
int result = connect(*proxyFD, (sockaddr *) &addr, sizeof(sockaddr_un));
*reason = EGET();
ResetTimer();
return result;
}
//
// Connect to remote proxy. If successful
// return FD of connection, else return -1.
//
int ConnectToRemote(ChannelEndPoint &socketAddress)
{
//
// How many times we retry to connect to remote
// host / Unix domain socket in case of failure?
//
int retryConnect = control -> OptionProxyRetryConnect;
//
// Show an alert after 20 seconds and use the
// same timeout to interrupt the connect. The
// retry timeout is incremental, starting from
// 100 miliseconds up to 1 second.
//
int alertTimeout = 20000;
int connectTimeout = 20000;
int retryTimeout = 100;
T_timestamp lastRetry = getNewTimestamp();
int result = -1;
int reason = -1;
int proxyFD = -1;
char *hostName = NULL;
long int portNum = -1;
char *unixPath = NULL;
for (;;)
{
#ifdef DEBUG
*logofs << "Loop: Timer set to " << connectTimeout / 1000
<< " S " << "with retry set to " << retryConnect
......@@ -7113,13 +7128,10 @@ int ConnectToRemote(const char *const hostName, int portNum)
<< "'.\n" << logofs_flush;
#endif
SetTimer(connectTimeout);
int result = connect(proxyFD, (sockaddr *) &addr, sizeof(sockaddr_in));
int reason = EGET();
ResetTimer();
if (socketAddress.getUnixPath(&unixPath))
result = PrepareProxyConnectionUnix(&unixPath, &connectTimeout, &proxyFD, &reason);
else if (socketAddress.getTCPHostAndPort(&hostName, &portNum))
result = PrepareProxyConnectionTCP(&hostName, &portNum, &connectTimeout, &proxyFD, &reason);
if (result < 0)
{
......@@ -7133,6 +7145,22 @@ int ConnectToRemote(const char *const hostName, int portNum)
{
ESET(reason);
if (socketAddress.isUnixSocket())
{
#ifdef PANIC
*logofs << "Loop: PANIC! Connection to Unix file socket '"
<< unixPath << "' failed. Error is "
<< EGET() << " '" << ESTR() << "'.\n"
<< logofs_flush;
#endif
cerr << "Error" << ": Connection to Unix file socket '"
<< unixPath << "' failed. Error is "
<< EGET() << " '" << ESTR() << "'.\n";
}
else
{
#ifdef PANIC
*logofs << "Loop: PANIC! Connection to '" << hostName
<< ":" << portNum << "' failed. Error is "
......@@ -7143,14 +7171,14 @@ int ConnectToRemote(const char *const hostName, int portNum)
cerr << "Error" << ": Connection to '" << hostName
<< ":" << portNum << "' failed. Error is "
<< EGET() << " '" << ESTR() << "'.\n";
}
goto ConnectToRemoteError;
}
else
{
#ifdef TEST
*logofs << "Loop: Sleeping " << retryTimeout
<< " Ms before retrying.\n"
<< " ms before retrying.\n"
<< logofs_flush;
#endif
......@@ -7219,10 +7247,20 @@ int ConnectToRemote(const char *const hostName, int portNum)
ESET(reason);
#ifdef TEST
if (unixPath[0] != '\0' )
{
*logofs << "Loop: Connection to Unix socket file '"
<< unixPath << "' failed with error '"
<< ESTR() << "'. Retrying.\n"
<< logofs_flush;
}
else
{
*logofs << "Loop: Connection to '" << hostName
<< ":" << portNum << "' failed with error '"
<< ESTR() << "'. Retrying.\n"
<< logofs_flush;
}
#endif
}
else
......@@ -8448,6 +8486,9 @@ int ParseEnvironmentOptions(const char *env, int force)
name = strtok(nextOpts, "=");
char connectHost[DEFAULT_STRING_LENGTH] = { 0 };
long connectPort = -1;
while (name)
{
value = strtok(NULL, ",");
......@@ -8468,6 +8509,7 @@ int ParseEnvironmentOptions(const char *env, int force)
}
else if (strcasecmp(name, "link") == 0)
{
if (control -> ProxyMode == proxy_server)
{
PrintOptionIgnored("local", name, value);
......@@ -8529,26 +8571,29 @@ int ParseEnvironmentOptions(const char *env, int force)
}
else if (strcasecmp(name, "listen") == 0)
{
if (*connectHost != '\0')
char *socketUri = NULL;
if (connectSocket.getSpec(&socketUri))
{
#ifdef PANIC
*logofs << "Loop: PANIC! Can't handle 'listen' and 'connect' parameters "
<< "at the same time.\n" << logofs_flush;
*logofs << "Loop: PANIC! Refusing 'listen' parameter with 'connect' being '"
<< connectHost << "'.\n" << logofs_flush;
<< socketUri << "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Can't handle 'listen' and 'connect' parameters "
<< "at the same time.\n";
cerr << "Error" << ": Refusing 'listen' parameter with 'connect' being '"
<< connectHost << "'.\n";
<< socketUri << "'.\n";
free(socketUri);
return -1;
}
listenPort = ValidateArg("local", name, value);
SetAndValidateChannelEndPointArg("local", name, value, listenSocket);
}
else if (strcasecmp(name, "loopback") == 0)
{
......@@ -8556,22 +8601,24 @@ int ParseEnvironmentOptions(const char *env, int force)
}
else if (strcasecmp(name, "accept") == 0)
{
if (*connectHost != '\0')
char *socketUri = NULL;
if (connectSocket.getSpec(&socketUri))
{
#ifdef PANIC
*logofs << "Loop: PANIC! Can't handle 'accept' and 'connect' parameters "
<< "at the same time.\n" << logofs_flush;
*logofs << "Loop: PANIC! Refusing 'accept' parameter with 'connect' being '"
<< connectHost << "'.\n" << logofs_flush;
<< socketUri << "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Can't handle 'accept' and 'connect' parameters "
<< "at the same time.\n";
cerr << "Error" << ": Refusing 'accept' parameter with 'connect' being '"
<< connectHost << "'.\n";
<< socketUri << "'.\n";
free(socketUri);
return -1;
}
......@@ -8597,8 +8644,12 @@ int ParseEnvironmentOptions(const char *env, int force)
return -1;
}
strncpy(connectHost, value, DEFAULT_STRING_LENGTH - 1);
if ((strncmp(value, "tcp:", 4) == 0) || (strncmp(value, "unix:", 5) == 0))
SetAndValidateChannelEndPointArg("local", name, value, connectSocket);
else
// if the "connect" parameter does not start with "unix:" or "tcp:" assume
// old parameter usage style (providing hostname string only).
strcpy(connectHost, value);
}
else if (strcasecmp(name, "port") == 0)
{
......@@ -9056,6 +9107,17 @@ int ParseEnvironmentOptions(const char *env, int force)
} // End of while (name) ...
// Assemble the connectSocket channel end point if parameter values have been old-school...
if (connectSocket.disabled() && (connectHost[0] != '\0') && (proxyPort > 0 || connectPort > 0))
{
if (connectPort < 0)
connectPort = proxyPort + DEFAULT_NX_PROXY_PORT_OFFSET;
char tcpHostAndPort[DEFAULT_STRING_LENGTH] = { 0 };
sprintf(tcpHostAndPort, "tcp:%s:%ld", connectHost, connectPort);
SetAndValidateChannelEndPointArg("local", name, tcpHostAndPort, connectSocket);
}
#ifdef TEST
*logofs << "Loop: Completed parsing of string '"
<< env << "'.\n" << logofs_flush;
......@@ -9296,15 +9358,20 @@ int ParseCommandLineOptions(int argc, const char **argv)
// command line at the connecting side.
//
if (ParseHostOption(nextArg, connectHost, connectPort) > 0)
char *cHost;
long cPort;
if (connectSocket.getTCPHostAndPort(&cHost, &cPort) && (ParseHostOption(nextArg, cHost, cPort) > 0))
{
//
// Assume port is at a proxied display offset.
//
proxyPort = connectPort;
proxyPort = cPort;
cPort += DEFAULT_NX_PROXY_PORT_OFFSET;
connectSocket.setSpec(cHost, cPort);
connectPort += DEFAULT_NX_PROXY_PORT_OFFSET;
}
else if (ParseEnvironmentOptions(nextArg, 1) < 0)
{
......@@ -13409,7 +13476,7 @@ int ParseBitrateOption(const char *opt)
return 1;
}
int ParseHostOption(const char *opt, char *host, int &port)
int ParseHostOption(const char *opt, char *host, long &port)
{
#ifdef TEST
*logofs << "Loop: Trying to parse options string '" << opt
......@@ -13676,40 +13743,6 @@ ParseFontPathError:
return -1;
}
int ParseListenOption(int &address)
{
if (*listenHost == '\0')
{
//
// On the X client side listen on any address.
// On the X server side listen to the forwarder
// on localhost.
//
if (control -> ProxyMode == proxy_server)
{
address = (int) inet_addr("127.0.0.1");
}
else
{
if ( loopbackBind )
{
address = htonl(INADDR_LOOPBACK);
}
else
{
address = htonl(INADDR_ANY);
}
}
}
else
{
address = inet_addr(listenHost);
}
return 1;
}
int OpenLogFile(char *name, ostream *&stream)
{
if (name == NULL || *name == '\0')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment