#include <rfb/screenTypes.h>
#include <rfb/util.h>
+namespace network { class Socket; }
+
namespace rfb {
class VNCServer;
// set via the VNCServer's setPixelBuffer() method by the time this call
// returns.
- virtual void start(VNCServer* __unused_attr vs) {}
+ virtual void start(VNCServer* vs) = 0;
// 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() {}
+ virtual void stop() = 0;
+
+ // queryConnection() is called when a connection has been
+ // successfully authenticated. The sock and userName arguments
+ // identify the socket and the name of the authenticated user, if
+ // any. At some point later VNCServer::approveConnection() should
+ // be called to either accept or reject the client.
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName) = 0;
// setScreenLayout() requests to reconfigure the framebuffer and/or
// the layout of screens.
server->setPixelBuffer(0);
server = 0;
}
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName) {
+ server->approveConnection(sock, true, NULL);
+ }
protected:
VNCServer* server;
{
lastEventTime = time(0);
- server->startDesktop();
-
// - Set the connection parameters appropriately
cp.width = server->pb->width();
cp.height = server->pb->height();
CharArray name; name.buf = sock->getPeerAddress();
server->blHosts->clearBlackmark(name.buf);
+ // - Prepare the desktop that we might be making calls
+ server->startDesktop();
+
// - Special case to provide a more useful error message
if (rfb::Server::neverShared && !rfb::Server::disconnectClients &&
server->authClientCount() > 0) {
#include <rfb/SSecurity.h>
#include <rfb/ScreenSet.h>
+namespace network { class Socket; }
+
namespace rfb {
class VNCServer : public UpdateTracker {
// bell() tells the server that it should make all clients make a bell sound.
virtual void bell() = 0;
+ // approveConnection() is called some time after
+ // SDesktop::queryConnection() has been called, to accept or reject
+ // the connection. The accept argument should be true for
+ // acceptance, or false for rejection, in which case a string
+ // reason may also be given.
+ virtual void approveConnection(network::Socket* sock, bool accept,
+ const char* reason = NULL) = 0;
+
// - Close all currently-connected clients, by calling
// their close() method with the supplied reason.
virtual void closeClients(const char* reason) = 0;
name(strDup(name_)), pointerClient(0), comparer(0),
cursor(new Cursor(0, 0, Point(), NULL)),
renderedCursorInvalid(false),
- queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
+ keyRemapper(&KeyRemapper::defInstance),
lastConnectionTime(0), disableclients(false),
frameTimer(this)
{
return false;
}
+void VNCServerST::queryConnection(network::Socket* sock,
+ const char* userName)
+{
+ desktop->queryConnection(sock, userName);
+}
+
// -=- Internal methods
void VNCServerST::startDesktop()
virtual void setScreenLayout(const ScreenSet& layout);
virtual PixelBuffer* getPixelBuffer() const { return pb; }
virtual void serverCutText(const char* str, int len);
+
+ virtual void approveConnection(network::Socket* sock, bool accept,
+ const char* reason);
+ virtual void closeClients(const char* reason) {closeClients(reason, 0);}
+
virtual void add_changed(const Region ®ion);
virtual void add_copied(const Region &dest, const Point &delta);
virtual void setCursor(int width, int height, const Point& hotspot,
virtual void bell();
- // - Close all currently-connected clients, by calling
- // their close() method with the supplied reason.
- virtual void closeClients(const char* reason) {closeClients(reason, 0);}
-
// VNCServerST-only methods
// closeClients() closes all RFB sessions, except the specified one (if
// clients
virtual void setName(const char* name_);
- // A QueryConnectionHandler, if supplied, is passed details of incoming
- // connections to approve, reject, or query the user about.
- //
// queryConnection() is called when a connection has been
// successfully authenticated. The sock and userName arguments identify
// the socket and the name of the authenticated user, if any.
// approveConnection() must be called some time later to accept or reject
// the connection.
- struct QueryConnectionHandler {
- virtual ~QueryConnectionHandler() {}
- virtual void queryConnection(network::Socket* sock,
- const char* userName) = 0;
- };
- void setQueryConnectionHandler(QueryConnectionHandler* qch) {
- queryConnectionHandler = qch;
- }
-
- // queryConnection is called as described above, and either passes the
- // request on to the registered handler, or accepts the connection if
- // no handler has been specified.
virtual void queryConnection(network::Socket* sock,
- const char* userName) {
- if (queryConnectionHandler) {
- queryConnectionHandler->queryConnection(sock, userName);
- return;
- }
- approveConnection(sock, true, NULL);
- }
-
- // approveConnection() is called by the active QueryConnectionHandler,
- // some time after queryConnection() has returned with PENDING, to accept
- // or reject the connection. The accept argument should be true for
- // acceptance, or false for rejection, in which case a string reason may
- // also be given.
- void approveConnection(network::Socket* sock, bool accept,
- const char* reason);
+ const char* userName);
// setBlacklist() is called to replace the VNCServerST's internal
// Blacklist instance with another instance. This allows a single
bool getComparerState();
- QueryConnectionHandler* queryConnectionHandler;
KeyRemapper* keyRemapper;
time_t lastUserInputTime;
* USA.
*/
+#include <assert.h>
+
#include <x0vncserver/XDesktop.h>
#include <X11/XKBlib.h>
"Send keyboard events straight through and "
"avoid mapping them to the current keyboard "
"layout", false);
+IntParameter queryConnectTimeout("QueryConnectTimeout",
+ "Number of seconds to show the Accept Connection dialog before "
+ "rejecting the connection",
+ 10);
static rfb::LogWriter vlog("XDesktop");
XDesktop::XDesktop(Display* dpy_, Geometry *geometry_)
: dpy(dpy_), geometry(geometry_), pb(0), server(0),
+ queryConnectDialog(0), queryConnectSock(0),
oldButtonMask(0), haveXtest(false), haveDamage(false),
maxButtons(0), running(false), ledMasks(), ledState(0),
codeMap(0), codeMapLen(0)
XDamageDestroy(dpy, damage);
#endif
+ delete queryConnectDialog;
+ queryConnectDialog = 0;
+
server->setPixelBuffer(0);
server = 0;
return running;
}
+void XDesktop::queryConnection(network::Socket* sock,
+ const char* userName)
+{
+ assert(isRunning());
+
+ if (queryConnectSock) {
+ server->approveConnection(sock, false, "Another connection is currently being queried.");
+ return;
+ }
+
+ if (!userName)
+ userName = "(anonymous)";
+
+ queryConnectSock = sock;
+
+ CharArray address(sock->getPeerAddress());
+ delete queryConnectDialog;
+ queryConnectDialog = new QueryConnectDialog(dpy, address.buf,
+ userName,
+ queryConnectTimeout,
+ this);
+ queryConnectDialog->map();
+}
+
void XDesktop::pointerEvent(const Point& pos, int buttonMask) {
#ifdef HAVE_XTEST
if (!haveXtest) return;
return false;
}
+void XDesktop::queryApproved()
+{
+ assert(isRunning());
+ server->approveConnection(queryConnectSock, true, 0);
+ queryConnectSock = 0;
+}
+
+void XDesktop::queryRejected()
+{
+ assert(isRunning());
+ server->approveConnection(queryConnectSock, false,
+ "Connection rejected by local user");
+ queryConnectSock = 0;
+}
+
bool XDesktop::setCursor()
{
XFixesCursorImage *cim;
#include <X11/extensions/Xdamage.h>
#endif
+#include <vncconfig/QueryConnectDialog.h>
+
class Geometry;
class XPixelBuffer;
// number of XKb indicator leds to handle
#define XDESKTOP_N_LEDS 3
-class XDesktop : public rfb::SDesktop, public TXGlobalEventHandler
+class XDesktop : public rfb::SDesktop,
+ public TXGlobalEventHandler,
+ public QueryResultCallback
{
public:
XDesktop(Display* dpy_, Geometry *geometry);
virtual void start(rfb::VNCServer* vs);
virtual void stop();
bool isRunning();
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName);
virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
KeyCode XkbKeysymToKeycode(Display* dpy, KeySym keysym);
virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down);
// -=- TXGlobalEventHandler interface
virtual bool handleGlobalEvent(XEvent* ev);
+ // -=- QueryResultCallback interface
+ virtual void queryApproved();
+ virtual void queryRejected();
+
protected:
Display* dpy;
Geometry* geometry;
XPixelBuffer* pb;
rfb::VNCServerST* server;
+ QueryConnectDialog* queryConnectDialog;
+ network::Socket* queryConnectSock;
int oldButtonMask;
bool haveXtest;
bool haveDamage;
#include <network/TcpSocket.h>
#include <network/UnixSocket.h>
-#include <vncconfig/QueryConnectDialog.h>
-
#include <signal.h>
#include <X11/X.h>
#include <X11/Xlib.h>
IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",5900);
StringParameter rfbunixpath("rfbunixpath", "Unix socket to listen for RFB protocol", "");
IntParameter rfbunixmode("rfbunixmode", "Unix socket access mode", 0600);
-IntParameter queryConnectTimeout("QueryConnectTimeout",
- "Number of seconds to show the Accept Connection dialog before "
- "rejecting the connection",
- 10);
StringParameter hostsFile("HostsFile", "File with IP access control rules", "");
//
}
-class QueryConnHandler : public VNCServerST::QueryConnectionHandler,
- public QueryResultCallback {
-public:
- QueryConnHandler(Display* dpy, VNCServerST* vs)
- : display(dpy), server(vs), queryConnectDialog(0), queryConnectSock(0) {}
- ~QueryConnHandler() { delete queryConnectDialog; }
-
- // -=- VNCServerST::QueryConnectionHandler interface
- virtual void queryConnection(network::Socket* sock,
- const char* userName) {
- if (queryConnectSock) {
- server->approveConnection(sock, false, "Another connection is currently being queried.");
- return;
- }
- if (!userName) userName = "(anonymous)";
- queryConnectSock = sock;
- CharArray address(sock->getPeerAddress());
- delete queryConnectDialog;
- queryConnectDialog = new QueryConnectDialog(display, address.buf,
- userName, queryConnectTimeout,
- this);
- queryConnectDialog->map();
- }
-
- // -=- QueryResultCallback interface
- virtual void queryApproved() {
- server->approveConnection(queryConnectSock, true, 0);
- queryConnectSock = 0;
- }
- virtual void queryRejected() {
- server->approveConnection(queryConnectSock, false,
- "Connection rejected by local user");
- queryConnectSock = 0;
- }
-private:
- Display* display;
- VNCServerST* server;
- QueryConnectDialog* queryConnectDialog;
- network::Socket* queryConnectSock;
-};
-
-
class FileTcpFilter : public TcpFilter
{
XDesktop desktop(dpy, &geo);
VNCServerST server("x0vncserver", &desktop);
- QueryConnHandler qcHandler(dpy, &server);
- server.setQueryConnectionHandler(&qcHandler);
if (rfbunixpath.getValueStr()[0] != '\0') {
listeners.push_back(new network::UnixListener(rfbunixpath, rfbunixmode));
server = new VNCServerST(name, this);
setFramebuffer(width, height, fbptr, stride);
- server->setQueryConnectionHandler(this);
for (std::list<SocketListener*>::iterator i = listeners.begin();
i != listeners.end();
server->setScreenLayout(::computeScreenLayout(&outputIdMap));
}
+void XserverDesktop::start(rfb::VNCServer* vs)
+{
+ // We already own the server object, and we always keep it in a
+ // ready state
+ assert(vs == server);
+}
+
+void XserverDesktop::stop()
+{
+}
+
void XserverDesktop::queryConnection(network::Socket* sock,
const char* userName)
{
namespace network { class SocketListener; class Socket; class SocketServer; }
class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
- public rfb::VNCServerST::QueryConnectionHandler,
public rfb::Timer::Callback {
public:
const char* rejectMsg=0);
// rfb::SDesktop callbacks
+ virtual void start(rfb::VNCServer* vs);
+ virtual void stop();
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName);
virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
virtual void clientCutText(const char* str, int len);
// rfb::PixelBuffer callbacks
virtual void grabRegion(const rfb::Region& r);
- // rfb::VNCServerST::QueryConnectionHandler callback
- virtual void queryConnection(network::Socket* sock,
- const char* userName);
-
protected:
bool handleListenerEvent(int fd,
std::list<network::SocketListener*>* sockets,
//
// The SDisplay class encapsulates a particular system display.
+#include <assert.h>
+
#include <rfb_win32/SDisplay.h>
#include <rfb_win32/Service.h>
#include <rfb_win32/TsSessions.h>
: server(0), pb(0), device(0),
core(0), ptr(0), kbd(0), clipboard(0),
inputs(0), monitor(0), cleanDesktop(0), cursor(0),
- statusLocation(0), ledState(0)
+ statusLocation(0), queryConnectionHandler(0), ledState(0)
{
updateEvent.h = CreateEvent(0, TRUE, FALSE, 0);
}
}
+void SDisplay::queryConnection(network::Socket* sock,
+ const char* userName)
+{
+ assert(server != NULL);
+
+ if (queryConnectionHandler) {
+ queryConnectionHandler->queryConnection(sock, userName);
+ return;
+ }
+
+ server->approveConnection(sock, true);
+}
+
+
void SDisplay::startCore() {
// Currently, we just check whether we're in the console session, and
virtual const char* methodName() const = 0;
};
+ class QueryConnectionHandler {
+ public:
+ virtual ~QueryConnectionHandler() {}
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName) = 0;
+ };
+
class SDisplay : public SDesktop,
WMMonitor::Notifier,
Clipboard::Notifier,
virtual void start(VNCServer* vs);
virtual void stop();
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName);
virtual void pointerEvent(const Point& pos, int buttonmask);
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
virtual void clientCutText(const char* str, int len);
void setStatusLocation(bool* status) {statusLocation = status;}
+ // -=- Set handler for incoming connections
+
+ void setQueryConnectionHandler(QueryConnectionHandler* qch) {
+ queryConnectionHandler = qch;
+ }
+
static IntParameter updateMethod;
static BoolParameter disableLocalInputs;
static StringParameter disconnectAction;
// -=- Where to write the active/inactive indicator to
bool* statusLocation;
+ // -=- Whom to query incoming connections
+ QueryConnectionHandler* queryConnectionHandler;
+
unsigned ledState;
};
// Initialise the desktop
desktop.setStatusLocation(&isDesktopStarted);
-
- // Initialise the VNC server
- vncServer.setQueryConnectionHandler(this);
+ desktop.setQueryConnectionHandler(this);
// Register the desktop's event to be handled
sockMgr.addEvent(desktop.getUpdateEvent(), &desktop);
class STrayIconThread;
- class VNCServerWin32 : rfb::VNCServerST::QueryConnectionHandler,
+ class VNCServerWin32 : rfb::win32::QueryConnectionHandler,
rfb::win32::SocketManager::AddressChangeNotifier,
rfb::win32::RegConfig::Callback,
rfb::win32::EventHandler {
bool setClientsStatus(rfb::ListConnInfo* LCInfo);
protected:
- // VNCServerST::QueryConnectionHandler interface
+ // QueryConnectionHandler interface
// Callback used to prompt user to accept or reject a connection.
// CALLBACK IN VNCServerST "HOST" THREAD
virtual void queryConnection(network::Socket* sock,