📄 vncclient.cpp
字号:
unsigned long y = (msg.pe.y * 65535) / (m_client->m_fullscreen.br.y); // Do the pointer event ::mouse_event(flags, (DWORD) x, (DWORD) y, data, 0); // Save the old position m_client->m_ptrevent = msg.pe; // Flag that a remote event occurred m_client->m_remoteevent = TRUE; // Tell the desktop hook system to grab the screen... m_client->m_encodemgr.m_buffer->m_desktop->TriggerUpdate(); } } break; case rfbClientCutText: // Read the rest of the message: if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbClientCutTextMsg-1)) { // Allocate storage for the text const UINT length = Swap32IfLE(msg.cct.length); char *text = new char [length+1]; if (text == NULL) break; text[length] = 0; // Read in the text if (!m_socket->ReadExact(text, length)) { delete [] text; break; } // Get the server to update the local clipboard m_server->UpdateLocalClipText(text); // Free the clip text we read delete [] text; } break; default: // Unknown message, so fail! connected = FALSE; } } // Move into the thread's original desktop vncService::SelectHDESK(home_desktop); // Quit this thread. This will automatically delete the thread and the // associated client. vnclog.Print(LL_CLIENTS, VNCLOG("client disconnected : %s (%hd)\n"), m_client->GetClientName(), m_client->GetClientId()); // Disable the protocol to ensure that the update thread // is not accessing the desktop and buffer objects m_client->DisableProtocol(); // Finally, it's safe to kill the update thread here if (m_client->m_updatethread) { m_client->m_updatethread->Kill(); m_client->m_updatethread->join(NULL); } // Remove the client from the server // This may result in the desktop and buffer being destroyed // It also guarantees that the client will not be passed further // updates m_server->RemoveClient(m_client->GetClientId());}// The vncClient itselfvncClient::vncClient(){ vnclog.Print(LL_INTINFO, VNCLOG("vncClient() executing...\n")); m_socket = NULL; m_client_name = 0; // Initialise mouse fields m_mousemoved = FALSE; m_ptrevent.buttonMask = 0; m_ptrevent.x = 0; m_ptrevent.y=0; // Other misc flags m_thread = NULL; m_palettechanged = FALSE; // Initialise the two update stores m_updatethread = NULL; m_update_tracker.init(this); m_remoteevent = FALSE; m_clipboard_text = 0; // IMPORTANT: Initially, client is not protocol-ready. m_disable_protocol = 1;}vncClient::~vncClient(){ vnclog.Print(LL_INTINFO, VNCLOG("~vncClient() executing...\n")); // We now know the thread is dead, so we can clean up if (m_client_name != 0) { free(m_client_name); m_client_name = 0; } // If we have a socket then kill it if (m_socket != NULL) { vnclog.Print(LL_INTINFO, VNCLOG("deleting socket\n")); delete m_socket; m_socket = NULL; }}// InitBOOLvncClient::Init(vncServer *server, VSocket *socket, BOOL auth, BOOL shared, vncClientId newid){ // Save the server id; m_server = server; // Save the socket m_socket = socket; // Save the name of the connecting client char *name = m_socket->GetPeerName(); if (name != 0) m_client_name = strdup(name); else m_client_name = strdup("<unknown>"); // Save the client id m_id = newid; // Spawn the child thread here m_thread = new vncClientThread; if (m_thread == NULL) return FALSE; return ((vncClientThread *)m_thread)->Init(this, m_server, m_socket, auth, shared); return FALSE;}voidvncClient::Kill(){ // Close the socket vnclog.Print(LL_INTERR, VNCLOG("client Kill() called")); if (m_socket != NULL) m_socket->Close();}// Client manipulation functions for use by the servervoidvncClient::SetBuffer(vncBuffer *buffer){ // Until authenticated, the client object has no access // to the screen buffer. This means that there only need // be a buffer when there's at least one authenticated client. m_encodemgr.SetBuffer(buffer);}voidvncClient::TriggerUpdateThread(){ // ALWAYS lock the client UpdateLock before calling this! // Check that this client has an update thread // The update thread never dissappears, and this is the only // thread allowed to create it, so this can be done without locking. if (!m_updatethread) { m_updatethread = new vncClientUpdateThread; if (!m_updatethread || !m_updatethread->Init(this)) { Kill(); } } if (m_updatethread) m_updatethread->Trigger();}voidvncClient::UpdateMouse(){ // Flag that the mouse has moved omni_mutex_lock l(GetUpdateLock()); m_mousemoved=TRUE;}voidvncClient::UpdateClipText(const char* text){ omni_mutex_lock l(GetUpdateLock()); if (m_clipboard_text) { free(m_clipboard_text); m_clipboard_text = 0; } m_clipboard_text = strdup(text); TriggerUpdateThread();}voidvncClient::UpdatePalette(){ omni_mutex_lock l(GetUpdateLock()); m_palettechanged = TRUE;}voidvncClient::UpdateLocalFormat(){ DisableProtocol(); vnclog.Print(LL_INTERR, VNCLOG("updating local pixel format\n")); m_encodemgr.SetServerFormat(); EnableProtocol();}// Functions used to set and retrieve the client settingsconst char*vncClient::GetClientName(){ return m_client_name;}// Enabling and disabling clipboard/GFX updatesvoidvncClient::DisableProtocol(){ BOOL disable = FALSE; { omni_mutex_lock l(GetUpdateLock()); if (m_disable_protocol == 0) disable = TRUE; m_disable_protocol++; if (disable && m_updatethread) m_updatethread->EnableUpdates(FALSE); }}voidvncClient::EnableProtocol(){ { omni_mutex_lock l(GetUpdateLock()); if (m_disable_protocol == 0) { vnclog.Print(LL_INTERR, VNCLOG("protocol enabled too many times!\n")); m_socket->Close(); return; } m_disable_protocol--; if ((m_disable_protocol == 0) && m_updatethread) m_updatethread->EnableUpdates(TRUE); }}// Internal methodsBOOLvncClient::SendRFBMsg(CARD8 type, BYTE *buffer, int buflen){ // Set the message type ((rfbServerToClientMsg *)buffer)->type = type; // Send the message if (!m_socket->SendExact((char *) buffer, buflen)) { vnclog.Print(LL_CONNERR, VNCLOG("failed to send RFB message to client\n")); Kill(); return FALSE; } return TRUE;}BOOLvncClient::SendUpdate(rfb::SimpleUpdateTracker &update){ // If there is nothing to send then exit if (update.is_empty()) { vnclog.Print(LL_INTERR, "no data to send\n"); return FALSE; } // Get the update info from the tracker rfb::UpdateInfo update_info; update.get_update(update_info); update.clear(); // Find out how many rectangles in total will be updated // This includes copyrects and changed rectangles split // up by codings such as CoRRE. int updates = 0; updates += update_info.copied.size(); rfb::RectVector::const_iterator i; for (i=update_info.changed.begin(); i != update_info.changed.end(); i++) { updates += m_encodemgr.GetNumCodedRects(*i); } // If there are no updates then return if (updates == 0) { vnclog.Print(LL_INTERR, "no data to send2\n"); return FALSE; } // Otherwise, send <number of rectangles> header rfbFramebufferUpdateMsg header; header.nRects = Swap16IfLE(updates); if (!SendRFBMsg(rfbFramebufferUpdate, (BYTE *) &header, sz_rfbFramebufferUpdateMsg)) return FALSE; // Send the copyrect rectangles if (!update_info.copied.empty()) { rfb::Point to_src_delta = update_info.copy_delta.negate(); for (i=update_info.copied.begin(); i!=update_info.copied.end(); i++) { rfb::Point src = (*i).tl.translate(to_src_delta); if (!SendCopyRect(*i, src)) return FALSE; } } // Encode & send the actual rectangles if (!SendRectangles(update_info.changed)) return FALSE; return TRUE;}// Send a set of rectanglesBOOLvncClient::SendRectangles(const rfb::RectVector &rects){ rfb::Rect rect; rfb::RectVector::const_iterator i; // Work through the list of rectangles, sending each one for (i=rects.begin();i!=rects.end();i++) { if (!SendRectangle(*i)) return FALSE; } return TRUE;}// Tell the encoder to send a single rectangleBOOLvncClient::SendRectangle(const rfb::Rect &rect){ // Get the buffer to encode the rectangle UINT bytes = m_encodemgr.EncodeRect(rect); // If the data could not be encoded then bytes is zero if (bytes == 0) return FALSE; // Send the encoded data return m_socket->SendExact((char *)(m_encodemgr.GetClientBuffer()), bytes);}// Send a single CopyRect messageBOOLvncClient::SendCopyRect(const rfb::Rect &dest, const rfb::Point &source){ // Create the message header rfbFramebufferUpdateRectHeader copyrecthdr; copyrecthdr.r.x = Swap16IfLE(dest.tl.x); copyrecthdr.r.y = Swap16IfLE(dest.tl.y); copyrecthdr.r.w = Swap16IfLE(dest.br.x-dest.tl.x); copyrecthdr.r.h = Swap16IfLE(dest.br.y-dest.tl.y); copyrecthdr.encoding = Swap32IfLE(rfbEncodingCopyRect); // Create the CopyRect-specific section rfbCopyRect copyrectbody; copyrectbody.srcX = Swap16IfLE(source.x); copyrectbody.srcY = Swap16IfLE(source.y); // Now send the message; if (!m_socket->SendExact((char *)©recthdr, sizeof(copyrecthdr))) return FALSE; if (!m_socket->SendExact((char *)©rectbody, sizeof(copyrectbody))) return FALSE; return TRUE;}// Send the encoder-generated palette to the client// This function only returns FALSE if the SendExact fails - any other// error is coped with internally...BOOLvncClient::SendPalette(){ rfbSetColourMapEntriesMsg setcmap; RGBQUAD *rgbquad; UINT ncolours = 256; // Reserve space for the colour data rgbquad = new RGBQUAD[ncolours]; if (rgbquad == NULL) return TRUE; // Get the data if (!m_encodemgr.GetPalette(rgbquad, ncolours)) { delete [] rgbquad; return TRUE; } // Compose the message setcmap.type = rfbSetColourMapEntries; setcmap.firstColour = Swap16IfLE(0); setcmap.nColours = Swap16IfLE(ncolours); if (!m_socket->SendExact((char *) &setcmap, sz_rfbSetColourMapEntriesMsg)) { delete [] rgbquad; return FALSE; } // Now send the actual colour data... for (int i=0; i<ncolours; i++) { struct _PIXELDATA { CARD16 r, g, b; } pixeldata; pixeldata.r = Swap16IfLE(((CARD16)rgbquad[i].rgbRed) << 8); pixeldata.g = Swap16IfLE(((CARD16)rgbquad[i].rgbGreen) << 8); pixeldata.b = Swap16IfLE(((CARD16)rgbquad[i].rgbBlue) << 8); if (!m_socket->SendExact((char *) &pixeldata, sizeof(pixeldata))) { delete [] rgbquad; return FALSE; } } // Delete the rgbquad data delete [] rgbquad; return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -