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

📄 clientconnection.cpp

📁 realvnc是一个非常流行的远程控制程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//// 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.// 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.#define _WIN32_WINDOWS 0x0410#define WINVER 0x0400#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 "AuthDialog.h"#include "AboutBox.h"#include "Exception.h"extern "C" {	#include "vncauth.h"}#include <rdr/FdInStream.h>#include <rdr/ZlibInStream.h>#include <rdr/Exception.h>#define INITIALNETBUFSIZE 4096#define MAX_ENCODINGS (LASTENCODING+1)#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};static LRESULT CALLBACK ClientConnection::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);// *************************************************************************//  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)   : fis(0), zis(0){	Init(pApp);}ClientConnection::ClientConnection(VNCviewerApp *pApp, SOCKET sock)   : fis(0), zis(0){	Init(pApp);        if (m_opts.autoDetect)          m_opts.m_Use8Bit = true;	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)  : fis(0), zis(0){	Init(pApp);        if (m_opts.autoDetect)          m_opts.m_Use8Bit = true;	_tcsncpy(m_host, host, MAX_HOST_NAME_LEN);	m_port = port;}void ClientConnection::Init(VNCviewerApp *pApp){	m_hwnd = 0;	m_desktopName = NULL;	m_port = -1;	m_serverInitiated = false;	m_netbuf = NULL;	m_netbufsize = 0;	m_hwndNextViewer = NULL;		m_pApp = pApp;	m_dormant = false;	m_hBitmapDC = NULL;	m_hBitmap = NULL;	m_hPalette = NULL;	m_encPasswd[0] = '\0';	// 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;	// Initialise a few fields that will be properly set when the	// connection has been negotiated	m_fullwinwidth = m_fullwinheight = 0;	m_si.framebufferWidth = m_si.framebufferHeight = 0;	m_hScrollPos = 0; m_vScrollPos = 0;	m_waitingOnEmulateTimer = false;	m_emulatingMiddleButton = false;        oldPointerX = oldPointerY = oldButtonMask = 0;	// Create a buffer for various network operations	CheckBufferSize(INITIALNETBUFSIZE);	m_pApp->RegisterConnection(this);        kbitsPerSecond = 0;        zis = new rdr::ZlibInStream;
}// // 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();	// Connect if we're not already connected	if (m_sock == INVALID_SOCKET) 		Connect();	SetSocketOptions();	NegotiateProtocolVersion();		Authenticate();	// Set up windows etc 	CreateDisplay();	SendClientInit();		ReadServerInit();		CreateLocalFramebuffer();	SetupPixelFormat();        SetFormatAndEncodings();        	// This starts the worker thread.	// The rest of the processing continues in run_undetached.	start_undetached();}void ClientConnection::CreateDisplay() {	// Create the window	WNDCLASS wndclass;	wndclass.style			= 0;	wndclass.lpfnWndProc	= ClientConnection::WndProc;	wndclass.cbClsExtra		= 0;	wndclass.cbWndExtra		= 0;	wndclass.hInstance		= m_pApp->m_instance;	wndclass.hIcon			= LoadIcon(m_pApp->m_instance, MAKEINTRESOURCE(IDI_MAINICON));	switch (m_opts.m_localCursor) {	case NOCURSOR:		wndclass.hCursor		= LoadCursor(m_pApp->m_instance, MAKEINTRESOURCE(IDC_NOCURSOR));		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	= (const TCHAR *) NULL;	wndclass.lpszClassName	= VWR_WND_CLASS_NAME;	RegisterClass(&wndclass);#ifdef _WIN32_WCE	const DWORD winstyle = WS_VSCROLL | WS_HSCROLL | WS_CAPTION | WS_SYSMENU;#else
	const DWORD winstyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | //Modified by: Lars Werner (http://lars.werner.no)	  WS_MINIMIZEBOX | WS_THICKFRAME | WS_VSCROLL | WS_HSCROLL;#endif	m_hwnd = CreateWindow(VWR_WND_CLASS_NAME,			      _T("VNCviewer"),			      winstyle,			      CW_USEDEFAULT,			      CW_USEDEFAULT,			      CW_USEDEFAULT,       // x-size			      CW_USEDEFAULT,       // y-size			      NULL,                // Parent handle			      NULL,                // Menu handle			      m_pApp->m_instance,			      NULL);	ShowWindow(m_hwnd, SW_HIDE);
	// record which client created this window	SetWindowLong(m_hwnd, GWL_USERDATA, (LONG) this);	// 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) {		log.Print(3, _T("Palette-based display - %d entries, %d reserved\n"), 			GetDeviceCaps(m_hBitmapDC, SIZEPALETTE), GetDeviceCaps(m_hBitmapDC, NUMRESERVED));		BYTE buf[sizeof(LOGPALETTE)+216*sizeof(PALETTEENTRY)];		LOGPALETTE *plp = (LOGPALETTE *) buf;		int pepos = 0;		for (int r = 5; r >= 0; r--) {			for (int g = 5; g >= 0; g--) {				for (int b = 5; b >= 0; b--) {					plp->palPalEntry[pepos].peRed   = r * 255 / 5; 						plp->palPalEntry[pepos].peGreen = g * 255 / 5;					plp->palPalEntry[pepos].peBlue  = b * 255 / 5;					plp->palPalEntry[pepos].peFlags  = NULL;					pepos++;				}			}		}		plp->palVersion = 0x300;		plp->palNumEntries = 216;		m_hPalette = CreatePalette(plp);	}	// Add stuff to System menu	HMENU hsysmenu = GetSystemMenu(m_hwnd, FALSE);	if (!m_opts.m_restricted) {		AppendMenu(hsysmenu, MF_STRING, IDC_OPTIONBUTTON,	_T("Connection &options..."));		AppendMenu(hsysmenu, MF_STRING, ID_CONN_ABOUT,		_T("Connection &info"));		AppendMenu(hsysmenu, MF_STRING, ID_REQUEST_REFRESH,	_T("Request screen &refresh"));		AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);		AppendMenu(hsysmenu, MF_STRING, ID_FULLSCREEN,		_T("&Full screen"));		AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL); 		AppendMenu(hsysmenu, MF_STRING, ID_CONN_CTLALTDEL,	_T("Send Ctl-Alt-Del"));		AppendMenu(hsysmenu, MF_STRING, ID_CONN_CTLDOWN,	_T("Ctrl Down"));		AppendMenu(hsysmenu, MF_STRING, ID_CONN_CTLUP,		_T("Ctrl Up"));		AppendMenu(hsysmenu, MF_STRING, ID_CONN_ALTDOWN,	_T("Alt Down"));		AppendMenu(hsysmenu, MF_STRING, ID_CONN_ALTUP,		_T("Alt Up"));		AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);		AppendMenu(hsysmenu, MF_STRING, ID_NEWCONN,			_T("Ne&w connection..."));		AppendMenu(hsysmenu, MF_STRING | (m_serverInitiated ? MF_GRAYED : 0), 			ID_CONN_SAVE_AS,	_T("Save connection info &as..."));	}    AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);	AppendMenu(hsysmenu, MF_STRING, IDD_APP_ABOUT,		_T("&About VNCviewer..."));	if (m_opts.m_listening) {		AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);		AppendMenu(hsysmenu, MF_STRING, ID_CLOSEDAEMON, _T("Close listening &daemon"));	}	DrawMenuBar(m_hwnd);	// Set up clipboard watching#ifndef _WIN32_WCE	// We want to know when the clipboard changes, so	// insert ourselves in the viewer chain. But doing	// this will cause us to be notified immediately of	// the current state.	// We don't want to send that.	m_initialClipboardSeen = false;	m_hwndNextViewer = SetClipboardViewer(m_hwnd); 	#endif

	//Added by: Lars Werner (http://lars.werner.no)
	if(TitleBar.GetSafeHwnd()==NULL) 
			TitleBar.Create(m_pApp->m_instance, m_hwnd);
}void ClientConnection::GetConnectDetails(){	if (m_opts.m_configSpecified) {		LoadConnection(m_opts.m_configFilename);	} else {		SessionDialog sessdlg(&m_opts);		if (!sessdlg.DoDialog()) {			throw QuietException("User Cancelled");		}		_tcsncpy(m_host, sessdlg.m_host, MAX_HOST_NAME_LEN);		m_port = sessdlg.m_port;                if (m_opts.autoDetect)                  m_opts.m_Use8Bit = true;	}	// This is a bit of a hack: 	// The config file may set various things in the app-level defaults which 	// we don't want to be used except for the first connection. So we clear them	// in the app defaults here.	m_pApp->m_options.m_host[0] = '\0';	m_pApp->m_options.m_port = -1;	m_pApp->m_options.m_connectionSpecified = false;	m_pApp->m_options.m_configSpecified = false;}void ClientConnection::Connect(){	struct sockaddr_in thataddr;	int res;		m_sock = socket(PF_INET, SOCK_STREAM, 0);	if (m_sock == INVALID_SOCKET) throw WarningException(_T("Error creating socket"));	int one = 1;		// The host may be specified as a dotted address "a.b.c.d"	// Try that first	thataddr.sin_addr.s_addr = inet_addr(m_host);		// If it wasn't one of those, do gethostbyname	if (thataddr.sin_addr.s_addr == INADDR_NONE) {		LPHOSTENT lphost;		lphost = gethostbyname(m_host);				if (lphost == NULL) { 			throw WarningException("Failed to get server address.\n\r"				"Did you type the host name correctly?"); 		};		thataddr.sin_addr.s_addr = ((LPIN_ADDR) lphost->h_addr)->s_addr;	};		thataddr.sin_family = AF_INET;	thataddr.sin_port = htons(m_port);	res = connect(m_sock, (LPSOCKADDR) &thataddr, sizeof(thataddr));	if (res == SOCKET_ERROR) throw WarningException("Failed to connect to server");	log.Print(0, _T("Connected to %s port %d\n"), m_host, m_port);}void ClientConnection::SetSocketOptions() {	// Disable Nagle's algorithm	BOOL nodelayval = TRUE;	if (setsockopt(m_sock, IPPROTO_TCP, TCP_NODELAY, (const char *) &nodelayval, sizeof(BOOL)))		throw WarningException("Error disabling Nagle's algorithm");        fis = new rdr::FdInStream(m_sock);}void ClientConnection::NegotiateProtocolVersion(){	rfbProtocolVersionMsg pv;   /* if the connection is immediately closed, don't report anything, so       that pmw's monitor can make test connections */    try {		ReadExact(pv, sz_rfbProtocolVersionMsg);	} catch (Exception &c) {		log.Print(0, _T("Error reading protocol version: %s\n"),                          c.m_info);		throw QuietException(c.m_info);	}    pv[sz_rfbProtocolVersionMsg] = 0;	// XXX This is a hack.  Under CE we just return to the server the	// version number it gives us without parsing it.  	// Too much hassle replacing sscanf for now. Fix this!#ifdef UNDER_CE	m_majorVersion = rfbProtocolMajorVersion;

⌨️ 快捷键说明

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