玉兔远程控制 0.1.0-bate16
载入中...
搜索中...
未找到
BackendLibVNCServer.cpp
1#include <QApplication>
2#include <QImage>
3#include <QClipboard>
4#include <QNetworkProxy>
5#include <QInputDialog>
6#include <QLoggingCategory>
7
8#include "Channel.h"
9#include "ConvertKeyCode.h"
10#include "BackendLibVNCServer.h"
11
12static Q_LOGGING_CATEGORY(log, "LibVNCServer.Backend")
13static Q_LOGGING_CATEGORY(logger, "LibVNCServer.Backend.log")
14static Q_LOGGING_CATEGORY(logKey, "LibVNCServer.Backend.Key")
15static Q_LOGGING_CATEGORY(logInputMethod, "LibVNCServer.Backend.InputMethod")
16static Q_LOGGING_CATEGORY(logMouse, "LibVNCServer.Backend.Mouse")
17
18const char* gThis = "This pointer";
19#define LOG_BUFFER_LENGTH 1024
20static void rfbQtClientLog(const char *format, ...)
21{
22 int nRet = 0;
23 va_list args;
24 char buf[LOG_BUFFER_LENGTH];
25
26 if(!rfbEnableClientLogging)
27 return;
28
29 va_start(args, format);
30 nRet = vsnprintf(buf, LOG_BUFFER_LENGTH, format, args);
31 va_end(args);
32 if(nRet < 0)
33 {
34 qCritical(log) << "vsnprintf fail";
35 return;
36 }
37 if(nRet >= LOG_BUFFER_LENGTH)
38 {
39 qCritical(log) << "vsprintf buf is short,"
40 << nRet << ">" << LOG_BUFFER_LENGTH
41 << ". Truncated it:" << nRet - LOG_BUFFER_LENGTH;
42 buf[LOG_BUFFER_LENGTH - 1] = 0;
43 }
44 qDebug(logger) << buf;
45}
46
47CBackendLibVNCServer::CBackendLibVNCServer(COperateLibVNCServer *pOperate)
48 : CBackendDesktop(pOperate),
49 m_pClient(nullptr),
50 m_pParameter(qobject_cast<CParameterLibVNCServer*>(pOperate->GetParameter()))
51#ifdef HAVE_LIBSSH
52 ,m_pThread(nullptr)
53#endif
54 , m_SecurityLevel(CSecurityLevel::Level::Risk)
55{
56 rfbClientLog = rfbQtClientLog;
57
58 if(!m_pParameter->GetLocalCursor())
59 {
60 emit sigUpdateCursor(QCursor(Qt::BlankCursor));
61 }
62}
63
64CBackendLibVNCServer::~CBackendLibVNCServer()
65{
66 qDebug(log) << "CConnectLibVNCServer::~CConnectLibVNCServer()";
67}
68
75CBackendLibVNCServer::OnStartReturnValue CBackendLibVNCServer::OnStart()
76{
77 qDebug(log) << "CConnectLibVNCServer::OnStart()";
78 if(m_pClient) Q_ASSERT(false);
79
80 m_pClient = rfbGetClient(8, 3, 4);
81 if(!m_pClient)
82 {
83 QString szErr;
84 szErr = tr("Protocol version error");
85 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
86 qCritical(log) << "rfbGetClient fail";
87 return OnStartReturnValue::Fail;
88 }
89
90 // Set parameters
91 m_pClient->programName = strdup(qApp->applicationName().toStdString().c_str());
92 m_pClient->appData.shareDesktop = m_pParameter->GetShared();
93 m_pClient->appData.viewOnly = m_pParameter->GetOnlyView();
94 m_pClient->appData.useRemoteCursor = m_pParameter->GetLocalCursor();
95
96 //Qt is support QImage::Format_RGB32, so we use default format QImage::Format_RGB32 in OnSize()
97 // m_pClient->appData.requestedDepth = m_pPara->nColorLevel;
98 // m_pClient->format.depth = m_pPara->nColorLevel;
99 // switch (m_pClient->format.depth) {
100 // case 8:
101 // m_pClient->format.depth = 8;
102 // m_pClient->format.bitsPerPixel = 8;
103 // m_pClient->format.blueMax = 3;
104 // m_pClient->format.blueShift = 6;
105 // m_pClient->format.greenMax = 7;
106 // m_pClient->format.greenShift = 3;
107 // m_pClient->format.redMax = 7;
108 // m_pClient->format.redShift = 0;
109 // break;
110 // case 16:
111 // m_pClient->format.depth = 15;
112 // m_pClient->format.bitsPerPixel = 16;
113 // m_pClient->format.redShift = 11;
114 // m_pClient->format.greenShift = 6;
115 // m_pClient->format.blueShift = 1;
116 // m_pClient->format.redMax = 31;
117 // m_pClient->format.greenMax = 31;
118 // m_pClient->format.blueMax = 31;
119 // break;
120 // case 32:
121 // default:
122 // m_pClient->format.depth = 24;
123 // m_pClient->format.bitsPerPixel = 32;
124 // m_pClient->format.blueShift = 0;
125 // m_pClient->format.redShift = 16;
126 // m_pClient->format.greenShift = 8;
127 // m_pClient->format.blueMax = 0xff;
128 // m_pClient->format.redMax = 0xff;
129 // m_pClient->format.greenMax = 0xff;
130 // break;
131 // }
132
133 m_pClient->appData.enableJPEG = m_pParameter->GetJpeg();
134 if(m_pClient->appData.enableJPEG)
135 m_pClient->appData.qualityLevel = m_pParameter->GetQualityLevel();
136 if(m_pParameter->GetEnableCompressLevel())
137 m_pClient->appData.compressLevel = m_pParameter->GetCompressLevel();
138
139 // Set callback function
140 m_pClient->MallocFrameBuffer = cb_resize;
141 m_pClient->GotFrameBufferUpdate = cb_update;
142 m_pClient->HandleKeyboardLedState = cb_kbd_leds;
143 m_pClient->Bell = cb_bell;
144 m_pClient->HandleTextChat = cb_text_chat;
145 m_pClient->GotXCutText = cb_got_selection;
146 m_pClient->GetCredential = cb_get_credential;
147 m_pClient->GetPassword = cb_get_password;
148 m_pClient->HandleCursorPos = cb_cursor_pos;
149 m_pClient->GotCursorShape = cb_got_cursor_shape;
150
151 m_pClient->canHandleNewFBSize = TRUE;
152 rfbClientSetClientData(m_pClient, (void*)gThis, this);
153
154 // Set sock
155 switch(m_pParameter->m_Proxy.GetUsedType())
156 {
157 case CParameterProxy::TYPE::None:
158 {
159 // Set server ip and port
160 if(m_pParameter->m_Net.GetHost().isEmpty())
161 {
162 QString szErr;
163 szErr = tr("The server is empty, please input it");
164 qCritical(log) << szErr;
165 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
166 return OnStartReturnValue::Fail;
167 }
168 auto &net = m_pParameter->m_Net;
169 m_pClient->serverHost = strdup(net.GetHost().toStdString().c_str());
170 m_pClient->serverPort = net.GetPort();
171
172 if(!rfbInitClient(m_pClient, nullptr, nullptr))
173 {
174 // Because delete m_pClient in rfbInitClient
175 m_pClient = nullptr;
176 QString szErr;
177 szErr = tr("Fail: Connect to %1:%2").arg(m_pParameter->m_Net.GetHost(),
178 QString::number(m_pParameter->m_Net.GetPort()));
179 qCritical(log) << szErr;
180 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
181 return OnStartReturnValue::Fail;
182 }
183
184 QString szInfo = QString("Connected to ") + m_pClient->desktopName;
185 qInfo(log) << szInfo;
186
187 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
188 emit sigServerName(m_pClient->desktopName);
189 emit sigInformation(szInfo);
190 emit sigSecurityLevel(m_SecurityLevel);
191 emit sigRunning();
192 return OnStartReturnValue::UseOnProcess;
193 }
194 /*case CParameterProxy::TYPE::SockesV5:
195 {
196 QNetworkProxy proxy;
197 proxy.setType(QNetworkProxy::Socks5Proxy);
198 auto &net = m_pParameter->m_Proxy.m_SockesV5;
199 proxy.setHostName(net.GetHost());
200 if(net.GetHost().isEmpty())
201 {
202 QString szErr;
203 szErr = tr("The proxy server is empty, please input it");
204 qCritical(log) << szErr;
205 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
206 return OnStartReturnValue::Fail;
207 }
208 proxy.setPort(net.GetPort());
209 auto &user = net.m_User;
210 proxy.setUser(user.GetUser());
211 proxy.setPassword(user.GetPassword());
212 m_tcpSocket.setProxy(proxy);
213 m_tcpSocket.connectToHost(m_pClient->serverHost, m_pClient->serverPort);
214 if (!m_tcpSocket.waitForConnected(3000))
215 return OnStartReturnValue::Fail;
216 //TODO: The is fail
217 m_pClient->sock = m_tcpSocket.socketDescriptor();
218 if(!rfbInitClient(m_pClient, nullptr, nullptr))
219 {
220 // Because delete m_pClient in rfbInitClient
221 m_pClient = nullptr;
222 QString szErr;
223 szErr = tr("Connect to %1:%2 fail").arg(m_pParameter->m_Net.GetHost(),
224 QString::number(m_pParameter->m_Net.GetPort()));
225 qCritical(log) << szErr;
226 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
227 return OnStartReturnValue::Fail;
228 }
229 break;
230 }//*/
231 /*TODO: add UltraVncRepeater
232 case (CParameterOperate::emProxy) CParameterLibVNCServer::emVncProxy::UltraVncRepeater:
233 m_pClient->destHost = strdup(m_pPara->GetProxyHost().toStdString().c_str());
234 m_pClient->destPort = m_pPara->GetProxyPort();//*/
235
237#ifdef HAVE_LIBSSH
238 case CParameterProxy::TYPE::SSHTunnel:
239 {
240 // Start ssh thread
241 if(!m_pThread) {
242 // Don' t delete it, It deletes itself when it ends. See: CSSHTunnelThread::CSSHTunnelThread()
243 m_pThread = new CSSHTunnelThread(
244 &m_pParameter->m_Proxy.m_SSH, &m_pParameter->m_Net, this);
245 }
246 if(!m_pThread)
247 return OnStartReturnValue::Fail;
248 bool check = connect(m_pThread, SIGNAL(sigServer(QString, quint16)),
249 this, SLOT(slotConnectProxyServer(QString, quint16)));
250 Q_ASSERT(check);
251#if defined(HAVE_UNIX_DOMAIN_SOCKET)
252 check = connect(m_pThread, SIGNAL(sigServer(QString)),
253 this, SLOT(slotConnectProxyServer(QString)));
254 Q_ASSERT(check);
255#endif
256 check = connect(m_pThread, SIGNAL(sigError(int,QString)),
257 this, SIGNAL(sigError(int,QString)));
258 Q_ASSERT(check);
259 check = connect(m_pThread, SIGNAL(sigStop()),
260 this, SIGNAL(sigStop()));
261 Q_ASSERT(check);
262 m_pThread->start();
263
264 return OnStartReturnValue::NotUseOnProcess;
265 }
266#endif // #ifdef HAVE_LIBSSH
268 default:
269 break;
270 }
271
272 return OnStartReturnValue::UseOnProcess;
273}
274
276{
277 qDebug(log) << "CConnectLibVNCServer::OnStop()";
278#ifdef HAVE_LIBSSH
279 if(m_pThread)
280 {
281 disconnect(m_pThread);
282 m_pThread->Exit();
283 m_pThread = nullptr;
284 }
285#endif
286 if(m_pClient)
287 {
288 //m_tcpSocket.close();
289 rfbClientCleanup(m_pClient);
290 m_pClient = nullptr;
291 }
292
293 emit sigFinished();
294 return 0;
295}
296
311{
312 //qDebug(log) << Q_FUNC_INFO;
313 int nRet = 0;
314 if(!m_pClient)
315 {
316 // Stop
317 return -1;
318 }
319
320 struct timeval timeout = {0, DEFAULT_TIMEOUT};
321 fd_set set;
322 FD_ZERO(&set);
323 if(RFB_INVALID_SOCKET != m_pClient->sock)
324 {
325 FD_SET(m_pClient->sock, &set);
326 }
327 rfbSocket eventFd = m_Event.GetFd();
328 if(RFB_INVALID_SOCKET != eventFd)
329 {
330 FD_SET(eventFd, &set);
331 }
332 rfbSocket fd = RFB_INVALID_SOCKET;
333 fd = std::max(eventFd, m_pClient->sock);
334 //qDebug(log) << "fd:" << fd << "select m_pClient->sock:" << (int)m_pClient->sock << "event:" << eventFd;
335 nRet = select(fd + 1, &set, NULL, NULL, &timeout);
336 //qDebug(log) << "select end";
337 if (nRet < 0) {
338 qCritical(log) << "select fail:" << nRet << "errno" << errno << strerror(errno);
339 return nRet;
340 }
341
342 /*if(0 == nRet)
343 {
344 //qDebug(log) << "Time out";
345 return 0;
346 }//*/
347
348 if(RFB_INVALID_SOCKET != eventFd && FD_ISSET(eventFd, &set))
349 {
350 //qDebug(log) << "fires event";
351 m_Event.Reset();
352 }
353
354 if(RFB_INVALID_SOCKET != m_pClient->sock
355 && FD_ISSET(m_pClient->sock, &set)) {
356 //qDebug(log) << "HandleRFBServerMessage";
357 if(!HandleRFBServerMessage(m_pClient))
358 {
359 qCritical(log) << "HandleRFBServerMessage fail";
360 return -2;
361 }
362 }
363
364 return 0;
365}
366
368{
369 return m_Event.WakeUp();
370}
371
373{
374 if(!m_pParameter || !m_pParameter->GetClipboard() || !m_pClient) return;
375 QClipboard* pClipboard = QApplication::clipboard();
376 if(pClipboard)
377 {
378 QString szText = pClipboard->text();
379 if(!szText.isEmpty() && m_pClient)
380 SendClientCutText(m_pClient,
381 (char*)szText.toStdString().c_str(),
382 szText.toStdString().length());
383 }
384}
385
386rfbBool CBackendLibVNCServer::cb_resize(rfbClient* client)
387{
388 //qDebug(log) << "CConnectLibVnc::cb_resize:" << client->width << client->height;
389 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
390 if(pThis->OnSize()) return FALSE;
391 return TRUE;
392}
393
394void CBackendLibVNCServer::cb_update(rfbClient *client, int x, int y, int w, int h)
395{
396 if(0 == w || 0 == h)
397 return;
398 //qDebug(log, "CConnectLibVnc::cb_update:(%d, %d, %d, %d)", x, y, w, h);
399 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
400 QRect rect(x, y, w, h);
401 QImage img = pThis->m_Image.copy(rect);
402 emit pThis->sigUpdateRect(rect, img);
403}
404
405void CBackendLibVNCServer::cb_got_selection(rfbClient *client, const char *text, int len)
406{
407 //qDebug(log, "CConnectLibVnc::cb_got_selection:%s", text);
408 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
409 if(!pThis->m_pParameter->GetClipboard()) return;
410 QClipboard* pClipboard = QApplication::clipboard();
411 if(pClipboard)
412 pClipboard->setText(text);
413}
414
415void CBackendLibVNCServer::cb_kbd_leds(rfbClient *client, int value, int pad)
416{
417 qDebug(log) << "CConnectLibVnc::cb_kbd_leds";
418}
419
420void CBackendLibVNCServer::cb_bell(struct _rfbClient *client)
421{
422 qApp->beep();
423}
424
425void CBackendLibVNCServer::cb_text_chat(rfbClient *client, int value, char *text)
426{
427 qDebug(log) << "CConnectLibVnc::cb_text_chat";
428}
429
430rfbCredential* CBackendLibVNCServer::cb_get_credential(rfbClient *cl, int credentialType)
431{
432 qDebug(log) <<"CConnectLibVnc::cb_get_credential";
433 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(cl, (void*)gThis);
434 rfbCredential *c = (rfbCredential*)malloc(sizeof(rfbCredential));
435 c->userCredential.username = (char*)malloc(RFB_BUF_SIZE);
436 memset(c->userCredential.username, 0, RFB_BUF_SIZE);
437 c->userCredential.password = (char*)malloc(RFB_BUF_SIZE);
438 memset(c->userCredential.password, 0, RFB_BUF_SIZE);
439
440 if(credentialType != rfbCredentialTypeUser) {
441 qCritical(log) << "something else than username and password required for authentication";
442 return NULL;
443 }
444
445 qDebug(log) << "Username and password required for authentication!";
446
447 memcpy(c->userCredential.username,
448 pThis->m_pParameter->m_Net.m_User.GetUser().toStdString().c_str(),
449 pThis->m_pParameter->m_Net.m_User.GetUser().toStdString().length());
450 memcpy(c->userCredential.password,
451 pThis->m_pParameter->m_Net.m_User.GetPassword().toStdString().c_str(),
452 pThis->m_pParameter->m_Net.m_User.GetPassword().toStdString().length());
453
454 return c;
455}
456
457char* CBackendLibVNCServer::cb_get_password(rfbClient *client)
458{
459 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
460 QString szPassword = pThis->m_pParameter->m_Net.m_User.GetPassword();
461 if(szPassword.isEmpty())
462 {
463 int nRet = QDialog::Rejected;
464 auto *net = &pThis->m_pParameter->m_Net;
465 emit pThis->sigBlockShowWidget("CDlgUserPassword", nRet, net);
466 if(QDialog::Accepted == nRet)
467 {
468 szPassword = net->m_User.GetPassword();
469 }
470 }
471 if(!szPassword.isEmpty())
472 pThis->m_SecurityLevel |= CSecurityLevel::Level::Authentication;
473 return strdup(szPassword.toStdString().c_str());
474}
475
476int CBackendLibVNCServer::OnSize()
477{
478 int nRet = 0;
479 int nWidth = m_pClient->width;
480 int nHeight = m_pClient->height;
481
482 m_Image = QImage(nWidth, nHeight, QImage::Format_RGB32);
483
484 m_pClient->frameBuffer = m_Image.bits();
485
486 m_pClient->format.bitsPerPixel = 32;
487 m_pClient->format.depth = m_Image.depth();
488 m_pClient->format.redShift = 16;
489 m_pClient->format.greenShift = 8;
490 m_pClient->format.blueShift = 0;
491 m_pClient->format.redMax = 255;
492 m_pClient->format.greenMax = 255;
493 m_pClient->format.blueMax = 255;
494 SetFormatAndEncodings(m_pClient);
495
496 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
497 return nRet;
498}
499
500rfbBool CBackendLibVNCServer::cb_cursor_pos(rfbClient *client, int x, int y)
501{
502 //qDebug(log, "CConnectLibVnc::cb_cursor_pos:%d,%d", x, y);
503 rfbBool bRet = true;
504
505 return bRet;
506}
507
508void CBackendLibVNCServer::cb_got_cursor_shape(rfbClient *client,
509 int xhot, int yhot,
510 int width, int height,
511 int bytesPerPixel)
512{
513 /*
514 qDebug(log, "CConnectLibVnc::cb_got_cursor_shape:x:%d, y:%d, width:%d, height:%d, bytesPerPixel:%d",
515 xhot, yhot, width, height, bytesPerPixel);//*/
516 if(!client->rcSource)
517 {
518 qCritical(log) << "client->rcSource is null";
519 return;
520 }
521 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
522 if ((width == 0) || (height == 0)) {
523 QImage cursor(1, 1, QImage::Format_ARGB32);
524 uchar* buffer = cursor.bits();
525 memset(buffer, 0, 4);
526 emit pThis->sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), xhot, yhot));
527 } else {
528 switch (bytesPerPixel) {
529 case 4:
530 {
531 QImage cursor(width, height, QImage::Format_ARGB32);
532 uchar *buffer = cursor.bits();
533 memcpy(buffer, client->rcSource, width * height * 4);
534 uchar* pMask = client->rcMask;
535 if(pMask)
536 {
537 uchar* pDest = buffer;
538 for(int y = 0; y < height; y++)
539 {
540 for(int w = 0; w < width; w++)
541 {
542 if(*pMask++)
543 {
544 // NOTE: Do not manipulate the memory,
545 // because the host byte order may be different
546 QColor c = cursor.pixel(w, y);
547 c.setAlpha(0xff);
548 cursor.setPixelColor(w,y,c);
549 }
550 else
551 *((uint32_t*)pDest) = 0;
552
553 pDest += 4;
554 }
555 }
556 }
557 emit pThis->sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), xhot, yhot));
558 break;
559 }
560 default:
561 break;
562 }
563 }
564}
565
566void CBackendLibVNCServer::mousePressEvent(QMouseEvent *event)
567{
568 if(!m_pClient) return;
569 if(m_pParameter && m_pParameter->GetOnlyView()) return;
570
571 unsigned char mask = 0;
572 if(event->button() & Qt::MouseButton::LeftButton)
573 mask |= 0x1;
574 if(event->button() & Qt::MouseButton::MiddleButton)
575 mask |= 0x2;
576 if(event->button() & Qt::MouseButton::RightButton)
577 mask |= 0x4;
578 if(event->button() & Qt::MouseButton::BackButton)
579 mask |= 0x80;
580 QPoint pos = event->pos();
581
582 //qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
583
584 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
585}
586
587void CBackendLibVNCServer::mouseReleaseEvent(QMouseEvent *event)
588{
589 if(!m_pClient) return;
590 if(m_pParameter && m_pParameter->GetOnlyView()) return;
591 int mask = 0;
592 QPoint pos = event->pos();
593 //qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
594 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
595}
596
597void CBackendLibVNCServer::mouseMoveEvent(QMouseEvent *event)
598{
599 if(!m_pClient) return;
600 if(m_pParameter && m_pParameter->GetOnlyView()) return;
601 int mask = 0;
602 if(event->buttons() & Qt::MouseButton::LeftButton)
603 mask |= 0x1;
604 if(event->buttons() & Qt::MouseButton::MiddleButton)
605 mask |= 0x2;
606 if(event->buttons() & Qt::MouseButton::RightButton)
607 mask |= 0x4;
608 if(event->buttons() & Qt::MouseButton::BackButton)
609 mask |= 0x80;
610 QPoint pos = event->pos();
611 //qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
612 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
613}
614
615// https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#pointerevent
616void CBackendLibVNCServer::wheelEvent(QWheelEvent *event)
617{
618 if(!m_pClient) return;
619 if(m_pParameter && m_pParameter->GetOnlyView()) return;
620 int mask = 0;
621 if(event->buttons() & Qt::MouseButton::LeftButton)
622 mask |= 0x1;
623 if(event->buttons() & Qt::MouseButton::MiddleButton)
624 mask |= 0x2;
625 if(event->buttons() & Qt::MouseButton::RightButton)
626 mask |= 0x4;
627 if(event->buttons() & Qt::MouseButton::BackButton)
628 mask |= 0x80;
629
630 QPoint d = event->angleDelta();
631 if(d.y() > 0)
632 mask |= 0x8;
633 if(d.y() < 0)
634 mask |= 0x10;
635 if(d.x() < 0)
636 mask |= 0x20;
637 if(d.x() > 0)
638 mask |= 0x40;
639
640 QPointF pos;
641#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
642 pos = event->position();
643#else
644 pos = event->pos();
645#endif
646
647 //qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->angleDelta() << pos;
648
649 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
650}
651
652void CBackendLibVNCServer::keyPressEvent(QKeyEvent *event)
653{
654 if(!m_pClient) return;
655 if(m_pParameter && m_pParameter->GetOnlyView()) return;
656 bool modifier = false;
657 if (event->modifiers() & Qt::ShiftModifier)
658 modifier = true;
659 uint32_t k = CConvertKeyCode::QtToRfbKey(event->key(), modifier);
660 //qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
661 SendKeyEvent(m_pClient, k, TRUE);
662}
663
664void CBackendLibVNCServer::keyReleaseEvent(QKeyEvent *event)
665{
666 if(!m_pClient) return;
667 if(m_pParameter && m_pParameter->GetOnlyView()) return;
668 bool modifier = false;
669 if (event->modifiers() & Qt::ShiftModifier)
670 modifier = true;
671 uint32_t k = CConvertKeyCode::QtToRfbKey(event->key(), modifier);
672 //qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
673 SendKeyEvent(m_pClient, k, FALSE);
674}
675
676void CBackendLibVNCServer::InputMethodEvent(QInputMethodEvent *event)
677{
678 //qDebug(logInputMethod) << Q_FUNC_INFO << event;
679 if(!m_pClient) return;
680 if(m_pParameter && m_pParameter->GetOnlyView()) return;
681
682 QString szText = event->commitString();
683 if (szText.isEmpty())
684 return;
685
686 //qDebug(logInputMethod) << Q_FUNC_INFO << szText;
687
688 QVector<uint32_t> ucs4 = szText.toUcs4();
689 foreach (uint32_t cp, ucs4) {
690 quint32 keysym = static_cast<quint32>(cp); // 直接用 Unicode code point 作为 keysym
691 SendKeyEvent(m_pClient, keysym, TRUE);
692 SendKeyEvent(m_pClient, keysym, FALSE);
693 }
694}
695
697void CBackendLibVNCServer::slotConnectProxyServer(QString szHost, quint16 nPort)
698{
699 QString szErr;
700 auto &net = m_pParameter->m_Proxy.m_SSH.m_Net;
701 //qDebug(log) << "CConnectLibVNCServer::slotConnectServer" << nPort;
702 // Set server ip and port
703 m_pClient->serverHost = strdup(szHost.toStdString().c_str());
704 m_pClient->serverPort = nPort;
705 szErr = tr("Will connect to local socket server: %1:%2")
706 .arg(m_pClient->serverHost,
707 QString::number(m_pClient->serverPort));
708 qDebug(log) << szErr;
709 if(!rfbInitClient(m_pClient, nullptr, nullptr))
710 {
711 // Because delete m_pClient in rfbInitClient
712 m_pClient = nullptr;
713 QString szErr;
714 szErr = tr("Fail: Connect to %1:%2 <- %3:%4 <- %5:%6")
715 .arg(m_pParameter->m_Net.GetHost(),
716 QString::number(m_pParameter->m_Net.GetPort()),
717 net.GetHost(), QString::number(net.GetPort()),
718 szHost, QString::number(nPort)
719 );
720 qCritical(log) << szErr;
721 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
722 return;
723 }
724
725 QString szInfo = QString("Connected to %1 <- %2:%3 <- %4:%5")
726 .arg(m_pClient->desktopName,
727 net.GetHost(), QString::number(net.GetPort()),
728 szHost, QString::number(nPort));
729 qInfo(log) << szInfo;
730 slotTimeOut();
731 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
732 emit sigServerName(m_pClient->desktopName);
733 emit sigInformation(szInfo);
734 emit sigSecurityLevel(m_SecurityLevel |= CSecurityLevel::Level::Proxy);
735 emit sigRunning();
736}
737
738#if defined(HAVE_UNIX_DOMAIN_SOCKET)
740{
741 QString szErr;
742 //qDebug(log) << "CConnectLibVNCServer::slotConnectServer" << szFile;
743 // Set server ip and port
744 m_pClient->serverHost = strdup(szFile.toStdString().c_str());
745 szErr = tr("Will connect to local socket server: ") + szFile;
746 qDebug(log) << szErr;
747 if(!rfbInitClient(m_pClient, nullptr, nullptr))
748 {
749 // Because delete m_pClient in rfbInitClient
750 m_pClient = nullptr;
751 QString szErr;
752 szErr = tr("Fail: Connect to %1:%2 with %3")
753 .arg(m_pParameter->m_Net.GetHost(),
754 QString::number(m_pParameter->m_Net.GetPort()),
755 szFile);
756 qCritical(log) << szErr;
757 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
758 return;
759 }
760
761 QString szInfo = QString("Connected to ") + m_pClient->desktopName + " with " + szFile;
762 qInfo(log) << szInfo;
763
764 slotTimeOut();
765 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
766 emit sigServerName(m_pClient->desktopName);
767 emit sigInformation(szInfo);
768 emit sigRunning();
769}
770#endif
远程桌面接口。它由协议插件实现。
void sigUpdateRect(const QRect &r, const QImage &image)
通知视图,图像更新
virtual OnStartReturnValue OnStart() override
void slotConnectProxyServer(QString szHost, quint16 nPort)
[connect local socket server]
virtual int WakeUp() override
唤醒后台线程。
virtual int OnStop() override
清理
virtual void slotClipBoardChanged() 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 事件循环(就是普通的循环处理), 可以重载它,或者 OnStart() 返回值 OnSta...
void sigSecurityLevel(CSecurityLevel::Levels level)
当安全级别改变时触发
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
阻塞后台线程,并在前台线程中显示窗口。
static quint32 QtToRfbKey(int inkey, bool modifier)
CConvertKeyCode::QtToRfbKey
CParameterUser m_User
[Instance user]
实现通过本地 SOCKET 与 SSH 隧道转发数据。适用于库没有实现传输层接口,只有 socket 的情况。
安全级别
定义 Stats.h:97