Browse Source

Merge branch 'exittimer' of https://github.com/CendioOssman/tigervnc

tags/v1.9.90
Pierre Ossman 5 years ago
parent
commit
b85febcd75

+ 0
- 7
common/network/Socket.h View File

@@ -144,13 +144,6 @@ namespace network {
// This is only necessary if the Socket has been put in non-blocking
// mode and needs this callback to flush the buffer.
virtual void processSocketWriteEvent(network::Socket* sock) = 0;

// checkTimeouts() allows the server to check socket timeouts, etc. The
// return value is the number of milliseconds to wait before
// checkTimeouts() should be called again. If this number is zero then
// there is no timeout and checkTimeouts() should be called the next time
// an event occurs.
virtual int checkTimeouts() = 0;
};

}

+ 6
- 0
common/rfb/SDesktop.h View File

@@ -75,6 +75,12 @@ namespace rfb {
virtual void queryConnection(network::Socket* sock,
const char* userName) = 0;

// terminate() is called by the server when it wishes to terminate
// itself, e.g. because it was configured to terminate when no one is
// using it.

virtual void terminate() = 0;

// setScreenLayout() requests to reconfigure the framebuffer and/or
// the layout of screens.
virtual unsigned int setScreenLayout(int __unused_attr fb_width,

+ 23
- 38
common/rfb/VNCSConnectionST.cxx View File

@@ -51,15 +51,23 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
fenceDataLen(0), fenceData(NULL), congestionTimer(this),
losslessTimer(this), server(server_), updates(false),
updateRenderedCursor(false), removeRenderedCursor(false),
continuousUpdates(false), encodeManager(this), pointerEventTime(0),
clientHasCursor(false)
continuousUpdates(false), encodeManager(this), idleTimer(this),
pointerEventTime(0), clientHasCursor(false)
{
setStreams(&sock->inStream(), &sock->outStream());
peerEndpoint.buf = sock->getPeerEndpoint();

// Configure the socket
setSocketTimeouts();
lastEventTime = time(0);

// Kick off the idle timer
if (rfb::Server::idleTimeout) {
// minimum of 15 seconds while authenticating
if (rfb::Server::idleTimeout < 15)
idleTimer.start(secsToMillis(15));
else
idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
}
}


@@ -312,36 +320,6 @@ void VNCSConnectionST::setLEDStateOrClose(unsigned int state)
}


int VNCSConnectionST::checkIdleTimeout()
{
int idleTimeout = rfb::Server::idleTimeout;
if (idleTimeout == 0) return 0;
if (state() != RFBSTATE_NORMAL && idleTimeout < 15)
idleTimeout = 15; // minimum of 15 seconds while authenticating
time_t now = time(0);
if (now < lastEventTime) {
// Someone must have set the time backwards. Set lastEventTime so that the
// idleTimeout will count from now.
vlog.info("Time has gone backwards - resetting idle timeout");
lastEventTime = now;
}
int timeLeft = lastEventTime + idleTimeout - now;
if (timeLeft < -60) {
// Our callback is over a minute late - someone must have set the time
// forwards. Set lastEventTime so that the idleTimeout will count from
// now.
vlog.info("Time has gone forwards - resetting idle timeout");
lastEventTime = now;
return secsToMillis(idleTimeout);
}
if (timeLeft <= 0) {
close("Idle timeout");
return 0;
}
return secsToMillis(timeLeft);
}


bool VNCSConnectionST::getComparerState()
{
// We interpret a low compression level as an indication that the client
@@ -412,7 +390,8 @@ void VNCSConnectionST::approveConnectionOrClose(bool accept,

void VNCSConnectionST::authSuccess()
{
lastEventTime = time(0);
if (rfb::Server::idleTimeout)
idleTimer.start(secsToMillis(rfb::Server::idleTimeout));

// - Set the connection parameters appropriately
cp.width = server->getPixelBuffer()->width();
@@ -438,7 +417,8 @@ void VNCSConnectionST::queryConnection(const char* userName)

void VNCSConnectionST::clientInit(bool shared)
{
lastEventTime = time(0);
if (rfb::Server::idleTimeout)
idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
if (rfb::Server::alwaysShared || reverseConnection) shared = true;
if (!accessCheck(AccessNonShared)) shared = true;
if (rfb::Server::neverShared) shared = false;
@@ -457,7 +437,9 @@ void VNCSConnectionST::setPixelFormat(const PixelFormat& pf)

void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask)
{
pointerEventTime = lastEventTime = time(0);
if (rfb::Server::idleTimeout)
idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
pointerEventTime = time(0);
if (!accessCheck(AccessPtrEvents)) return;
if (!rfb::Server::acceptPointerEvents) return;
pointerEventPos = pos;
@@ -489,7 +471,8 @@ public:
void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) {
rdr::U32 lookup;

lastEventTime = time(0);
if (rfb::Server::idleTimeout)
idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
if (!accessCheck(AccessKeyEvents)) return;
if (!rfb::Server::acceptKeyEvents) return;

@@ -765,6 +748,9 @@ bool VNCSConnectionST::handleTimeout(Timer* t)
close(e.str());
}

if (t == &idleTimer)
close("Idle timeout");

return false;
}

@@ -1106,7 +1092,6 @@ void VNCSConnectionST::setLEDState(unsigned int ledstate)
void VNCSConnectionST::setSocketTimeouts()
{
int timeoutms = rfb::Server::clientWaitTimeMillis;
soonestTimeout(&timeoutms, secsToMillis(rfb::Server::idleTimeout));
if (timeoutms == 0)
timeoutms = -1;
sock->inStream().setTimeout(timeoutms);

+ 2
- 6
common/rfb/VNCSConnectionST.h View File

@@ -77,11 +77,6 @@ namespace rfb {
void setLEDStateOrClose(unsigned int state);
void approveConnectionOrClose(bool accept, const char* reason);

// checkIdleTimeout() returns the number of milliseconds left until the
// idle timeout expires. If it has expired, the connection is closed and
// zero is returned. Zero is also returned if there is no idle timeout.
int checkIdleTimeout();

// The following methods never throw exceptions

// getComparerState() returns if this client would like the framebuffer
@@ -182,7 +177,8 @@ namespace rfb {

std::map<rdr::U32, rdr::U32> pressedKeys;

time_t lastEventTime;
Timer idleTimer;

time_t pointerEventTime;
Point pointerEventPos;
bool clientHasCursor;

+ 29
- 92
common/rfb/VNCServerST.cxx View File

@@ -81,10 +81,16 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
cursor(new Cursor(0, 0, Point(), NULL)),
renderedCursorInvalid(false),
keyRemapper(&KeyRemapper::defInstance),
lastConnectionTime(0), frameTimer(this)
idleTimer(this), disconnectTimer(this), connectTimer(this),
frameTimer(this)
{
lastUserInputTime = lastDisconnectTime = time(0);
slog.debug("creating single-threaded server %s", name.buf);

// FIXME: Do we really want to kick off these right away?
if (rfb::Server::maxIdleTime)
idleTimer.start(secsToMillis(rfb::Server::maxIdleTime));
if (rfb::Server::maxDisconnectionTime)
disconnectTimer.start(secsToMillis(rfb::Server::maxDisconnectionTime));
}

VNCServerST::~VNCServerST()
@@ -144,9 +150,10 @@ void VNCServerST::addSocket(network::Socket* sock, bool outgoing)
name.buf = sock->getPeerEndpoint();
connectionsLog.status("accepted: %s", name.buf);

if (clients.empty()) {
lastConnectionTime = time(0);
}
// Adjust the exit timers
if (rfb::Server::maxConnectionTime && clients.empty())
connectTimer.start(secsToMillis(rfb::Server::maxConnectionTime));
disconnectTimer.stop();

VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing);
clients.push_front(client);
@@ -164,8 +171,10 @@ void VNCServerST::removeSocket(network::Socket* sock) {
if (pointerClient == *ci)
pointerClient = NULL;

if ((*ci)->authenticated())
lastDisconnectTime = time(0);
// Adjust the exit timers
connectTimer.stop();
if (rfb::Server::maxDisconnectionTime && clients.empty())
disconnectTimer.start(secsToMillis(rfb::Server::maxDisconnectionTime));

// - Delete the per-Socket resources
delete *ci;
@@ -215,89 +224,6 @@ void VNCServerST::processSocketWriteEvent(network::Socket* sock)
throw rdr::Exception("invalid Socket in VNCServerST");
}

int VNCServerST::checkTimeouts()
{
int timeout = 0;
std::list<VNCSConnectionST*>::iterator ci, ci_next;

soonestTimeout(&timeout, Timer::checkTimeouts());

for (ci=clients.begin();ci!=clients.end();ci=ci_next) {
ci_next = ci; ci_next++;
soonestTimeout(&timeout, (*ci)->checkIdleTimeout());
}

int timeLeft;
time_t 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) {
slog.info("MaxIdleTime reached, exiting");
exit(0);
}
soonestTimeout(&timeout, timeLeft * 1000);
}
return timeout;
}


// VNCServer methods

void VNCServerST::blockUpdates()
@@ -495,7 +421,8 @@ void VNCServerST::setLEDState(unsigned int state)

void VNCServerST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
{
lastUserInputTime = time(0);
if (rfb::Server::maxIdleTime)
idleTimer.start(secsToMillis(rfb::Server::maxIdleTime));

// Remap the key if required
if (keyRemapper) {
@@ -513,7 +440,8 @@ void VNCServerST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
void VNCServerST::pointerEvent(VNCSConnectionST* client,
const Point& pos, int buttonMask)
{
lastUserInputTime = time(0);
if (rfb::Server::maxIdleTime)
idleTimer.start(secsToMillis(rfb::Server::maxIdleTime));

// Let one client own the cursor whilst buttons are pressed in order
// to provide a bit more sane user experience
@@ -628,6 +556,15 @@ bool VNCServerST::handleTimeout(Timer* t)
}

return true;
} else if (t == &idleTimer) {
slog.info("MaxIdleTime reached, exiting");
desktop->terminate();
} else if (t == &disconnectTimer) {
slog.info("MaxDisconnectionTime reached, exiting");
desktop->terminate();
} else if (t == &connectTimer) {
slog.info("MaxConnectionTime reached, exiting");
desktop->terminate();
}

return false;

+ 3
- 9
common/rfb/VNCServerST.h View File

@@ -76,12 +76,6 @@ namespace rfb {
// Flush pending data from the Socket on to the network.
virtual void processSocketWriteEvent(network::Socket* sock);

// checkTimeouts
// Returns the number of milliseconds left until the next idle timeout
// expires. If any have already expired, the corresponding connections
// are closed. Zero is returned if there is no idle timeout.
virtual int checkTimeouts();


// Methods overridden from VNCServer

@@ -198,9 +192,9 @@ namespace rfb {

KeyRemapper* keyRemapper;

time_t lastUserInputTime;
time_t lastDisconnectTime;
time_t lastConnectionTime;
Timer idleTimer;
Timer disconnectTimer;
Timer connectTimer;

Timer frameTimer;
};

+ 6
- 0
unix/x0vncserver/XDesktop.cxx View File

@@ -19,6 +19,8 @@
*/

#include <assert.h>
#include <signal.h>
#include <unistd.h>

#include <rfb/LogWriter.h>

@@ -273,6 +275,10 @@ void XDesktop::stop() {
pb = 0;
}

void XDesktop::terminate() {
kill(getpid(), SIGTERM);
}

bool XDesktop::isRunning() {
return running;
}

+ 1
- 0
unix/x0vncserver/XDesktop.h View File

@@ -49,6 +49,7 @@ public:
// -=- SDesktop interface
virtual void start(rfb::VNCServer* vs);
virtual void stop();
virtual void terminate();
bool isRunning();
virtual void queryConnection(network::Socket* sock,
const char* userName);

+ 2
- 2
unix/x0vncserver/x0vncserver.cxx View File

@@ -322,7 +322,7 @@ int main(int argc, char** argv)
}
}

soonestTimeout(&wait_ms, server.checkTimeouts());
soonestTimeout(&wait_ms, Timer::checkTimeouts());

tv.tv_sec = wait_ms / 1000;
tv.tv_usec = (wait_ms % 1000) * 1000;
@@ -357,7 +357,7 @@ int main(int argc, char** argv)
}
}

server.checkTimeouts();
Timer::checkTimeouts();

// Client list could have been changed.
server.getSockets(&sockets);

+ 7
- 1
unix/xserver/hw/vnc/XserverDesktop.cc View File

@@ -22,6 +22,7 @@
//

#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
@@ -367,7 +368,7 @@ void XserverDesktop::blockHandler(int* timeout)
}

// Trigger timers and check when the next will expire
int nextTimeout = server->checkTimeouts();
int nextTimeout = Timer::checkTimeouts();
if (nextTimeout > 0 && (*timeout == -1 || nextTimeout < *timeout))
*timeout = nextTimeout;
} catch (rdr::Exception& e) {
@@ -423,6 +424,11 @@ void XserverDesktop::approveConnection(uint32_t opaqueId, bool accept,
// SDesktop callbacks


void XserverDesktop::terminate()
{
kill(getpid(), SIGTERM);
}

void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
{
vncPointerMove(pos.x + vncGetScreenX(screenIndex),

+ 1
- 0
unix/xserver/hw/vnc/XserverDesktop.h View File

@@ -87,6 +87,7 @@ public:
// rfb::SDesktop callbacks
virtual void start(rfb::VNCServer* vs);
virtual void stop();
virtual void terminate();
virtual void queryConnection(network::Socket* sock,
const char* userName);
virtual void pointerEvent(const rfb::Point& pos, int buttonMask);

+ 6
- 0
win/rfb_win32/SDisplay.cxx View File

@@ -71,6 +71,7 @@ SDisplay::SDisplay()
statusLocation(0), queryConnectionHandler(0), ledState(0)
{
updateEvent.h = CreateEvent(0, TRUE, FALSE, 0);
terminateEvent.h = CreateEvent(0, TRUE, FALSE, 0);
}

SDisplay::~SDisplay()
@@ -140,6 +141,11 @@ void SDisplay::stop()
if (statusLocation) *statusLocation = false;
}

void SDisplay::terminate()
{
SetEvent(terminateEvent);
}


void SDisplay::queryConnection(network::Socket* sock,
const char* userName)

+ 4
- 0
win/rfb_win32/SDisplay.h View File

@@ -72,6 +72,7 @@ namespace rfb {

virtual void start(VNCServer* vs);
virtual void stop();
virtual void terminate();
virtual void queryConnection(network::Socket* sock,
const char* userName);
virtual void pointerEvent(const Point& pos, int buttonmask);
@@ -89,6 +90,7 @@ namespace rfb {
// -=- EventHandler interface

HANDLE getUpdateEvent() {return updateEvent;}
HANDLE getTerminateEvent() {return terminateEvent;}
virtual void processEvent(HANDLE event);

// -=- Notification of whether or not SDisplay is started
@@ -161,6 +163,8 @@ namespace rfb {

// -=- Event signalled to trigger an update to be flushed
Handle updateEvent;
// -=- Event signalled to terminate the server
Handle terminateEvent;

// -=- Where to write the active/inactive indicator to
bool* statusLocation;

+ 2
- 1
win/rfb_win32/SocketManager.cxx View File

@@ -21,6 +21,7 @@
#include <winsock2.h>
#include <list>
#include <rfb/LogWriter.h>
#include <rfb/Timer.h>
#include <rfb_win32/SocketManager.h>

using namespace rfb;
@@ -161,7 +162,7 @@ int SocketManager::checkTimeouts() {

std::map<HANDLE,ListenInfo>::iterator i;
for (i=listeners.begin(); i!=listeners.end(); i++)
soonestTimeout(&timeout, i->second.server->checkTimeouts());
soonestTimeout(&timeout, Timer::checkTimeouts());

std::list<network::Socket*> shutdownSocks;
std::map<HANDLE,ConnInfo>::iterator j, j_next;

+ 3
- 1
win/winvnc/VNCServerWin32.cxx View File

@@ -76,6 +76,7 @@ VNCServerWin32::VNCServerWin32()

// Register the desktop's event to be handled
sockMgr.addEvent(desktop.getUpdateEvent(), &desktop);
sockMgr.addEvent(desktop.getTerminateEvent(), this);

// Register the queued command event to be handled
sockMgr.addEvent(commandEvent, this);
@@ -335,7 +336,8 @@ void VNCServerWin32::processEvent(HANDLE event_) {
command = NoCommand;
commandSig->signal();
}
} else if (event_ == sessionEvent.h) {
} else if ((event_ == sessionEvent.h) ||
(event_ == desktop.getTerminateEvent())) {
stop();
}
}

Loading…
Cancel
Save