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

📄 vncclient.cpp

📁 realvnc是一个非常流行的远程控制程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//  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.// vncClient.cpp// The per-client object.  This object takes care of all per-client stuff,// such as socket input and buffering of updates.// vncClient class handles the following functions:// - Recieves requests from the connected client and//   handles them// - Handles incoming updates properly, using a vncBuffer//   object to keep track of screen changes// It uses a vncBuffer and is passed the vncDesktop and// vncServer to communicate with.// Includes#include "stdhdrs.h"#include <omnithread.h>#include "resource.h"// Custom#include "vncServer.h"#include "vncClient.h"#include "VSocket.h"#include "vncDesktop.h"#include "rfbRegion.h"#include "vncBuffer.h"#include "vncService.h"#include "vncPasswd.h"#include "vncAcceptDialog.h"#include "vncKeymap.h"// #include "rfb.h"// vncClient update thread classclass vncClientUpdateThread : public omni_thread{public:	// Init	BOOL Init(vncClient *client);	// Kick the thread to send an update	void Trigger();	// Kill the thread	void Kill();	// Disable/enable updates	void EnableUpdates(BOOL enable);	// The main thread function  virtual void *run_undetached(void *arg);protected:	virtual ~vncClientUpdateThread();	// Fieldsprotected:	vncClient *m_client;	omni_condition *m_signal;	omni_condition *m_sync_sig;	BOOL m_active;	BOOL m_enable;};BOOLvncClientUpdateThread::Init(vncClient *client){	vnclog.Print(LL_INTINFO, VNCLOG("init update thread\n"));	m_client = client;	omni_mutex_lock l(m_client->GetUpdateLock());	m_signal = new omni_condition(&m_client->GetUpdateLock());	m_sync_sig = new omni_condition(&m_client->GetUpdateLock());	m_active = TRUE;	m_enable = m_client->m_disable_protocol == 0;	if (m_signal && m_sync_sig) {		start_undetached();		return TRUE;	}	return FALSE;}vncClientUpdateThread::~vncClientUpdateThread(){	if (m_signal) delete m_signal;	if (m_sync_sig) delete m_sync_sig;	vnclog.Print(LL_INTINFO, VNCLOG("update thread gone\n"));}voidvncClientUpdateThread::Trigger(){	// ALWAYS lock client UpdateLock before calling this!	// Only trigger an update if protocol is enabled	if (m_client->m_disable_protocol == 0) {		m_signal->signal();	}}voidvncClientUpdateThread::Kill(){	vnclog.Print(LL_INTINFO, VNCLOG("kill update thread\n"));	omni_mutex_lock l(m_client->GetUpdateLock());	m_active=FALSE;	m_signal->signal();}voidvncClientUpdateThread::EnableUpdates(BOOL enable){	// ALWAYS call this with the UpdateLock held!	if (enable) {		vnclog.Print(LL_INTINFO, VNCLOG("enable update thread\n"));	} else {		vnclog.Print(LL_INTINFO, VNCLOG("disable update thread\n"));	}	m_enable = enable;	m_signal->signal();	m_sync_sig->wait();	vnclog.Print(LL_INTINFO, VNCLOG("enable/disable synced\n"));}void*vncClientUpdateThread::run_undetached(void *arg){	rfb::SimpleUpdateTracker update;	rfb::Region2D clipregion;	char *clipboard_text = 0;	update.enable_copyrect(true);	BOOL send_palette = FALSE;	unsigned long updates_sent=0;	vnclog.Print(LL_INTINFO, VNCLOG("starting update thread\n"));	// Set client update threads to high priority	// *** set_priority(omni_thread::PRIORITY_HIGH);	while (1)	{		// Block waiting for an update to send		{			omni_mutex_lock l(m_client->GetUpdateLock());			m_client->m_incr_rgn = m_client->m_incr_rgn.union_(clipregion);			// We block as long as updates are disabled, or the client			// isn't interested in them, unless this thread is killed.			while (m_active && (						!m_enable || (							m_client->m_update_tracker.get_changed_region().intersect(m_client->m_incr_rgn).is_empty() &&							m_client->m_update_tracker.get_copied_region().intersect(m_client->m_incr_rgn).is_empty() &&							!m_client->m_clipboard_text							)						)					) {				// Issue the synchronisation signal, to tell other threads				// where we have got to				m_sync_sig->broadcast();				// Wait to be kicked into action				m_signal->wait();			}			// If the thread is being killed then quit			if (!m_active) break;			// SEND AN UPDATE!			// The thread is active, updates are enabled, and the			// client is expecting an update - let's see if there			// is anything to send.			// Has the palette changed?			send_palette = m_client->m_palettechanged;			m_client->m_palettechanged = FALSE;			// Fetch the incremental region			clipregion = m_client->m_incr_rgn;			m_client->m_incr_rgn.clear();			// Get the clipboard data, if any			if (m_client->m_clipboard_text) {				clipboard_text = m_client->m_clipboard_text;				m_client->m_clipboard_text = 0;			}			// Get the update details from the update tracker			m_client->m_update_tracker.flush_update(update, clipregion);			// Render the mouse if required			if (m_client->m_mousemoved)			{				// Re-render its old location				m_client->m_oldmousepos =					m_client->m_oldmousepos.intersect(m_client->m_fullscreen);				if (!m_client->m_oldmousepos.is_empty())					update.add_changed(m_client->m_oldmousepos);				// And render its new one				m_client->m_encodemgr.m_buffer->GetMousePos(m_client->m_oldmousepos);				m_client->m_oldmousepos =					m_client->m_oldmousepos.intersect(m_client->m_fullscreen);				if (!m_client->m_oldmousepos.is_empty())					update.add_changed(m_client->m_oldmousepos);				m_client->m_mousemoved = FALSE;			}			// Get the encode manager to update the client back buffer			m_client->m_encodemgr.GrabRegion(update.get_changed_region());		}		// SEND THE CLIPBOARD		// If there is clipboard text to be sent then send it		if (clipboard_text) {			rfbServerCutTextMsg message;			message.length = Swap32IfLE(strlen(clipboard_text));			if (!m_client->SendRFBMsg(rfbServerCutText,				(BYTE *) &message, sizeof(message))) {				m_client->m_socket->Close();			}			if (!m_client->m_socket->SendExact(clipboard_text, strlen(clipboard_text)))			{				m_client->m_socket->Close();			}			free(clipboard_text);			clipboard_text = 0;		}		// SEND AN UPDATE		// We do this without holding locks, to avoid network problems		// stalling the server.		// Update the client palette if necessary		if (send_palette) {			m_client->SendPalette();		}		// Send updates to the client - this implicitly clears		// the supplied update tracker		if (m_client->SendUpdate(update)) {			updates_sent++;			clipregion.clear();		}	}	vnclog.Print(LL_INTINFO, VNCLOG("stopping update thread\n"));		vnclog.Print(LL_INTERR, "client sent %lu updates\n", updates_sent);	return 0;}// vncClient thread classclass vncClientThread : public omni_thread{public:	// Init	virtual BOOL Init(vncClient *client,		vncServer *server,		VSocket *socket,		BOOL auth,		BOOL shared);	// Sub-Init routines	virtual BOOL InitVersion();	virtual BOOL InitAuthenticate();	// The main thread function	virtual void run(void *arg);protected:	virtual ~vncClientThread();	// Fieldsprotected:	VSocket *m_socket;	vncServer *m_server;	vncClient *m_client;	BOOL m_auth;	BOOL m_shared;};vncClientThread::~vncClientThread(){	// If we have a client object then delete it	if (m_client != NULL)		delete m_client;}BOOLvncClientThread::Init(vncClient *client, vncServer *server, VSocket *socket, BOOL auth, BOOL shared){	// Save the server pointer and window handle	m_server = server;	m_socket = socket;	m_client = client;	m_auth = auth;	m_shared = shared;	// Start the thread	start();	return TRUE;}BOOLvncClientThread::InitVersion(){	// Generate the server's protocol version	rfbProtocolVersionMsg protocolMsg;	sprintf((char *)protocolMsg,		rfbProtocolVersionFormat,		rfbProtocolMajorVersion,		rfbProtocolMinorVersion);	// Send the protocol message	if (!m_socket->SendExact((char *)&protocolMsg, sz_rfbProtocolVersionMsg))		return FALSE;	// Now, get the client's protocol version	rfbProtocolVersionMsg protocol_ver;	protocol_ver[12] = 0;	if (!m_socket->ReadExact((char *)&protocol_ver, sz_rfbProtocolVersionMsg))		return FALSE;	// Check the protocol version	int major, minor;	sscanf((char *)&protocol_ver, rfbProtocolVersionFormat, &major, &minor);	if (major != rfbProtocolMajorVersion)		return FALSE;	return TRUE;}BOOLvncClientThread::InitAuthenticate(){	// Retrieve the local password	char password[MAXPWLEN];	m_server->GetPassword(password);	vncPasswd::ToText plain(password);	// Verify the peer host name against the AuthHosts string	vncServer::AcceptQueryReject verified;	if (m_auth) {		verified = vncServer::aqrAccept;	} else {		verified = m_server->VerifyHost(m_socket->GetPeerName());	}		// If necessary, query the connection with a timed dialog	if (verified == vncServer::aqrQuery) {		vncAcceptDialog *acceptDlg = new vncAcceptDialog(m_server->QueryTimeout(), m_socket->GetPeerName());		if ((acceptDlg == 0) || (!(acceptDlg->DoDialog())))			verified = vncServer::aqrReject;	}	if (verified == vncServer::aqrReject) {		CARD32 auth_val = Swap32IfLE(rfbConnFailed);		char *errmsg = "Your connection has been rejected.";		CARD32 errlen = Swap32IfLE(strlen(errmsg));		if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))			return FALSE;		if (!m_socket->SendExact((char *)&errlen, sizeof(errlen)))			return FALSE;		m_socket->SendExact(errmsg, strlen(errmsg));		return FALSE;	}	// By default we disallow passwordless workstations!	if ((strlen(plain) == 0) && m_server->AuthRequired())	{		vnclog.Print(LL_CONNERR, VNCLOG("no password specified for server - client rejected\n"));		// Send an error message to the client		CARD32 auth_val = Swap32IfLE(rfbConnFailed);		char *errmsg =			"This server does not have a valid password enabled.  "			"Until a password is set, incoming connections cannot be accepted.";		CARD32 errlen = Swap32IfLE(strlen(errmsg));		if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))			return FALSE;		if (!m_socket->SendExact((char *)&errlen, sizeof(errlen)))			return FALSE;		m_socket->SendExact(errmsg, strlen(errmsg));		return FALSE;	}	// By default we filter out local loop connections, because they're pointless	if (!m_server->LoopbackOk())	{		char *localname = strdup(m_socket->GetSockName());		char *remotename = strdup(m_socket->GetPeerName());		// Check that the local & remote names are different!		if ((localname != NULL) && (remotename != NULL))		{			BOOL ok = strcmp(localname, remotename) != 0;			if (localname != NULL)				free(localname);			if (remotename != NULL)				free(remotename);			if (!ok)			{				vnclog.Print(LL_CONNERR, VNCLOG("loopback connection attempted - client rejected\n"));								// Send an error message to the client				CARD32 auth_val = Swap32IfLE(rfbConnFailed);				char *errmsg = "Local loop-back connections are disabled.";				CARD32 errlen = Swap32IfLE(strlen(errmsg));				if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))					return FALSE;				if (!m_socket->SendExact((char *)&errlen, sizeof(errlen)))					return FALSE;				m_socket->SendExact(errmsg, strlen(errmsg));				return FALSE;			}		}	}	// Authenticate the connection, if required	if (m_auth || (strlen(plain) == 0))

⌨️ 快捷键说明

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