Added support for terminating inactive/active/disconnected sessions. This is a port of the SF patch 1025108.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@203 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/rfb/ServerCore.cxx b/rfb/ServerCore.cxx
index ea1ff27..fe61ecb 100644
--- a/rfb/ServerCore.cxx
+++ b/rfb/ServerCore.cxx
@@ -30,6 +30,19 @@
("IdleTimeout",
"The number of seconds after which an idle VNC connection will be dropped",
0);
+
+rfb::IntParameter rfb::Server::maxDisconnectionTime
+("MaxDisconnectionTime",
+ "Terminate when no client has been connected for s seconds",
+ 0);
+rfb::IntParameter rfb::Server::maxConnectionTime
+("MaxConnectionTime",
+ "Terminate when a client has been connected for s seconds",
+ 0);
+rfb::IntParameter rfb::Server::maxIdleTime
+("MaxIdleTime",
+ "Terminate after s seconds of user inactivity",
+ 0);
rfb::IntParameter rfb::Server::clientWaitTimeMillis
("ClientWaitTimeMillis",
"The number of milliseconds to wait for a client which is no longer "
diff --git a/rfb/ServerCore.h b/rfb/ServerCore.h
index 74d7443..b01fcfd 100644
--- a/rfb/ServerCore.h
+++ b/rfb/ServerCore.h
@@ -33,6 +33,9 @@
public:
static IntParameter idleTimeout;
+ static IntParameter maxDisconnectionTime;
+ static IntParameter maxConnectionTime;
+ static IntParameter maxIdleTime;
static IntParameter clientWaitTimeMillis;
static StringParameter sec_types;
static StringParameter rev_sec_types;
diff --git a/rfb/VNCSConnectionST.cxx b/rfb/VNCSConnectionST.cxx
index a20ec01..ce48b3e 100644
--- a/rfb/VNCSConnectionST.cxx
+++ b/rfb/VNCSConnectionST.cxx
@@ -98,6 +98,10 @@
else
vlog.debug("second close: %s (%s)", peerEndpoint.buf, reason);
+ if (authenticated()) {
+ server->lastDisconnectTime = time(0);
+ }
+
// Just shutdown the socket. This will cause processMessages to
// eventually fail, causing us and our socket to be deleted.
sock->shutdown();
@@ -389,6 +393,7 @@
void VNCSConnectionST::pointerEvent(int x, int y, int buttonMask)
{
pointerEventTime = lastEventTime = time(0);
+ server->lastUserInputTime = lastEventTime;
if (!(accessRights & AccessPtrEvents)) return;
if (!rfb::Server::acceptPointerEvents) return;
if (!server->pointerClient || server->pointerClient == this) {
@@ -421,6 +426,7 @@
// multiple down events (for autorepeat), but only allow a single up event.
void VNCSConnectionST::keyEvent(rdr::U32 key, bool down) {
lastEventTime = time(0);
+ server->lastUserInputTime = lastEventTime;
if (!(accessRights & AccessKeyEvents)) return;
if (!rfb::Server::acceptKeyEvents) return;
diff --git a/rfb/VNCServerST.cxx b/rfb/VNCServerST.cxx
index b3f9e88..9a8013e 100644
--- a/rfb/VNCServerST.cxx
+++ b/rfb/VNCServerST.cxx
@@ -80,8 +80,10 @@
name(strDup(name_)), pointerClient(0), comparer(0),
renderedCursorInvalid(false),
securityFactory(sf ? sf : &defaultSecurityFactory),
- queryConnectionHandler(0), useEconomicTranslate(false)
+ queryConnectionHandler(0), useEconomicTranslate(false),
+ lastConnectionTime(0)
{
+ lastUserInputTime = lastDisconnectTime = time(0);
slog.debug("creating single-threaded server %s", name.buf);
}
@@ -138,6 +140,10 @@
return;
}
+ if (clients.empty()) {
+ lastConnectionTime = time(0);
+ }
+
VNCSConnectionST* client = new VNCSConnectionST(this, sock, reverse);
client->init();
}
@@ -179,6 +185,79 @@
ci_next = ci; ci_next++;
soonestTimeout(&timeout, (*ci)->checkIdleTimeout());
}
+
+ int timeLeft;
+ time_t now;
+
+ // Optimization: Only call time() if using any maxTime.
+ if (rfb::Server::maxDisconnectionTime || rfb::Server::maxConnectionTime || rfb::Server::maxIdleTime) {
+ now = time(0);
+ }
+
+ // Check MaxDisconnectionTime
+ if (rfb::Server::maxDisconnectionTime && clients.empty()) {
+ if (now < lastDisconnectTime) {
+ // Someone must have set the time backwards.
+ slog.info("Time has gone backwards - resetting lastDisconnectTime");
+ lastDisconnectTime = now;
+ }
+ timeLeft = lastDisconnectTime + rfb::Server::maxDisconnectionTime - now;
+ if (timeLeft < -60) {
+ // Someone must have set the time forwards.
+ slog.info("Time has gone forwards - resetting lastDisconnectTime");
+ lastDisconnectTime = now;
+ timeLeft = rfb::Server::maxDisconnectionTime;
+ }
+ if (timeLeft <= 0) {
+ slog.info("MaxDisconnectionTime reached, exiting");
+ exit(0);
+ }
+ soonestTimeout(&timeout, timeLeft * 1000);
+ }
+
+ // Check MaxConnectionTime
+ if (rfb::Server::maxConnectionTime && lastConnectionTime && !clients.empty()) {
+ if (now < lastConnectionTime) {
+ // Someone must have set the time backwards.
+ slog.info("Time has gone backwards - resetting lastConnectionTime");
+ lastConnectionTime = now;
+ }
+ timeLeft = lastConnectionTime + rfb::Server::maxConnectionTime - now;
+ if (timeLeft < -60) {
+ // Someone must have set the time forwards.
+ slog.info("Time has gone forwards - resetting lastConnectionTime");
+ lastConnectionTime = now;
+ timeLeft = rfb::Server::maxConnectionTime;
+ }
+ if (timeLeft <= 0) {
+ slog.info("MaxConnectionTime reached, exiting");
+ exit(0);
+ }
+ soonestTimeout(&timeout, timeLeft * 1000);
+ }
+
+
+ // Check MaxIdleTime
+ if (rfb::Server::maxIdleTime) {
+ if (now < lastUserInputTime) {
+ // Someone must have set the time backwards.
+ slog.info("Time has gone backwards - resetting lastUserInputTime");
+ lastUserInputTime = now;
+ }
+ timeLeft = lastUserInputTime + rfb::Server::maxIdleTime - now;
+ if (timeLeft < -60) {
+ // Someone must have set the time forwards.
+ slog.info("Time has gone forwards - resetting lastUserInputTime");
+ lastUserInputTime = now;
+ timeLeft = rfb::Server::maxIdleTime;
+ }
+ if (timeLeft <= 0) { // enough time has gone
+ slog.info("MaxIdleTime reached, exiting");
+ exit(0);
+ }
+ soonestTimeout(&timeout, timeLeft * 1000);
+ }
+
return timeout;
}
diff --git a/rfb/VNCServerST.h b/rfb/VNCServerST.h
index 6655a0d..a6939c8 100644
--- a/rfb/VNCServerST.h
+++ b/rfb/VNCServerST.h
@@ -225,6 +225,10 @@
SSecurityFactory* securityFactory;
QueryConnectionHandler* queryConnectionHandler;
bool useEconomicTranslate;
+
+ time_t lastUserInputTime;
+ time_t lastDisconnectTime;
+ time_t lastConnectionTime;
};
};