Force queryConnection() to always call back to approveConnection() rather than return special values. This makes the flow easier to follow as it will be the same in all cases.tags/v1.9.90
} | } | ||||
// - Get the server to display an Accept/Reject dialog, if required | // - Get the server to display an Accept/Reject dialog, if required | ||||
// If a dialog is displayed, the result will be PENDING, and the | |||||
// server will call approveConnection at a later time | |||||
CharArray reason; | |||||
VNCServerST::queryResult qr = server->queryConnection(sock, userName, | |||||
&reason.buf); | |||||
if (qr == VNCServerST::PENDING) | |||||
return; | |||||
// - If server returns ACCEPT/REJECT then pass result to SConnection | |||||
approveConnection(qr == VNCServerST::ACCEPT, reason.buf); | |||||
server->queryConnection(sock, userName); | |||||
} | } | ||||
void VNCSConnectionST::clientInit(bool shared) | void VNCSConnectionST::clientInit(bool shared) |
void serverCutTextOrClose(const char *str, int len); | void serverCutTextOrClose(const char *str, int len); | ||||
void setDesktopNameOrClose(const char *name); | void setDesktopNameOrClose(const char *name); | ||||
void setLEDStateOrClose(unsigned int state); | void setLEDStateOrClose(unsigned int state); | ||||
void approveConnectionOrClose(bool accept, const char* reason); | |||||
// checkIdleTimeout() returns the number of milliseconds left until the | // checkIdleTimeout() returns the number of milliseconds left until the | ||||
// idle timeout expires. If it has expired, the connection is closed and | // idle timeout expires. If it has expired, the connection is closed and | ||||
const char* getPeerEndpoint() const {return peerEndpoint.buf;} | const char* getPeerEndpoint() const {return peerEndpoint.buf;} | ||||
// approveConnectionOrClose() is called some time after | |||||
// VNCServerST::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 approveConnectionOrClose(bool accept, const char* reason); | |||||
char* getStartTime(); | char* getStartTime(); | ||||
void setStatus(int status); | void setStatus(int status); |
// | // | ||||
// queryConnection() is called when a connection has been | // queryConnection() is called when a connection has been | ||||
// successfully authenticated. The sock and userName arguments identify | // 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, | |||||
// the socket and the name of the authenticated user, if any. | |||||
// approveConnection() must be called some time later to accept or reject | // approveConnection() must be called some time later to accept or reject | ||||
// the connection. | // the connection. | ||||
enum queryResult { ACCEPT, REJECT, PENDING }; | |||||
struct QueryConnectionHandler { | struct QueryConnectionHandler { | ||||
virtual ~QueryConnectionHandler() {} | virtual ~QueryConnectionHandler() {} | ||||
virtual queryResult queryConnection(network::Socket* sock, | |||||
const char* userName, | |||||
char** reason) = 0; | |||||
virtual void queryConnection(network::Socket* sock, | |||||
const char* userName) = 0; | |||||
}; | }; | ||||
void setQueryConnectionHandler(QueryConnectionHandler* qch) { | void setQueryConnectionHandler(QueryConnectionHandler* qch) { | ||||
queryConnectionHandler = qch; | queryConnectionHandler = qch; | ||||
// queryConnection is called as described above, and either passes the | // queryConnection is called as described above, and either passes the | ||||
// request on to the registered handler, or accepts the connection if | // request on to the registered handler, or accepts the connection if | ||||
// no handler has been specified. | // no handler has been specified. | ||||
virtual queryResult queryConnection(network::Socket* sock, | |||||
const char* userName, | |||||
char** reason) { | |||||
return queryConnectionHandler | |||||
? queryConnectionHandler->queryConnection(sock, userName, reason) | |||||
: ACCEPT; | |||||
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, | // approveConnection() is called by the active QueryConnectionHandler, |
~QueryConnHandler() { delete queryConnectDialog; } | ~QueryConnHandler() { delete queryConnectDialog; } | ||||
// -=- VNCServerST::QueryConnectionHandler interface | // -=- VNCServerST::QueryConnectionHandler interface | ||||
virtual VNCServerST::queryResult queryConnection(network::Socket* sock, | |||||
const char* userName, | |||||
char** reason) { | |||||
virtual void queryConnection(network::Socket* sock, | |||||
const char* userName) { | |||||
if (queryConnectSock) { | if (queryConnectSock) { | ||||
*reason = strDup("Another connection is currently being queried."); | |||||
return VNCServerST::REJECT; | |||||
server->approveConnection(sock, false, "Another connection is currently being queried."); | |||||
return; | |||||
} | } | ||||
if (!userName) userName = "(anonymous)"; | if (!userName) userName = "(anonymous)"; | ||||
queryConnectSock = sock; | queryConnectSock = sock; | ||||
userName, queryConnectTimeout, | userName, queryConnectTimeout, | ||||
this); | this); | ||||
queryConnectDialog->map(); | queryConnectDialog->map(); | ||||
return VNCServerST::PENDING; | |||||
} | } | ||||
// -=- QueryResultCallback interface | // -=- QueryResultCallback interface |
server->setScreenLayout(::computeScreenLayout(&outputIdMap)); | server->setScreenLayout(::computeScreenLayout(&outputIdMap)); | ||||
} | } | ||||
rfb::VNCServerST::queryResult | |||||
XserverDesktop::queryConnection(network::Socket* sock, | |||||
const char* userName, | |||||
char** reason) | |||||
void XserverDesktop::queryConnection(network::Socket* sock, | |||||
const char* userName) | |||||
{ | { | ||||
int count; | int count; | ||||
if (queryConnectTimer.isStarted()) { | if (queryConnectTimer.isStarted()) { | ||||
*reason = strDup("Another connection is currently being queried."); | |||||
return rfb::VNCServerST::REJECT; | |||||
server->approveConnection(sock, false, "Another connection is currently being queried."); | |||||
return; | |||||
} | } | ||||
count = vncNotifyQueryConnect(); | count = vncNotifyQueryConnect(); | ||||
if (count == 0) { | if (count == 0) { | ||||
*reason = strDup("Unable to query the local user to accept the connection."); | |||||
return rfb::VNCServerST::REJECT; | |||||
server->approveConnection(sock, false, "Unable to query the local user to accept the connection."); | |||||
return; | |||||
} | } | ||||
queryConnectAddress.replaceBuf(sock->getPeerAddress()); | queryConnectAddress.replaceBuf(sock->getPeerAddress()); | ||||
queryConnectSocket = sock; | queryConnectSocket = sock; | ||||
queryConnectTimer.start(queryConnectTimeout * 1000); | queryConnectTimer.start(queryConnectTimeout * 1000); | ||||
return rfb::VNCServerST::PENDING; | |||||
} | } | ||||
void XserverDesktop::bell() | void XserverDesktop::bell() |
virtual void grabRegion(const rfb::Region& r); | virtual void grabRegion(const rfb::Region& r); | ||||
// rfb::VNCServerST::QueryConnectionHandler callback | // rfb::VNCServerST::QueryConnectionHandler callback | ||||
virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock, | |||||
const char* userName, | |||||
char** reason); | |||||
virtual void queryConnection(network::Socket* sock, | |||||
const char* userName); | |||||
protected: | protected: | ||||
bool handleListenerEvent(int fd, | bool handleListenerEvent(int fd, |
return queueCommand(SetClientsStatus, LCInfo, 0); | return queueCommand(SetClientsStatus, LCInfo, 0); | ||||
} | } | ||||
VNCServerST::queryResult VNCServerWin32::queryConnection(network::Socket* sock, | |||||
const char* userName, | |||||
char** reason) | |||||
void VNCServerWin32::queryConnection(network::Socket* sock, | |||||
const char* userName) | |||||
{ | { | ||||
if (queryOnlyIfLoggedOn && CurrentUserToken().noUserLoggedOn()) | |||||
return VNCServerST::ACCEPT; | |||||
if (queryOnlyIfLoggedOn && CurrentUserToken().noUserLoggedOn()) { | |||||
vncServer.approveConnection(sock, true, NULL); | |||||
return; | |||||
} | |||||
if (queryConnectDialog) { | if (queryConnectDialog) { | ||||
*reason = rfb::strDup("Another connection is currently being queried."); | |||||
return VNCServerST::REJECT; | |||||
vncServer.approveConnection(sock, false, "Another connection is currently being queried."); | |||||
return; | |||||
} | } | ||||
queryConnectDialog = new QueryConnectDialog(sock, userName, this); | queryConnectDialog = new QueryConnectDialog(sock, userName, this); | ||||
queryConnectDialog->startDialog(); | queryConnectDialog->startDialog(); | ||||
return VNCServerST::PENDING; | |||||
} | } | ||||
void VNCServerWin32::queryConnectionComplete() { | void VNCServerWin32::queryConnectionComplete() { |
// VNCServerST::QueryConnectionHandler interface | // VNCServerST::QueryConnectionHandler interface | ||||
// Callback used to prompt user to accept or reject a connection. | // Callback used to prompt user to accept or reject a connection. | ||||
// CALLBACK IN VNCServerST "HOST" THREAD | // CALLBACK IN VNCServerST "HOST" THREAD | ||||
virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock, | |||||
const char* userName, | |||||
char** reason); | |||||
virtual void queryConnection(network::Socket* sock, | |||||
const char* userName); | |||||
// SocketManager::AddressChangeNotifier interface | // SocketManager::AddressChangeNotifier interface | ||||
// Used to keep tray icon up to date | // Used to keep tray icon up to date |