This makes it generally useful and other code doesn't have to know of the specific sub-class.tags/v1.9.90
@@ -269,6 +269,16 @@ void SConnection::writeConnFailedFromScratch(const char* msg, | |||
os->flush(); | |||
} | |||
void SConnection::setAccessRights(AccessRights ar) | |||
{ | |||
accessRights = ar; | |||
} | |||
bool SConnection::accessCheck(AccessRights ar) const | |||
{ | |||
return (accessRights & ar) == ar; | |||
} | |||
void SConnection::setEncodings(int nEncodings, const rdr::S32* encodings) | |||
{ | |||
int i; | |||
@@ -342,6 +352,11 @@ void SConnection::clientInit(bool shared) | |||
state_ = RFBSTATE_NORMAL; | |||
} | |||
void SConnection::close(const char* reason) | |||
{ | |||
state_ = RFBSTATE_CLOSING; | |||
} | |||
void SConnection::setPixelFormat(const PixelFormat& pf) | |||
{ | |||
SMsgHandler::setPixelFormat(pf); |
@@ -69,6 +69,13 @@ namespace rfb { | |||
void approveConnection(bool accept, const char* reason=0); | |||
// Methods to terminate the connection | |||
// close() shuts down the connection to the client and awaits | |||
// cleanup of the SConnection object by the server | |||
virtual void close(const char* reason); | |||
// Overridden from SMsgHandler | |||
virtual void setEncodings(int nEncodings, const rdr::S32* encodings); | |||
@@ -118,8 +125,10 @@ namespace rfb { | |||
virtual void enableContinuousUpdates(bool enable, | |||
int x, int y, int w, int h); | |||
// Other methods | |||
// setAccessRights() allows a security package to limit the access rights | |||
// of a VNCSConnectionST to the server. How the access rights are treated | |||
// of a SConnection to the server. How the access rights are treated | |||
// is up to the derived class. | |||
typedef rdr::U16 AccessRights; | |||
@@ -132,9 +141,8 @@ namespace rfb { | |||
static const AccessRights AccessDefault; // The default rights, INCLUDING FUTURE ONES | |||
static const AccessRights AccessNoQuery; // Connect without local user accepting | |||
static const AccessRights AccessFull; // All of the available AND FUTURE rights | |||
virtual void setAccessRights(AccessRights ar) = 0; | |||
// Other methods | |||
virtual void setAccessRights(AccessRights ar); | |||
virtual bool accessCheck(AccessRights ar) const; | |||
// authenticated() returns true if the client has authenticated | |||
// successfully. | |||
@@ -201,6 +209,7 @@ namespace rfb { | |||
SSecurity* ssecurity; | |||
stateEnum state_; | |||
rdr::S32 preferredEncoding; | |||
AccessRights accessRights; | |||
}; | |||
} | |||
#endif |
@@ -52,8 +52,7 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s, | |||
losslessTimer(this), server(server_), updates(false), | |||
updateRenderedCursor(false), removeRenderedCursor(false), | |||
continuousUpdates(false), encodeManager(this), pointerEventTime(0), | |||
clientHasCursor(false), | |||
accessRights(AccessDefault), startTime(time(0)) | |||
clientHasCursor(false), startTime(time(0)) | |||
{ | |||
setStreams(&sock->inStream(), &sock->outStream()); | |||
peerEndpoint.buf = sock->getPeerEndpoint(); | |||
@@ -94,17 +93,16 @@ VNCSConnectionST::~VNCSConnectionST() | |||
} | |||
// Methods called from VNCServerST | |||
// SConnection methods | |||
bool VNCSConnectionST::init() | |||
bool VNCSConnectionST::accessCheck(AccessRights ar) const | |||
{ | |||
try { | |||
initialiseProtocol(); | |||
} catch (rdr::Exception& e) { | |||
close(e.str()); | |||
return false; | |||
} | |||
return true; | |||
// Reverse connections are user initiated, so they are implicitly | |||
// allowed to bypass the query | |||
if (reverseConnection) | |||
ar &= ~AccessNoQuery; | |||
return SConnection::accessCheck(ar); | |||
} | |||
void VNCSConnectionST::close(const char* reason) | |||
@@ -123,7 +121,22 @@ void VNCSConnectionST::close(const char* reason) | |||
// calling code will call VNCServerST's removeSocket() method causing us to | |||
// be deleted. | |||
sock->shutdown(); | |||
setState(RFBSTATE_CLOSING); | |||
SConnection::close(reason); | |||
} | |||
// Methods called from VNCServerST | |||
bool VNCSConnectionST::init() | |||
{ | |||
try { | |||
initialiseProtocol(); | |||
} catch (rdr::Exception& e) { | |||
close(e.str()); | |||
return false; | |||
} | |||
return true; | |||
} | |||
@@ -267,7 +280,7 @@ void VNCSConnectionST::bellOrClose() | |||
void VNCSConnectionST::serverCutTextOrClose(const char *str, int len) | |||
{ | |||
try { | |||
if (!(accessRights & AccessCutText)) return; | |||
if (!accessCheck(AccessCutText)) return; | |||
if (!rfb::Server::sendCutText) return; | |||
if (state() == RFBSTATE_NORMAL) | |||
writer()->writeServerCutText(str, len); | |||
@@ -447,9 +460,8 @@ void VNCSConnectionST::queryConnection(const char* userName) | |||
} | |||
// - Does the client have the right to bypass the query? | |||
if (reverseConnection || | |||
!(rfb::Server::queryConnect || sock->requiresQuery()) || | |||
(accessRights & AccessNoQuery)) | |||
if (!(rfb::Server::queryConnect || sock->requiresQuery()) || | |||
accessCheck(AccessNoQuery)) | |||
{ | |||
approveConnection(true); | |||
return; | |||
@@ -463,10 +475,10 @@ void VNCSConnectionST::clientInit(bool shared) | |||
{ | |||
lastEventTime = time(0); | |||
if (rfb::Server::alwaysShared || reverseConnection) shared = true; | |||
if (!(accessRights & AccessNonShared)) shared = true; | |||
if (!accessCheck(AccessNonShared)) shared = true; | |||
if (rfb::Server::neverShared) shared = false; | |||
if (!shared) { | |||
if (rfb::Server::disconnectClients && (accessRights & AccessNonShared)) { | |||
if (rfb::Server::disconnectClients && accessCheck(AccessNonShared)) { | |||
// - Close all the other connected clients | |||
vlog.debug("non-shared connection - closing clients"); | |||
server->closeClients("Non-shared connection requested", getSock()); | |||
@@ -494,7 +506,7 @@ void VNCSConnectionST::setPixelFormat(const PixelFormat& pf) | |||
void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask) | |||
{ | |||
pointerEventTime = lastEventTime = time(0); | |||
if (!(accessRights & AccessPtrEvents)) return; | |||
if (!accessCheck(AccessPtrEvents)) return; | |||
if (!rfb::Server::acceptPointerEvents) return; | |||
pointerEventPos = pos; | |||
server->pointerEvent(this, pointerEventPos, buttonMask); | |||
@@ -526,7 +538,7 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) { | |||
rdr::U32 lookup; | |||
lastEventTime = time(0); | |||
if (!(accessRights & AccessKeyEvents)) return; | |||
if (!accessCheck(AccessKeyEvents)) return; | |||
if (!rfb::Server::acceptKeyEvents) return; | |||
if (down) | |||
@@ -636,7 +648,7 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) { | |||
void VNCSConnectionST::clientCutText(const char* str, int len) | |||
{ | |||
if (!(accessRights & AccessCutText)) return; | |||
if (!accessCheck(AccessCutText)) return; | |||
if (!rfb::Server::acceptCutText) return; | |||
server->clientCutText(str, len); | |||
} | |||
@@ -645,7 +657,7 @@ void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental) | |||
{ | |||
Rect safeRect; | |||
if (!(accessRights & AccessView)) return; | |||
if (!accessCheck(AccessView)) return; | |||
SConnection::framebufferUpdateRequest(r, incremental); | |||
@@ -684,7 +696,7 @@ void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height, | |||
{ | |||
unsigned int result; | |||
if (!(accessRights & AccessSetDesktopSize)) return; | |||
if (!accessCheck(AccessSetDesktopSize)) return; | |||
if (!rfb::Server::acceptSetDesktopSize) return; | |||
result = server->setDesktopSize(this, fb_width, fb_height, layout); | |||
@@ -1158,27 +1170,34 @@ char* VNCSConnectionST::getStartTime() | |||
void VNCSConnectionST::setStatus(int status) | |||
{ | |||
AccessRights ar; | |||
ar = AccessDefault; | |||
switch (status) { | |||
case 0: | |||
accessRights = accessRights | AccessPtrEvents | AccessKeyEvents | AccessView; | |||
ar |= AccessPtrEvents | AccessKeyEvents | AccessView; | |||
break; | |||
case 1: | |||
accessRights = (accessRights & ~(AccessPtrEvents | AccessKeyEvents)) | AccessView; | |||
ar |= rfb::SConnection::AccessView; | |||
ar &= ~(AccessPtrEvents | AccessKeyEvents); | |||
break; | |||
case 2: | |||
accessRights = accessRights & ~(AccessPtrEvents | AccessKeyEvents | AccessView); | |||
ar &= ~(AccessPtrEvents | AccessKeyEvents | AccessView); | |||
break; | |||
} | |||
setAccessRights(ar); | |||
framebufferUpdateRequest(server->getPixelBuffer()->getRect(), false); | |||
} | |||
int VNCSConnectionST::getStatus() | |||
{ | |||
if ((accessRights & (AccessPtrEvents | AccessKeyEvents | AccessView)) == 0x0007) | |||
if (accessCheck(AccessPtrEvents | AccessKeyEvents | AccessView)) | |||
return 0; | |||
if ((accessRights & (AccessPtrEvents | AccessKeyEvents | AccessView)) == 0x0001) | |||
else if (accessCheck(AccessView)) | |||
return 1; | |||
if ((accessRights & (AccessPtrEvents | AccessKeyEvents | AccessView)) == 0x0000) | |||
else | |||
return 2; | |||
return 4; | |||
} | |||
@@ -43,6 +43,11 @@ namespace rfb { | |||
VNCSConnectionST(VNCServerST* server_, network::Socket* s, bool reverse); | |||
virtual ~VNCSConnectionST(); | |||
// SConnection methods | |||
virtual bool accessCheck(AccessRights ar) const; | |||
virtual void close(const char* reason); | |||
// Methods called from VNCServerST. None of these methods ever knowingly | |||
// throw an exception. | |||
@@ -54,10 +59,6 @@ namespace rfb { | |||
// returns false, and close() will have been called. | |||
bool init(); | |||
// close() shuts down the socket to the client and deletes the | |||
// SConnectionST object. | |||
void close(const char* reason); | |||
// processMessages() processes incoming messages from the client, invoking | |||
// various callbacks as a result. It continues to process messages until | |||
// reading might block. shutdown() will be called on the connection's | |||
@@ -141,12 +142,6 @@ namespace rfb { | |||
virtual void supportsContinuousUpdates(); | |||
virtual void supportsLEDState(); | |||
// setAccessRights() allows a security package to limit the access rights | |||
// of a VNCSConnectioST to the server. These access rights are applied | |||
// such that the actual rights granted are the minimum of the server's | |||
// default access settings and the connection's access settings. | |||
virtual void setAccessRights(AccessRights ar) {accessRights=ar;} | |||
// Timer callbacks | |||
virtual bool handleTimeout(Timer* t); | |||
@@ -202,8 +197,6 @@ namespace rfb { | |||
Point pointerEventPos; | |||
bool clientHasCursor; | |||
AccessRights accessRights; | |||
CharArray closeReason; | |||
time_t startTime; | |||
}; |
@@ -73,6 +73,10 @@ namespace rfb { | |||
// their close() method with the supplied reason. | |||
virtual void closeClients(const char* reason) = 0; | |||
// getConnection() gets the SConnection for a particular Socket. If | |||
// the Socket is not recognised then null is returned. | |||
virtual SConnection* getConnection(network::Socket* sock) = 0; | |||
// setCursor() tells the server that the cursor has changed. The | |||
// cursorData argument contains width*height rgba quadruplets with | |||
// non-premultiplied alpha. |
@@ -583,7 +583,7 @@ void VNCServerST::getSockets(std::list<network::Socket*>* sockets) | |||
} | |||
} | |||
SConnection* VNCServerST::getSConnection(network::Socket* sock) { | |||
SConnection* VNCServerST::getConnection(network::Socket* sock) { | |||
std::list<VNCSConnectionST*>::iterator ci; | |||
for (ci = clients.begin(); ci != clients.end(); ci++) { | |||
if ((*ci)->getSock() == sock) |
@@ -99,6 +99,7 @@ namespace rfb { | |||
virtual void approveConnection(network::Socket* sock, bool accept, | |||
const char* reason); | |||
virtual void closeClients(const char* reason) {closeClients(reason, 0);} | |||
virtual SConnection* getConnection(network::Socket* sock); | |||
virtual void add_changed(const Region ®ion); | |||
virtual void add_copied(const Region &dest, const Point &delta); | |||
@@ -133,11 +134,6 @@ namespace rfb { | |||
// any), and logs the specified reason for closure. | |||
void closeClients(const char* reason, network::Socket* sock); | |||
// getSConnection() gets the SConnection for a particular Socket. If | |||
// the Socket is not recognised then null is returned. | |||
SConnection* getSConnection(network::Socket* sock); | |||
// 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. |