浅析winvnc网络单元启动流程和一个client消息被接收流程
WinMain // VC6.0程序入口函数
==>WinVNCAppMain
==>vncMenu *menu = new vncMenu(&server); // 建立vncMenu对象
==>vncMenu::vncMenu(vncServer *server) // 在构造方法中调用m_properties.Init
class vncMenu
{
......
protected:
// Check that the password has been set
void CheckPassword();
// The server that this tray icon handles
vncServer *m_server;
// Properties object for this server
vncProperties m_properties;
......
};
// vncMenu::WndProc消息处理函数,
// 处理WM_TIMER,WM_SRV_CLIENT_DISCONNECT,WM_COMMAND,
// WM_TRAYNOTIFY,WM_USERCHANGED等系统消息[luther.gliethttp]
==>m_properties.Init(m_server) // 就是调用vncProperties::Init
==>vncProperties::Init 或者 vncProperties::Show
==>vncProperties::Load(BOOL usersettings) // 加载注册表中的设置
==>vncProperties::ApplyUserPrefs 或者 vncServer::SetPort // 加载注册表数值之后,生效所有设置[luther.gliethttp]
==>vncServer::SockConnect(TRUE); // 将执行下面的new vncSockConnect对象创建操作
==>m_socketConn = new vncSockConnect();
==>m_socketConn->Init(this, m_port); // 就是调用vncSockConnect::Init
==>vncSockConnect::Init(vncServer *server, UINT port)
==>m_thread = new vncSockConnectThread;
class vncSockConnectThread : public omni_thread
{
public:
// Init routine
virtual BOOL Init(VSocket *socket, vncServer *server);
// Code to be executed by the thread
virtual void *run_undetached(void * arg); // 覆盖父类omni_thread的run_undetached方法
......
}
==>((vncSockConnectThread *)m_thread)->Init(&m_socket, server);
// Method implementations
BOOL vncSockConnectThread::Init(VSocket *socket, vncServer *server)
{
// Save the server pointer
m_server = server;
// Save the socket pointer
m_socket = socket;
// Start the thread
m_shutdown = FALSE;
start_undetached(); // 执行父类omni_thread的start_undetached方法
return TRUE;
}
void
omni_thread::start_undetached(void)
{
if ((fn_void != NULL) || (fn_ret != NULL))
throw omni_thread_invalid();
detached = 0; // 这样omni_thread::detached = 0;
start();
}
==>omni_thread_wrapper // 该函数的分析见下面[luther.gliethttp]
==>vncSockConnectThread::run_undetached
// Code to be executed by the thread
void *vncSockConnectThread::run_undetached(void * arg)
{
log.Print(LL_STATE, VNCLOG("started socket connection thread\n"));
// Go into a loop, listening for connections on the given socket
while (!m_shutdown)
{
// Accept an incoming connection
VSocket *new_socket = m_socket->Accept();
if (new_socket == NULL)
break;
log.Print(LL_CLIENTS, VNCLOG("accepted connection from %s\n"), new_socket->GetPeerName());
// Successful accept - start the client unauthenticated
m_server->AddClient(new_socket, FALSE, FALSE);
}
log.Print(LL_STATE, VNCLOG("quitting socket connection thread\n"));
return NULL;
}
==>m_server->AddClient(new_socket, FALSE, FALSE); // 就是调用vncServer::AddClient
==>vncServer::AddClient(VSocket *socket, BOOL auth, BOOL shared)
==>client = new vncClient();
==>client->Init(this, socket, auth, shared, clientid); // 就是调用vncClient::Init
==>vncClient::Init(vncServer *server, VSocket *socket, BOOL auth, BOOL shared, vncClientId newid);
==>m_thread = new vncClientThread; // 父类omni_thread将执行下面的构造函数
omni_thread::omni_thread(void* arg, priority_t pri)
{
common_constructor(arg, pri, 1); // 这样omni_thread::detached = 1;
fn_void = NULL;
fn_ret = NULL;
}
==>((vncClientThread *)m_thread)->Init(this, m_server, m_socket, auth, shared);
BOOL
vncClientThread::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(); // 执行父类omni_thread的start()方法,启动线程
return TRUE;
}
omni_thread::start(void)
{
handle = (HANDLE)_beginthreadex(
NULL,
0,
omni_thread_wrapper, // 创建线程
(LPVOID)this,
CREATE_SUSPENDED,
&t);
SetThreadPriority(handle, _priority);
ResumeThread(handle); // 启动线程函数omni_thread_wrapper执行
}
extern "C"
#ifndef __BCPLUSPLUS__
unsigned __stdcall
#else
void _USERENTRY
#endif
omni_thread_wrapper(void* ptr)
{
omni_thread* me = (omni_thread*)ptr;
DB(cerr << "omni_thread_wrapper: thread " << me->id()
<< " started\n");
if (!TlsSetValue(self_tls_index, (LPVOID)me))
throw omni_thread_fatal(GetLastError());
//
// Now invoke the thread function with the given argument.
//
if (me->fn_void != NULL) {
(*me->fn_void)(me->thread_arg);
omni_thread::exit();
}
if (me->fn_ret != NULL) {
void* return_value = (*me->fn_ret)(me->thread_arg);
omni_thread::exit(return_value);
}
if (me->detached) {
me->run(me->thread_arg);
// 执行该方法子类重新实现函数vncClientThread::run();
// 执行该句,对me->detached的赋值见上面::omni_thread构造函数
omni_thread::exit();
} else {
void* return_value = me->run_undetached(me->thread_arg);
// 执行该方法子类重新实现函数vncSockConnectThread::run_undetachedme->thread_arg();
// vncSockConnectThread执行到这里,
// 因为omni_thread::start_undetached()方法设置omni_thread::detached = 0;
// 对该赋值操作分析见上面[luther.gliethttp]
omni_thread::exit(return_value);
}
// should never get here.
#ifndef __BCPLUSPLUS__
return 0;
#endif
}
class vncClientThread : public omni_thread // 继承父类omni_thread
class _OMNITHREAD_NTDLL_ omni_thread {
public:
......
omni_thread(void (*fn)(void*), void* arg = NULL,
priority_t pri = PRIORITY_NORMAL);
omni_thread(void* (*fn)(void*), void* arg = NULL,
priority_t pri = PRIORITY_NORMAL);
// these constructors create a thread which will run the given function
// when start() is called. The thread will be detached if given a
// function with void return type, undetached if given a function
// returning void*. If a thread is detached, storage for the thread is
// reclaimed automatically on termination. Only an undetached thread
// can be joined.
void start(void);
// start() causes a thread created with one of the constructors to
// start executing the appropriate function.
protected:
// 继承的子类触发该构造函数[luther.gliethttp]
omni_thread(void* arg = NULL, priority_t pri = PRIORITY_NORMAL);
// this constructor is used in a derived class. The thread will
// execute the run() or run_undetached() member functions depending on
// whether start() or start_undetached() is called respectively.
......
private:
virtual void run(void* arg) {} // 虚函数,如果vncClientThread子类实现了该同名方法,
// 那么子类的方法将覆盖父类的方法,故父类调用的方法将是子类
// 重新实现的方法[luther.gliethttp]
// 这里就是void vncClientThread::run(void *arg);
virtual void* run_undetached(void* arg) { return NULL; }
// can be overridden in a derived class. When constructed using the
// the constructor omni_thread(void*, priority_t), these functions are
// called by start() and start_undetached() respectively.
void common_constructor(void* arg, priority_t pri, int det);
// implements the common parts of the constructors.
......
};
void
vncClientThread::run(void *arg)
{
......
// MAIN LOOP
BOOL connected = TRUE;
while (connected) {
rfbClientToServerMsg msg;
// Ensure that we're running in the correct desktop
if (!vncService::InputDesktopSelected())
if (!vncService::SelectDesktop(NULL))
break;
// Try to read a message ID
if (!m_socket->ReadExact((char *)&msg.type, sizeof(msg.type))) // 首先读取消息ID
{
connected = FALSE;
break;
}
// What to do is determined by the message id
switch(msg.type) {
case rfbSetPixelFormat:
// Read the rest of the message:
......
break;
case rfbSetEncodings:
// Read the rest of the message:
......
break;
case rfbFramebufferUpdateRequest:
// Read the rest of the message:
......
break;
case rfbKeyEvent:
// Read the rest of the message:
if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbKeyEventMsg-1))
{
if (m_client->m_keyboardenabled)
{
msg.ke.key = Swap32IfLE(msg.ke.key);
// Get the keymapper to do the work
m_client->m_keymap.DoXkeysym(msg.ke.key, msg.ke.down);
m_client->m_remoteevent = TRUE;
}
}
break;
case rfbPointerEvent:
// Read the rest of the message:
if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbPointerEventMsg-1))
{
if (m_client->m_pointerenabled)
{
// Convert the coords to Big Endian
msg.pe.x = Swap16IfLE(msg.pe.x);
msg.pe.y = Swap16IfLE(msg.pe.y);
// Work out the flags for this event
DWORD flags = MOUSEEVENTF_ABSOLUTE;
if (msg.pe.x != m_client->m_ptrevent.x ||
msg.pe.y != m_client->m_ptrevent.y)
flags |= MOUSEEVENTF_MOVE;
if ( (msg.pe.buttonMask & rfbButton1Mask) !=
(m_client->m_ptrevent.buttonMask & rfbButton1Mask) )
{
if (GetSystemMetrics(SM_SWAPBUTTON))
flags |= (msg.pe.buttonMask & rfbButton1Mask)
? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
else
flags |= (msg.pe.buttonMask & rfbButton1Mask)
? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
}
if ( (msg.pe.buttonMask & rfbButton2Mask) !=
(m_client->m_ptrevent.buttonMask & rfbButton2Mask) )
{
flags |= (msg.pe.buttonMask & rfbButton2Mask)
? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP;
}
if ( (msg.pe.buttonMask & rfbButton3Mask) !=
(m_client->m_ptrevent.buttonMask & rfbButton3Mask) )
{
if (GetSystemMetrics(SM_SWAPBUTTON))
flags |= (msg.pe.buttonMask & rfbButton3Mask)
? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
else
flags |= (msg.pe.buttonMask & rfbButton3Mask)
? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
}
// Generate coordinate values
unsigned long x = (msg.pe.x * 65535) / (m_client->m_fullscreen.right);
unsigned long y = (msg.pe.y * 65535) / (m_client->m_fullscreen.bottom);
// Do the pointer event
::mouse_event(flags, (DWORD) x, (DWORD) y, 0, 0);
// Save the old position
m_client->m_ptrevent = msg.pe;
// Flag that a remote event occurred
m_client->m_remoteevent = TRUE;
// Flag that the mouse moved
m_client->UpdateMouse();
// Trigger an update
m_server->RequestUpdate();
}
}
break;
case rfbClientCutText:
// Read the rest of the message:
......
break;
}
}
}
==>VSocket::ReadExact
==>VSocket::Read // 从网络读取数据
VInt
VSocket::Read(char *buff, const VCard bufflen)
{
return recv(sock, buff, bufflen, 0);
}
|