Skip to content

Commit

Permalink
Merge branch 'present' of github.com:CendioOssman/tigervnc
Browse files Browse the repository at this point in the history
  • Loading branch information
CendioOssman committed Jun 19, 2024
2 parents 78510b9 + 28c3f12 commit 858a859
Show file tree
Hide file tree
Showing 36 changed files with 419 additions and 170 deletions.
6 changes: 2 additions & 4 deletions common/rfb/EncodeManager.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ void EncodeManager::writeLosslessRefresh(const Region& req, const PixelBuffer* p
Region(), Point(), pb, renderedCursor);
}

bool EncodeManager::handleTimeout(Timer* t)
void EncodeManager::handleTimeout(Timer* t)
{
if (t == &recentChangeTimer) {
// Any lossy region that wasn't recently updated can
Expand All @@ -307,10 +307,8 @@ bool EncodeManager::handleTimeout(Timer* t)

// Will there be more to do? (i.e. do we need another round)
if (!lossyRegion.subtract(pendingRefreshRegion).is_empty())
return true;
t->repeat();
}

return false;
}

void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
Expand Down
2 changes: 1 addition & 1 deletion common/rfb/EncodeManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ namespace rfb {
size_t maxUpdateSize);

protected:
virtual bool handleTimeout(Timer* t);
virtual void handleTimeout(Timer* t);

void doUpdate(bool allowLossy, const Region& changed,
const Region& copied, const Point& copy_delta,
Expand Down
8 changes: 3 additions & 5 deletions common/rfb/SConnection.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,11 @@ bool SConnection::processInitMsg()
return reader_->readClientInit();
}

bool SConnection::handleAuthFailureTimeout(Timer* /*t*/)
void SConnection::handleAuthFailureTimeout(Timer* /*t*/)
{
if (state_ != RFBSTATE_SECURITY_FAILURE) {
close("SConnection::handleAuthFailureTimeout: invalid state");
return false;
return;
}

try {
Expand All @@ -292,12 +292,10 @@ bool SConnection::handleAuthFailureTimeout(Timer* /*t*/)
os->flush();
} catch (rdr::Exception& e) {
close(e.str());
return false;
return;
}

close(authFailureMsg.c_str());

return false;
}

void SConnection::throwConnFailedException(const char* format, ...)
Expand Down
2 changes: 1 addition & 1 deletion common/rfb/SConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ namespace rfb {
bool processSecurityFailure();
bool processInitMsg();

bool handleAuthFailureTimeout(Timer* t);
void handleAuthFailureTimeout(Timer* t);

int defaultMajorVersion, defaultMinorVersion;

Expand Down
25 changes: 13 additions & 12 deletions common/rfb/SDesktop.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2009-2019 Pierre Ossman for Cendio AB
* Copyright 2009-2024 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -49,20 +49,21 @@ namespace rfb {

class SDesktop : public InputHandler {
public:
// init() is called immediately when the VNCServer gets a reference
// to the SDesktop, so that a reverse reference can be set up.
virtual void init(rfb::VNCServer* vs) = 0;

// start() is called by the server when the first client authenticates
// successfully, and can be used to begin any expensive tasks which are not
// needed when there are no clients. A valid PixelBuffer must have been
// set via the VNCServer's setPixelBuffer() method by the time this call
// returns.

virtual void start(VNCServer* vs) = 0;
virtual void start() {}

// stop() is called by the server when there are no longer any
// authenticated clients, and therefore the desktop can cease any
// expensive tasks. No further calls to the VNCServer passed to start()
// can be made once stop has returned.

virtual void stop() = 0;
// expensive tasks.
virtual void stop() {}

// queryConnection() is called when a connection has been
// successfully authenticated. The sock and userName arguments
Expand All @@ -86,6 +87,10 @@ namespace rfb {
return resultProhibited;
}

// frameTick() is called whenever a frame update has been processed,
// signalling that a good time to render new data
virtual void frameTick(uint64_t msc) { (void)msc; }

// InputHandler interface
// pointerEvent(), keyEvent() and clientCutText() are called in response to
// the relevant RFB protocol messages from clients.
Expand Down Expand Up @@ -136,14 +141,10 @@ namespace rfb {
if (buffer) delete buffer;
}

virtual void start(VNCServer* vs) {
virtual void init(VNCServer* vs) {
server = vs;
server->setPixelBuffer(buffer);
}
virtual void stop() {
server->setPixelBuffer(0);
server = 0;
}
virtual void queryConnection(network::Socket* sock,
const char* /*userName*/) {
server->approveConnection(sock, true, NULL);
Expand Down
67 changes: 40 additions & 27 deletions common/rfb/Timer.cxx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2016-2018 Pierre Ossman for Cendio AB
* Copyright 2016-2024 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -61,44 +61,33 @@ int Timer::checkTimeouts() {
timeval start;

if (pending.empty())
return 0;
return -1;

gettimeofday(&start, 0);
while (pending.front()->isBefore(start)) {
Timer* timer;
timeval before;

timer = pending.front();
pending.pop_front();

gettimeofday(&before, 0);
if (timer->cb->handleTimeout(timer)) {
timeval now;
timer->lastDueTime = timer->dueTime;
timer->cb->handleTimeout(timer);

gettimeofday(&now, 0);

timer->dueTime = addMillis(timer->dueTime, timer->timeoutMs);
if (timer->isBefore(now)) {
// Time has jumped forwards, or we're not getting enough
// CPU time for the timers

timer->dueTime = addMillis(before, timer->timeoutMs);
if (timer->isBefore(now))
timer->dueTime = now;
}

insertTimer(timer);
} else if (pending.empty()) {
return 0;
}
if (pending.empty())
return -1;
}
return getNextTimeout();
}

int Timer::getNextTimeout() {
timeval now;
gettimeofday(&now, 0);
int toWait = __rfbmax(1, pending.front()->getRemainingMs());

if (pending.empty())
return -1;

int toWait = pending.front()->getRemainingMs();

if (toWait > pending.front()->timeoutMs) {
if (toWait - pending.front()->timeoutMs < 1000) {
vlog.info("gettimeofday is broken...");
Expand All @@ -107,8 +96,9 @@ int Timer::getNextTimeout() {
// Time has jumped backwards!
vlog.info("time has moved backwards!");
pending.front()->dueTime = now;
toWait = 1;
toWait = 0;
}

return toWait;
}

Expand All @@ -128,13 +118,36 @@ void Timer::start(int timeoutMs_) {
gettimeofday(&now, 0);
stop();
timeoutMs = timeoutMs_;
// The rest of the code assumes non-zero timeout
if (timeoutMs <= 0)
timeoutMs = 1;
dueTime = addMillis(now, timeoutMs);
insertTimer(this);
}

void Timer::repeat(int timeoutMs_) {
timeval now;

gettimeofday(&now, 0);

if (isStarted()) {
vlog.error("Incorrectly repeating already running timer");
stop();
}

if (msBetween(&lastDueTime, &dueTime) != 0)
vlog.error("Timer incorrectly modified whilst repeating");

if (timeoutMs_ != -1)
timeoutMs = timeoutMs_;

dueTime = addMillis(lastDueTime, timeoutMs);
if (isBefore(now)) {
// Time has jumped forwards, or we're not getting enough
// CPU time for the timers
dueTime = now;
}

insertTimer(this);
}

void Timer::stop() {
pending.remove(this);
}
Expand Down
77 changes: 46 additions & 31 deletions common/rfb/Timer.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2018 Pierre Ossman for Cendio AB
* Copyright 2018-2024 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -27,93 +27,108 @@ namespace rfb {

/* Timer
Cross-platform timeout handling. The caller creates instances of Timer and passes a
Callback implementation to each. The Callback will then be called with a pointer to
the Timer instance that timed-out when the timeout occurs.
Cross-platform timeout handling. The caller creates instances of
Timer and passes a Callback implementation to each. The Callback
will then be called with a pointer to the Timer instance that
timed-out when the timeout occurs.
The static methods of Timer are used by the main loop of the application both to
dispatch elapsed Timer callbacks and to determine how long to wait in select() for
the next timeout to occur.
The static methods of Timer are used by the main loop of the
application both to dispatch elapsed Timer callbacks and to
determine how long to wait in select() for the next timeout to
occur.
For classes that can be derived it's best to use MethodTimer which can call a specific
method on the class, thus avoiding conflicts when subclassing.
For classes that can be derived it's best to use MethodTimer which
can call a specific method on the class, thus avoiding conflicts
when subclassing.
*/

struct Timer {

struct Callback {
// handleTimeout
// Passed a pointer to the Timer that has timed out. If the handler returns true
// then the Timer is reset and left running, causing another timeout after the
// appropriate interval.
// Passed a pointer to the Timer that has timed out. If the
// handler returns true then the Timer is reset and left
// running, causing another timeout after the appropriate
// interval.
// If the handler returns false then the Timer is cancelled.
virtual bool handleTimeout(Timer* t) = 0;
virtual void handleTimeout(Timer* t) = 0;

virtual ~Callback() {}
};

// checkTimeouts()
// Dispatches any elapsed Timers, and returns the number of milliseconds until the
// next Timer will timeout.
// Dispatches any elapsed Timers, and returns the number of
// milliseconds until the next Timer will timeout.
static int checkTimeouts();

// getNextTimeout()
// Returns the number of milliseconds until the next timeout, without dispatching
// any elapsed Timers.
// Returns the number of milliseconds until the next timeout,
// without dispatching any elapsed Timers.
static int getNextTimeout();

// Create a Timer with the specified callback handler
Timer(Callback* cb_) {cb = cb_;}
~Timer() {stop();}

// startTimer
// Starts the timer, causing a timeout after the specified number of milliseconds.
// If the timer is already active then it will be implicitly cancelled and re-started.
// start()
// Starts the timer, causing a timeout after the specified number
// of milliseconds. If the timer is already active then it will
// be implicitly cancelled and re-started.
void start(int timeoutMs_);

// stopTimer
// repeat()
// Restarts the timer in a way that repeats that last timeout.
// This allows you to have a periodic timer without the risk of
// accumulating drift caused by processing delays.
// A new interval can be specified, otherwise the previous
// interval is reused.
void repeat(int timeoutMs_=-1);

// stop()
// Cancels the timer.
void stop();

// isStarted
// isStarted()
// Determines whether the timer is started.
bool isStarted();

// getTimeoutMs
// getTimeoutMs()
// Determines the previously used timeout value, if any.
// Usually used with isStarted() to get the _current_ timeout.
int getTimeoutMs();

// getRemainingMs
// getRemainingMs()
// Determines how many milliseconds are left before the Timer
// will timeout. Only valid for an active timer.
int getRemainingMs();

// isBefore
// Determine whether the Timer will timeout before the specified time.
// isBefore()
// Determine whether the Timer will timeout before the specified
// time.
bool isBefore(timeval other);

protected:
timeval dueTime;
timeval dueTime, lastDueTime;
int timeoutMs;
Callback* cb;

static void insertTimer(Timer* t);
// The list of currently active Timers, ordered by time left until timeout.
// The list of currently active Timers, ordered by time left until
// timeout.
static std::list<Timer*> pending;
};

template<class T> class MethodTimer
: public Timer, public Timer::Callback {
public:
MethodTimer(T* obj_, bool (T::*cb_)(Timer*))
MethodTimer(T* obj_, void (T::*cb_)(Timer*))
: Timer(this), obj(obj_), cb(cb_) {}

virtual bool handleTimeout(Timer* t) { return (obj->*cb)(t); }
virtual void handleTimeout(Timer* t) { (obj->*cb)(t); }

private:
T* obj;
bool (T::*cb)(Timer*);
void (T::*cb)(Timer*);
};

};
Expand Down
Loading

0 comments on commit 858a859

Please sign in to comment.