📄 vncserver.cpp
字号:
// Copyright (C) 2006 Teamviewer GmbH. All Rights Reserved.
// Copyright (C) 2002 Ultr@Vnc Team Members. All Rights Reserved.
// Copyright (C) 2000-2002 Const Kaplinsky. All Rights Reserved.
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
// This file is part of TeamViewer.
//
// TeamViewer 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 TeamViewer is not available from the place
// whence you received this file, check http://www.teamviewer.com
// for information on obtaining it.
// vncServer.cpp
// vncServer class implementation
// Includes
#include "stdhdrs.h"
// Custom
#include "vncServer.h"
#include "vncSockConnect.h"
#include "vncClient.h"
#include "vncService.h"
#include "vncTimedMsgBox.h"
#include "vncMenu.h"
#include "Global.h"
#include "../../vncviewer/SessionDialog.h"
#include "localization.h" // ACT : Add localization on messages
bool g_Server_running;
extern bool g_Desktop_running;
extern bool isQuickSupport;
extern vncMenu* menu;
using namespace std;
// vncServer::UpdateTracker routines
void
vncServer::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++)
{
// Post the update
// REalVNC 336 change
// m_server->GetClient(*i)->GetUpdateTracker().add_changed(rgn);
vncClient* client = m_server->GetClient(*i);
omni_mutex_lock l(client->GetUpdateLock());
client->GetUpdateTracker().add_changed(rgn);
}
}
void
vncServer::ServerUpdateTracker::add_cached(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++)
{
// Post the update
// RealVNC 336 change
// m_server->GetClient(*i)->GetUpdateTracker().add_cached(rgn);
vncClient* client = m_server->GetClient(*i);
omni_mutex_lock l(client->GetUpdateLock());
client->GetUpdateTracker().add_cached(rgn);
}
}
void
vncServer::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++)
{
// Post the update
// RealVNC 336 change
//m_server->GetClient(*i)->GetUpdateTracker().add_copied(dest, delta);
vncClient* client = m_server->GetClient(*i);
omni_mutex_lock l(client->GetUpdateLock());
client->GetUpdateTracker().add_copied(dest, delta);
}
}
// Constructor/destructor
vncServer::vncServer()
{
// Initialise some important stuffs...
g_Server_running=true;
m_socketConn = NULL;
m_httpConn = NULL;
m_enableHttpConn = false;
m_desktop = NULL;
m_name = NULL;
m_port = DISPLAY_TO_PORT(0);
m_port_http = DISPLAY_TO_HPORT(0); // TightVNC 1.2.7
m_autoportselect = TRUE;
m_passwd_required = TRUE;
m_auth_hosts = 0;
m_blacklist = 0;
{
vncPasswd::FromClear clearPWD;
memcpy(m_password, clearPWD, MAXPWLEN);
}
m_querysetting = 4;
m_queryaccept = 0;
m_querytimeout = 10;
// Autolock settings
m_lock_on_exit = 0;
// Set the polling mode options
m_poll_fullscreen = TRUE;
m_poll_foreground = FALSE;
m_poll_undercursor = FALSE;
m_poll_oneventonly = FALSE;
m_poll_consoleonly = TRUE;
m_driver = false;
m_hook = true;
sethook=false;
// General options
m_loopbackOnly = FALSE;
m_loopback_allowed = true;
m_lock_on_exit = 0;
m_connect_pri = 0;
m_disableTrayIcon = FALSE;
m_AllowEditClients = FALSE;
// 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);
// Modif sf@2002
m_SingleWindow = FALSE;
strcpy(m_szWindowName, "");
// Modif sf@2002
m_TurboMode = false;
// m_fCursorMoved = false;
// TR@2003
m_AcceptDialog = false;
m_shutdown = false;
//m_autostartsetting = 1;
// sf@2002 - v1.1.2
// m_fQueuingEnabled = false;
m_fFileTransferEnabled = 2; // TR@2004 - defaults to allowed after query
m_nDefaultScale = 1;
m_fMSLogonRequired = false;
m_fXRichCursor = false;
// sf@2003 - Autoreconnect
m_fAutoReconnect = false;
m_AutoReconnectPort = 0;
strcpy(m_szAutoReconnectAdr, "");
// sf@2005 - No FT User Impersonnation
m_fFTUserImpersonation = true;
m_fBlackAlphaBlending = false;
// Staudenmeyer@2005
m_displayQuality = 1; // autoselect
m_incomingConnections=ConnectionNone;
m_sessionDialogShown=false;
m_hSessionDialog = NULL;
m_updateHandling=UpdateHandlingOptimizeQuality;
//m_keepDialogOpen=false;
m_useDynGate=true;
m_serverMode=false;
m_logging=false;
m_connectionLogging=true;
m_identity[0] = '\0';
m_remove_wallpaper = FALSE;
m_sessionPassword=GenerateSessionPassword();
m_idle_timeout = 0;
m_DesktopLocked = false;
}
std::string vncServer::GenerateSessionPassword()
{
srand((unsigned int)time(NULL));
const int passwordLength=4;
string chars="1234567890";
string password="";
for(int i=0;i<passwordLength;i++)
{
int index=rand()%chars.length();
password=password+chars[index];
}
#ifdef _DEBUG
password = "0";
#endif
return password;
}
vncServer::~vncServer()
{
vnclog.Print(LL_STATE, VNCLOG("shutting down server object"));
// If there is a socket_conn object then delete it
if (m_socketConn != NULL)
{
delete m_socketConn;
m_socketConn = 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;
}
}
while (g_Desktop_running)
{
Sleep(100);
vnclog.Print(LL_STATE, VNCLOG("Waiting for desktop to shutdown"));
}
// 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;
}
//We need to give the client thread to give some time to close
// bad hack
Sleep(500);
//sometimes crash, vnclog seems already removed
// vnclog.Print(LL_STATE, VNCLOG("shutting down server object(4)"));
g_Server_running=false;
}
// Client handling functions
vncClientId
vncServer::AddClient(VSocket *socket, BOOL auth, BOOL shared)
{
SYSTEMTIME dummyTime;
GetSystemTime(&dummyTime);
return AddClient(socket, auth, shared, 0, NULL, "", dummyTime);
}
vncClientId
vncServer::AddClient(VSocket *socket, BOOL auth, BOOL shared, string clientname, SYSTEMTIME start)
{
return AddClient(socket, auth, shared,0, NULL, clientname, start);
}
vncClientId
vncServer::AddClient(VSocket *socket, BOOL auth, BOOL shared, rfbProtocolVersionMsg *protocolMsg)
{
SYSTEMTIME dummyTime;
GetSystemTime(&dummyTime);
return AddClient(socket, auth, shared, 0, protocolMsg, "", dummyTime);
}
vncClientId
vncServer::AddClient(VSocket *socket, BOOL auth, BOOL shared,
int capability, rfbProtocolVersionMsg *protocolMsg, string clientname, SYSTEMTIME start)
{
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->SetProtocolVersion(protocolMsg);
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"));
delete client;
return -1;
}
client->connectionLogUser = clientname;
client->connectionLogStartTime = start;
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);
// after start of a new connection input is not disabled and the monitor is never blank
m_fInputIsDisabled = false;
m_fMonitorIsBlanked = false;
vnclog.Print(LL_INTINFO, VNCLOG("AddClient() done"));
return clientid;
}
BOOL
vncServer::Authenticated(vncClientId clientid)
{
vncClientList::iterator i;
BOOL authok = TRUE;
// vnclog.Print(LL_INTINFO, VNCLOG("Lock2"));
omni_mutex_lock l1(m_desktopLock);
// vnclog.Print(LL_INTINFO, VNCLOG("Lock3"));
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);
//CW@2004
//Client zum l鰏chen freigeben
client->m_IsAuthed = TRUE;
// 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))
{
vnclog.Print(LL_INTINFO, VNCLOG("Desktop init failed, unlock in application mode ? "));
if(TeamviewerInfo::getLocalInfo(tvError) == "") // if TeamViewer-Error is set kill client later
{
client->Kill();
authok = FALSE;
}
delete m_desktop; // but delete m_desktop so that it is created again next time
m_desktop = NULL;
break;
}
}
else if(m_DesktopLocked)
{
vnclog.Print(LL_INTINFO, VNCLOG("Desktop is locked"));
TeamviewerInfo::setLocalInfo(tvError, "WORKSTATION_LOCKED");
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"));
return authok;
}
void
vncServer::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"));
// 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"));
// Yes, so kill it
vncClient *client = GetClient(clientid);
client->Kill();
done = TRUE;
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -