免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1399 | 回复: 0

vnc调试------之反向连接 [复制链接]

论坛徽章:
0
发表于 2011-12-22 08:51 |显示全部楼层
    由于测试vnc反向连接出错,所以这几天一直在调试vnc的反向连接问题。
    通过初步调试得知是在协议的server端连接到viewer端的版本信息验证错误,故追查之。
    要让vncviewer端支持反向连接,可在命令行加参数,也可以修还源码的vncviewer.cxx文件中的linstenmode为ture。
    相对于viewer端,server的情况比较复杂一点,跟踪了好几天终于找到地方了,关键点在vncconndialog.cpp文件,下面把重要的源代码部分贴出来。
   
// Callback function - handles messages sent to the dialog box

BOOL CALLBACK vncConnDialog::vncConnDlgProc(HWND hwnd,
                                            UINT uMsg,
                                            WPARAM wParam,
                                            LPARAM lParam) {
    // This is a static method, so we don't know which instantiation we're
    // dealing with. But we can get a pseudo-this from the parameter to
    // WM_INITDIALOG, which we therafter store with the window and retrieve
    // as follows:
     vncConnDialog *_this = helper::SafeGetWindowUserData<vncConnDialog>(hwnd);

    switch (uMsg) {
    case WM_PAINT:
        {
            //adzm 2009-06-20
            if (GetUpdateRect(hwnd, NULL, TRUE)) {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hwnd, &ps);

                {
                    RECT rcIcon;
                    rcIcon.top = 0;
                    rcIcon.left = 0;
                    rcIcon.bottom = 48;
                    rcIcon.right = 48;
                   
                    RECT rcClient;
                    if (GetClientRect(hwnd, &rcClient)) {
                        int nDifference = (rcClient.bottom - rcIcon.bottom) / 2;
                        if (nDifference > 0) {
                            rcIcon.top += nDifference;
                            rcIcon.bottom += nDifference;
                        }
                    }

                    RECT rcLabel;
                    HWND hwndLabel = GetDlgItem(hwnd, IDC_CONNECTION_NUMBER_STATIC);
                    if (GetWindowRect(hwndLabel, &rcLabel)) {
                        LPRECT lprcLabel = &rcLabel;
                        ScreenToClient(hwnd, (LPPOINT)lprcLabel);
                        ScreenToClient(hwnd, ((LPPOINT)lprcLabel)+1);

                        int nAdjustment = (rcLabel.left - rcIcon.right) / 2;

                        rcIcon.left += nAdjustment;
                        rcIcon.right += nAdjustment;
                    }

                    RECT rcIntersect;

                    if (IntersectRect(&rcIntersect, &rcIcon, &(ps.rcPaint))) {
                        if (_this->m_hicon == NULL) {
                            _this->m_hicon = (HICON)LoadImage(hInstResDLL, MAKEINTRESOURCE(IDI_WINVNC), IMAGE_ICON,
                               48, 48, 0);
                        }
                        if (_this->m_hicon) {
                            HBRUSH hbr = (HBRUSH)SendMessage(hwnd, WM_CTLCOLORDLG, (WPARAM)hdc, (WPARAM)hwnd);
                            DrawIconEx(hdc, rcIcon.left, rcIcon.top, _this->m_hicon, 48, 48, 0, hbr, DI_NORMAL);
                        }
                    }
                }

                EndPaint(hwnd, &ps);
            }

            return 0;
        }

        // Dialog has just been created
    case WM_INITDIALOG:
        {
            // Save the lParam into our user data so that subsequent calls have
            // access to the parent C++ object
            helper::SafeSetWindowUserData(hwnd, lParam);

            vncConnDialog *_this = (vncConnDialog *) lParam;

            //adzm 2009-06-20
            if (g_szRepeaterHost) {
                SetDlgItemText(hwnd, IDC_HOSTNAME_EDIT, g_szRepeaterHost);

                //adzm 2009-06-20
                if (SPECIAL_SC_PROMPT) {
                    HWND hwndChild = GetDlgItem(hwnd, IDC_HOSTNAME_EDIT);
                    if (hwndChild) {
                        ShowWindow(hwndChild, SW_HIDE);
                    }
                    hwndChild = GetDlgItem(hwnd, IDC_HOSTNAME_STATIC);
                    if (hwndChild) {
                        ShowWindow(hwndChild, SW_HIDE);
                    }

                    HWND hwndEdit = GetDlgItem(hwnd, IDC_IDCODE);
                    HWND hwndLabel = GetDlgItem(hwnd, IDC_CONNECTION_NUMBER_STATIC);

                    RECT rcEdit;
                    RECT rcLabel;
                    GetWindowRect(hwndEdit, &rcEdit);
                    GetWindowRect(hwndLabel, &rcLabel);

                    LPRECT lprcEdit = &rcEdit;
                    LPRECT lprcLabel = &rcLabel;

                    ScreenToClient(hwnd, (LPPOINT)lprcEdit);
                    ScreenToClient(hwnd, ((LPPOINT)lprcEdit)+1);
                   
                    ScreenToClient(hwnd, (LPPOINT)lprcLabel);
                    ScreenToClient(hwnd, ((LPPOINT)lprcLabel)+1);

                    RECT rcClient;
                    GetClientRect(hwnd, &rcClient);

                    long nTotalHeight = rcEdit.bottom - rcLabel.top;

                    long nAdjustedTop = (rcClient.bottom - nTotalHeight) / 2;

                    long nAdjustment = nAdjustedTop - rcLabel.top;

                    MoveWindow(hwndLabel, rcLabel.left, rcLabel.top + nAdjustment, rcLabel.right - rcLabel.left, rcLabel.bottom - rcLabel.top, TRUE);
                    MoveWindow(hwndEdit, rcEdit.left, rcEdit.top + nAdjustment, rcEdit.right - rcEdit.left, rcEdit.bottom - rcEdit.top, TRUE);

                    HWND hwndCaption = GetDlgItem(hwnd, IDC_CAPTION_STATIC);
                    HFONT hFont = (HFONT)SendMessage(hwndCaption, WM_GETFONT, 0, 0);
                    if (hFont) {
                        LOGFONT lf;
                        if (GetObject(hFont, sizeof(LOGFONT), &lf)) {
                            lf.lfWidth = 0;
                            lf.lfHeight = (lf.lfHeight * 6) / 4;

                            _this->m_hfont = CreateFontIndirect(&lf);

                            if (_this->m_hfont) {
                                SendMessage(hwndCaption, WM_SETFONT, (WPARAM)_this->m_hfont, (LPARAM)TRUE);
                            }
                        }
                    }
                    SetWindowText(hwndCaption, "Connect to Technical Support");
                    ShowWindow(hwndCaption, SW_SHOWNA);
                }

                SetFocus(GetDlgItem(hwnd, IDC_IDCODE));
            } else {           
                // Make the text entry box active
                SetFocus(GetDlgItem(hwnd, IDC_HOSTNAME_EDIT));
            }
           
            SetForegroundWindow(hwnd);
           
            // Return success!
            return TRUE;
        }

        // Dialog has just received a command
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
            // User clicked OK or pressed return
        case IDOK:
        {
            // sf@2002 - host:num & host::num analyse.
            // Compatible with both RealVNC and TightVNC methods
            char hostname[_MAX_PATH];
            char actualhostname[_MAX_PATH];
            char idcode[_MAX_PATH];
            char *portp;
            int port;
            bool id;

            // Get the hostname of the VNCviewer
            GetDlgItemText(hwnd, IDC_HOSTNAME_EDIT, hostname, _MAX_PATH);
            GetDlgItemText(hwnd, IDC_IDCODE, idcode, _MAX_PATH);
            if (strcmp(idcode,"")==NULL) id=false;
            else id=true;

            strcpy(actualhostname, hostname);
           
            //adzm 2010-02-15 - Multiple repeaters chosen by modulo of ID

            char finalidcode[_MAX_PATH];

            //adzm 2009-06-20
            if (id) {
                size_t i = 0;

                for (i = 0; i < strlen(idcode); i++)
                {
                    finalidcode[i] = toupper(idcode[i]);
                }
                finalidcode[i] = 0;

                if (0 != strncmp("ID:", idcode, 3)) {
                    strcpy(finalidcode, "ID:");
                   
                    for (i = 0; i < strlen(idcode); i++)
                    {
                        finalidcode[i+3] = toupper(idcode[i]);
                    }
                    finalidcode[i+3] = 0;
                }

               
                //adzm 2010-02-15 - At this point, finalidcode is of the form "ID:#####"
                int numericId = atoi(finalidcode + 3);

                int numberOfHosts = 1;
                for (i = 0; i < strlen(hostname); i++) {
                    if (hostname[i] == ';') {
                        numberOfHosts++;
                    }
                }

                if (numberOfHosts <= 1) {
                    // then hostname == actualhostname
                } else {
                    int modulo = numericId % numberOfHosts;

                    char* szToken = strtok(hostname, ";");
                    while (szToken) {
                        if (modulo == 0) {
                            strcpy(actualhostname, szToken);
                            break;
                        }

                        modulo--;
                        szToken = strtok(NULL, ";");
                    }
                }
            }

            // Calculate the Display and Port offset.
            port = INCOMING_PORT_OFFSET;
            portp = strchr(actualhostname, ':');
            if (portp)
            {
                *portp++ = '\0';
                if (*portp == ':') // Tight127 method
                {
                    port = atoi(++portp);        // Port number after "::"
                }
                else // RealVNC method
                {
                    if (atoi(portp) < 100)        // If < 100 after ":" -> display number
                        port += atoi(portp);
                    else
                        port = atoi(portp);        // If > 100 after ":" -> Port number
                }
            }


           
            // Attempt to create a new socket
            VSocket *tmpsock;
            tmpsock = new VSocket;
            if (!tmpsock) {
                return TRUE;
            }
           
            // Connect out to the specified host on the VNCviewer listen port
            // To be really good, we should allow a display number here but
            // for now we'll just assume we're connecting to display zero
            tmpsock->Create();
            if (tmpsock->Connect(actualhostname, port))
            {
                     id=false;                   //debug by qz.这个地方我们要绕过去,不然就连接不上客户端了。
                if (id)
                    {                           
                       

                        tmpsock->Send(finalidcode,250);
                        tmpsock->SetTimeout(0);
/*                        if (strncmp(hostname,"ID",2)!=0)
                        {
                        while (true)
                        {
                            char result[1];
                            tmpsock->Read(result,1);
                            if (strcmp(result,"2")==0)
                                break;
                            tmpsock->Send("1",1);
                        }
                        }*/
                       
                        // adzm 2009-07-05 - repeater IDs
                        // Add the new client to this server
                        // adzm 2009-08-02
                        _this->m_server->AddClient(tmpsock, TRUE, TRUE, 0, NULL, finalidcode, actualhostname, port);
                    } else {
                        // Add the new client to this server
                        // adzm 2009-08-02
                        _this->m_server->AddClient(tmpsock, TRUE, TRUE, 0, NULL, NULL, actualhostname, port);               
                    }
                // And close the dialog
                EndDialog(hwnd, TRUE);
            }
            else
            {
                // Print up an error message
                MessageBox(NULL,
                    sz_ID_FAILED_CONNECT_LISTING_VIEW,
                    sz_ID_OUTGOING_CONNECTION,
                    MB_OK | MB_ICONEXCLAMATION );
                delete tmpsock;
            }
            return TRUE;
        }
       
            // Cancel the dialog
        case IDCANCEL:
            EndDialog(hwnd, FALSE);
            return TRUE;
        };

        break;

    case WM_DESTROY:
        EndDialog(hwnd, FALSE);
        if (_this->m_hicon != NULL) {
            DestroyIcon(_this->m_hicon);
            _this->m_hicon = NULL;
        }
        if (_this->m_hfont != NULL) {
            DeleteObject(_this->m_hfont);
            _this->m_hfont = NULL;
        }
        return TRUE;
    }
    return 0;
}


您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP