📄 clientconnection.cpp
字号:
if (!BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-ps.rcPaint.left, ps.rcPaint.bottom-ps.rcPaint.top, m_hBitmapDC, ps.rcPaint.left+m_hScrollPos, ps.rcPaint.top+m_vScrollPos, SRCCOPY)) { log.Print(0, _T("Blit error %d\n"), GetLastError()); // throw ErrorException("Error in blit!\n"); } } EndPaint(m_hwnd, &ps);}inline void ClientConnection::UpdateScrollbars() { // We don't update the actual scrollbar info in full-screen mode // because it causes them to flicker. bool setInfo = !InFullScreenMode(); SCROLLINFO scri; scri.cbSize = sizeof(scri); scri.fMask = SIF_ALL; scri.nMin = 0; scri.nMax = m_hScrollMax; scri.nPage= m_cliwidth; scri.nPos = m_hScrollPos; if (setInfo) SetScrollInfo(m_hwnd, SB_HORZ, &scri, TRUE); scri.cbSize = sizeof(scri); scri.fMask = SIF_ALL; scri.nMin = 0; scri.nMax = m_vScrollMax; scri.nPage= m_cliheight; scri.nPos = m_vScrollPos; if (setInfo) SetScrollInfo(m_hwnd, SB_VERT, &scri, TRUE);}void ClientConnection::ShowConnInfo(){ TCHAR buf[2048];#ifndef UNDER_CE char kbdname[9]; GetKeyboardLayoutName(kbdname);#else TCHAR *kbdname = _T("(n/a)");#endif _stprintf( buf, _T("Connected to: %s:\n\r") _T("Host: %s port: %d\n\r\n\r") _T("Desktop geometry: %d x %d x %d\n\r") _T("Using depth: %d\n\r") _T("Line speed estimate: %d kbit/s\n") _T("Current protocol version: %d.%d\n\r\n\r") _T("Current keyboard name: %s\n\r"), m_desktopName, m_host, m_port, m_si.framebufferWidth, m_si.framebufferHeight, m_si.format.depth, m_myFormat.depth, kbitsPerSecond, m_majorVersion, m_minorVersion, kbdname); MessageBox(NULL, buf, _T("VNC connection info"), MB_ICONINFORMATION | MB_OK);}// ********************************************************************// Methods after this point are generally called by the worker thread.// They finish the initialisation, then chiefly read data from the server.// ********************************************************************void* ClientConnection::run_undetached(void* arg) { log.Print(9,_T("Update-processing thread started\n")); m_threadStarted = true; try { SendFullFramebufferUpdateRequest(); RealiseFullScreenMode(); m_running = true; UpdateWindow(m_hwnd);
while (!m_bKillThread) { rdr::U8 msgType = fis->readU8(); switch (msgType) { case rfbFramebufferUpdate: ReadScreenUpdate(); break; case rfbSetColourMapEntries: log.Print(3, _T("rfbSetColourMapEntries read but not supported\n") ); throw WarningException("Unhandled SetColormap message type received!\n"); break; case rfbBell: ReadBell(); break; case rfbServerCutText: ReadServerCutText(); break; default: log.Print(3, _T("Unknown message type x%02x\n"), msgType ); throw WarningException("Unhandled message type received!\n"); break; /* default: log.Print(3, _T("Unknown message type x%02x\n"), msgType ); throw WarningException("Unhandled message type received!\n"); */ } } log.Print(4, _T("Update-processing thread finishing\n") ); } catch (WarningException) { PostMessage(m_hwnd, WM_CLOSE, 0, 0); } catch (QuietException &e) { e.Report(); PostMessage(m_hwnd, WM_CLOSE, 0, 0); } catch (rdr::Exception& e) { log.Print(0,"rdr::Exception: %s\n",e.str()); PostMessage(m_hwnd, WM_CLOSE, 0, 0); } return this;}//// Requesting screen updates from the server//inline voidClientConnection::SendFramebufferUpdateRequest(int x, int y, int w, int h, bool incremental){ rfbFramebufferUpdateRequestMsg fur; fur.type = rfbFramebufferUpdateRequest; fur.incremental = incremental ? 1 : 0; fur.x = Swap16IfLE(x); fur.y = Swap16IfLE(y); fur.w = Swap16IfLE(w); fur.h = Swap16IfLE(h); log.Print(10, _T("Request %s update\n"), incremental ? _T("incremental") : _T("full")); WriteExact((char *)&fur, sz_rfbFramebufferUpdateRequestMsg);}inline void ClientConnection::SendIncrementalFramebufferUpdateRequest(){ SendFramebufferUpdateRequest(0, 0, m_si.framebufferWidth, m_si.framebufferHeight, true);}inline void ClientConnection::SendFullFramebufferUpdateRequest(){ SendFramebufferUpdateRequest(0, 0, m_si.framebufferWidth, m_si.framebufferHeight, false);}void ClientConnection::SendAppropriateFramebufferUpdateRequest(){ if (m_pendingFormatChange) { log.Print(3, _T("Requesting new pixel format\n") ); rfbPixelFormat oldFormat = m_myFormat; SetupPixelFormat(); SetFormatAndEncodings(); m_pendingFormatChange = false; // If the pixel format has changed, request whole screen if (!PF_EQ(m_myFormat, oldFormat)) { SendFullFramebufferUpdateRequest(); } else { SendIncrementalFramebufferUpdateRequest(); } } else { if (!m_dormant) SendIncrementalFramebufferUpdateRequest(); }}// A ScreenUpdate message has been receivedvoid ClientConnection::ReadScreenUpdate(){ fis->startTiming(); rfbFramebufferUpdateMsg sut; ReadExact(((char *) &sut)+1, sz_rfbFramebufferUpdateMsg-1); sut.nRects = Swap16IfLE(sut.nRects); //if (sut.nRects == 0) return; XXX tjr removed this - is this OK? for (UINT i=0; i < sut.nRects; i++) { rfbFramebufferUpdateRectHeader surh; ReadExact((char *) &surh, sz_rfbFramebufferUpdateRectHeader); surh.r.x = Swap16IfLE(surh.r.x); surh.r.y = Swap16IfLE(surh.r.y); surh.r.w = Swap16IfLE(surh.r.w); surh.r.h = Swap16IfLE(surh.r.h); surh.encoding = Swap32IfLE(surh.encoding); switch (surh.encoding) { case rfbEncodingRaw: ReadRawRect(&surh); break; case rfbEncodingCopyRect: ReadCopyRect(&surh); break; case rfbEncodingRRE: ReadRRERect(&surh); break; case rfbEncodingCoRRE: ReadCoRRERect(&surh); break; case rfbEncodingHextile: ReadHextileRect(&surh); break; case rfbEncodingZRLE: zrleDecode(surh.r.x, surh.r.y, surh.r.w, surh.r.h); break; default: log.Print(0, _T("Unknown encoding %d - not supported!\n"), surh.encoding); break; } RECT rect; if (m_opts.m_scaling) { // If we're scaling, we transform the coordinates of the rectangle received // into the corresponding window coords, and invalidate *that* region. // First, we adjust coords to avoid rounding down when scaling. int n = m_opts.m_scale_num; int d = m_opts.m_scale_den; int left = (surh.r.x / d) * d; int top = (surh.r.y / d) * d; int right = (surh.r.x + surh.r.w + d - 1) / d * d; // round up int bottom = (surh.r.y + surh.r.h + d - 1) / d * d; // round up // Then we scale the rectangle, which should now give whole numbers rect.left = (left * n / d) - m_hScrollPos; rect.top = (top * n / d) - m_vScrollPos; rect.right = (right * n / d) - m_hScrollPos; rect.bottom = (bottom * n / d) - m_vScrollPos;; } else { rect.left = surh.r.x - m_hScrollPos; rect.top = surh.r.y - m_vScrollPos; rect.right = rect.left + surh.r.w; rect.bottom = rect.top + surh.r.h; } InvalidateRect(m_hwnd, &rect, FALSE); } fis->stopTiming(); kbitsPerSecond = fis->kbitsPerSecond(); if (m_opts.autoDetect) { // Above 10Mbps, switch to hextile // Below 4Mbps, switch to ZRLE // Above 1Mbps, switch from 8bit //fprintf(stderr," kbps %d \r",kbitsPerSecond); if (kbitsPerSecond > 10000) { if (m_opts.m_PreferredEncoding != rfbEncodingHextile) { fprintf(stderr,"Throughput %d kbit/s - changing to Hextile\n", kbitsPerSecond); m_opts.m_PreferredEncoding = rfbEncodingHextile; m_pendingFormatChange = true; } } else if (kbitsPerSecond < 4000) { if (m_opts.m_PreferredEncoding != rfbEncodingZRLE) { fprintf(stderr,"Throughput %d kbit/s - changing to ZRLE\n", kbitsPerSecond); m_opts.m_PreferredEncoding = rfbEncodingZRLE; m_pendingFormatChange = true; } } if (kbitsPerSecond > 1000) { if (m_opts.m_Use8Bit) { fprintf(stderr,"Throughput %d kbit/s - changing from 8bit\n", kbitsPerSecond); m_opts.m_Use8Bit = false; m_pendingFormatChange = true; } } } // Inform the other thread that an update is needed. PostMessage(m_hwnd, WM_REGIONUPDATED, NULL, NULL);} void ClientConnection::SetDormant(bool newstate){ log.Print(5, _T("%s dormant mode\n"), newstate ? _T("Entering") : _T("Leaving")); m_dormant = newstate; if (!m_dormant) SendIncrementalFramebufferUpdateRequest();}// The server has copied some text to the clipboard - put it // in the local clipboard too.void ClientConnection::ReadServerCutText() { rfbServerCutTextMsg sctm; log.Print(6, _T("Read remote clipboard change\n")); ReadExact(((char *) &sctm)+1, sz_rfbServerCutTextMsg-1); int len = Swap32IfLE(sctm.length); CheckBufferSize(len); if (len == 0) { m_netbuf[0] = '\0'; } else { ReadString(m_netbuf, len); } UpdateLocalClipboard(m_netbuf, len);}void ClientConnection::ReadBell() { rfbBellMsg bm; ReadExact(((char *) &bm)+1, sz_rfbBellMsg-1); #ifdef UNDER_CE MessageBeep( MB_OK ); #else if (! ::PlaySound("VNCViewerBell", NULL, SND_APPLICATION | SND_ALIAS | SND_NODEFAULT | SND_ASYNC) ) { ::Beep(440, 125); } #endif if (m_opts.m_DeiconifyOnBell) { if (IsIconic(m_hwnd)) { SetDormant(false); ShowWindow(m_hwnd, SW_SHOWNORMAL); } } log.Print(6, _T("Bell!\n"));}// General utilities -------------------------------------------------// Reads the number of bytes specified into the buffer givenvoid ClientConnection::ReadExact(char *inbuf, int wanted){ try { fis->readBytes(inbuf, wanted); } catch (rdr::Exception& e) { log.Print(0, "rdr::Exception: %s\n",e.str()); throw QuietException(e.str()); }}// Read the number of bytes and return them zero terminated in the buffer inline void ClientConnection::ReadString(char *buf, int length){ if (length > 0) ReadExact(buf, length); buf[length] = '\0'; log.Print(10, _T("Read a %d-byte string\n"), length);}// Sends the number of bytes specified from the bufferinline void ClientConnection::WriteExact(char *buf, int bytes){ if (bytes == 0) return; omni_mutex_lock l(m_writeMutex); log.Print(10, _T(" writing %d bytes\n"), bytes); int i = 0; int j; while (i < bytes) { j = send(m_sock, buf+i, bytes-i, 0); if (j == SOCKET_ERROR || j==0) { LPVOID lpMsgBuf; int err = ::GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); // Process any inserts in lpMsgBuf. log.Print(1, _T("Socket error %d: %s\n"), err, lpMsgBuf); LocalFree( lpMsgBuf ); m_running = false; throw WarningException("WriteExact: Socket error while writing."); } i += j; }}// Makes sure netbuf is at least as big as the specified size.// Note that netbuf itself may change as a result of this call.// Throws an exception on failure.inline void ClientConnection::CheckBufferSize(int bufsize){ if (m_netbufsize > bufsize) return; omni_mutex_lock l(m_bufferMutex); char *newbuf = new char[bufsize+256];; if (newbuf == NULL) { throw ErrorException("Insufficient memory to allocate network buffer."); } // Only if we're successful... if (m_netbuf != NULL) delete [] m_netbuf; m_netbuf = newbuf; m_netbufsize=bufsize + 256; log.Print(4, _T("bufsize expanded to %d\n"), m_netbufsize);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -