玉兔远程控制 0.1.0-bate11
载入中...
搜索中...
未找到
BackendLibVNCServer.cpp
1#include <QApplication>
2#include <QImage>
3#include <QClipboard>
4#include <QNetworkProxy>
5#include <QInputDialog>
6#include <QLoggingCategory>
7
8#include "BackendLibVNCServer.h"
9#include "Channel.h"
10
11static Q_LOGGING_CATEGORY(log, "LibVNCServer.Backend")
12static Q_LOGGING_CATEGORY(logger, "LibVNCServer.Backend.log")
13static Q_LOGGING_CATEGORY(logKey, "LibVNCServer.Backend.Key")
14static Q_LOGGING_CATEGORY(logInputMethod, "LibVNCServer.Backend.InputMethod")
15static Q_LOGGING_CATEGORY(logMouse, "LibVNCServer.Backend.Mouse")
16
17const char* gThis = "This pointer";
18#define LOG_BUFFER_LENGTH 1024
19static void rfbQtClientLog(const char *format, ...)
20{
21 int nRet = 0;
22 va_list args;
23 char buf[LOG_BUFFER_LENGTH];
24
25 if(!rfbEnableClientLogging)
26 return;
27
28 va_start(args, format);
29 nRet = vsnprintf(buf, LOG_BUFFER_LENGTH, format, args);
30 va_end(args);
31 if(nRet < 0)
32 {
33 qCritical(log) << "vsnprintf fail";
34 return;
35 }
36 if(nRet >= LOG_BUFFER_LENGTH)
37 {
38 qCritical(log) << "vsprintf buf is short,"
39 << nRet << ">" << LOG_BUFFER_LENGTH
40 << ". Truncated it:" << nRet - LOG_BUFFER_LENGTH;
41 buf[LOG_BUFFER_LENGTH - 1] = 0;
42 }
43 qDebug(logger) << buf;
44}
45
46CBackendLibVNCServer::CBackendLibVNCServer(COperateLibVNCServer *pOperate)
47 : CBackendDesktop(pOperate),
48 m_pClient(nullptr),
49 m_pParameter(qobject_cast<CParameterLibVNCServer*>(pOperate->GetParameter()))
50#ifdef HAVE_LIBSSH
51 ,m_pThread(nullptr)
52#endif
53 , m_SecurityLevel(CSecurityLevel::Level::Risk)
54{
55 rfbClientLog = rfbQtClientLog;
56
57 if(!m_pParameter->GetLocalCursor())
58 {
59 emit sigUpdateCursor(QCursor(Qt::BlankCursor));
60 }
61}
62
63CBackendLibVNCServer::~CBackendLibVNCServer()
64{
65 qDebug(log) << "CConnectLibVNCServer::~CConnectLibVNCServer()";
66}
67
74CBackendLibVNCServer::OnInitReturnValue CBackendLibVNCServer::OnInit()
75{
76 qDebug(log) << "CConnectLibVNCServer::OnInit()";
77 if(m_pClient) Q_ASSERT(false);
78
79 m_pClient = rfbGetClient(8, 3, 4);
80 if(!m_pClient)
81 {
82 QString szErr;
83 szErr = tr("Protocol version error");
84 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
85 qCritical(log) << "rfbGetClient fail";
86 return OnInitReturnValue::Fail;
87 }
88
89 // Set parameters
90 m_pClient->programName = strdup(qApp->applicationName().toStdString().c_str());
91 m_pClient->appData.shareDesktop = m_pParameter->GetShared();
92 m_pClient->appData.viewOnly = m_pParameter->GetOnlyView();
93 m_pClient->appData.useRemoteCursor = m_pParameter->GetLocalCursor();
94
95 //Qt is support QImage::Format_RGB32, so we use default format QImage::Format_RGB32 in OnSize()
96 // m_pClient->appData.requestedDepth = m_pPara->nColorLevel;
97 // m_pClient->format.depth = m_pPara->nColorLevel;
98 // switch (m_pClient->format.depth) {
99 // case 8:
100 // m_pClient->format.depth = 8;
101 // m_pClient->format.bitsPerPixel = 8;
102 // m_pClient->format.blueMax = 3;
103 // m_pClient->format.blueShift = 6;
104 // m_pClient->format.greenMax = 7;
105 // m_pClient->format.greenShift = 3;
106 // m_pClient->format.redMax = 7;
107 // m_pClient->format.redShift = 0;
108 // break;
109 // case 16:
110 // m_pClient->format.depth = 15;
111 // m_pClient->format.bitsPerPixel = 16;
112 // m_pClient->format.redShift = 11;
113 // m_pClient->format.greenShift = 6;
114 // m_pClient->format.blueShift = 1;
115 // m_pClient->format.redMax = 31;
116 // m_pClient->format.greenMax = 31;
117 // m_pClient->format.blueMax = 31;
118 // break;
119 // case 32:
120 // default:
121 // m_pClient->format.depth = 24;
122 // m_pClient->format.bitsPerPixel = 32;
123 // m_pClient->format.blueShift = 0;
124 // m_pClient->format.redShift = 16;
125 // m_pClient->format.greenShift = 8;
126 // m_pClient->format.blueMax = 0xff;
127 // m_pClient->format.redMax = 0xff;
128 // m_pClient->format.greenMax = 0xff;
129 // break;
130 // }
131
132 m_pClient->appData.enableJPEG = m_pParameter->GetJpeg();
133 if(m_pClient->appData.enableJPEG)
134 m_pClient->appData.qualityLevel = m_pParameter->GetQualityLevel();
135 if(m_pParameter->GetEnableCompressLevel())
136 m_pClient->appData.compressLevel = m_pParameter->GetCompressLevel();
137
138 // Set callback function
139 m_pClient->MallocFrameBuffer = cb_resize;
140 m_pClient->GotFrameBufferUpdate = cb_update;
141 m_pClient->HandleKeyboardLedState = cb_kbd_leds;
142 m_pClient->Bell = cb_bell;
143 m_pClient->HandleTextChat = cb_text_chat;
144 m_pClient->GotXCutText = cb_got_selection;
145 m_pClient->GetCredential = cb_get_credential;
146 m_pClient->GetPassword = cb_get_password;
147 m_pClient->HandleCursorPos = cb_cursor_pos;
148 m_pClient->GotCursorShape = cb_got_cursor_shape;
149
150 m_pClient->canHandleNewFBSize = TRUE;
151 rfbClientSetClientData(m_pClient, (void*)gThis, this);
152
153 // Set sock
154 switch(m_pParameter->m_Proxy.GetUsedType())
155 {
156 case CParameterProxy::TYPE::None:
157 {
158 // Set server ip and port
159 if(m_pParameter->m_Net.GetHost().isEmpty())
160 {
161 QString szErr;
162 szErr = tr("The server is empty, please input it");
163 qCritical(log) << szErr;
164 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
165 return OnInitReturnValue::Fail;
166 }
167 auto &net = m_pParameter->m_Net;
168 m_pClient->serverHost = strdup(net.GetHost().toStdString().c_str());
169 m_pClient->serverPort = net.GetPort();
170
171 if(!rfbInitClient(m_pClient, nullptr, nullptr))
172 {
173 // Because delete m_pClient in rfbInitClient
174 m_pClient = nullptr;
175 QString szErr;
176 szErr = tr("Fail: Connect to %1:%2").arg(m_pParameter->m_Net.GetHost(),
177 QString::number(m_pParameter->m_Net.GetPort()));
178 qCritical(log) << szErr;
179 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
180 return OnInitReturnValue::Fail;
181 }
182
183 QString szInfo = QString("Connected to ") + m_pClient->desktopName;
184 qInfo(log) << szInfo;
185
186 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
187 emit sigServerName(m_pClient->desktopName);
188 emit sigInformation(szInfo);
189 emit sigSecurityLevel(m_SecurityLevel);
190 emit sigRunning();
191 return OnInitReturnValue::UseOnProcess;
192 }
193 /*case CParameterProxy::TYPE::SockesV5:
194 {
195 QNetworkProxy proxy;
196 proxy.setType(QNetworkProxy::Socks5Proxy);
197 auto &net = m_pParameter->m_Proxy.m_SockesV5;
198 proxy.setHostName(net.GetHost());
199 if(net.GetHost().isEmpty())
200 {
201 QString szErr;
202 szErr = tr("The proxy server is empty, please input it");
203 qCritical(log) << szErr;
204 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
205 return OnInitReturnValue::Fail;
206 }
207 proxy.setPort(net.GetPort());
208 auto &user = net.m_User;
209 proxy.setUser(user.GetUser());
210 proxy.setPassword(user.GetPassword());
211 m_tcpSocket.setProxy(proxy);
212 m_tcpSocket.connectToHost(m_pClient->serverHost, m_pClient->serverPort);
213 if (!m_tcpSocket.waitForConnected(3000))
214 return OnInitReturnValue::Fail;
215 //TODO: The is fail
216 m_pClient->sock = m_tcpSocket.socketDescriptor();
217 if(!rfbInitClient(m_pClient, nullptr, nullptr))
218 {
219 // Because delete m_pClient in rfbInitClient
220 m_pClient = nullptr;
221 QString szErr;
222 szErr = tr("Connect to %1:%2 fail").arg(m_pParameter->m_Net.GetHost(),
223 QString::number(m_pParameter->m_Net.GetPort()));
224 qCritical(log) << szErr;
225 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
226 return OnInitReturnValue::Fail;
227 }
228 break;
229 }//*/
230 /*TODO: add UltraVncRepeater
231 case (CParameterOperate::emProxy) CParameterLibVNCServer::emVncProxy::UltraVncRepeater:
232 m_pClient->destHost = strdup(m_pPara->GetProxyHost().toStdString().c_str());
233 m_pClient->destPort = m_pPara->GetProxyPort();//*/
234
236#ifdef HAVE_LIBSSH
237 case CParameterProxy::TYPE::SSHTunnel:
238 {
239 // Start ssh thread
240 if(!m_pThread) {
241 // Don' t delete it, It deletes itself when it ends. See: CSSHTunnelThread::CSSHTunnelThread()
242 m_pThread = new CSSHTunnelThread(
243 &m_pParameter->m_Proxy.m_SSH, &m_pParameter->m_Net, this);
244 }
245 if(!m_pThread)
246 return OnInitReturnValue::Fail;
247 bool check = connect(m_pThread, SIGNAL(sigServer(QString, quint16)),
248 this, SLOT(slotConnectProxyServer(QString, quint16)));
249 Q_ASSERT(check);
250#if defined(HAVE_UNIX_DOMAIN_SOCKET)
251 check = connect(m_pThread, SIGNAL(sigServer(QString)),
252 this, SLOT(slotConnectProxyServer(QString)));
253 Q_ASSERT(check);
254#endif
255 check = connect(m_pThread, SIGNAL(sigError(int,QString)),
256 this, SIGNAL(sigError(int,QString)));
257 Q_ASSERT(check);
258 check = connect(m_pThread, SIGNAL(sigStop()),
259 this, SIGNAL(sigStop()));
260 Q_ASSERT(check);
261 m_pThread->start();
262
263 return OnInitReturnValue::NotUseOnProcess;
264 }
265#endif // #ifdef HAVE_LIBSSH
267 default:
268 break;
269 }
270
271 return OnInitReturnValue::UseOnProcess;
272}
273
275{
276 qDebug(log) << "CConnectLibVNCServer::OnClean()";
277#ifdef HAVE_LIBSSH
278 if(m_pThread)
279 {
280 disconnect(m_pThread);
281 m_pThread->Exit();
282 m_pThread = nullptr;
283 }
284#endif
285 if(m_pClient)
286 {
287 //m_tcpSocket.close();
288 rfbClientCleanup(m_pClient);
289 m_pClient = nullptr;
290 }
291
292 emit sigFinished();
293 return 0;
294}
295
310{
311 //qDebug(log) << Q_FUNC_INFO;
312 int nRet = 0;
313 if(!m_pClient)
314 {
315 // Stop
316 return -1;
317 }
318
319 struct timeval timeout = {0, DEFAULT_TIMEOUT};
320 fd_set set;
321 FD_ZERO(&set);
322 if(RFB_INVALID_SOCKET != m_pClient->sock)
323 {
324 FD_SET(m_pClient->sock, &set);
325 }
326 rfbSocket eventFd = m_Event.GetFd();
327 if(RFB_INVALID_SOCKET != eventFd)
328 {
329 FD_SET(eventFd, &set);
330 }
331 rfbSocket fd = RFB_INVALID_SOCKET;
332 fd = std::max(eventFd, m_pClient->sock);
333 //qDebug(log) << "fd:" << fd << "select m_pClient->sock:" << (int)m_pClient->sock << "event:" << eventFd;
334 nRet = select(fd + 1, &set, NULL, NULL, &timeout);
335 //qDebug(log) << "select end";
336 if (nRet < 0) {
337 qCritical(log) << "select fail:" << nRet << "errno" << errno << strerror(errno);
338 return nRet;
339 }
340
341 /*if(0 == nRet)
342 {
343 //qDebug(log) << "Time out";
344 return 0;
345 }//*/
346
347 if(RFB_INVALID_SOCKET != eventFd && FD_ISSET(eventFd, &set))
348 {
349 //qDebug(log) << "fires event";
350 m_Event.Reset();
351 }
352
353 if(RFB_INVALID_SOCKET != m_pClient->sock
354 && FD_ISSET(m_pClient->sock, &set)) {
355 //qDebug(log) << "HandleRFBServerMessage";
356 if(!HandleRFBServerMessage(m_pClient))
357 {
358 qCritical(log) << "HandleRFBServerMessage fail";
359 return -2;
360 }
361 }
362
363 return 0;
364}
365
367{
368 return m_Event.WakeUp();
369}
370
372{
373 if(!m_pParameter || !m_pParameter->GetClipboard() || !m_pClient) return;
374 QClipboard* pClipboard = QApplication::clipboard();
375 if(pClipboard)
376 {
377 QString szText = pClipboard->text();
378 if(!szText.isEmpty() && m_pClient)
379 SendClientCutText(m_pClient,
380 (char*)szText.toStdString().c_str(),
381 szText.toStdString().length());
382 }
383}
384
385rfbBool CBackendLibVNCServer::cb_resize(rfbClient* client)
386{
387 //qDebug(log) << "CConnectLibVnc::cb_resize:" << client->width << client->height;
388 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
389 if(pThis->OnSize()) return FALSE;
390 return TRUE;
391}
392
393void CBackendLibVNCServer::cb_update(rfbClient *client, int x, int y, int w, int h)
394{
395 if(0 == w || 0 == h)
396 return;
397 //qDebug(LibVNCServer, "CConnectLibVnc::cb_update:(%d, %d, %d, %d)", x, y, w, h);
398 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
399 QRect rect(x, y, w, h);
400 QImage img = pThis->m_Image.copy(rect);
401 emit pThis->sigUpdateRect(rect, img);
402}
403
404void CBackendLibVNCServer::cb_got_selection(rfbClient *client, const char *text, int len)
405{
406 //qDebug(LibVNCServer, "CConnectLibVnc::cb_got_selection:%s", text);
407 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
408 if(!pThis->m_pParameter->GetClipboard()) return;
409 QClipboard* pClipboard = QApplication::clipboard();
410 if(pClipboard)
411 pClipboard->setText(text);
412}
413
414void CBackendLibVNCServer::cb_kbd_leds(rfbClient *client, int value, int pad)
415{
416 qDebug(log) << "CConnectLibVnc::cb_kbd_leds";
417}
418
419void CBackendLibVNCServer::cb_bell(struct _rfbClient *client)
420{
421 qApp->beep();
422}
423
424void CBackendLibVNCServer::cb_text_chat(rfbClient *client, int value, char *text)
425{
426 qDebug(log) << "CConnectLibVnc::cb_text_chat";
427}
428
429rfbCredential* CBackendLibVNCServer::cb_get_credential(rfbClient *cl, int credentialType)
430{
431 qDebug(log) <<"CConnectLibVnc::cb_get_credential";
432 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(cl, (void*)gThis);
433 rfbCredential *c = (rfbCredential*)malloc(sizeof(rfbCredential));
434 c->userCredential.username = (char*)malloc(RFB_BUF_SIZE);
435 memset(c->userCredential.username, 0, RFB_BUF_SIZE);
436 c->userCredential.password = (char*)malloc(RFB_BUF_SIZE);
437 memset(c->userCredential.password, 0, RFB_BUF_SIZE);
438
439 if(credentialType != rfbCredentialTypeUser) {
440 qCritical(log) << "something else than username and password required for authentication";
441 return NULL;
442 }
443
444 qDebug(log) << "Username and password required for authentication!";
445
446 memcpy(c->userCredential.username,
447 pThis->m_pParameter->m_Net.m_User.GetUser().toStdString().c_str(),
448 pThis->m_pParameter->m_Net.m_User.GetUser().toStdString().length());
449 memcpy(c->userCredential.password,
450 pThis->m_pParameter->m_Net.m_User.GetPassword().toStdString().c_str(),
451 pThis->m_pParameter->m_Net.m_User.GetPassword().toStdString().length());
452
453 return c;
454}
455
456char* CBackendLibVNCServer::cb_get_password(rfbClient *client)
457{
458 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
459 QString szPassword = pThis->m_pParameter->m_Net.m_User.GetPassword();
460 if(szPassword.isEmpty())
461 {
462 int nRet = QDialog::Rejected;
463 auto *net = &pThis->m_pParameter->m_Net;
464 emit pThis->sigBlockShowWidget("CDlgUserPassword", nRet, net);
465 if(QDialog::Accepted == nRet)
466 {
467 szPassword = net->m_User.GetPassword();
468 }
469 }
470 if(!szPassword.isEmpty())
471 pThis->m_SecurityLevel |= CSecurityLevel::Level::Authentication;
472 return strdup(szPassword.toStdString().c_str());
473}
474
475int CBackendLibVNCServer::OnSize()
476{
477 int nRet = 0;
478 int nWidth = m_pClient->width;
479 int nHeight = m_pClient->height;
480
481 m_Image = QImage(nWidth, nHeight, QImage::Format_RGB32);
482
483 m_pClient->frameBuffer = m_Image.bits();
484
485 m_pClient->format.bitsPerPixel = 32;
486 m_pClient->format.depth = m_Image.depth();
487 m_pClient->format.redShift = 16;
488 m_pClient->format.greenShift = 8;
489 m_pClient->format.blueShift = 0;
490 m_pClient->format.redMax = 255;
491 m_pClient->format.greenMax = 255;
492 m_pClient->format.blueMax = 255;
493 SetFormatAndEncodings(m_pClient);
494
495 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
496 return nRet;
497}
498
499rfbBool CBackendLibVNCServer::cb_cursor_pos(rfbClient *client, int x, int y)
500{
501 //qDebug(LibVNCServer, "CConnectLibVnc::cb_cursor_pos:%d,%d", x, y);
502 rfbBool bRet = true;
503
504 return bRet;
505}
506
507void CBackendLibVNCServer::cb_got_cursor_shape(rfbClient *client,
508 int xhot, int yhot,
509 int width, int height,
510 int bytesPerPixel)
511{
512 /*
513 qDebug(LibVNCServer, "CConnectLibVnc::cb_got_cursor_shape:x:%d, y:%d, width:%d, height:%d, bytesPerPixel:%d",
514 xhot, yhot, width, height, bytesPerPixel);//*/
515 if(!client->rcSource)
516 {
517 qCritical(log) << "client->rcSource is null";
518 return;
519 }
520 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
521 if ((width == 0) || (height == 0)) {
522 QImage cursor(1, 1, QImage::Format_ARGB32);
523 uchar* buffer = cursor.bits();
524 memset(buffer, 0, 4);
525 emit pThis->sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), xhot, yhot));
526 } else {
527 switch (bytesPerPixel) {
528 case 4:
529 {
530 QImage cursor(width, height, QImage::Format_ARGB32);
531 uchar *buffer = cursor.bits();
532 memcpy(buffer, client->rcSource, width * height * 4);
533 uchar* pMask = client->rcMask;
534 if(pMask)
535 {
536 uchar* pDest = buffer;
537 for(int y = 0; y < height; y++)
538 {
539 for(int w = 0; w < width; w++)
540 {
541 if(*pMask++)
542 {
543 // NOTE: Do not manipulate the memory,
544 // because the host byte order may be different
545 QColor c = cursor.pixel(w, y);
546 c.setAlpha(0xff);
547 cursor.setPixelColor(w,y,c);
548 }
549 else
550 *((uint32_t*)pDest) = 0;
551
552 pDest += 4;
553 }
554 }
555 }
556 emit pThis->sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), xhot, yhot));
557 break;
558 }
559 default:
560 break;
561 }
562 }
563}
564
565void CBackendLibVNCServer::mousePressEvent(QMouseEvent *event)
566{
567 if(!m_pClient) return;
568 if(m_pParameter && m_pParameter->GetOnlyView()) return;
569
570 unsigned char mask = 0;
571 if(event->button() & Qt::MouseButton::LeftButton)
572 mask |= 0x1;
573 if(event->button() & Qt::MouseButton::MiddleButton)
574 mask |= 0x2;
575 if(event->button() & Qt::MouseButton::RightButton)
576 mask |= 0x4;
577 if(event->button() & Qt::MouseButton::BackButton)
578 mask |= 0x80;
579 QPoint pos = event->pos();
580
581 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
582
583 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
584}
585
586void CBackendLibVNCServer::mouseReleaseEvent(QMouseEvent *event)
587{
588 if(!m_pClient) return;
589 if(m_pParameter && m_pParameter->GetOnlyView()) return;
590 int mask = 0;
591 QPoint pos = event->pos();
592 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
593 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
594}
595
596void CBackendLibVNCServer::mouseMoveEvent(QMouseEvent *event)
597{
598 if(!m_pClient) return;
599 if(m_pParameter && m_pParameter->GetOnlyView()) return;
600 int mask = 0;
601 if(event->buttons() & Qt::MouseButton::LeftButton)
602 mask |= 0x1;
603 if(event->buttons() & Qt::MouseButton::MiddleButton)
604 mask |= 0x2;
605 if(event->buttons() & Qt::MouseButton::RightButton)
606 mask |= 0x4;
607 if(event->buttons() & Qt::MouseButton::BackButton)
608 mask |= 0x80;
609 QPoint pos = event->pos();
610 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
611 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
612}
613
614// https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#pointerevent
615void CBackendLibVNCServer::wheelEvent(QWheelEvent *event)
616{
617 if(!m_pClient) return;
618 if(m_pParameter && m_pParameter->GetOnlyView()) return;
619 int mask = 0;
620 if(event->buttons() & Qt::MouseButton::LeftButton)
621 mask |= 0x1;
622 if(event->buttons() & Qt::MouseButton::MiddleButton)
623 mask |= 0x2;
624 if(event->buttons() & Qt::MouseButton::RightButton)
625 mask |= 0x4;
626 if(event->buttons() & Qt::MouseButton::BackButton)
627 mask |= 0x80;
628
629 QPoint d = event->angleDelta();
630 if(d.y() > 0)
631 mask |= 0x8;
632 if(d.y() < 0)
633 mask |= 0x10;
634 if(d.x() < 0)
635 mask |= 0x20;
636 if(d.x() > 0)
637 mask |= 0x40;
638
639 QPointF pos;
640#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
641 pos = event->position();
642#else
643 pos = event->pos();
644#endif
645
646 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->angleDelta() << pos;
647
648 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
649}
650
658uint32_t TranslateRfbKey(quint32 inkey, bool modifier)
659{
660 quint32 k = 5000;
661
662 switch (inkey)
663 {
664 case Qt::Key_Backspace: k = XK_BackSpace; break;
665 case Qt::Key_Tab: k = XK_Tab; break;
666 case Qt::Key_Clear: k = XK_Clear; break;
667 case Qt::Key_Return: k = XK_Return; break;
668 case Qt::Key_Pause: k = XK_Pause; break;
669 case Qt::Key_Escape: k = XK_Escape; break;
670 case Qt::Key_Space: k = XK_space; break;
671 case Qt::Key_Delete: k = XK_Delete; break;
672 case Qt::Key_Period: k = XK_period; break;
673
674 /* International & multi-key character composition */
675 case Qt::Key_Multi_key: k = XK_Multi_key; break;
676 case Qt::Key_SingleCandidate: k = XK_SingleCandidate; break;
677 case Qt::Key_MultipleCandidate: k = XK_MultipleCandidate; break;
678 case Qt::Key_PreviousCandidate: k = XK_PreviousCandidate; break;
679
680 /* Japanese keyboard support */
681 case Qt::Key_Kanji: k = XK_Kanji; break;
682 case Qt::Key_Muhenkan: k = XK_Muhenkan; break;
683 case Qt::Key_Henkan: k = XK_Henkan; break;
684 case Qt::Key_Romaji: k = XK_Romaji; break;
685 case Qt::Key_Hiragana: k = XK_Hiragana; break;
686 case Qt::Key_Katakana: k = XK_Katakana; break;
687 case Qt::Key_Hiragana_Katakana: k = XK_Hiragana_Katakana;break;
688 case Qt::Key_Zenkaku: k = XK_Zenkaku; break;
689 case Qt::Key_Hankaku: k = XK_Hankaku; break;
690 case Qt::Key_Zenkaku_Hankaku: k = XK_Zenkaku_Hankaku; break;
691 case Qt::Key_Touroku: k = XK_Touroku; break;
692 case Qt::Key_Massyo: k = XK_Massyo; break;
693 case Qt::Key_Kana_Lock: k = XK_Kana_Lock; break;
694 case Qt::Key_Kana_Shift: k = XK_Kana_Shift; break;
695 case Qt::Key_Eisu_Shift: k = XK_Eisu_Shift; break;
696 case Qt::Key_Eisu_toggle: k = XK_Eisu_toggle; break;
697
698 //special keyboard char
699 case Qt::Key_Exclam: k = XK_exclam; break;
700 case Qt::Key_QuoteDbl: k = XK_quotedbl; break; //"
701 case Qt::Key_NumberSign: k = XK_numbersign; break; //#
702 case Qt::Key_Percent: k = XK_percent; break; //%
703 case Qt::Key_Dollar: k = XK_dollar; break; //$
704 case Qt::Key_Ampersand: k = XK_ampersand; break; //&
705 case Qt::Key_Apostrophe: k = XK_apostrophe; break;
706 case Qt::Key_ParenLeft: k = XK_parenleft; break; // (
707 case Qt::Key_ParenRight: k = XK_parenright; break; // )
708
709 case Qt::Key_Slash: k = XK_slash; break; // /
710 case Qt::Key_Asterisk: k = XK_asterisk; break; //*
711 case Qt::Key_Minus: k = XK_minus; break; //-
712 case Qt::Key_Plus: k = XK_plus; break; //+
713 case Qt::Key_Enter: k = XK_Return; break; //
714 case Qt::Key_Equal: k = XK_equal; break; //=
715 case Qt::Key_Comma: return XK_comma; //,
716
717 case Qt::Key_Colon: k = XK_colon;break; // :
718 case Qt::Key_Semicolon: k = XK_semicolon; break; //;
719 case Qt::Key_Less: k = XK_less; break; // <
720 case Qt::Key_Greater: k = XK_greater; break; // >
721 case Qt::Key_Question: k = XK_question; break; //?
722 case Qt::Key_At: k = XK_at; break; //@
723
724 case Qt::Key_BracketLeft: k = XK_bracketleft; break;
725 case Qt::Key_Backslash: k = XK_backslash;break;
726 case Qt::Key_BracketRight: k = XK_bracketright;break;
727 case Qt::Key_AsciiCircum: k = XK_asciicircum;break;
728 case Qt::Key_Underscore: k = XK_underscore;break;
729 case Qt::Key_QuoteLeft: k = XK_quoteleft;break;
730 case Qt::Key_BraceLeft: k = XK_braceleft;break;
731 case Qt::Key_Bar: k = XK_bar; break;
732 case Qt::Key_BraceRight: k = XK_braceright;break;
733 case Qt::Key_AsciiTilde: k = XK_asciitilde;break;
734 case Qt::Key_nobreakspace: k = XK_nobreakspace;break;
735 case Qt::Key_exclamdown: k = XK_exclamdown;break;
736 case Qt::Key_cent: k = XK_cent;break;
737 case Qt::Key_sterling: k = XK_sterling;break;
738 case Qt::Key_currency: k = XK_currency;break;
739 case Qt::Key_yen: k = XK_yen;break;
740 case Qt::Key_brokenbar: k = XK_brokenbar;break;
741 case Qt::Key_section: k = XK_section;break;
742 case Qt::Key_diaeresis: k = XK_diaeresis;break;
743 case Qt::Key_copyright: k = XK_copyright; break;
744 case Qt::Key_ordfeminine: k = XK_ordfeminine; break;
745 case Qt::Key_guillemotleft: k = XK_guillemotleft; break;
746 case Qt::Key_guillemotright: k = XK_guillemotright; break;
747 case Qt::Key_notsign: k = XK_notsign; break;
748 case Qt::Key_hyphen: k = XK_hyphen; break;
749 case Qt::Key_registered: k = XK_registered; break;
750
751 case Qt::Key_Up: k = XK_Up; break;
752 case Qt::Key_Down: k = XK_Down; break;
753 case Qt::Key_Right: k = XK_Right; break;
754 case Qt::Key_Left: k = XK_Left; break;
755 case Qt::Key_Insert: k = XK_Insert; break;
756 case Qt::Key_Home: k = XK_Home; break;
757 case Qt::Key_End: k = XK_End; break;
758 case Qt::Key_PageUp: k = XK_Page_Up; break;
759 case Qt::Key_PageDown: k = XK_Page_Down; break;
760 case Qt::Key_MediaPrevious: k = XK_Prior; break;
761 case Qt::Key_MediaNext: k = XK_Next; break;
762 case Qt::Key_MediaPlay: k = XK_Begin; break;
763
764 /* Misc Functions */
765 case Qt::Key_Select: k = XK_Select; break;
766 case Qt::Key_Printer: k = XK_Print; break;
767 case Qt::Key_Execute: k = XK_Execute; break;
768 case Qt::Key_Undo: k = XK_Undo; break;
769 case Qt::Key_Redo: k = XK_Redo; break;
770 case Qt::Key_Menu: k = XK_Menu;break;
771 case Qt::Key_Find: k = XK_Find; break;
772 case Qt::Key_Exit:
773 case Qt::Key_Cancel:
774 case Qt::Key_Stop:
775 k = XK_Cancel;
776 break;
777 case Qt::Key_Mode_switch: k = XK_Mode_switch; break;
778
779 case Qt::Key_F1: k = XK_F1; break;
780 case Qt::Key_F2: k = XK_F2; break;
781 case Qt::Key_F3: k = XK_F3; break;
782 case Qt::Key_F4: k = XK_F4; break;
783 case Qt::Key_F5: k = XK_F5; break;
784 case Qt::Key_F6: k = XK_F6; break;
785 case Qt::Key_F7: k = XK_F7; break;
786 case Qt::Key_F8: k = XK_F8; break;
787 case Qt::Key_F9: k = XK_F9; break;
788 case Qt::Key_F10: k = XK_F10; break;
789 case Qt::Key_F11: k = XK_F11; break;
790 case Qt::Key_F12: k = XK_F12; break;
791 case Qt::Key_F13: k = XK_F13; break;
792 case Qt::Key_F14: k = XK_F14; break;
793 case Qt::Key_F15: k = XK_F15; break;
794 case Qt::Key_F16: k = XK_F16; break;
795 case Qt::Key_F17: k = XK_F17; break;
796 case Qt::Key_F18: k = XK_F18; break;
797 case Qt::Key_F19: k = XK_F19; break;
798 case Qt::Key_F20: k = XK_F20; break;
799 case Qt::Key_F21: k = XK_F21; break;
800 case Qt::Key_F22: k = XK_F22; break;
801 case Qt::Key_F23: k = XK_F23; break;
802 case Qt::Key_F24: k = XK_F24; break;
803 case Qt::Key_F25: k = XK_F25; break;
804 case Qt::Key_F26: k = XK_F26; break;
805 case Qt::Key_F27: k = XK_F27; break;
806 case Qt::Key_F28: k = XK_F28; break;
807 case Qt::Key_F29: k = XK_F29; break;
808 case Qt::Key_F30: k = XK_F30; break;
809 case Qt::Key_F31: k = XK_F31; break;
810 case Qt::Key_F32: k = XK_F32; break;
811 case Qt::Key_F33: k = XK_F33; break;
812 case Qt::Key_F34: k = XK_F34; break;
813 case Qt::Key_F35: k = XK_F35; break;
814
815 case Qt::Key_NumLock: k = XK_Num_Lock; break;
816 case Qt::Key_CapsLock: k = XK_Caps_Lock; break;
817 case Qt::Key_ScrollLock: k = XK_Scroll_Lock; break;
818
819 case Qt::Key_Shift: k = XK_Shift_R; break; //k = XK_Shift_L; break;
820 case Qt::Key_Control: k = XK_Control_R; break;// k = XK_Control_L; break;
821 case Qt::Key_Alt: k = XK_Alt_R; break;//k = XK_Alt_L; break;
822 case Qt::Key_Meta: k = XK_Meta_R; break;//k = XK_Meta_L; break;*/
823
824 case Qt::Key_Super_L: k = XK_Super_L; break; /* left "windows" key */
825 case Qt::Key_Super_R: k = XK_Super_R; break; /* right "windows" key */
826
827 case Qt::Key_Help: k = XK_Help; break;
828 case Qt::Key_Print: k = XK_Print; break;
829 case Qt::Key_SysReq: k = XK_Sys_Req; break;
830 case Qt::Key_0: k = XK_0;break;
831 case Qt::Key_1: k = XK_1;break;
832 case Qt::Key_2: k = XK_2;break;
833 case Qt::Key_3: k = XK_3;break;
834 case Qt::Key_4: k = XK_4;break;
835 case Qt::Key_5: k = XK_5;break;
836 case Qt::Key_6: k = XK_6;break;
837 case Qt::Key_7: k = XK_7;break;
838 case Qt::Key_8: k = XK_8;break;
839 case Qt::Key_9: k = XK_9;break;
840 }
841
842 if (k == 5000)
843 {
844
845 if (!modifier)
846 {
847 switch (inkey)
848 {
849 case Qt::Key_A: k = XK_a;break;
850 case Qt::Key_B: k = XK_b;break;
851 case Qt::Key_C: k = XK_c;break;
852 case Qt::Key_D: k = XK_d;break;
853 case Qt::Key_E: k = XK_e;break;
854 case Qt::Key_F: k = XK_f;break;
855 case Qt::Key_G: k = XK_g;break;
856 case Qt::Key_H: k = XK_h;break;
857 case Qt::Key_I: k = XK_i;break;
858 case Qt::Key_J: k = XK_j;break;
859 case Qt::Key_K: k = XK_k;break;
860 case Qt::Key_L: k = XK_l;break;
861 case Qt::Key_M: k = XK_m;break;
862 case Qt::Key_N: k = XK_n;break;
863 case Qt::Key_O: k = XK_o;break;
864 case Qt::Key_P: k = XK_p;break;
865 case Qt::Key_Q: k = XK_q;break;
866 case Qt::Key_R: k = XK_r;break;
867 case Qt::Key_S: k = XK_s;break;
868 case Qt::Key_T: k = XK_t;break;
869 case Qt::Key_U: k = XK_u;break;
870 case Qt::Key_V: k = XK_v;break;
871 case Qt::Key_W: k = XK_w;break;
872 case Qt::Key_X: k = XK_x;break;
873 case Qt::Key_Y: k = XK_y;break;
874 case Qt::Key_Z: k = XK_z;break;
875 }
876 }
877 else
878 {
879 switch (inkey)
880 {
881 case Qt::Key_A: k = XK_A;break;
882 case Qt::Key_B: k = XK_B;break;
883 case Qt::Key_C: k = XK_C;break;
884 case Qt::Key_D: k = XK_D;break;
885 case Qt::Key_E: k = XK_E;break;
886 case Qt::Key_F: k = XK_F;break;
887 case Qt::Key_G: k = XK_G;break;
888 case Qt::Key_H: k = XK_H;break;
889 case Qt::Key_I: k = XK_I;break;
890 case Qt::Key_J: k = XK_J;break;
891 case Qt::Key_K: k = XK_K;break;
892 case Qt::Key_L: k = XK_L;break;
893 case Qt::Key_M: k = XK_M;break;
894 case Qt::Key_N: k = XK_N;break;
895 case Qt::Key_O: k = XK_O;break;
896 case Qt::Key_P: k = XK_P;break;
897 case Qt::Key_Q: k = XK_Q;break;
898 case Qt::Key_R: k = XK_R;break;
899 case Qt::Key_S: k = XK_S;break;
900 case Qt::Key_T: k = XK_T;break;
901 case Qt::Key_U: k = XK_U;break;
902 case Qt::Key_V: k = XK_V;break;
903 case Qt::Key_W: k = XK_W;break;
904 case Qt::Key_X: k = XK_X;break;
905 case Qt::Key_Y: k = XK_Y;break;
906 case Qt::Key_Z: k = XK_Z;break;
907 }
908 }
909 }
910
911 return k;
912}
913
914void CBackendLibVNCServer::keyPressEvent(QKeyEvent *event)
915{
916 if(!m_pClient) return;
917 if(m_pParameter && m_pParameter->GetOnlyView()) return;
918 bool modifier = false;
919 if (event->modifiers() & Qt::ShiftModifier)
920 modifier = true;
921 uint32_t k = TranslateRfbKey(event->key(), modifier);
922 qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
923 SendKeyEvent(m_pClient, k, TRUE);
924}
925
926void CBackendLibVNCServer::keyReleaseEvent(QKeyEvent *event)
927{
928 if(!m_pClient) return;
929 if(m_pParameter && m_pParameter->GetOnlyView()) return;
930 bool modifier = false;
931 if (event->modifiers() & Qt::ShiftModifier)
932 modifier = true;
933 uint32_t k = TranslateRfbKey(event->key(), modifier);
934 qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
935 SendKeyEvent(m_pClient, k, FALSE);
936}
937
938void CBackendLibVNCServer::InputMethodEvent(QInputMethodEvent *event)
939{
940}
941
943void CBackendLibVNCServer::slotConnectProxyServer(QString szHost, quint16 nPort)
944{
945 QString szErr;
946 auto &net = m_pParameter->m_Proxy.m_SSH.m_Net;
947 //qDebug(log) << "CConnectLibVNCServer::slotConnectServer" << nPort;
948 // Set server ip and port
949 m_pClient->serverHost = strdup(szHost.toStdString().c_str());
950 m_pClient->serverPort = nPort;
951 szErr = tr("Will connect to local socket server: %1:%2")
952 .arg(m_pClient->serverHost,
953 QString::number(m_pClient->serverPort));
954 qDebug(log) << szErr;
955 if(!rfbInitClient(m_pClient, nullptr, nullptr))
956 {
957 // Because delete m_pClient in rfbInitClient
958 m_pClient = nullptr;
959 QString szErr;
960 szErr = tr("Fail: Connect to %1:%2 <- %3:%4 <- %5:%6")
961 .arg(m_pParameter->m_Net.GetHost(),
962 QString::number(m_pParameter->m_Net.GetPort()),
963 net.GetHost(), QString::number(net.GetPort()),
964 szHost, QString::number(nPort)
965 );
966 qCritical(log) << szErr;
967 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
968 return;
969 }
970
971 QString szInfo = QString("Connected to %1 <- %2:%3 <- %4:%5")
972 .arg(m_pClient->desktopName,
973 net.GetHost(), QString::number(net.GetPort()),
974 szHost, QString::number(nPort));
975 qInfo(log) << szInfo;
976 slotTimeOut();
977 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
978 emit sigServerName(m_pClient->desktopName);
979 emit sigInformation(szInfo);
980 emit sigSecurityLevel(m_SecurityLevel |= CSecurityLevel::Level::Proxy);
981 emit sigRunning();
982}
983
984#if defined(HAVE_UNIX_DOMAIN_SOCKET)
986{
987 QString szErr;
988 //qDebug(log) << "CConnectLibVNCServer::slotConnectServer" << szFile;
989 // Set server ip and port
990 m_pClient->serverHost = strdup(szFile.toStdString().c_str());
991 szErr = tr("Will connect to local socket server: ") + szFile;
992 qDebug(log) << szErr;
993 if(!rfbInitClient(m_pClient, nullptr, nullptr))
994 {
995 // Because delete m_pClient in rfbInitClient
996 m_pClient = nullptr;
997 QString szErr;
998 szErr = tr("Fail: Connect to %1:%2 with %3")
999 .arg(m_pParameter->m_Net.GetHost(),
1000 QString::number(m_pParameter->m_Net.GetPort()),
1001 szFile);
1002 qCritical(log) << szErr;
1003 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
1004 return;
1005 }
1006
1007 QString szInfo = QString("Connected to ") + m_pClient->desktopName + " with " + szFile;
1008 qInfo(log) << szInfo;
1009
1010 slotTimeOut();
1011 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
1012 emit sigServerName(m_pClient->desktopName);
1013 emit sigInformation(szInfo);
1014 emit sigRunning();
1015}
1016#endif
远程桌面接口。它由协议插件实现。
void sigUpdateRect(const QRect &r, const QImage &image)
通知视图,图像更新
virtual int OnClean() override
清理
void slotConnectProxyServer(QString szHost, quint16 nPort)
[connect local socket server]
virtual int WakeUp() override
唤醒后台线程。
virtual void slotClipBoardChanged() override
当剪切板发生改变时调用
virtual OnInitReturnValue OnInit() override
virtual int OnProcess() override
插件连接的具体操作处理。因为此插件是非Qt事件,所以在此函数中等待。
void sigInformation(const QString &szInfo)
从后台线程中触发在主线程中显示信息,不阻塞后台线程
void sigStop()
需要通知用户停止时触发。仅由插件触发。 当从插件中需要停止时触发。例如:对端断开连接、重置连接或者连接出错。
void sigShowMessageBox(const QString &szTitle, const QString &szMessage, const QMessageBox::Icon &icon=QMessageBox::Information)
从后台线程中触发在主线程中显示消息对话框(QMessageBox),不阻塞后台线程
void sigError(const int nError, const QString &szError=QString())
当有错误产生时触发
void sigRunning()
当插件开始成功后触发。仅由插件触发
void sigFinished()
停止成功信号。仅由插件触发
virtual void slotTimeOut()
一个非 Qt 事件处理,它调用 OnProcess(),并根据其返回值开始新的定时器。 如果是不是一个非 Qt 事件循环(就是普通的循环处理), 可以重载它,或者 OnInit() 返回值 OnInit...
void sigSecurityLevel(CSecurityLevel::Levels level)
当安全级别改变时触发
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
阻塞后台线程,并在前台线程中显示窗口。
CParameterUser m_User
[Instance user]
实现通过本地 SOCKET 与 SSH 隧道转发数据。适用于库没有实现传输层接口,只有 socket 的情况。
安全级别
定义 Stats.h:97