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

// This is only necessary if the Socket has been put in non-blocking // This is only necessary if the Socket has been put in non-blocking
// mode and needs this callback to flush the buffer. // mode and needs this callback to flush the buffer.
virtual void processSocketWriteEvent(network::Socket* sock) = 0; 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

virtual void queryConnection(network::Socket* sock, virtual void queryConnection(network::Socket* sock,
const char* userName) = 0; 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 // setScreenLayout() requests to reconfigure the framebuffer and/or
// the layout of screens. // the layout of screens.
virtual unsigned int setScreenLayout(int __unused_attr fb_width, virtual unsigned int setScreenLayout(int __unused_attr fb_width,

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

fenceDataLen(0), fenceData(NULL), congestionTimer(this), fenceDataLen(0), fenceData(NULL), congestionTimer(this),
losslessTimer(this), server(server_), updates(false), losslessTimer(this), server(server_), updates(false),
updateRenderedCursor(false), removeRenderedCursor(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()); setStreams(&sock->inStream(), &sock->outStream());
peerEndpoint.buf = sock->getPeerEndpoint(); peerEndpoint.buf = sock->getPeerEndpoint();


// Configure the socket // Configure the socket
setSocketTimeouts(); 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));
}
} }




} }




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() bool VNCSConnectionST::getComparerState()
{ {
// We interpret a low compression level as an indication that the client // We interpret a low compression level as an indication that the client


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


// - Set the connection parameters appropriately // - Set the connection parameters appropriately
cp.width = server->getPixelBuffer()->width(); cp.width = server->getPixelBuffer()->width();


void VNCSConnectionST::clientInit(bool shared) 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 (rfb::Server::alwaysShared || reverseConnection) shared = true;
if (!accessCheck(AccessNonShared)) shared = true; if (!accessCheck(AccessNonShared)) shared = true;
if (rfb::Server::neverShared) shared = false; if (rfb::Server::neverShared) shared = false;


void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask) 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 (!accessCheck(AccessPtrEvents)) return;
if (!rfb::Server::acceptPointerEvents) return; if (!rfb::Server::acceptPointerEvents) return;
pointerEventPos = pos; pointerEventPos = pos;
void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) { void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) {
rdr::U32 lookup; rdr::U32 lookup;


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


close(e.str()); close(e.str());
} }


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

return false; return false;
} }


void VNCSConnectionST::setSocketTimeouts() void VNCSConnectionST::setSocketTimeouts()
{ {
int timeoutms = rfb::Server::clientWaitTimeMillis; int timeoutms = rfb::Server::clientWaitTimeMillis;
soonestTimeout(&timeoutms, secsToMillis(rfb::Server::idleTimeout));
if (timeoutms == 0) if (timeoutms == 0)
timeoutms = -1; timeoutms = -1;
sock->inStream().setTimeout(timeoutms); sock->inStream().setTimeout(timeoutms);

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

void setLEDStateOrClose(unsigned int state); void setLEDStateOrClose(unsigned int state);
void approveConnectionOrClose(bool accept, const char* reason); 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 // The following methods never throw exceptions


// getComparerState() returns if this client would like the framebuffer // getComparerState() returns if this client would like the framebuffer


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


time_t lastEventTime;
Timer idleTimer;

time_t pointerEventTime; time_t pointerEventTime;
Point pointerEventPos; Point pointerEventPos;
bool clientHasCursor; bool clientHasCursor;

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

cursor(new Cursor(0, 0, Point(), NULL)), cursor(new Cursor(0, 0, Point(), NULL)),
renderedCursorInvalid(false), renderedCursorInvalid(false),
keyRemapper(&KeyRemapper::defInstance), 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); 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() VNCServerST::~VNCServerST()
name.buf = sock->getPeerEndpoint(); name.buf = sock->getPeerEndpoint();
connectionsLog.status("accepted: %s", name.buf); 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); VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing);
clients.push_front(client); clients.push_front(client);
if (pointerClient == *ci) if (pointerClient == *ci)
pointerClient = NULL; 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 the per-Socket resources
delete *ci; delete *ci;
throw rdr::Exception("invalid Socket in VNCServerST"); 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 // VNCServer methods


void VNCServerST::blockUpdates() void VNCServerST::blockUpdates()


void VNCServerST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) 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 // Remap the key if required
if (keyRemapper) { if (keyRemapper) {
void VNCServerST::pointerEvent(VNCSConnectionST* client, void VNCServerST::pointerEvent(VNCSConnectionST* client,
const Point& pos, int buttonMask) 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 // Let one client own the cursor whilst buttons are pressed in order
// to provide a bit more sane user experience // to provide a bit more sane user experience
} }


return true; 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; return false;

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

// Flush pending data from the Socket on to the network. // Flush pending data from the Socket on to the network.
virtual void processSocketWriteEvent(network::Socket* sock); 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 // Methods overridden from VNCServer




KeyRemapper* keyRemapper; KeyRemapper* keyRemapper;


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


Timer frameTimer; Timer frameTimer;
}; };

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

*/ */


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


#include <rfb/LogWriter.h> #include <rfb/LogWriter.h>


pb = 0; pb = 0;
} }


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

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

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

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

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

} }
} }


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


tv.tv_sec = wait_ms / 1000; tv.tv_sec = wait_ms / 1000;
tv.tv_usec = (wait_ms % 1000) * 1000; tv.tv_usec = (wait_ms % 1000) * 1000;
} }
} }


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


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

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

// //


#include <assert.h> #include <assert.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <strings.h> #include <strings.h>
} }


// Trigger timers and check when the next will expire // Trigger timers and check when the next will expire
int nextTimeout = server->checkTimeouts();
int nextTimeout = Timer::checkTimeouts();
if (nextTimeout > 0 && (*timeout == -1 || nextTimeout < *timeout)) if (nextTimeout > 0 && (*timeout == -1 || nextTimeout < *timeout))
*timeout = nextTimeout; *timeout = nextTimeout;
} catch (rdr::Exception& e) { } catch (rdr::Exception& e) {
// SDesktop callbacks // SDesktop callbacks




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

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

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

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

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

statusLocation(0), queryConnectionHandler(0), ledState(0) statusLocation(0), queryConnectionHandler(0), ledState(0)
{ {
updateEvent.h = CreateEvent(0, TRUE, FALSE, 0); updateEvent.h = CreateEvent(0, TRUE, FALSE, 0);
terminateEvent.h = CreateEvent(0, TRUE, FALSE, 0);
} }


SDisplay::~SDisplay() SDisplay::~SDisplay()
if (statusLocation) *statusLocation = false; if (statusLocation) *statusLocation = false;
} }


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



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

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



virtual void start(VNCServer* vs); virtual void start(VNCServer* vs);
virtual void stop(); virtual void stop();
virtual void terminate();
virtual void queryConnection(network::Socket* sock, virtual void queryConnection(network::Socket* sock,
const char* userName); const char* userName);
virtual void pointerEvent(const Point& pos, int buttonmask); virtual void pointerEvent(const Point& pos, int buttonmask);
// -=- EventHandler interface // -=- EventHandler interface


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


// -=- Notification of whether or not SDisplay is started // -=- Notification of whether or not SDisplay is started


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


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

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

#include <winsock2.h> #include <winsock2.h>
#include <list> #include <list>
#include <rfb/LogWriter.h> #include <rfb/LogWriter.h>
#include <rfb/Timer.h>
#include <rfb_win32/SocketManager.h> #include <rfb_win32/SocketManager.h>


using namespace rfb; using namespace rfb;


std::map<HANDLE,ListenInfo>::iterator i; std::map<HANDLE,ListenInfo>::iterator i;
for (i=listeners.begin(); i!=listeners.end(); 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::list<network::Socket*> shutdownSocks;
std::map<HANDLE,ConnInfo>::iterator j, j_next; std::map<HANDLE,ConnInfo>::iterator j, j_next;

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



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


// Register the queued command event to be handled // Register the queued command event to be handled
sockMgr.addEvent(commandEvent, this); sockMgr.addEvent(commandEvent, this);
command = NoCommand; command = NoCommand;
commandSig->signal(); commandSig->signal();
} }
} else if (event_ == sessionEvent.h) {
} else if ((event_ == sessionEvent.h) ||
(event_ == desktop.getTerminateEvent())) {
stop(); stop();
} }
} }

Loading…
Cancel
Save