📄 vncserver.cpp
字号:
// 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 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 "vncClient.h"
#include "vncService.h"
#include "vncTimedMsgBox.h"
#include "mmSystem.h" // sf@2002
#include "localization.h" // ACT : Add localization on messages
bool g_Server_running;
extern bool g_Desktop_running;
// 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_enableXdmcpConn = 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 = 2;
m_queryaccept = 0;
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;
m_driver = FALSE;
m_hook = FALSE;
m_virtual = FALSE;
sethook=false;
// General options
m_loopbackOnly = FALSE;
m_loopback_allowed = FALSE;
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;
// sf@2002 - v1.1.2
// m_fQueuingEnabled = false;
m_fFileTransferEnabled = true;
m_nDefaultScale = 1;
// sf@2002 - Data Stream Modification Plugin handling
m_pDSMPlugin = new CDSMPlugin();
m_fDSMPluginEnabled = false;
strcpy(m_szDSMPlugin, "");
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_fCaptureAlphaBlending = false;
m_fBlackAlphaBlending = false;
m_impersonationtoken=NULL; //byteboon
m_xdmcpConn=NULL;
m_impersonationtoken=NULL; // Modif Jeremy C.
}
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_httpConn != NULL)
{
delete m_httpConn;
m_httpConn = NULL;
}
// Modif Jeremy C.
if(m_impersonationtoken)
CloseHandle(m_impersonationtoken);
// 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\n"));
}
// 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;
}
// Modif sf@2002 - DSMPlugin handling
if (m_pDSMPlugin != NULL)
delete(m_pDSMPlugin);
// 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)\n"));
g_Server_running=false;
}
// Client handling functions
vncClientId
vncServer::AddClient(VSocket *socket, BOOL auth, BOOL shared)
{
return AddClient(socket, auth, shared, /*FALSE,*/ 0, /*TRUE, TRUE,*/NULL);
}
vncClientId
vncServer::AddClient(VSocket *socket, BOOL auth, BOOL shared,rfbProtocolVersionMsg *protocolMsg)
{
return AddClient(socket, auth, shared, /*FALSE,*/ 0, /*TRUE, TRUE,*/protocolMsg);
}
vncClientId
vncServer::AddClient(VSocket *socket, BOOL auth, BOOL shared,
int capability,
/*BOOL keysenabled, BOOL ptrenabled,*/rfbProtocolVersionMsg *protocolMsg)
{
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\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;
}
BOOL
vncServer::Authenticated(vncClientId clientid)
{
vncClientList::iterator i;
BOOL authok = TRUE;
// vnclog.Print(LL_INTINFO, VNCLOG("Lock2\n"));
omni_mutex_lock l1(m_desktopLock);
// vnclog.Print(LL_INTINFO, VNCLOG("Lock3\n"));
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))
{
vnclog.Print(LL_INTINFO, VNCLOG("Desktop init failed, unlock in application mode ? \n"));
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;
}
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\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"));
}
//
// sf@2002 - Kill the client which has the passed name
//
void vncServer::KillClient(LPSTR szClientName)
{
vncClientList::iterator i;
omni_mutex_lock l(m_clientsLock);
vncClient *pClient = NULL;
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
{
pClient = GetClient(*i);
if (!stricmp(pClient->GetClientName(), szClientName))
{
vnclog.Print(LL_INTINFO, VNCLOG("Killing client named: %s\n"), szClientName);
pClient->Kill();
}
}
vnclog.Print(LL_INTINFO, VNCLOG("KillClient() from name done\n"));
}
//
// sf@2002 - Open a textchat window with the named client
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -