📄 vncserver.cpp
字号:
// Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.//// This file is part of the VNC system.//// The VNC system 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 program 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 program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,// USA.//// If the source code for the VNC system is not available from the place // whence you received this file, check http://www.uk.research.att.com/vnc or contact// the authors on vnc@uk.research.att.com for information on obtaining it.// vncServer.cpp// vncServer class implementation// Includes#include "stdhdrs.h"#include <omnithread.h>#include <string.h>#include <lmcons.h>// Custom#include "WinVNC.h"#include "vncServer.h"#include "vncSockConnect.h"#include "vncCorbaConnect.h"#include "vncClient.h"#include "vncService.h"// vncServer::UpdateTracker routinesvoidvncServer::ServerUpdateTracker::add_changed(const rfb::Region2D &rgn) { vncClientList::iterator i; omni_mutex_lock l(m_server->m_clientsLock); // Post this update to all the connected clients for (i = m_server->m_authClients.begin(); i != m_server->m_authClients.end(); i++) { vncClient* client = m_server->GetClient(*i); // Post the update omni_mutex_lock l(client->GetUpdateLock()); client->GetUpdateTracker().add_changed(rgn); }}voidvncServer::ServerUpdateTracker::add_copied(const rfb::Region2D &dest, const rfb::Point &delta) { vncClientList::iterator i; omni_mutex_lock l(m_server->m_clientsLock); // Post this update to all the connected clients for (i = m_server->m_authClients.begin(); i != m_server->m_authClients.end(); i++) { vncClient* client = m_server->GetClient(*i); // Post the update omni_mutex_lock l(client->GetUpdateLock()); client->GetUpdateTracker().add_copied(dest, delta); }}// Constructor/destructorvncServer::vncServer(){ // Initialise some important stuffs... m_socketConn = NULL; m_corbaConn = NULL; m_httpConn = NULL; m_enableHttpConn = false; m_desktop = NULL; m_name = NULL; m_port = DISPLAY_TO_PORT(0); m_autoportselect = TRUE; m_passwd_required = TRUE; m_auth_hosts = 0; m_blacklist = 0; { vncPasswd::FromClear clearPWD; memcpy(m_password, clearPWD, MAXPWLEN); } m_querysetting = 2; m_querytimeout = 10; // Autolock settings m_lock_on_exit = 0; // Set the polling mode options m_poll_fullscreen = FALSE; m_poll_foreground = FALSE; m_poll_undercursor = TRUE; m_poll_oneventonly = FALSE; m_poll_consoleonly = TRUE; // General options m_loopbackOnly = FALSE; m_loopback_allowed = FALSE; m_lock_on_exit = 0; m_connect_pri = 0; // Set the input options m_enable_remote_inputs = TRUE; m_disable_local_inputs = FALSE; // Clear the client mapping table for (int x=0; x<MAX_CLIENTS; x++) m_clientmap[x] = NULL; m_nextid = 0; // Initialise the update tracker m_update_tracker.init(this); // Signal set when a client quits m_clientquitsig = new omni_condition(&m_clientsLock);}vncServer::~vncServer(){ vnclog.Print(LL_STATE, VNCLOG("shutting down server object\n")); // If there is a socket_conn object then delete it if (m_socketConn != NULL) { delete m_socketConn; m_socketConn = NULL; } if (m_corbaConn != NULL) { delete m_corbaConn; m_corbaConn = NULL; } if (m_httpConn != NULL) { delete m_httpConn; m_httpConn = NULL; } // Remove any active clients! KillAuthClients(); KillUnauthClients(); // Wait for all the clients to die WaitUntilAuthEmpty(); WaitUntilUnauthEmpty(); // Don't free the desktop until no KillClient is likely to free it { omni_mutex_lock l(m_desktopLock); if (m_desktop != NULL) { delete m_desktop; m_desktop = NULL; } } // Don't free the authhosts string until no more connections are possible if (m_auth_hosts != 0) { free(m_auth_hosts); m_auth_hosts = 0; } if (m_name != NULL) { free(m_name); m_name = NULL; } if (m_clientquitsig != NULL) { delete m_clientquitsig; m_clientquitsig = NULL; } // Free the host blacklist while (m_blacklist) { vncServer::BlacklistEntry *current = m_blacklist; m_blacklist=m_blacklist->_next; free (current->_machineName); delete current; } vnclog.Print(LL_STATE, VNCLOG("shutting down server object(4)\n"));}// Client handling functionsvncClientIdvncServer::AddClient(VSocket *socket, BOOL auth, BOOL shared){ return AddClient(socket, auth, shared, FALSE, 0, TRUE, TRUE); }vncClientIdvncServer::AddClient(VSocket *socket, BOOL auth, BOOL shared, BOOL teleport, int capability, BOOL keysenabled, BOOL ptrenabled){ vncClient *client; omni_mutex_lock l(m_clientsLock); // Try to allocate a client id... vncClientId clientid = m_nextid; do { clientid = (clientid+1) % MAX_CLIENTS; if (clientid == m_nextid) { delete socket; return -1; } } while (m_clientmap[clientid] != NULL); // Create a new client and add it to the relevant client list client = new vncClient(); if (client == NULL) { delete socket; return -1; } // Set the client's settings client->SetTeleport(teleport); client->SetCapability(capability); client->EnableKeyboard(keysenabled && m_enable_remote_inputs); client->EnablePointer(ptrenabled && m_enable_remote_inputs); // Start the client if (!client->Init(this, socket, auth, shared, clientid)) { // The client will delete the socket for us... vnclog.Print(LL_CONNERR, VNCLOG("failed to initialise client object\n")); delete client; return -1; } m_clientmap[clientid] = client; // Add the client to unauth the client list m_unauthClients.push_back(clientid); // Notify anyone interested about this event DoNotify(WM_SRV_CLIENT_CONNECT, 0, 0); vnclog.Print(LL_INTINFO, VNCLOG("AddClient() done\n")); return clientid;}BOOLvncServer::Authenticated(vncClientId clientid){ vncClientList::iterator i; BOOL authok = TRUE; omni_mutex_lock l1(m_desktopLock); omni_mutex_lock l2(m_clientsLock); // Search the unauthenticated client list for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++) { // Is this the right client? if ((*i) == clientid) { vncClient *client = GetClient(clientid); // Yes, so remove the client and add it to the auth list m_unauthClients.erase(i); // Create the screen handler if necessary if (m_desktop == NULL) { m_desktop = new vncDesktop(); if (m_desktop == NULL) { client->Kill(); authok = FALSE; break; } if (!m_desktop->Init(this)) { client->Kill(); authok = FALSE; delete m_desktop; m_desktop = NULL; break; } } // Tell the client about this new buffer client->SetBuffer(&(m_desktop->m_buffer)); // Add the client to the auth list m_authClients.push_back(clientid); break; } } // Notify anyone interested of this event DoNotify(WM_SRV_CLIENT_AUTHENTICATED, 0, 0); vnclog.Print(LL_INTINFO, VNCLOG("Authenticated() done\n")); return authok;}voidvncServer::KillClient(vncClientId clientid){ vncClientList::iterator i; BOOL done = FALSE; omni_mutex_lock l(m_clientsLock); // Find the client in one of the two lists for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++) { // Is this the right client? if ((*i) == clientid) { vnclog.Print(LL_INTINFO, VNCLOG("killing unauth client\n")); // Ask the client to die vncClient *client = GetClient(clientid); client->Kill(); done = TRUE; break; } } if (!done) { for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Is this the right client? if ((*i) == clientid) { vnclog.Print(LL_INTINFO, VNCLOG("killing auth client\n")); // Yes, so kill it vncClient *client = GetClient(clientid); client->Kill(); done = TRUE; break; } } } vnclog.Print(LL_INTINFO, VNCLOG("KillClient() done\n"));}voidvncServer::KillAuthClients(){ vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Tell all the authorised clients to die! for (i = m_authClients.begin(); i != m_authClients.end(); i++) { vnclog.Print(LL_INTINFO, VNCLOG("killing auth client\n")); // Kill the client GetClient(*i)->Kill(); } vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() done\n"));}voidvncServer::KillUnauthClients(){ vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Tell all the authorised clients to die! for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++) { vnclog.Print(LL_INTINFO, VNCLOG("killing unauth client\n")); // Kill the client GetClient(*i)->Kill(); } vnclog.Print(LL_INTINFO, VNCLOG("KillUnauthClients() done\n"));}UINTvncServer::AuthClientCount(){ omni_mutex_lock l(m_clientsLock); return m_authClients.size();}UINTvncServer::UnauthClientCount(){ omni_mutex_lock l(m_clientsLock); return m_unauthClients.size();}BOOLvncServer::UpdateWanted(){ vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Iterate over the authorised clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { if (GetClient(*i)->UpdateWanted()) return TRUE; } return FALSE;}BOOLvncServer::RemoteEventReceived(){ vncClientList::iterator i; BOOL result = FALSE; omni_mutex_lock l(m_clientsLock); // Iterate over the authorised clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { result = result || GetClient(*i)->RemoteEventReceived(); } return result;}voidvncServer::WaitUntilAuthEmpty(){ omni_mutex_lock l(m_clientsLock); // Wait for all the clients to exit while (!m_authClients.empty()) { // Wait for a client to quit m_clientquitsig->wait(); }}voidvncServer::WaitUntilUnauthEmpty(){ omni_mutex_lock l(m_clientsLock); // Wait for all the clients to exit while (!m_unauthClients.empty()) { // Wait for a client to quit m_clientquitsig->wait(); }}// Client info retrieval/setupvncClient*vncServer::GetClient(vncClientId clientid){ if ((clientid >= 0) && (clientid < MAX_CLIENTS)) return m_clientmap[clientid]; return NULL;}vncClientListvncServer::ClientList(){ vncClientList clients; omni_mutex_lock l(m_clientsLock); clients = m_authClients; return clients;}voidvncServer::SetTeleport(vncClientId clientid, BOOL teleport){ omni_mutex_lock l(m_clientsLock); vncClient *client = GetClient(clientid); if (client != NULL) client->SetTeleport(teleport);}voidvncServer::SetCapability(vncClientId clientid, int capability){ omni_mutex_lock l(m_clientsLock); vncClient *client = GetClient(clientid); if (client != NULL) client->SetCapability(capability);}voidvncServer::SetKeyboardEnabled(vncClientId clientid, BOOL enabled){ omni_mutex_lock l(m_clientsLock); vncClient *client = GetClient(clientid); if (client != NULL) client->EnableKeyboard(enabled);}voidvncServer::SetPointerEnabled(vncClientId clientid, BOOL enabled){ omni_mutex_lock l(m_clientsLock); vncClient *client = GetClient(clientid); if (client != NULL) client->EnablePointer(enabled);}BOOLvncServer::IsTeleport(vncClientId clientid){ omni_mutex_lock l(m_clientsLock); vncClient *client = GetClient(clientid); if (client != NULL) return client->IsTeleport(); return FALSE;}intvncServer::GetCapability(vncClientId clientid){ omni_mutex_lock l(m_clientsLock); vncClient *client = GetClient(clientid); if (client != NULL) return client->GetCapability(); return 0;}BOOLvncServer::GetKeyboardEnabled(vncClientId clientid){ omni_mutex_lock l(m_clientsLock); vncClient *client = GetClient(clientid); if (client != NULL) return client->IsKeyboardEnabled(); return FALSE;}BOOLvncServer::GetPointerEnabled(vncClientId clientid){ omni_mutex_lock l(m_clientsLock); vncClient *client = GetClient(clientid); if (client != NULL) return client->IsPointerEnabled(); return FALSE;}const char*vncServer::GetClientName(vncClientId clientid){ omni_mutex_lock l(m_clientsLock); vncClient *client = GetClient(clientid); if (client != NULL) return client->GetClientName(); return NULL;}// RemoveClient should ONLY EVER be used by the client to remove itself.voidvncServer::RemoveClient(vncClientId clientid){ vncClientList::iterator i; BOOL done = FALSE; omni_mutex_lock l1(m_desktopLock); { omni_mutex_lock l2(m_clientsLock); // Find the client in one of the two lists for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++) { // Is this the right client? if ((*i) == clientid) { vnclog.Print(LL_INTINFO, VNCLOG("removing unauthorised client\n")); // Yes, so remove the client and kill it m_unauthClients.erase(i); m_clientmap[clientid] = NULL; done = TRUE; break; } } if (!done) { for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Is this the right client? if ((*i) == clientid) { vnclog.Print(LL_INTINFO, VNCLOG("removing authorised client\n")); // Yes, so remove the client and kill it m_authClients.erase(i); m_clientmap[clientid] = NULL; done = TRUE; break; } } } // Signal that a client has quit m_clientquitsig->signal(); } // Unlock the clientLock // Are there any authorised clients connected? if (m_authClients.empty() && (m_desktop != NULL)) { vnclog.Print(LL_STATE, VNCLOG("deleting desktop server\n")); // Are there locksettings set? if (LockSettings() == 1) { // Yes - lock the machine on disconnect! vncService::LockWorkstation(); } else if (LockSettings() > 1) { char username[UNLEN+1]; vncService::CurrentUser((char *)&username, sizeof(username)); if (strcmp(username, "") != 0) { // Yes - force a user logoff on disconnect! if (!ExitWindowsEx(EWX_LOGOFF, 0)) vnclog.Print(LL_CONNERR, VNCLOG("client disconnect - failed to logoff user!\n")); } } // Delete the screen server delete m_desktop; m_desktop = NULL; } // Notify anyone interested of the change DoNotify(WM_SRV_CLIENT_DISCONNECT, 0, 0); vnclog.Print(LL_INTINFO, VNCLOG("RemoveClient() done\n"));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -