aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Gabriel <mike.gabriel@das-netzwerkteam.de>2016-10-28 14:48:25 +0200
committerMike Gabriel <mike.gabriel@das-netzwerkteam.de>2016-10-28 14:48:25 +0200
commitc9da511cf0cf93efc9a9d8578ef1e0924ccee33c (patch)
tree549a8e65cfdb30a04e62f680a54c6a60b7810fdf
parenta5de79181092ce829ce3878d3d9ce671c3cd3cbc (diff)
parentc7eac1f95626e376b17ccd684b2a4e9402b3c17c (diff)
downloadnx-libs-c9da511cf0cf93efc9a9d8578ef1e0924ccee33c.tar.gz
nx-libs-c9da511cf0cf93efc9a9d8578ef1e0924ccee33c.tar.bz2
nx-libs-c9da511cf0cf93efc9a9d8578ef1e0924ccee33c.zip
Merge branch 'theqvd-slave-channel' into 3.6.x
Attributes GH PR #232: https://github.com/ArcticaProject/nx-libs/pull/232
-rw-r--r--nxcomp/Loop.cpp4
-rw-r--r--nxcomp/Misc.cpp7
-rw-r--r--nxcomp/Proxy.cpp183
-rw-r--r--nxcomp/Proxy.h3
-rw-r--r--nxproxy/man/nxproxy.17
5 files changed, 170 insertions, 34 deletions
diff --git a/nxcomp/Loop.cpp b/nxcomp/Loop.cpp
index 46031e70d..09ba6f952 100644
--- a/nxcomp/Loop.cpp
+++ b/nxcomp/Loop.cpp
@@ -359,7 +359,7 @@ static void RestoreSignal(int signal);
static int HandleChildren();
-static int HandleChild(int child);
+int HandleChild(int child);
static int CheckChild(int pid, int status);
static int WaitChild(int child, const char *label, int force);
@@ -6250,6 +6250,8 @@ int HandleChildren()
return 1;
}
+ proxy->checkSlaves();
+
//
// This can actually happen either because we
// reset the pid of the child process as soon
diff --git a/nxcomp/Misc.cpp b/nxcomp/Misc.cpp
index 71013fc6f..09a0b29d2 100644
--- a/nxcomp/Misc.cpp
+++ b/nxcomp/Misc.cpp
@@ -358,6 +358,13 @@ tolerancechecks=s\n\
ory compared to the other programs, to make easier\n\
for the user to execute the program from the shell.\n\
\n\
+ NX_SLAVE_CMD The full path to the slave channel handler. When the\n\
+ slave channel is enabled, the agent will listen on a\n\
+ port and forward the connection to the NX_SLAVE_CMD\n\
+ program. This can be used to implement agent/proxy\n\
+ communication for applications such as serial port and\n\
+ USB forwarding.\n\
+\n\
Shell environment:\n\
\n\
HOME The variable is checked in the case NX_HOME is not\n\
diff --git a/nxcomp/Proxy.cpp b/nxcomp/Proxy.cpp
index e499b443e..123181489 100644
--- a/nxcomp/Proxy.cpp
+++ b/nxcomp/Proxy.cpp
@@ -29,6 +29,8 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <signal.h>
+
#ifdef ANDROID
#include <netinet/in.h>
#include <netinet/ip.h>
@@ -92,6 +94,8 @@ struct sockaddr_un
extern void CleanupListeners();
+extern int HandleChild(int);
+
//
// Default size of string buffers.
//
@@ -165,6 +169,7 @@ Proxy::Proxy(int fd)
fdMap_[channelId] = nothing;
channelMap_[channelId] = nothing;
+ slavePidMap_[channelId] = nothing;
}
inputChannel_ = nothing;
@@ -296,6 +301,66 @@ Proxy::~Proxy()
}
}
+ //
+ // Kill all active slave channel children, and
+ // give them 5 seconds to exit nicely.
+
+ #ifdef DEBUG
+ *logofs << "Proxy: Killing active slaves" << endl;
+ #endif
+
+ int slave_count = 999;
+ int loop_count = 0;
+
+ while(slave_count > 0 && loop_count < 50)
+ {
+ slave_count = 0;
+
+ for (int channelId = 0; channelId<CONNECTIONS_LIMIT; channelId++)
+ {
+ int pid = slavePidMap_[channelId];
+
+ if (pid > 1) {
+ slave_count++;
+
+ #ifdef DEBUG
+ *logofs << "Proxy: Active slave with pid " << pid << logofs_flush;
+ #endif
+
+ if ( loop_count == 0 )
+ {
+ #ifdef DEBUG
+ *logofs << "Proxy: Sending SIGTERM to " << pid << logofs_flush;
+ #endif
+ kill(pid, SIGTERM);
+ }
+ else if ( loop_count == 25 )
+ {
+ #ifdef DEBUG
+ *logofs << "Proxy: Sending SIGKILL to " << pid << logofs_flush;
+ #endif
+ kill(pid, SIGKILL);
+ }
+
+ if (HandleChild(pid))
+ {
+ #ifdef DEBUG
+ *logofs << "Proxy: Slave " << pid << " terminated" << logofs_flush;
+ #endif
+ slavePidMap_[channelId] = nothing;
+ }
+ }
+ }
+
+ if ( slave_count > 0 )
+ {
+ cerr << "Proxy: Error: Failed to kill all slave channel processes. " << slave_count << " processes still remaining." << endl;
+ }
+
+ usleep(200000);
+ loop_count++;
+ }
+
delete transport_;
delete compressor_;
@@ -6308,42 +6373,94 @@ int Proxy::handleNewGenericConnectionFromProxyUnix(int channelId, T_channel_type
int Proxy::handleNewSlaveConnectionFromProxy(int channelId)
{
- //
- // Implementation is incomplete. Opening a
- // slave channel should let the proxy fork
- // a new client and pass to it the channel
- // descriptors. For now we make the channel
- // fail immediately.
- //
- // #include <fcntl.h>
- // #include <sys/types.h>
- // #include <sys/stat.h>
- //
- // char *slaveServer = "/dev/null";
- //
- // #ifdef TEST
- // *logofs << "Proxy: Opening file '" << slaveServer
- // << "'.\n" << logofs_flush;
- // #endif
- //
- // int serverFd = open(slaveServer, O_RDWR);
- //
- // if (handlePostConnectionFromProxy(channelId, serverFd, channel_slave, "slave") < 0)
- // {
- // return -1;
- // }
- //
- #ifdef WARNING
- *logofs << "Proxy: Refusing new slave connection for "
- << "channel ID#" << channelId << "\n"
- << logofs_flush;
- #endif
+ cerr << "Info" << ": New slave connection on "
+ << "channel ID#" << channelId << "\n";
+
+ char *nx_slave_cmd = getenv("NX_SLAVE_CMD");
+ if (nx_slave_cmd == NULL) {
+ return -1;
+ }
- cerr << "Warning" << ": Refusing new slave connection for "
- << "channel ID#" << channelId << "\n";
+ int spair[2];
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, spair) == -1) {
+ perror("socketpair");
+ return -1;
+ }
- return -1;
+ int serverFd = spair[0];
+ int clientFd = spair[1];
+
+ if (handlePostConnectionFromProxy(channelId, serverFd, channel_slave, "slave") < 0)
+ {
+ close(serverFd);
+ close(clientFd);
+ return -1;
+ }
+
+
+ int pid = fork();
+ if (pid == 0)
+ {
+
+ if (dup2(clientFd, 0) == -1)
+ {
+ perror("dup2");
+ exit(1);
+ }
+
+ if (dup2(clientFd, 1) == -1)
+ {
+ perror("dup2");
+ exit(1);
+ }
+
+ close(serverFd);
+ close(clientFd);
+
+ /* Close FDs used by NX, QVD #1208 */
+ for (int fd = 3; fd < 256; fd++) {
+ close(fd);
+ }
+
+ char *const argv[2] = {nx_slave_cmd, NULL};
+
+ if (execv(nx_slave_cmd, argv) == -1)
+ {
+ perror("execv");
+ }
+ exit(1);
+
+ }
+ else if (pid == -1)
+ {
+ // TODO Test this!
+ perror("fork");
+ close(serverFd);
+ close(clientFd);
+ return -1;
+ }
+
+ close(clientFd);
+ slavePidMap_[channelId] = pid;
+
+ cerr << "Info" << ": slave channel ID#" << channelId << " handler has PID " << pid << endl;
+
+ return 1;
+}
+
+void Proxy::checkSlaves()
+{
+ for (int channelId = 0; channelId<CONNECTIONS_LIMIT; channelId++)
+ {
+ int pid = slavePidMap_[channelId];
+
+ if (pid > 1 && HandleChild(pid))
+ {
+ slavePidMap_[channelId] = nothing;
+ cerr << "Info:" << " Handled death of slave with pid " << pid << endl;
+ }
+ }
}
int Proxy::handlePostConnectionFromProxy(int channelId, int serverFd,
diff --git a/nxcomp/Proxy.h b/nxcomp/Proxy.h
index 8259ddbb7..ea60c827a 100644
--- a/nxcomp/Proxy.h
+++ b/nxcomp/Proxy.h
@@ -302,6 +302,8 @@ class Proxy
int handleNewSlaveConnectionFromProxy(int channelId);
+ void checkSlaves();
+
//
// Force closure of channels.
//
@@ -1268,6 +1270,7 @@ class Proxy
int channelMap_[CONNECTIONS_LIMIT];
int fdMap_[CONNECTIONS_LIMIT];
+ int slavePidMap_[CONNECTIONS_LIMIT];
};
#endif /* Proxy_H */
diff --git a/nxproxy/man/nxproxy.1 b/nxproxy/man/nxproxy.1
index 7b950a607..3cf95c992 100644
--- a/nxproxy/man/nxproxy.1
+++ b/nxproxy/man/nxproxy.1
@@ -339,6 +339,13 @@ where <nxclient> is located in a different directory compared to the
other programs, to make easier for the user to execute the program from
the shell.
+.TP 8
+.B NX_SLAVE_CMD
+The full path to the slave channel handler. When the slave channel is
+enabled, the agent will listen on a port and forward the connection to
+the NX_SLAVE_CMD program. This can be used to implement agent/proxy
+communication for applications such as serial port and USB forwarding.
+
.SH SHELL ENVIRONMENT VARIABLES
.TP 8