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

📄 clientconnection.cpp

📁 tightvnc源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//  Copyright (C) 2003-2006 Constantin Kaplinsky. All Rights Reserved.
//  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.


// Many thanks to Randy Brown <rgb@inven.com> for providing the 3-button
// emulation code.

// This is the main source for a ClientConnection object.
// It handles almost everything to do with a connection to a server.
// The decoding of specific rectangle encodings is done in separate files.

#include "stdhdrs.h"

#include "vncviewer.h"

#ifdef UNDER_CE
#include "omnithreadce.h"
#define SD_BOTH 0x02
#else
#include "omnithread.h"
#endif

#include "ClientConnection.h"
#include "SessionDialog.h"
#include "LoginAuthDialog.h"
#include "AboutBox.h"
#include "FileTransfer.h"
#include "commctrl.h"
#include "Exception.h"
extern "C" {
#include "vncauth.h"
#include "d3des.h"
}

#define INITIALNETBUFSIZE 4096
#define MAX_ENCODINGS 20
#define VWR_WND_CLASS_NAME _T("VNCviewer")

/*
 * Macro to compare pixel formats.
 */

#define PF_EQ(x,y)							\
	((x.bitsPerPixel == y.bitsPerPixel) &&				\
	 (x.depth == y.depth) &&					\
	 ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) &&	\
	 (x.trueColour == y.trueColour) &&				\
	 (!x.trueColour || ((x.redMax == y.redMax) &&			\
			    (x.greenMax == y.greenMax) &&		\
			    (x.blueMax == y.blueMax) &&			\
			    (x.redShift == y.redShift) &&		\
			    (x.greenShift == y.greenShift) &&		\
			    (x.blueShift == y.blueShift))))

const rfbPixelFormat vnc8bitFormat = {8, 8, 0, 1, 7,7,3, 0,3,6,0,0};
const rfbPixelFormat vnc16bitFormat = {16, 16, 0, 1, 63, 31, 31, 0,6,11,0,0};


// *************************************************************************
//  A Client connection involves two threads - the main one which sets up
//  connections and processes window messages and inputs, and a 
//  client-specific one which receives, decodes and draws output data 
//  from the remote server.
//  This first section contains bits which are generally called by the main
//  program thread.
// *************************************************************************

ClientConnection::ClientConnection(VNCviewerApp *pApp) 
{
	Init(pApp);
}

ClientConnection::ClientConnection(VNCviewerApp *pApp, SOCKET sock) 
{
	Init(pApp);
	m_sock = sock;
	m_serverInitiated = true;
	struct sockaddr_in svraddr;
	int sasize = sizeof(svraddr);
	if (getpeername(sock, (struct sockaddr *) &svraddr, 
		&sasize) != SOCKET_ERROR) {
		_stprintf(m_host, _T("%d.%d.%d.%d"), 
			svraddr.sin_addr.S_un.S_un_b.s_b1, 
			svraddr.sin_addr.S_un.S_un_b.s_b2, 
			svraddr.sin_addr.S_un.S_un_b.s_b3, 
			svraddr.sin_addr.S_un.S_un_b.s_b4);
		m_port = svraddr.sin_port;
	} else {
		_tcscpy(m_host,_T("(unknown)"));
		m_port = 0;
	};
}

ClientConnection::ClientConnection(VNCviewerApp *pApp, LPTSTR host, int port)
{
	Init(pApp);
	_tcsncpy(m_host, host, MAX_HOST_NAME_LEN);
	m_port = port;
}

void ClientConnection::Init(VNCviewerApp *pApp)
{
	m_hwnd = NULL;
	m_hwnd1 = NULL;
	m_hwndscroll = NULL;
	m_hToolbar = NULL;
	m_desktopName = NULL;
	m_port = -1;
	m_serverInitiated = false;
	m_netbuf = NULL;
	m_netbufsize = 0;
	m_zlibbuf = NULL;
	m_zlibbufsize = 0;
	m_hwndNextViewer = NULL;	
	m_pApp = pApp;
	m_dormant = false;
	m_hBitmapDC = NULL;
	m_hBitmap = NULL;
	m_hPalette = NULL;
	m_encPasswd[0] = '\0';

	m_connDlg = NULL;

	m_enableFileTransfers = false;
	m_fileTransferDialogShown = false;
	m_pFileTransfer = new FileTransfer(this, m_pApp);

	// We take the initial conn options from the application defaults
	m_opts = m_pApp->m_options;
	
	m_sock = INVALID_SOCKET;
	m_bKillThread = false;
	m_threadStarted = true;
	m_running = false;
	m_pendingFormatChange = false;

	m_hScrollPos = 0; m_vScrollPos = 0;

	m_waitingOnEmulateTimer = false;
	m_emulatingMiddleButton = false;

	m_decompStreamInited = false;

	m_decompStreamRaw.total_in = ZLIBHEX_DECOMP_UNINITED;
	m_decompStreamEncoded.total_in = ZLIBHEX_DECOMP_UNINITED;

	for (int i = 0; i < 4; i++)
		m_tightZlibStreamActive[i] = false;

	prevCursorSet = false;
	rcCursorX = 0;
	rcCursorY = 0;

	// Create a buffer for various network operations
	CheckBufferSize(INITIALNETBUFSIZE);

	m_pApp->RegisterConnection(this);
}

void ClientConnection::InitCapabilities()
{
	// Supported authentication methods
	m_authCaps.Add(rfbAuthNone, rfbStandardVendor, sig_rfbAuthNone,
				   "No authentication");
	m_authCaps.Add(rfbAuthVNC, rfbStandardVendor, sig_rfbAuthVNC,
				   "Standard VNC password authentication");

	// Known server->client message types
	m_serverMsgCaps.Add(rfbFileListData, rfbTightVncVendor,
						sig_rfbFileListData, "File list data");
	m_serverMsgCaps.Add(rfbFileDownloadData, rfbTightVncVendor,
						sig_rfbFileDownloadData, "File download data");
	m_serverMsgCaps.Add(rfbFileUploadCancel, rfbTightVncVendor,
						sig_rfbFileUploadCancel, "File upload cancel request");
	m_serverMsgCaps.Add(rfbFileDownloadFailed, rfbTightVncVendor,
						sig_rfbFileDownloadFailed, "File download failure notification");

	// Known client->server message types
	m_clientMsgCaps.Add(rfbFileListRequest, rfbTightVncVendor,
						sig_rfbFileListRequest, "File list request");
	m_clientMsgCaps.Add(rfbFileDownloadRequest, rfbTightVncVendor,
						sig_rfbFileDownloadRequest, "File download request");
	m_clientMsgCaps.Add(rfbFileUploadRequest, rfbTightVncVendor,
						sig_rfbFileUploadRequest, "File upload request");
	m_clientMsgCaps.Add(rfbFileUploadData, rfbTightVncVendor,
						sig_rfbFileUploadData, "File upload data");
	m_clientMsgCaps.Add(rfbFileDownloadCancel, rfbTightVncVendor,
						sig_rfbFileDownloadCancel, "File download cancel request");
	m_clientMsgCaps.Add(rfbFileUploadFailed, rfbTightVncVendor,
						sig_rfbFileUploadFailed, "File upload failure notification");

	// Supported encoding types
	m_encodingCaps.Add(rfbEncodingCopyRect, rfbStandardVendor,
					   sig_rfbEncodingCopyRect, "Standard CopyRect encoding");
	m_encodingCaps.Add(rfbEncodingRRE, rfbStandardVendor,
					   sig_rfbEncodingRRE, "Standard RRE encoding");
	m_encodingCaps.Add(rfbEncodingCoRRE, rfbStandardVendor,
					   sig_rfbEncodingCoRRE, "Standard CoRRE encoding");
	m_encodingCaps.Add(rfbEncodingHextile, rfbStandardVendor,
					   sig_rfbEncodingHextile, "Standard Hextile encoding");
	m_encodingCaps.Add(rfbEncodingZlib, rfbTridiaVncVendor,
					   sig_rfbEncodingZlib, "Zlib encoding from TridiaVNC");
	m_encodingCaps.Add(rfbEncodingZlibHex, rfbTridiaVncVendor,
					   sig_rfbEncodingZlibHex, "ZlibHex encoding from TridiaVNC");
	m_encodingCaps.Add(rfbEncodingTight, rfbTightVncVendor,
					   sig_rfbEncodingTight, "Tight encoding by Constantin Kaplinsky");

	// Supported "fake" encoding types
	m_encodingCaps.Add(rfbEncodingCompressLevel0, rfbTightVncVendor,
					   sig_rfbEncodingCompressLevel0, "Compression level");
	m_encodingCaps.Add(rfbEncodingQualityLevel0, rfbTightVncVendor,
					   sig_rfbEncodingQualityLevel0, "JPEG quality level");
	m_encodingCaps.Add(rfbEncodingXCursor, rfbTightVncVendor,
					   sig_rfbEncodingXCursor, "X-style cursor shape update");
	m_encodingCaps.Add(rfbEncodingRichCursor, rfbTightVncVendor,
					   sig_rfbEncodingRichCursor, "Rich-color cursor shape update");
	m_encodingCaps.Add(rfbEncodingPointerPos, rfbTightVncVendor,
					   sig_rfbEncodingPointerPos, "Pointer position update");
	m_encodingCaps.Add(rfbEncodingLastRect, rfbTightVncVendor,
					   sig_rfbEncodingLastRect, "LastRect protocol extension");
	m_encodingCaps.Add(rfbEncodingNewFBSize, rfbTightVncVendor,
					   sig_rfbEncodingNewFBSize, "Framebuffer size change");
}

// 
// Run() creates the connection if necessary, does the initial negotiations
// and then starts the thread running which does the output (update) processing.
// If Run throws an Exception, the caller must delete the ClientConnection object.
//

void ClientConnection::Run()
{
	// Get the host name and port if we haven't got it

	if (m_port == -1) {
		GetConnectDetails();
	} else {
		if (m_pApp->m_options.m_listening) {
			m_opts.LoadOpt(m_opts.m_display, 
							KEY_VNCVIEWER_HISTORI);
		}
	}

	// Show the "Connecting..." dialog box
	m_connDlg = new ConnectingDialog(m_pApp->m_instance, m_opts.m_display);

	// Connect if we're not already connected
	if (m_sock == INVALID_SOCKET)
		Connect();

	SetSocketOptions();

	NegotiateProtocolVersion();

	PerformAuthentication();

	// Set up windows etc 
	CreateDisplay();

	SendClientInit();
	ReadServerInit();

	// Only for protocol version 3.7t
	if (m_tightVncProtocol) {
		// Determine which protocol messages and encodings are supported.
		ReadInteractionCaps();
		// Enable file transfers only if the server supports that.
		m_enableFileTransfers = false;
		if ( m_clientMsgCaps.IsEnabled(rfbFileListRequest) &&
			 m_serverMsgCaps.IsEnabled(rfbFileListData) ) {
			m_enableFileTransfers = true;
		}
	}

	// Close the "Connecting..." dialog box if not closed yet.
	if (m_connDlg != NULL) {
		delete m_connDlg;
		m_connDlg = NULL;
	}

	EnableFullControlOptions();

	CreateLocalFramebuffer();
	
	SetupPixelFormat();
	
	SetFormatAndEncodings();

	// This starts the worker thread.
	// The rest of the processing continues in run_undetached.
	start_undetached();
}

static WNDCLASS wndclass;	// FIXME!

void ClientConnection::CreateDisplay() 
{
	// Create the window
	
	WNDCLASS wndclass;
	
	wndclass.style			= 0;
	wndclass.lpfnWndProc	= ClientConnection::Proc;
	wndclass.cbClsExtra		= 0;
	wndclass.cbWndExtra		= 0;
	wndclass.hInstance		= m_pApp->m_instance;
	wndclass.hIcon			= (HICON)LoadIcon(m_pApp->m_instance,
												MAKEINTRESOURCE(IDI_MAINICON));
	wndclass.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground	= (HBRUSH) GetSysColorBrush(COLOR_BTNFACE);
    wndclass.lpszMenuName	= (LPCTSTR)NULL;
	wndclass.lpszClassName	= VWR_WND_CLASS_NAME;

	RegisterClass(&wndclass);

	wndclass.style			= 0;
	wndclass.lpfnWndProc	= ClientConnection::ScrollProc;
	wndclass.cbClsExtra		= 0;
	wndclass.cbWndExtra		= 0;
	wndclass.hInstance		= m_pApp->m_instance;
	wndclass.hIcon			= NULL;
	wndclass.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground	= (HBRUSH) GetStockObject(BLACK_BRUSH);
    wndclass.lpszMenuName	= (LPCTSTR)NULL;
	wndclass.lpszClassName	= "ScrollClass";

	RegisterClass(&wndclass);
	 
	wndclass.style			= 0;
	wndclass.lpfnWndProc	= ClientConnection::Proc;
	wndclass.cbClsExtra		= 0;
	wndclass.cbWndExtra		= 0;
	wndclass.hInstance		= m_pApp->m_instance;
	wndclass.hIcon			= NULL;
	switch (m_pApp->m_options.m_localCursor) {
	case NOCURSOR:
		wndclass.hCursor	= LoadCursor(m_pApp->m_instance, 
										MAKEINTRESOURCE(IDC_NOCURSOR));
		break;
	case SMALLCURSOR:
		wndclass.hCursor	= LoadCursor(m_pApp->m_instance, 
										MAKEINTRESOURCE(IDC_SMALLDOT));
		break;
	case NORMALCURSOR:
		wndclass.hCursor	=LoadCursor(NULL,IDC_ARROW);
		break;
	case DOTCURSOR:
	default:
		wndclass.hCursor	= LoadCursor(m_pApp->m_instance, 
										MAKEINTRESOURCE(IDC_DOTCURSOR));
	}
	wndclass.hbrBackground	= (HBRUSH) GetStockObject(BLACK_BRUSH);
    wndclass.lpszMenuName	= (LPCTSTR)NULL;
	wndclass.lpszClassName	= "ChildClass";

	RegisterClass(&wndclass);
	
	m_hwnd1 = CreateWindow(VWR_WND_CLASS_NAME,
			      _T("VNCviewer"),
			      WS_BORDER|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|
				  WS_MINIMIZEBOX|WS_MAXIMIZEBOX|
				  WS_CLIPCHILDREN,
			      CW_USEDEFAULT,
			      CW_USEDEFAULT,
			      CW_USEDEFAULT,       // x-size
			      CW_USEDEFAULT,       // y-size
			      NULL,                // Parent handle
			      NULL,                // Menu handle
			      m_pApp->m_instance,
			      NULL);
	SetWindowLong(m_hwnd1, GWL_USERDATA, (LONG) this);
	SetWindowLong(m_hwnd1, GWL_WNDPROC, (LONG)ClientConnection::WndProc1);
	ShowWindow(m_hwnd1, SW_HIDE);

	m_hwndscroll = CreateWindow("ScrollClass",
			      NULL,
			      WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER,
			      CW_USEDEFAULT,
			      CW_USEDEFAULT,
			      CW_USEDEFAULT,       // x-size
			      CW_USEDEFAULT,       // y-size
			      m_hwnd1,                // Parent handle
			      NULL,                // Menu handle
			      m_pApp->m_instance,
			      NULL);
	SetWindowLong(m_hwndscroll, GWL_USERDATA, (LONG) this);
	ShowWindow(m_hwndscroll, SW_HIDE);
	
	// Create a memory DC which we'll use for drawing to
	// the local framebuffer
	m_hBitmapDC = CreateCompatibleDC(NULL);

	// Set a suitable palette up
	if (GetDeviceCaps(m_hBitmapDC, RASTERCAPS) & RC_PALETTE) {

⌨️ 快捷键说明

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