Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15496632
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: WINDOWS

2009-05-31 18:07:31

浅析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);
}

阅读(2011) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~