📄 vncclient.cpp
字号:
path_file[msg.fdr.fNameSize] = '\0';
ConvertPath(path_file);
strcpy(m_client->m_DownloadFilename, path_file);
HANDLE hFile;
DWORD sz_rfbFileSize;
DWORD sz_rfbBlockSize = 8192;
DWORD dwNumberOfBytesRead = 0;
DWORD dwNumberOfAllBytesRead = 0;
WIN32_FIND_DATA FindFileData;
SetErrorMode(SEM_FAILCRITICALERRORS);
hFile = FindFirstFile(path_file, &FindFileData);
DWORD LastError = GetLastError();
SetErrorMode(0);
vnclog.Print(LL_CLIENTS, VNCLOG("file download requested: %s\n"),
path_file);
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
(hFile == INVALID_HANDLE_VALUE) || (path_file[0] == '\0')) {
FindClose(hFile);
char reason[] = "Cannot open file, perhaps it is absent or is a directory";
int reasonLen = strlen(reason);
m_client->SendFileDownloadFailed(reasonLen, reason);
break;
}
sz_rfbFileSize = FindFileData.nFileSizeLow;
FindClose(hFile);
m_client->m_modTime = m_client->FiletimeToTime70(FindFileData.ftLastWriteTime);
if (sz_rfbFileSize == 0) {
m_client->SendFileDownloadData(m_client->m_modTime);
} else {
if (sz_rfbFileSize <= sz_rfbBlockSize) sz_rfbBlockSize = sz_rfbFileSize;
SetErrorMode(SEM_FAILCRITICALERRORS);
m_client->m_hFileToRead = CreateFile(path_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
SetErrorMode(0);
if (m_client->m_hFileToRead != INVALID_HANDLE_VALUE) {
m_client->m_bDownloadStarted = TRUE;
m_client->SendFileDownloadPortion();
}
}
}
break;
case rfbFileUploadRequest:
if (!m_server->FileTransfersEnabled() || !m_client->IsInputEnabled()) {
connected = FALSE;
break;
}
if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbFileUploadRequestMsg-1))
{
msg.fupr.fNameSize = Swap16IfLE(msg.fupr.fNameSize);
msg.fupr.position = Swap32IfLE(msg.fupr.position);
if (msg.fupr.fNameSize > MAX_PATH) {
m_socket->ReadExact(NULL, msg.fupr.fNameSize);
char reason[] = "Path length exceeds MAX_PATH value";
int reasonLen = strlen(reason);
m_client->SendFileUploadCancel(reasonLen, reason);
break;
}
m_socket->ReadExact(m_client->m_UploadFilename, msg.fupr.fNameSize);
m_client->m_UploadFilename[msg.fupr.fNameSize] = '\0';
ConvertPath(m_client->m_UploadFilename);
vnclog.Print(LL_CLIENTS, VNCLOG("file upload requested: %s\n"),
m_client->m_UploadFilename);
m_client->m_hFileToWrite = CreateFile(m_client->m_UploadFilename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
m_client->m_bUploadStarted = TRUE;
if (m_client->m_hFileToWrite == INVALID_HANDLE_VALUE) {
char reason[] = "Could not create file";
int reasonLen = strlen(reason);
m_client->SendFileUploadCancel(reasonLen, reason);
}
DWORD dwError = GetLastError();
/*
SYSTEMTIME systime;
FILETIME filetime;
GetSystemTime(&systime);
SystemTimeToFileTime(&systime, &filetime);
m_client->beginUploadTime = m_client->FiletimeToTime70(filetime);
*/
/*
DWORD dwFilePtr;
if (msg.fupr.position > 0) {
dwFilePtr = SetFilePointer(m_hFiletoWrite, msg.fupr.position, NULL, FILE_BEGIN);
if ((dwFilePtr == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR)) {
char reason[] = "Invalid file pointer position";
int reasonLen = strlen(reason);
m_client->SendFileUploadCancel(reasonLen, reason);
CloseHandle(m_hFiletoWrite);
break;
}
}
*/
}
break;
case rfbFileUploadData:
if (!m_server->FileTransfersEnabled() || !m_client->IsInputEnabled()) {
connected = FALSE;
break;
}
if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbFileUploadDataMsg-1))
{
msg.fud.realSize = Swap16IfLE(msg.fud.realSize);
msg.fud.compressedSize = Swap16IfLE(msg.fud.compressedSize);
if ((msg.fud.realSize == 0) && (msg.fud.compressedSize == 0)) {
CARD32 mTime;
m_socket->ReadExact((char *) &mTime, sizeof(CARD32));
mTime = Swap32IfLE(mTime);
FILETIME Filetime;
m_client->Time70ToFiletime(mTime, &Filetime);
if (!SetFileTime(m_client->m_hFileToWrite, &Filetime, &Filetime, &Filetime)) {
vnclog.Print(LL_INTINFO, VNCLOG("SetFileTime() failed\n"));
}
// DWORD dwFileSize = GetFileSize(m_client->m_hFileToWrite, NULL);
CloseHandle(m_client->m_hFileToWrite);
m_client->m_bUploadStarted = FALSE;
// SYSTEMTIME systime;
// FILETIME filetime;
// GetSystemTime(&systime);
// SystemTimeToFileTime(&systime, &filetime);
// m_client->endUploadTime = m_client->FiletimeToTime70(filetime);
// unsigned int uploadTime = m_client->endUploadTime - m_client->beginUploadTime + 1;
// DWORD dwBytePerSecond = dwFileSize / uploadTime;
// vnclog.Print(LL_CLIENTS, VNCLOG("file upload complete: %s; Speed (B/s) = %d; FileSize = %d, UploadTime = %d\n"),
// m_client->m_UploadFilename, dwBytePerSecond, dwFileSize, uploadTime);
vnclog.Print(LL_CLIENTS, VNCLOG("file upload complete: %s;\n"),
m_client->m_UploadFilename);
break;
}
DWORD dwNumberOfBytesWritten;
char *pBuff = new char [msg.fud.compressedSize];
m_socket->ReadExact(pBuff, msg.fud.compressedSize);
if (msg.fud.compressedLevel != 0) {
char reason[] = "Server does not support data compression on upload";
int reasonLen = strlen(reason);
m_client->SendFileUploadCancel(reasonLen, reason);
m_client->CloseUndoneFileTransfer();
break;
}
BOOL bResult = WriteFile(m_client->m_hFileToWrite, pBuff, msg.fud.compressedSize, &dwNumberOfBytesWritten, NULL);
if ((dwNumberOfBytesWritten != msg.fud.compressedSize) || !bResult) {
char reason[] = "Error writing file data";
int reasonLen = strlen(reason);
m_client->SendFileUploadCancel(reasonLen, reason);
m_client->CloseUndoneFileTransfer();
break;
}
delete [] pBuff;
}
break;
case rfbFileDownloadCancel:
if (!m_server->FileTransfersEnabled() || !m_client->IsInputEnabled()) {
connected = FALSE;
break;
}
if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbFileDownloadCancelMsg-1))
{
msg.fdc.reasonLen = Swap16IfLE(msg.fdc.reasonLen);
char *reason = new char[msg.fdc.reasonLen + 1];
m_socket->ReadExact(reason, msg.fdc.reasonLen);
reason[msg.fdc.reasonLen] = '\0';
m_client->CloseUndoneFileTransfer();
delete [] reason;
}
break;
case rfbFileUploadFailed:
if (!m_server->FileTransfersEnabled() || !m_client->IsInputEnabled()) {
connected = FALSE;
break;
}
if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbFileUploadFailedMsg-1))
{
msg.fuf.reasonLen = Swap16IfLE(msg.fuf.reasonLen);
char *reason = new char[msg.fuf.reasonLen + 1];
m_socket->ReadExact(reason, msg.fuf.reasonLen);
reason[msg.fuf.reasonLen] = '\0';
m_client->CloseUndoneFileTransfer();
delete [] reason;
}
break;
case rfbFileCreateDirRequest:
if (!m_server->FileTransfersEnabled() || !m_client->IsInputEnabled()) {
connected = FALSE;
break;
}
if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbFileCreateDirRequestMsg-1))
{
msg.fcdr.dNameLen = Swap16IfLE(msg.fcdr.dNameLen);
char *dirName = new char[msg.fcdr.dNameLen + 1];
m_socket->ReadExact(dirName, msg.fcdr.dNameLen);
dirName[msg.fcdr.dNameLen] = '\0';
dirName = ConvertPath(dirName);
CreateDirectory((LPCTSTR) dirName, NULL);
delete [] dirName;
}
break;
default:
// Unknown message, so fail!
vnclog.Print(LL_CLIENTS, VNCLOG("invalid message received : %d\n"),
(int)msg.type);
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 (id %hd)\n"),
m_client->GetClientName(), m_client->GetClientId());
// Remove the client from the server, just in case!
m_server->RemoveClient(m_client->GetClientId());
}
// The vncClient itself
vncClient::vncClient()
{
vnclog.Print(LL_INTINFO, VNCLOG("vncClient() executing...\n"));
m_socket = NULL;
m_client_name = 0;
m_server_name = 0;
m_buffer = NULL;
m_keyboardenabled = FALSE;
m_pointerenabled = FALSE;
m_inputblocked = FALSE;
m_copyrect_use = FALSE;
m_mousemoved = FALSE;
m_ptrevent.buttonMask = 0;
m_ptrevent.x = 0;
m_ptrevent.y = 0;
m_cursor_update_pending = FALSE;
m_cursor_update_sent = FALSE;
m_cursor_pos_changed = FALSE;
m_pointer_event_time = (time_t)0;
m_cursor_pos.x = -1;
m_cursor_pos.y = -1;
m_thread = NULL;
m_updatewanted = FALSE;
m_palettechanged = FALSE;
m_copyrect_set = FALSE;
m_remoteevent = FALSE;
m_bDownloadStarted = FALSE;
m_bUploadStarted = FALSE;
// IMPORTANT: Initially, client is not protocol-ready.
m_protocol_ready = FALSE;
m_fb_size_changed = FALSE;
m_use_NewFBSize = FALSE;
}
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 (m_server_name != 0) {
free(m_server_name);
m_server_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;
}
// Kill the screen buffer
if (m_buffer != NULL)
{
vnclog.Print(LL_INTINFO, VNCLOG("deleting buffer\n"));
delete m_buffer;
m_buffer = NULL;
}
}
// Init
BOOL
vncClient::Init(vncServer *server,
VSocket *socket,
BOOL reverse,
BOOL shared,
vncClientId newid)
{
// Save the server id;
m_server = server;
// Save the socket
m_socket = socket;
// Save the name/ip 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 server name/ip
name = m_socket->GetSockName();
if (name != 0)
m_server_name = strdup(name);
else
m_server_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, reverse, shared);
return FALSE;
}
void
vncClient::Kill()
{
// Close file transfer
CloseUndoneFileTransfer();
// Close the socket
if (m_socket != NULL)
m_socket->Close();
}
// Client manipulation functions for use by the server
void
vncClient::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_buffer = buffer;
}
void
vncClient::TriggerUpdate()
{
// Lock the updates stored so far
omni_mutex_lock l(m_regionLock);
if (!m_protocol_ready)
return;
if (m_updatewanted)
{
// Check if cursor shape update has to be sent
m_cursor_update_pending = m_buffer->IsCursorUpdatePending();
// Send an update if one is waiting
if (!m_changed_rgn.IsEmpty() ||
!m_full_rgn.IsEmpty() ||
m_copyrect_set ||
m_cursor_update_pending ||
m_cursor_pos_changed ||
(m_mousemoved && !m_use_PointerPos))
{
// Has the palette changed?
if (m_palettechanged)
{
m_palettechanged = FALSE;
if (!SendPalette())
return;
}
// Now send the update
m_updatewanted = !SendUpdate();
}
}
}
void
vncClient::UpdateMouse()
{
if (!m_mousemoved && !m_cursor_update_sent) {
omni_mutex_lock l(m_regionLock);
if (IntersectRect(&m_oldmousepos, &m_oldmousepos, &m_server->GetSharedRect()))
m_changed_rgn.AddRect(m_oldmousepos);
m_mousemoved = TRUE;
} else if (m_use_PointerPos) {
omni_mutex_lock l(m_regionLock);
SetCursorPosChanged();
}
}
void
vncClient::UpdateRect(RECT &rect)
{
// Add the rectangle to the update region
if (IsRectEmpty(&rect))
return;
omni_mutex_lock l(m_regionLock);
if (IntersectRect(&rect, &rect, &m_server->GetSharedRect()))
m_changed_rgn.AddRect(rect);
}
void
vncClient::UpdateRegion(vncRegion ®ion)
{
// Merge our current update region with the supplied one
if (region.IsEmpty())
return;
{
omni_mutex_lock l(m_regionLock);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -