/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ // -=- VNCServerST.h // Single-threaded VNCServer implementation #ifndef __RFB_VNCSERVERST_H__ #define __RFB_VNCSERVERST_H__ #include <list> #include <rfb/SDesktop.h> #include <rfb/VNCServer.h> #include <rfb/Configuration.h> #include <rfb/LogWriter.h> #include <rfb/Blacklist.h> #include <rfb/Cursor.h> #include <network/Socket.h> namespace rfb { class VNCSConnectionST; class ComparingUpdateTracker; class PixelBuffer; class VNCServerST : public VNCServer, public network::SocketServer { public: // -=- Constructors // Create a server exporting the supplied desktop. VNCServerST(const char* name_, SDesktop* desktop_, SSecurityFactory* securityFactory_=0); virtual ~VNCServerST(); // Methods overridden from SocketServer // - Run a client connection on the supplied socket // This causes the server to allocate the required structures // to handle a client connection, and to initialise the RFB // protocol. // NB: The server assumes ownership of the Socket object. virtual void addClient(network::Socket* sock); // - Process an input event on a particular Socket // The platform-specific side of the server implementation calls // this method whenever data arrives on one of the active // network sockets. // The method returns true if the Socket is still in use by the // server, or false if it is no longer required and has been // deleted. // NB: If false is returned then the Socket is deleted and must // not be accessed again! virtual bool processSocketEvent(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 virtual void setPixelBuffer(PixelBuffer* pb); virtual void setColourMapEntries(int firstColour=0, int nColours=0); virtual void serverCutText(const char* str, int len); virtual void add_changed(const Region ®ion); virtual void add_copied(const Region &dest, const Point &delta); virtual bool clientsReadyForUpdate(); virtual void tryUpdate(); virtual void setCursor(int width, int height, int hotspotX, int hotspotY, void* cursorData, void* mask); virtual void setCursorPos(int x, int y); virtual void setSSecurityFactory(SSecurityFactory* f) {securityFactory=f;} 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 // If a particular VNCSConnectionST* is specified then // that connection will NOT be closed. void closeClients(const char* reason, network::Socket* sock); // addClient() with an extra flag to say if this is a reverse connection to // a listening client. Reverse connections are not authenticated and are // always shared (unless the NeverShared parameter is set). void addClient(network::Socket* sock, bool reverse); // getSockets() gets a list of sockets. This can be used to generate an // fd_set for calling select(). void getSockets(std::list<network::Socket*>* sockets); // getSConnection() gets the SConnection for a particular Socket. If // the Socket is not recognised then null is returned. SConnection* getSConnection(network::Socket* sock); // getDesktopSize() returns the size of the SDesktop exported by this // server. Point getDesktopSize() const {return desktop->getFbSize();} // getName() returns the name of this VNC Server. NB: The value returned // is the server's internal buffer which may change after any other methods // are called - take a copy if necessary. const char* getName() const {return name.buf;} // setName() specifies the desktop name that the server should provide to // clients void setName(const char* name_) {name.replaceBuf(strDup(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. It should // return ACCEPT if the connection should be accepted, REJECT if it should // be rejected, or PENDING if a decision cannot yet be reached. If REJECT // is returned, *reason can be set to a string describing the reason - this // will be delete[]ed when it is finished with. If PENDING is returned, // approveConnection() must be called some time later to accept or reject // the connection. enum queryResult { ACCEPT, REJECT, PENDING }; struct QueryConnectionHandler { virtual ~QueryConnectionHandler() {} virtual queryResult queryConnection(network::Socket* sock, const char* userName, char** reason) = 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 queryResult queryConnection(network::Socket* sock, const char* userName, char** reason) { return queryConnectionHandler ? queryConnectionHandler->queryConnection(sock, userName, reason) : ACCEPT; } // 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); // setBlacklist() is called to replace the VNCServerST's internal // Blacklist instance with another instance. This allows a single // Blacklist to be shared by multiple VNCServerST instances. void setBlacklist(Blacklist* bl) {blHosts = bl ? bl : &blacklist;} // setEconomicTranslate() determines (for new connections) whether pixels // should be translated for <=16bpp clients using a large lookup table (fast) // or separate, smaller R, G and B tables (slower). If set to true, small tables // are used, to save memory. void setEconomicTranslate(bool et) { useEconomicTranslate = et; } protected: friend class VNCSConnectionST; void startDesktop(); static LogWriter connectionsLog; Blacklist blacklist; Blacklist* blHosts; SDesktop* desktop; bool desktopStarted; PixelBuffer* pb; CharArray name; std::list<VNCSConnectionST*> clients; VNCSConnectionST* pointerClient; std::list<network::Socket*> closingSockets; ComparingUpdateTracker* comparer; Point cursorPos; Cursor cursor; Point cursorTL() { return cursorPos.subtract(cursor.hotspot); } Point renderedCursorTL; ManagedPixelBuffer renderedCursor; bool renderedCursorInvalid; // - Check how many of the clients are authenticated. int authClientCount(); bool needRenderedCursor(); void checkUpdate(); SSecurityFactory* securityFactory; QueryConnectionHandler* queryConnectionHandler; bool useEconomicTranslate; time_t lastUserInputTime; time_t lastDisconnectTime; time_t lastConnectionTime; }; }; #endif