Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions common/rfb/SDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,9 @@ namespace rfb {

// setScreenLayout() requests to reconfigure the framebuffer and/or
// the layout of screens.
virtual unsigned int setScreenLayout(int /*fb_width*/,
int /*fb_height*/,
const ScreenSet& /*layout*/) {
return resultProhibited;
}
virtual void setScreenLayout(int /*fb_width*/,
int /*fb_height*/,
const ScreenSet& /*layout*/) = 0;

// frameTick() is called whenever a frame update has been processed,
// signalling that a good time to render new data
Expand Down
21 changes: 16 additions & 5 deletions common/rfb/VNCSConnectionST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,16 @@ void VNCSConnectionST::desktopReadyOrClose()
}
}

void VNCSConnectionST::setDesktopSizeDoneOrClose(uint16_t result)
{
try {
if (state() != RFBSTATE_NORMAL) return;
setDesktopSizeDone(result);
} catch(std::exception& e) {
close(e.what());
}
}

bool VNCSConnectionST::getComparerState()
{
// We interpret a low compression level as an indication that the client
Expand Down Expand Up @@ -461,6 +471,10 @@ void VNCSConnectionST::desktopReady()
SConnection::desktopReady();
}

void VNCSConnectionST::setDesktopSizeDone(uint16_t result)
{
writer()->writeDesktopSize(reasonClient, result);
}

void VNCSConnectionST::approveConnectionOrClose(bool accept,
const char* reason)
Expand Down Expand Up @@ -699,7 +713,6 @@ void VNCSConnectionST::framebufferUpdateRequest(const core::Rect& r,
void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height,
const ScreenSet& layout)
{
unsigned int result;
char buffer[2048];

vlog.debug("Got request for framebuffer resize to %dx%d",
Expand All @@ -709,12 +722,10 @@ void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height,

if (!accessCheck(AccessSetDesktopSize)) {
vlog.debug("Rejecting unauthorized framebuffer resize request");
result = resultProhibited;
setDesktopSizeDoneOrClose(resultProhibited);
} else {
result = server->setDesktopSize(this, fb_width, fb_height, layout);
server->setDesktopSizeRequest(this, fb_width, fb_height, layout);
}

writer()->writeDesktopSize(reasonClient, result);
}

void VNCSConnectionST::fence(uint32_t flags, unsigned len, const uint8_t data[])
Expand Down
2 changes: 2 additions & 0 deletions common/rfb/VNCSConnectionST.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ namespace rfb {
void announceClipboardOrClose(bool available);
void sendClipboardDataOrClose(const char* data);
void desktopReadyOrClose();
void setDesktopSizeDoneOrClose(uint16_t result);

// The following methods never throw exceptions

Expand Down Expand Up @@ -172,6 +173,7 @@ namespace rfb {
void setDesktopName(const char *name);
void setLEDState(unsigned int state);
void desktopReady() override;
void setDesktopSizeDone(uint16_t result);

private:
network::Socket* sock;
Expand Down
3 changes: 3 additions & 0 deletions common/rfb/VNCServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ namespace rfb {
// the pixelbuffer. Clients will be notified of the new layout.
virtual void setScreenLayout(const ScreenSet& layout) = 0;

// FIXME: Change code comments above
virtual void setScreenLayoutDone(uint16_t result) = 0;

// getPixelBuffer() returns a pointer to the PixelBuffer object.
virtual const PixelBuffer* getPixelBuffer() const = 0;

Expand Down
70 changes: 52 additions & 18 deletions common/rfb/VNCServerST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
: desktop(desktop_), desktopStarted(false),
desktopStarting(false), blockCounter(0), pb(nullptr),
ledState(ledUnknown), name(name_), pointerClient(nullptr),
clipboardClient(nullptr), pointerClientTime(0),
comparer(nullptr), cursor(new Cursor(0, 0, {}, nullptr)),
renderedCursorInvalid(false),
clipboardClient(nullptr), resizeClient(nullptr),
pointerClientTime(0), comparer(nullptr),
cursor(new Cursor(0, 0, {}, nullptr)), renderedCursorInvalid(false),
keyRemapper(&KeyRemapper::defInstance),
idleTimer(this), disconnectTimer(this), connectTimer(this),
msc(0), queuedMsc(0), frameTimer(this)
resizeTimer(this), msc(0), queuedMsc(0), frameTimer(this)
{
slog.debug("Creating single-threaded server %s", name.c_str());

Expand Down Expand Up @@ -607,50 +607,79 @@ void VNCServerST::handleClipboardData(VNCSConnectionST* client,
desktop->handleClipboardData(data);
}

unsigned int VNCServerST::setDesktopSize(VNCSConnectionST* requester,
int fb_width, int fb_height,
const ScreenSet& layout)
void VNCServerST::setDesktopSizeRequest(VNCSConnectionST* requester,
int fb_width, int fb_height,
const ScreenSet& layout)
{
unsigned int result;
std::list<VNCSConnectionST*>::iterator ci;

if (resizeClient) {
slog.debug("Rejecting concurrent framebuffer resize request");
requester->setDesktopSizeDoneOrClose(resultNoResources);
return;
}

if (!rfb::Server::acceptSetDesktopSize) {
slog.debug("Rejecting unauthorized framebuffer resize request");
return resultProhibited;
requester->setDesktopSizeDoneOrClose(resultNoResources);
return;
}

// We can't handle a framebuffer larger than this, so don't let a
// client set one (see PixelBuffer.cxx)
if ((fb_width > 16384) || (fb_height > 16384)) {
slog.error("Rejecting too large framebuffer resize request");
return resultProhibited;
requester->setDesktopSizeDoneOrClose(resultNoResources);
return;
}

// Don't bother the desktop with an invalid configuration
if (!layout.validate(fb_width, fb_height)) {
slog.error("Invalid screen layout requested by client");
return resultInvalid;
requester->setDesktopSizeDoneOrClose(resultNoResources);
return;
}

// FIXME: the desktop will call back to VNCServerST and an extra set
// of ExtendedDesktopSize messages will be sent. This is okay
// protocol-wise, but unnecessary.
result = desktop->setScreenLayout(fb_width, fb_height, layout);
if (result != resultSuccess)
return result;
resizeClient = requester;
resizeTimer.start(2000);
desktop->setScreenLayout(fb_width, fb_height, layout);
}

void VNCServerST::setScreenLayoutDone(uint16_t result)
{
std::list<VNCSConnectionST*>::iterator ci;

// This means we've timed out
// FIXME: This doesn't feel robust...
if (!resizeClient)
return;

if (result != resultSuccess) {
resizeClient->setDesktopSizeDoneOrClose(result);
resizeClient = nullptr;
resizeTimer.stop();
return;
}

// Sanity check
if (screenLayout != layout)
if (screenLayout != getScreenLayout()) {
resizeClient = nullptr;
resizeTimer.stop();
throw std::runtime_error("Desktop configured a different screen layout than requested");
}

// Notify other clients
for (ci = clients.begin(); ci != clients.end(); ++ci) {
if ((*ci) == requester)
if ((*ci) == resizeClient)
continue;
(*ci)->screenLayoutChangeOrClose(reasonOtherClient);
}

return resultSuccess;
resizeClient->setDesktopSizeDoneOrClose(result);
resizeClient = nullptr;
resizeTimer.stop();
}

// Other public methods
Expand Down Expand Up @@ -732,6 +761,11 @@ void VNCServerST::handleTimeout(core::Timer* t)
} else if (t == &connectTimer) {
slog.info("MaxConnectionTime reached, exiting");
desktop->terminate();
} else if (t == &resizeTimer) {
assert(resizeClient);
// FIXME: This is not robust.
resizeClient->setDesktopSizeDoneOrClose(resultNoResources);
resizeClient = nullptr;
}
}

Expand Down
9 changes: 6 additions & 3 deletions common/rfb/VNCServerST.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ namespace rfb {
void setPixelBuffer(PixelBuffer* pb, const ScreenSet& layout) override;
void setPixelBuffer(PixelBuffer* pb) override;
void setScreenLayout(const ScreenSet& layout) override;
void setScreenLayoutDone(uint16_t result) override;
const PixelBuffer* getPixelBuffer() const override { return pb; }

void requestClipboard() override;
Expand Down Expand Up @@ -127,9 +128,9 @@ namespace rfb {
void handleClipboardAnnounce(VNCSConnectionST* client, bool available);
void handleClipboardData(VNCSConnectionST* client, const char* data);

unsigned int setDesktopSize(VNCSConnectionST* requester,
int fb_width, int fb_height,
const ScreenSet& layout);
void setDesktopSizeRequest(VNCSConnectionST* requester,
int fb_width, int fb_height,
const ScreenSet& layout);

// closeClients() closes all RFB sessions, except the specified one (if
// any), and logs the specified reason for closure.
Expand Down Expand Up @@ -194,6 +195,7 @@ namespace rfb {
std::list<VNCSConnectionST*> clients;
VNCSConnectionST* pointerClient;
VNCSConnectionST* clipboardClient;
VNCSConnectionST* resizeClient;
std::list<VNCSConnectionST*> clipboardRequestors;

time_t pointerClientTime;
Expand All @@ -210,6 +212,7 @@ namespace rfb {
core::Timer idleTimer;
core::Timer disconnectTimer;
core::Timer connectTimer;
core::Timer resizeTimer;

uint64_t msc, queuedMsc;
core::Timer frameTimer;
Expand Down
8 changes: 4 additions & 4 deletions unix/w0vncserver/portals/PortalDesktop.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,11 @@ void PortalDesktop::terminate()
kill(getpid(), SIGTERM);
}

unsigned int PortalDesktop::setScreenLayout(int /* fb_width */,
int /* fb_height */,
const rfb::ScreenSet& /* layout */)
void PortalDesktop::setScreenLayout(int /* fb_width */,
int /* fb_height */,
const rfb::ScreenSet& /* layout */)
{
return rfb::resultProhibited;
server->setScreenLayoutDone(rfb::resultProhibited);
}

void PortalDesktop::keyEvent(uint32_t keysym, uint32_t keycode, bool down)
Expand Down
4 changes: 2 additions & 2 deletions unix/w0vncserver/portals/PortalDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ class PortalDesktop : public rfb::SDesktop
void queryConnection(network::Socket* sock,
const char* userName) override;
void terminate() override;
unsigned int setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout) override;
void setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout) override;
void keyEvent(uint32_t keysym, uint32_t keycode, bool down) override;
void pointerEvent(const core::Point& pos,
uint16_t buttonMask) override;
Expand Down
6 changes: 6 additions & 0 deletions unix/w0vncserver/wayland/WaylandDesktop.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ void WaylandDesktop::terminate()
kill(getpid(), SIGTERM);
}

void WaylandDesktop::setScreenLayout(int /*fb_width*/, int /*fb_height*/,
const rfb::ScreenSet& /*layout*/)
{
server->setScreenLayoutDone(rfb::resultProhibited);
}

void WaylandDesktop::handleClipboardRequest()
{
if (!dataControl)
Expand Down
5 changes: 4 additions & 1 deletion unix/w0vncserver/wayland/WaylandDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

#include <rfb/SDesktop.h>

namespace rfb { class VNCServer; }
namespace rfb { class VNCServer; struct ScreenSet; }

namespace wayland {
class Output;
Expand Down Expand Up @@ -55,6 +55,9 @@ class WaylandDesktop : public rfb::SDesktop {
const char* userName) override;
void terminate() override;

void setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout) override;

virtual void handleClipboardRequest() override;
virtual void handleClipboardAnnounce(bool available) override;
virtual void handleClipboardData(const char* data) override;
Expand Down
Loading
Loading