由于测试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(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;
}
阅读(7415) | 评论(0) | 转发(1) |