⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vncserver.cpp

📁 Web VNC samples delphi
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//  Copyright (C) 2000 Tridia Corporation. 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.
//
// TightVNC distribution homepage on the Web: http://www.tightvnc.com/
//
// 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"

// Constructor/destructor
vncServer::vncServer()
{
	ResetPasswordsValidityInfo();

	// Initialise some important stuffs...
	m_socketConn = NULL;
	m_corbaConn = NULL;
	m_httpConn = NULL;
	m_desktop = NULL;
	m_name = NULL;
	m_port = DISPLAY_TO_PORT(0);
	m_port_http = DISPLAY_TO_HPORT(0);
	m_autoportselect = TRUE;
	m_passwd_required = TRUE;
	m_beepConnect = FALSE;
	m_beepDisconnect = FALSE;
	m_auth_hosts = 0;
	m_blacklist = 0;
	{
		vncPasswd::FromClear clearPWD;
		memcpy(m_password, clearPWD, MAXPWLEN);
		m_password_set = FALSE;
		memcpy(m_password_viewonly, clearPWD, MAXPWLEN);
		m_password_viewonly_set = FALSE;
	}
	m_querysetting = 2;
	m_querytimeout = 10;
	m_queryaccept = FALSE;
	m_queryallownopass = FALSE;

	// 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_dont_set_hooks = FALSE;
	m_dont_use_driver = FALSE;
	m_driver_direct_access_en = TRUE;

	// General options
	m_loopbackOnly = FALSE;
	m_disableTrayIcon = FALSE;
	m_loopback_allowed = FALSE;
	m_httpd_enabled = TRUE;
	m_httpd_params_enabled = 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;

	// Signal set when a client quits
	m_clientquitsig = new omni_condition(&m_clientsLock);
	m_clients_disabled = FALSE;
	m_local_input_priority = FALSE;

	m_full_screen = TRUE;
	m_WindowShared= FALSE;
	m_hwndShared = NULL;
	m_screen_area = FALSE;
	m_primary_display_only_shared = FALSE;
	m_disable_time = 3;
	SetSharedRect(GetScreenRect());
	SetPollingCycle(300);
	PollingCycleChanged(false);
	m_cursor_pos.x = 0;
	m_cursor_pos.y = 0;

	// initialize
	m_enable_file_transfers = FALSE;
	m_remove_wallpaper = FALSE;
	m_blank_screen = FALSE;

#ifdef HORIZONLIVE
	m_full_screen = FALSE;
	m_WindowShared= TRUE;
	m_local_input_priority = TRUE;
	m_remote_mouse = 1;
	m_remote_keyboard = 1;
#endif

	m_wallpaper_wait = FALSE;
}

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;
	}

	vnclog.Print(LL_STATE, VNCLOG("shutting down server object(4)\n"));
}

// Client handling functions
void
vncServer::DisableClients(BOOL state)
{
	m_clients_disabled = state;
}

BOOL
vncServer::ClientsDisabled()
{
	return m_clients_disabled;
}

vncClientId
vncServer::AddClient(VSocket *socket, BOOL reverse, BOOL shared)
{
	return AddClient(socket, reverse, shared, TRUE, TRUE);
}

vncClientId
vncServer::AddClient(VSocket *socket, BOOL reverse, BOOL shared,
					 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)
		{
			vnclog.Print(LL_CONNERR, VNCLOG("too many clients already connected\n"));
			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) {
		vnclog.Print(LL_CONNERR, VNCLOG("failed to allocate client object\n"));
		delete socket;
		return -1;
	}

	// Set the client's settings
	client->EnableKeyboard(keysenabled && m_enable_remote_inputs);
	client->EnablePointer(ptrenabled && m_enable_remote_inputs);

	// Start the client
	if (!client->Init(this, socket, reverse, shared, clientid))
	{
		// The client will delete the socket for us...
		vnclog.Print(LL_CONNERR, VNCLOG("failed to initialize 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;

	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)
			{
				if (RemoveWallpaperEnabled()) {
					m_wallpaper_wait = TRUE;
					DoNotify(WM_SRV_CLIENT_HIDEWALLPAPER, 0, 0);
				}
				m_desktop = new vncDesktop();
				if (m_desktop == NULL)
				{
					vnclog.Print(LL_CONNERR, VNCLOG("failed to allocate desktop object\n"));
					client->Kill();
					authok = FALSE;
					break;
				}
				if (!m_desktop->Init(this))
				{
					vnclog.Print(LL_CONNERR, VNCLOG("failed to initialize desktop object\n"));

					client->Kill();
					authok = FALSE;

					delete m_desktop;
					m_desktop = NULL;

					break;
				}
			}

			// Create a buffer object for this client
			vncBuffer *buffer = new vncBuffer(m_desktop);
			if (buffer == NULL)
			{
				vnclog.Print(LL_CONNERR, VNCLOG("failed to allocate buffer object\n"));
				client->Kill();
				authok = FALSE;
				break;
			}

			// Tell the client about this new buffer
			client->SetBuffer(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"));

	// If so configured, beep to indicate the new connection is
	// present.
	if (authok && GetBeepConnect())
	{
		MessageBeep(MB_OK);
	}

	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"));
}

void
vncServer::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"));
}

void
vncServer::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"));
}

UINT
vncServer::AuthClientCount()
{
	omni_mutex_lock l(m_clientsLock);

	return m_authClients.size();
}

UINT
vncServer::UnauthClientCount()
{
	omni_mutex_lock l(m_clientsLock);

	return m_unauthClients.size();
}

void
vncServer::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();
	}
}

void
vncServer::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();
	}
}

BOOL
vncServer::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;
}

// Client info retrieval/setup
vncClient*
vncServer::GetClient(vncClientId clientid)
{
	if ((clientid >= 0) && (clientid < MAX_CLIENTS))
		return m_clientmap[clientid];
	return NULL;
}

vncClientList
vncServer::ClientList()
{
	vncClientList clients;

	omni_mutex_lock l(m_clientsLock);

	clients = m_authClients;

	return clients;
}

void
vncServer::BlockRemoteInput(BOOL block)
{
	omni_mutex_lock l(m_clientsLock);

	vncClientList::iterator i;
	for (i = m_authClients.begin(); i != m_authClients.end(); i++)
		GetClient(*i)->BlockInput(block);
}

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.
void
vncServer::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"));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -