玉兔远程控制 0.1.0-bate8
载入中...
搜索中...
未找到
BackendVnc.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include "BackendVnc.h"
4#include "OperateDesktop.h"
5
6#ifndef WIN32
7#include <string.h>
8#include "network/UnixSocket.h"
9#endif
10
11#include <rfb/CMsgWriter.h>
12#include <rfb/Hostname.h>
13#include "rfb/LogWriter.h"
14#include <rfb/util.h>
15#include <rfb/clipboardTypes.h>
16#include <rfb/LogWriter.h>
17#include <rfb/Logger_stdio.h>
18#include <rfb/fenceTypes.h>
19
20// the X11 headers on some systems
21#ifndef XK_VoidSymbol
22#define XK_LATIN1
23#define XK_MISCELLANY
24#define XK_XKB_KEYS
25#include <rfb/keysymdef.h>
26#endif
27
28
29#include "FramePixelBuffer.h"
30
31#include <QDir>
32#include <QMimeData>
33#include <QClipboard>
34#include <QApplication>
35#include <QLoggingCategory>
36#include <QThread>
37#include <QKeyEvent>
38#include <QMouseEvent>
39#include <QNetworkProxy>
40#include <QMutex>
41#include <QInputDialog>
42
43#include "rfb/Security.h"
44#include "rfb/Exception.h"
45#ifdef HAVE_GNUTLS
46#include "rfb/CSecurityTLS.h"
47#endif
48
49#ifdef HAVE_ICE
50 #include "Ice.h"
51 #include "ChannelIce.h"
52#endif
53
54#ifdef HAVE_LIBSSH
55 #include "ChannelSSHTunnel.h"
56#endif
57
58static Q_LOGGING_CATEGORY(log, "VNC.Connect")
59static Q_LOGGING_CATEGORY(logVNC, "VNC.Log")
60static Q_LOGGING_CATEGORY(logKey, "VNC.Connect.Key")
61static Q_LOGGING_CATEGORY(logMouse, "VNC.Connect.Mouse")
62
63class VncLogger: public rfb::Logger
64{
65public:
66 VncLogger(const char *name) : rfb::Logger(name)
67 {}
68 void write(int level, const char *logname, const char *text) override
69 {
70 if (level >= rfb::LogWriter::LEVEL_DEBUG) {
71 qDebug(logVNC) << logname << text;
72 } else if (level >= rfb::LogWriter::LEVEL_INFO) {
73 qInfo(logVNC) << logname << text;
74 } else if (level >= rfb::LogWriter::LEVEL_STATUS) {
75 qWarning(logVNC) << logname << text;
76 } else {
77 qCritical(logVNC) << logname << text;
78 }
79 }
80};
81
82static VncLogger g_logger("Rabbit");
83
84// 8 colours (1 bit per component)
85static const rfb::PixelFormat verylowColourPF(8, 3,false, true, 1, 1, 1, 2, 1, 0);
86// 64 colours (2 bits per component)
87static const rfb::PixelFormat lowColourPF(8, 6, false, true, 3, 3, 3, 4, 2, 0);
88// 256 colours (2-3 bits per component)
89static const rfb::PixelFormat mediumColourPF(8, 8, false, true, 7, 7, 3, 5, 2, 0);
90
91// RGB (4 bits per component)
92static const rfb::PixelFormat fullColourPF(32, 24, false, true, 255, 255, 255, 16, 8, 0);
93
94// Time new bandwidth estimates are weighted against (in ms)
95static const unsigned bpsEstimateWindow = 1000;
96
97CBackendVnc::CBackendVnc(COperateDesktop *pOperate)
98 : CBackendDesktop(pOperate)
99 , m_pOperate(pOperate)
100 , m_pPara(nullptr)
101 , m_SecurityLevel(CSecurityLevel::Level::Risk)
102{
103 static bool initlog = false;
104 if(!initlog)
105 {
106 g_logger.registerLogger();
107 rfb::LogWriter::setLogParams("*:Rabbit:100");
108 /*rfb::initStdIOLoggers();
109 rfb::LogWriter::setLogParams("*:stderr:100");
110 QString szFile = RabbitCommon::CDir::Instance()->GetDirLog()
111 + QDir::separator()
112 + "TigerVnc.log";
113 rfb::initFileLogger(szFile.toStdString().c_str());
114 rfb::LogWriter::setLogParams("*:file:100");
115 */
116 initlog = true;
117 }
118 m_pPara = dynamic_cast<CParameterVnc*>(pOperate->GetParameter());
119 Q_ASSERT(m_pPara);
120
121 if(!m_pPara->GetLocalCursor())
122 {
123 emit sigUpdateCursor(QCursor(Qt::BlankCursor));
124 }
125}
126
127CBackendVnc::~CBackendVnc()
128{
129 qDebug(log) << "CConnectVnc::~CConnectVnc()";
130}
131
132int CBackendVnc::SetPara()
133{
134 QDir d(os::getvncconfigdir());
135 if(!d.exists())
136 d.mkpath(os::getvncconfigdir());
137 QDir dstat(os::getvncstatedir());
138 if(!dstat.exists())
139 dstat.mkpath(os::getvncstatedir());
140 QDir dvnc(os::getvncdatadir());
141 if(!dvnc.exists())
142 dvnc.mkpath(os::getvncdatadir());
143
144 setServerName(m_pPara->m_Net.GetHost().toStdString().c_str());
145 setShared(m_pPara->GetShared());
146 supportsLocalCursor = m_pPara->GetLocalCursor();
147 supportsCursorPosition = m_pPara->GetCursorPosition();
148 supportsDesktopResize = m_pPara->GetSupportsDesktopResize();
149 supportsLEDState = m_pPara->GetLedState();
150
151 std::list<uint32_t> sec;
152 switch(m_pPara->m_Net.m_User.GetUsedType()) {
153 case CParameterUser::TYPE::None:
154 sec.push_back(rfb::secTypeNone);
155 break;
156 case CParameterUser::TYPE::OnlyPassword:
157 sec.push_back(rfb::secTypeVncAuth);
158 break;
159 case CParameterUser::TYPE::UserPassword:
160 sec.push_back(rfb::secTypePlain);
161 break;
163 sec.push_back(rfb::secTypeTLSVnc);
164 break;
165 case CParameterUser::TYPE::OnlyPasswordX509:
166 sec.push_back(rfb::secTypeX509Vnc);
167 break;
168 case CParameterUser::TYPE::UserPasswordX509None:
169 sec.push_back(rfb::secTypeTLSPlain);
170 break;
171 case CParameterUser::TYPE::UserPasswordX509:
172 sec.push_back(rfb::secTypeX509Plain);
173 break;
174 //TODO: add authentication
175 }
176 //*
177 qDebug(log) << "secTypes:" << security.GetEnabledSecTypes() << security.ToString()
178 << "new:" << sec; // << "Type:" << m_pPara->m_Net.m_User.GetType();//*/
179 security.SetSecTypes(sec);
180
181 // Set Preferred Encoding
182 setPreferredEncoding(m_pPara->GetPreferredEncoding());
183 setCompressLevel(m_pPara->GetCompressLevel());
184 setQualityLevel(m_pPara->GetQualityLevel());
185
186 // Set server pixmap format
187 updatePixelFormat();
188 return 0;
189}
190
191/*
192 * \return
193 * \li OnInitReturnValue::Fail: error
194 * \li OnInitReturnValue::UseOnProcess: Use OnProcess (non-Qt event loop)
195 * \li OnInitReturnValue::NotUseOnProcess: Don't use OnProcess (qt event loop)
196 */
197CBackendVnc::OnInitReturnValue CBackendVnc::OnInit()
198{
199 qDebug(log) << "CConnectVnc::OnInit()";
200 int nRet = 0;
201
202 if(m_pPara->GetIce())
203 nRet = IceInit();
204 else {
205#ifdef HAVE_LIBSSH
206 if(m_pPara->m_Proxy.GetUsedType() == CParameterProxy::TYPE::SSHTunnel) {
207 nRet = SSHInit();
208 if(nRet) return OnInitReturnValue::Fail; // error
209 return OnInitReturnValue::UseOnProcess;
210 }
211#endif
212 nRet = SocketInit();
213 }
214 if(nRet) return OnInitReturnValue::Fail; // error
215 // Don't use OnProcess (qt event loop)
216 return OnInitReturnValue::NotUseOnProcess;
217}
218
219int CBackendVnc::IceInit()
220{
221#ifdef HAVE_ICE
222 CIceSignal* pSignal = CICE::Instance()->GetSignal().data();
223 if(!pSignal || !pSignal->IsConnected())
224 {
225 qCritical(log) << "The g_pSignal is null. or signal don't connect server";
226 return -1;
227 }
228
229 qInfo(log, "Connected to signal server:%s:%d; user:%s",
230 CICE::Instance()->GetParameter()->getSignalServer().toStdString().c_str(),
231 CICE::Instance()->GetParameter()->getSignalPort(),
232 CICE::Instance()->GetParameter()->getSignalUser().toStdString().c_str());
233 auto channel = QSharedPointer<CChannelIce>(new CChannelIce(pSignal));
234 if(!channel)
235 {
236 qCritical(log) << "new CDataChannelIce fail";
237 return -2;
238 }
239 m_DataChannel = channel;
240 SetChannelConnect(channel);
241
242 rtc::Configuration config;
243 rtc::IceServer stun(CICE::Instance()->GetParameter()->getStunServer().toStdString().c_str(),
244 CICE::Instance()->GetParameter()->getStunPort());
245 rtc::IceServer turn(CICE::Instance()->GetParameter()->getTurnServer().toStdString().c_str(),
246 CICE::Instance()->GetParameter()->getTurnPort(),
247 CICE::Instance()->GetParameter()->getTurnUser().toStdString().c_str(),
248 CICE::Instance()->GetParameter()->getTurnPassword().toStdString().c_str());
249 config.iceServers.push_back(stun);
250 config.iceServers.push_back(turn);
251 channel->SetConfigure(config);
252
253 bool bRet = channel->open(CICE::Instance()->GetParameter()->getSignalUser(),
254 m_pPara->GetPeerUser(), true);
255 if(!bRet)
256 {
257 emit sigError(-1, "Open channel fail");
258 }
259
260#endif
261 return 0;
262}
263
264int CBackendVnc::SocketInit()
265{
266 int nRet = 0;
267 try{
268 QTcpSocket* pSock = new QTcpSocket(this);
269 if(!pSock)
270 return -1;
271 m_DataChannel = QSharedPointer<CChannel>(new CChannel(pSock));
272 if(!m_DataChannel) {
273 qCritical(log) << "New CChannel fail";
274 return -1;
275 }
276
277 SetChannelConnect(m_DataChannel);
278
279 if(!m_DataChannel->open(QIODevice::ReadWrite))
280 {
281 qCritical(log) << "Open channel fail";
282 return -1;
283 }
284
285 QNetworkProxy::ProxyType type = QNetworkProxy::NoProxy;
286 // Set sock
287 switch(m_pPara->m_Proxy.GetUsedType())
288 {
289 case CParameterProxy::TYPE::SockesV5:
290 type = QNetworkProxy::Socks5Proxy;
291 break;
292 case CParameterProxy::TYPE::System:
293 type = QNetworkProxy::DefaultProxy;
294 break;
295 case CParameterProxy::TYPE::Http:
296 type = QNetworkProxy::HttpProxy;
297 break;
298 case CParameterProxy::TYPE::None:
299 default:
300 break;
301 }
302
303 switch(type) {
304 case QNetworkProxy::DefaultProxy:
305 {
306 pSock->setProxy(QNetworkProxy::applicationProxy());
307 break;
308 }
309 case QNetworkProxy::HttpProxy:
310 case QNetworkProxy::Socks5Proxy:
311 {
312 QNetworkProxy proxy;
313 auto net = &m_pPara->m_Proxy.m_SockesV5;
314 if(QNetworkProxy::HttpProxy == type) {
315 net = &m_pPara->m_Proxy.m_Http;
316 }
317 if(net->GetHost().isEmpty())
318 {
319 QString szErr;
320 szErr = tr("The proxy server is empty, please input it");
321 qCritical(log) << szErr;
322 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
323 return -1;
324 }
325 proxy.setHostName(net->GetHost());
326 proxy.setPort(net->GetPort());
327 auto &user = net->m_User;
328 if(((user.GetUsedType() == CParameterUser::TYPE::UserPassword)
329 && (user.GetPassword().isEmpty() || user.GetUser().isEmpty()))
330 || ((user.GetUsedType() == CParameterUser::TYPE::PublicKey)
331 && user.GetPassphrase().isEmpty())) {
332 int nRet = QDialog::Rejected;
333 emit sigBlockShowWidget("CDlgUserPassword", nRet, net);
334 if(QDialog::Accepted != nRet)
335 {
336 return -1;
337 }
338 }
339 proxy.setUser(user.GetUser());
340 proxy.setPassword(user.GetPassword());
341 proxy.setType(type);
342 pSock->setProxy(proxy);
343 break;
344 }
345 default:
346 break;
347 }
348
349 if(m_pPara->m_Net.GetHost().isEmpty())
350 {
351 QString szErr;
352 szErr = tr("The server is empty, please input it");
353 qCritical(log) << szErr;
354 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
355 return -1;
356 }
357 pSock->connectToHost(m_pPara->m_Net.GetHost(), m_pPara->m_Net.GetPort());
358
359 QString serverHost;
360 serverHost = pSock->peerName();
361 qDebug(log) << "Server Host:" << serverHost;
362 setServerName(serverHost.toStdString().c_str());
363
364 return nRet;
365 } catch (rdr::Exception& e) {
366 qCritical(log) << "SocketInit exception:" << e.str();
367 emit sigError(-1, e.str());
368 nRet = -1;
369 }
370 return nRet;
371}
372
373int CBackendVnc::SSHInit()
374{
375#ifdef HAVE_LIBSSH
376 auto channel = QSharedPointer<CChannelSSHTunnel>(
377 new CChannelSSHTunnel(&m_pPara->m_Proxy.m_SSH, &m_pPara->m_Net, this));
378 if(!channel) {
379 qCritical(log) << "New CChannelSSHTunnel fail";
380 return -1;
381 }
382 m_DataChannel = channel;
383 SetChannelConnect(m_DataChannel);
384 if(!channel->open(QIODevice::ReadWrite))
385 {
386 QString szErr;
387 szErr = tr("Failed to open SSH tunnel:");
388 szErr += "(" + m_pPara->m_Proxy.m_SSH.m_Net.GetHost();
389 szErr += ":";
390 szErr += QString::number(m_pPara->m_Proxy.m_SSH.m_Net.GetPort());
391 szErr += " - ";
392 szErr += m_pPara->m_Net.GetHost();
393 szErr += ":";
394 szErr += QString::number(m_pPara->m_Net.GetPort()) + ")";
395 QString szMsg = szErr + "\n" + channel->errorString();
396 emit sigShowMessageBox(tr("Error"), szMsg, QMessageBox::Critical);
397 return -2;
398 }
399 m_SecurityLevel = CSecurityLevel::Level::Proxy;
400#endif
401 return 0;
402}
403
404int CBackendVnc::SetChannelConnect(QSharedPointer<CChannel> channel)
405{
406 bool check = false;
407 check = connect(channel.data(), SIGNAL(sigConnected()),
408 this, SLOT(slotConnected()));
409 Q_ASSERT(check);
410 check = connect(channel.data(), SIGNAL(sigDisconnected()),
411 this, SLOT(slotDisConnected()));
412 Q_ASSERT(check);
413 check = connect(channel.data(), SIGNAL(readyRead()),
414 this, SLOT(slotReadyRead()));
415 Q_ASSERT(check);
416 check = connect(channel.data(), SIGNAL(sigError(int, const QString&)),
417 this, SLOT(slotChannelError(int, const QString&)));
418 Q_ASSERT(check);
419 if(m_pOperate && m_pOperate->GetStats()) {
420 check = connect(channel.data(), SIGNAL(sigReceive(quint64)),
421 m_pOperate->GetStats(), SLOT(AddReceives(quint64)));
422 Q_ASSERT(check);
423 check = connect(channel.data(), SIGNAL(sigSend(quint64)),
424 m_pOperate->GetStats(), SLOT(AddSends(quint64)));
425 Q_ASSERT(check);
426 }
427 return 0;
428}
429
431{
432 qDebug(log) << "CConnectVnc::OnClean()";
433 close();
434 setStreams(nullptr, nullptr);
435 if(m_DataChannel) {
436 m_DataChannel->close();
437 }
438 return 0;
439}
440
455{
456 int nRet = 0;
457#ifdef HAVE_LIBSSH
458 if(m_pPara->m_Proxy.GetUsedType() == CParameterProxy::TYPE::SSHTunnel) {
459 CChannelSSHTunnel* channel = (CChannelSSHTunnel*)m_DataChannel.data();
460 if(channel)
461 nRet = channel->Process();
462 }
463#endif
464
465 return nRet;
466}
467
469{
470#ifdef HAVE_LIBSSH
471 if(m_pPara->m_Proxy.GetUsedType() == CParameterProxy::TYPE::SSHTunnel) {
472 CChannelSSHTunnel* channel = (CChannelSSHTunnel*)m_DataChannel.data();
473 if(channel)
474 channel->WakeUp();
475 }
476#endif
477 return 0;
478}
479
480void CBackendVnc::slotConnected()
481{
482 qDebug(log) << Q_FUNC_INFO;
483 if(m_pPara->GetIce())
484 qInfo(log) << "Connected to peer " + m_pPara->GetPeerUser();
485 else {
486 auto &net = m_pPara->m_Net;
487 QString szInfo = "Connected to "
488 + net.GetHost() + ":" + QString::number(net.GetPort());
489#ifdef HAVE_LIBSSH
490 if(CParameterProxy::TYPE::SSHTunnel == m_pPara->m_Proxy.GetUsedType())
491 {
492 auto &sshNet = m_pPara->m_Proxy.m_SSH.m_Net;
493 szInfo += " with ssh turnnel: " + sshNet.GetHost()
494 + ":" + QString::number(sshNet.GetPort());
495 }
496#endif
497 qInfo(log) << szInfo;
498 }
499 int nRet = SetPara();
500 if(nRet)
501 {
502 emit sigStop();
503 return;
504 }
505 m_InStream = QSharedPointer<rdr::InStream>(new CInStreamChannel(m_DataChannel.data()));
506 m_OutStream = QSharedPointer<rdr::OutStream>(new COutStreamChannel(m_DataChannel.data()));
507 if(!(m_InStream && m_OutStream))
508 {
509 qCritical(log) << "m_InStream or m_OutStream is null";
510 emit sigStop();
511 return;
512 }
513 setStreams(m_InStream.data(), m_OutStream.data());
514 initialiseProtocol();
515}
516
517void CBackendVnc::slotDisConnected()
518{
519 QString szInfo;
520 szInfo = "CConnectVnc::slotDisConnected() from "
521 + m_pPara->m_Net.GetHost() + ":"
522 + QString::number(m_pPara->m_Net.GetPort());
523#ifdef HAVE_LIBSSH
524 if(CParameterProxy::TYPE::SSHTunnel == m_pPara->m_Proxy.GetUsedType())
525 {
526 auto &net = m_pPara->m_Proxy.m_SSH.m_Net;
527 szInfo += " with ssh turnnel: " + net.GetHost()
528 + ":" + QString::number(net.GetPort());
529 }
530#endif
531 qInfo(log) << szInfo;
532}
533
534void CBackendVnc::slotReadyRead()
535{
536 //qDebug(log) << "CConnectVnc::slotReadyRead";
537 QString szErr("processMsg exception: ");
538 int nRet = -1;
539 try {
540 getOutStream()->flush();
541
542 getOutStream()->cork(true);
543 while(processMsg())
544 ;
545 getOutStream()->cork(false);
546 return;
547 } catch (rfb::AuthFailureException& e) {
548 szErr = tr("Logon to ");
549 szErr += m_pPara->m_Net.GetHost();
550 szErr += ":";
551 szErr += QString::number(m_pPara->m_Net.GetPort());
552 szErr += tr(" fail.");
553 QString szMsg = szErr + "\n" + tr("Please check that the username and password are correct.") + "\n";
554 emit sigShowMessageBox(tr("Error"), szMsg, QMessageBox::Critical);
555
556 szErr += " [";
557 szErr += e.str();
558 szErr += "]";
559 } catch (rfb::ConnFailedException& e) {
560 QString szErr;
561 szErr = tr("Connect to ");
562 szErr += m_pPara->m_Net.GetHost();
563 szErr += ":";
564 szErr += QString::number(m_pPara->m_Net.GetPort());
565 szErr += tr(" fail.");
566 szErr += " [";
567 szErr += e.str();
568 szErr += "]";
569 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
570 } catch (rdr::EndOfStream& e) {
571 szErr += e.str();
572 } catch(rdr::GAIException &e) {
573 nRet = e.err;
574 szErr += "[" + QString::number(e.err) + "] " + e.str();
575 } catch(rdr::SystemException &e) {
576 nRet = e.err;
577 szErr += "[" + QString::number(e.err) + "] " + e.str();
578 } catch (rdr::Exception& e) {
579 szErr += e.str();
580 } catch (std::exception &e) {
581 szErr += e.what();
582 } catch(...) {
583 szErr += "unknown exception";
584 }
585 qCritical(log) << szErr;
586 emit sigError(nRet, szErr);
587 emit sigStop();
588}
589
590void CBackendVnc::slotChannelError(int nErr, const QString& szErr)
591{
592 qDebug(log) << "Channel error:" << nErr << "-" << szErr;
593 emit sigError(nErr, szErr);
594 emit sigStop();
595}
596
597// initDone() is called when the serverInit message has been received. At
598// this point we create the desktop window and display it. We also tell the
599// server the pixel format and encodings to use and request the first update.
600void CBackendVnc::initDone()
601{
602 Q_ASSERT(m_pPara);
603 qDebug(log, "initDone: %s", ConnectInformation().toStdString().c_str());
604
605 emit sigSetDesktopSize(server.width(), server.height());
606 QString szName = QString::fromUtf8(server.name());
607 emit sigServerName(szName);
608
609 //Set viewer frame buffer
610 setFramebuffer(new CFramePixelBuffer(server.width(), server.height()));
611
612 // Force a switch to the format and encoding we'd like
613 // Set Preferred Encoding
614 setPreferredEncoding(m_pPara->GetPreferredEncoding());
615 updatePixelFormat();
616
617 emit sigSecurityLevel(m_SecurityLevel);
618 emit sigRunning();
619}
620
621void CBackendVnc::resizeFramebuffer()
622{
623 rfb::ModifiablePixelBuffer* buffer = getFramebuffer();
624
625 qDebug(log) << "CConnectVnc::resizeFramebuffer: new:"
626 << server.width() << server.height()
627 << "old:" << buffer->width() << buffer->height();
628
629 if(server.width() == buffer->width() && server.height() == buffer->height())
630 return;
631
632 //Set viewer frame buffer
633 setFramebuffer(new CFramePixelBuffer(server.width(), server.height()));
634 emit sigSetDesktopSize(server.width(), server.height());
635}
636
637void CBackendVnc::setColourMapEntries(int firstColour, int nColours, uint16_t *rgbs)
638{
639 qCritical(log) << "Invalid SetColourMapEntries from server!";
640}
641
642void CBackendVnc::bell()
643{
644 qApp->beep();
645}
646
647void CBackendVnc::setLEDState(unsigned int state)
648{
649 qDebug(log) << "CConnectVnc::setLEDState" << state;
650 CConnection::setLEDState(state);
651 emit sigUpdateLedState(state);
652}
653
654void CBackendVnc::setCursor(int width, int height, const rfb::Point &hotspot, const uint8_t *data)
655{
656 //qDebug(log) << "CConnectVnc::setCursor x:" << hotspot.x << ";y:" << hotspot.y;
657 if ((width == 0) || (height == 0)) {
658 QImage cursor(1, 1, QImage::Format_ARGB32);
659 uint8_t *buffer = cursor.bits();
660 memset(buffer, 0, 4);
661 emit sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), hotspot.x, hotspot.y));
662 } else {
663 QImage cursor(width, height, QImage::Format_ARGB32);
664 uint8_t *buffer = cursor.bits();
665 memcpy(buffer, data, width * height * 4);
666 emit sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), hotspot.x, hotspot.y));
667 }
668}
669
670void CBackendVnc::setCursorPos(const rfb::Point &pos)
671{
672 //qDebug(log) << "CConnectVnc::setCursorPos x:" << pos.x << ";y:" << pos.y;
673 emit sigUpdateCursorPosition(QPoint(pos.x, pos.y));
674}
675
676void CBackendVnc::fence(uint32_t flags, unsigned int len, const uint8_t data[])
677{
678 //qDebug(log, "CConnectVnc::fence:flags:0x%X; len:%d", flags, len);
679 CMsgHandler::fence(flags, len, data);
680 if (!(flags & rfb::fenceFlagRequest))
681 return;
682
683 // We handle everything synchronously so we trivially honor these modes
684 flags = flags & (rfb::fenceFlagBlockBefore | rfb::fenceFlagBlockAfter);
685 writer()->writeFence(flags, len, data);
686 return;
687}
688
689void CBackendVnc::getUserPasswd(bool secure, std::string *user, std::string *password)
690{
691 if(password)
692 {
693 auto &user = m_pPara->m_Net.m_User;
694 *password = user.GetPassword().toStdString();
695 if(user.GetPassword().isEmpty())
696 {
697 int nRet = QDialog::Rejected;
698 auto *net = &m_pPara->m_Net;
699 emit sigBlockShowWidget("CDlgUserPassword", nRet, net);
700 if(QDialog::Accepted == nRet)
701 {
702 *password = user.GetPassword().toStdString();
703 }
704 }
705 if(!password->empty())
706 m_SecurityLevel |= CSecurityLevel::Level::Authentication;
707 }
708}
709
710int CBackendVnc::getX509File(std::string *ca, std::string *crl)
711{
712 auto &user = m_pPara->m_Net.m_User;
713 if(ca)
714 *ca = user.GetCAFile().toStdString().c_str();
715 if(crl)
716 *crl = user.GetCRLFile().toStdString().c_str();
717 return 0;
718}
719
720bool CBackendVnc::showMsgBox(rfb::MsgBoxFlags flags, const char *title, const char *text)
721{
722 qDebug(log) << title << text;
723 QMessageBox::StandardButton nRet = QMessageBox::No;
724 QMessageBox::StandardButtons fgBtn = QMessageBox::No;
725 bool bCheckBox = 0;
726 if((int)flags & (int)rfb::MsgBoxFlags::M_OK)
727 fgBtn |= QMessageBox::Ok;
728
729 if((int)flags & (int)rfb::MsgBoxFlags::M_OKCANCEL)
730 fgBtn |= QMessageBox::Ok | QMessageBox::Cancel;
731 if((int)flags & (int)rfb::MsgBoxFlags::M_YESNO)
732 fgBtn |= QMessageBox::Yes | QMessageBox::No;
733
734 emit sigBlockShowMessageBox(QString(title), QString(text),
735 fgBtn, nRet, bCheckBox);
736 if(QMessageBox::Ok == nRet
737 || QMessageBox::Yes == nRet)
738 return true;
739 return false;
740}
741
742// setName() is called when the desktop name changes
743void CBackendVnc::setName(const char *name)
744{
745 qDebug(log) << "CConnectVnc::setName:" << name;
746 CConnection::setName(name);
747 QString szName = QString::fromUtf8(server.name());
748 emit sigServerName(szName);
749}
750
751// framebufferUpdateStart() is called at the beginning of an update.
752// Here we try to send out a new framebuffer update request so that the
753// next update can be sent out in parallel with us decoding the current
754// one.
755void CBackendVnc::framebufferUpdateStart()
756{
757 //qDebug(log) << "CConnectVnc::framebufferUpdateStart()";
758 CConnection::framebufferUpdateStart();
759}
760
761// framebufferUpdateEnd() is called at the end of an update.
762// For each rectangle, the FdInStream will have timed the speed
763// of the connection, allowing us to select format and encoding
764// appropriately, and then request another incremental update.
765void CBackendVnc::framebufferUpdateEnd()
766{
767 //qDebug(log) << "CConnectVnc::framebufferUpdateEnd()";
768 rfb::CConnection::framebufferUpdateEnd();
769
770 if(m_pPara /*&& m_pPara->GetBufferEndRefresh()*/)
771 {
772 const QImage& img = dynamic_cast<CFramePixelBuffer*>(getFramebuffer())->getImage();
773 emit sigUpdateRect(img);
774 }
775}
776
777// requestNewUpdate() requests an update from the server, having set the
778// format and encoding appropriately.
779void CBackendVnc::updatePixelFormat()
780{
781 Q_ASSERT(m_pPara);
782
783 if(!m_pPara) return;
784 rfb::PixelFormat pf;
785
786 switch (m_pPara->GetColorLevel()) {
787 case CParameterVnc::Full:
788 pf = fullColourPF;
789 break;
790 case CParameterVnc::Medium:
791 pf = mediumColourPF;
792 break;
793 case CParameterVnc::Low:
794 pf = lowColourPF;
795 break;
796 case CParameterVnc::VeryLow:
797 pf = verylowColourPF;
798 break;
799 }
800
801 char str[256];
802 pf.print(str, 256);
803 qInfo(log) << "Update pixel format:" << str;
804 setPF(pf);
805}
806
807void CBackendVnc::mousePressEvent(QMouseEvent *event)
808{
809 if(!writer()) return;
810 if(m_pPara && m_pPara->GetOnlyView()) return;
811
812 uint8_t mask = 0;
813 if(event->button() & Qt::MouseButton::LeftButton)
814 mask |= 0x1;
815 if(event->button() & Qt::MouseButton::MiddleButton)
816 mask |= 0x2;
817 if(event->button() & Qt::MouseButton::RightButton)
818 mask |= 0x4;
819 if(event->button() & Qt::MouseButton::BackButton)
820 mask |= 0x80;
821
822 QPoint pos = event->pos();
823 rfb::Point p(pos.x(), pos.y());
824
825 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
826
827 try{
828 writer()->writePointerEvent(p, mask);
829 } catch (rdr::Exception& e) {
830 emit sigError(-1, e.str());
831 }
832}
833
834void CBackendVnc::mouseReleaseEvent(QMouseEvent *event)
835{
836 if(!writer()) return;
837 if(m_pPara && m_pPara->GetOnlyView()) return;
838 uint8_t mask = 0;
839 QPoint pos = event->pos();
840 rfb::Point p(pos.x(), pos.y());
841 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
842 try{
843 writer()->writePointerEvent(p, mask);
844 } catch (rdr::Exception& e) {
845 emit sigError(-1, e.str());
846 }
847}
848
849void CBackendVnc::mouseMoveEvent(QMouseEvent *event)
850{
851 if(!writer()) return;
852 if(m_pPara && m_pPara->GetOnlyView()) return;
853
854 QPoint pos = event->pos();
855 rfb::Point p(pos.x(), pos.y());
856 uint8_t mask = 0;
857 if(event->buttons() & Qt::MouseButton::LeftButton)
858 mask |= 0x1;
859 if(event->buttons() & Qt::MouseButton::MiddleButton)
860 mask |= 0x2;
861 if(event->buttons() & Qt::MouseButton::RightButton)
862 mask |= 0x4;
863 if(event->buttons() & Qt::MouseButton::BackButton)
864 mask |= 0x80;
865
866 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
867
868 try{
869 writer()->writePointerEvent(p, mask);
870 } catch (rdr::Exception& e) {
871 emit sigError(-1, e.str());
872 }
873}
874
875// https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#pointerevent
876void CBackendVnc::wheelEvent(QWheelEvent *event)
877{
878 if(!writer()) return;
879 if(m_pPara && m_pPara->GetOnlyView()) return;
880 uint8_t mask = 0;
881 if(event->buttons() & Qt::MouseButton::LeftButton)
882 mask |= 0x1;
883 if(event->buttons() & Qt::MouseButton::MiddleButton)
884 mask |= 0x2;
885 if(event->buttons() & Qt::MouseButton::RightButton)
886 mask |= 0x4;
887 if(event->buttons() & Qt::MouseButton::BackButton)
888 mask |= 0x80;
889
890 QPoint d = event->angleDelta();
891 if(d.y() > 0)
892 mask |= 0x8;
893 if(d.y() < 0)
894 mask |= 0x10;
895 if(d.x() < 0)
896 mask |= 0x20;
897 if(d.x() > 0)
898 mask |= 0x40;
899
900 QPointF pos;
901#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
902 pos = event->position();
903#else
904 pos = event->pos();
905#endif
906
907 rfb::Point p(pos.x(), pos.y());
908 //*
909 qDebug(logMouse) << Q_FUNC_INFO << event->buttons()
910#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
911 << event->button()
912#endif
913 << pos << mask; //*/
914
915 try{
916 writer()->writePointerEvent(p, mask);
917 } catch (rdr::Exception& e) {
918 emit sigError(-1, e.str());
919 }
920}
921
922void CBackendVnc::keyPressEvent(QKeyEvent *event)
923{
924 if(!writer()) return;
925 if(m_pPara && m_pPara->GetOnlyView()) return;
926 bool modifier = false;
927 if (event->modifiers() & Qt::ShiftModifier)
928 modifier = true;
929
930 uint32_t k = TranslateRfbKey(event->key(), modifier);
931 qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
932
933 try{
934 writer()->writeKeyEvent(k, 0, true);
935 } catch (rdr::Exception& e) {
936 emit sigError(-1, e.str());
937 }
938}
939
940void CBackendVnc::keyReleaseEvent(QKeyEvent *event)
941{
942 if(m_pPara && m_pPara->GetOnlyView()) return;
943 if(!writer()) return;
944 bool modifier = false;
945 if (event->modifiers() & Qt::ShiftModifier)
946 modifier = true;
947
948 uint32_t k = TranslateRfbKey(event->key(), modifier);
949 qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
950
951 try{
952 writer()->writeKeyEvent(k, 0, false);
953 } catch (rdr::Exception& e) {
954 emit sigError(-1, e.str());
955 }
956}
957
958QString CBackendVnc::ConnectInformation()
959{
960 const int len = 128;
961 char buf[len];
962 QString szInfo;
963 szInfo = QString("Desktop name: ") + server.name() + "\n";
964 szInfo += QString("Size: %1 x %2").arg(server.width()).arg(server.height()) + "\n";
965
966 // TRANSLATORS: Will be filled in with a string describing the
967 // protocol pixel format in a fairly language neutral way
968 server.pf().print(buf, len);
969 szInfo += QString("Pixel format: ") + buf + "\n";
970 szInfo += QString("Requested encoding: ") + rfb::encodingName(getPreferredEncoding()) + "\n";
971 szInfo += QString("Protocol version: %1.%2").arg(server.majorVersion).arg(server.minorVersion) + "\n";
972 szInfo += QString("Security method: ") + rfb::secTypeName(csecurity->getType()) + "\n";
973 szInfo += QString("Support local cursor: %1").arg(supportsLocalCursor) + "\n";
974 szInfo += QString("Support cursor position: %1").arg(supportsCursorPosition) + "\n";
975 szInfo += QString("Support desktop resize: %1").arg(supportsDesktopResize) + "\n";
976 szInfo += QString("Support LED state: %1").arg(supportsLEDState) + "\n";
977 szInfo += QString("Led state: %1").arg(server.ledState()) + "\n";
978 szInfo += QString("Supports QEMU KeyEvent: %1").arg(server.supportsQEMUKeyEvent) + "\n";
979 szInfo += QString("Supports Set Desktop Size: %1").arg(server.supportsSetDesktopSize) + "\n";
980 szInfo += QString("Support fance: %1").arg(server.supportsFence) + "\n";
981 szInfo += QString("Support continue updates: %1").arg(server.supportsContinuousUpdates) + "\n";
982
983 return szInfo;
984}
985
993quint32 CBackendVnc::TranslateRfbKey(quint32 inkey, bool modifier)
994{
995 quint32 k = 5000;
996
997 switch (inkey)
998 {
999 case Qt::Key_Backspace: k = XK_BackSpace; break;
1000 case Qt::Key_Tab: k = XK_Tab; break;
1001 case Qt::Key_Clear: k = XK_Clear; break;
1002 case Qt::Key_Return: k = XK_Return; break;
1003 case Qt::Key_Pause: k = XK_Pause; break;
1004 case Qt::Key_Escape: k = XK_Escape; break;
1005 case Qt::Key_Space: k = XK_space; break;
1006 case Qt::Key_Delete: k = XK_Delete; break;
1007 case Qt::Key_Period: k = XK_period; break;
1008
1009 /* International & multi-key character composition */
1010 case Qt::Key_Multi_key: k = XK_Multi_key; break;
1011 case Qt::Key_Codeinput: k = XK_Codeinput; break;
1012 case Qt::Key_SingleCandidate: k = XK_SingleCandidate; break;
1013 case Qt::Key_MultipleCandidate: k = XK_MultipleCandidate; break;
1014 case Qt::Key_PreviousCandidate: k = XK_PreviousCandidate; break;
1015
1016 /* Japanese keyboard support */
1017 case Qt::Key_Kanji: k = XK_Kanji; break;
1018 case Qt::Key_Muhenkan: k = XK_Muhenkan; break;
1019 case Qt::Key_Henkan: k = XK_Henkan; break;
1020 case Qt::Key_Romaji: k = XK_Romaji; break;
1021 case Qt::Key_Hiragana: k = XK_Hiragana; break;
1022 case Qt::Key_Katakana: k = XK_Katakana; break;
1023 case Qt::Key_Hiragana_Katakana: k = XK_Hiragana_Katakana;break;
1024 case Qt::Key_Zenkaku: k = XK_Zenkaku; break;
1025 case Qt::Key_Hankaku: k = XK_Hankaku; break;
1026 case Qt::Key_Zenkaku_Hankaku: k = XK_Zenkaku_Hankaku; break;
1027 case Qt::Key_Touroku: k = XK_Touroku; break;
1028 case Qt::Key_Massyo: k = XK_Massyo; break;
1029 case Qt::Key_Kana_Lock: k = XK_Kana_Lock; break;
1030 case Qt::Key_Kana_Shift: k = XK_Kana_Shift; break;
1031 case Qt::Key_Eisu_Shift: k = XK_Eisu_Shift; break;
1032 case Qt::Key_Eisu_toggle: k = XK_Eisu_toggle; break;
1033
1034 //special keyboard char
1035 case Qt::Key_Exclam: k = XK_exclam; break;
1036 case Qt::Key_QuoteDbl: k = XK_quotedbl; break; //"
1037 case Qt::Key_NumberSign: k = XK_numbersign; break; //#
1038 case Qt::Key_Percent: k = XK_percent; break; //%
1039 case Qt::Key_Dollar: k = XK_dollar; break; //$
1040 case Qt::Key_Ampersand: k = XK_ampersand; break; //&
1041 case Qt::Key_Apostrophe: k = XK_apostrophe; break;
1042 case Qt::Key_ParenLeft: k = XK_parenleft; break; // (
1043 case Qt::Key_ParenRight: k = XK_parenright; break; // )
1044
1045 case Qt::Key_Slash: k = XK_slash; break; // /
1046 case Qt::Key_Asterisk: k = XK_asterisk; break; //*
1047 case Qt::Key_Minus: k = XK_minus; break; //-
1048 case Qt::Key_Plus: k = XK_plus; break; //+
1049 case Qt::Key_Enter: k = XK_Return; break; //
1050 case Qt::Key_Equal: k = XK_equal; break; //=
1051 case Qt::Key_Comma: return XK_comma; //,
1052
1053 case Qt::Key_Colon: k = XK_colon;break; // :
1054 case Qt::Key_Semicolon: k = XK_semicolon; break; //;
1055 case Qt::Key_Less: k = XK_less; break; // <
1056 case Qt::Key_Greater: k = XK_greater; break; // >
1057 case Qt::Key_Question: k = XK_question; break; //?
1058 case Qt::Key_At: k = XK_at; break; //@
1059
1060 case Qt::Key_BracketLeft: k = XK_bracketleft; break;
1061 case Qt::Key_Backslash: k = XK_backslash;break;
1062 case Qt::Key_BracketRight: k = XK_bracketright;break;
1063 case Qt::Key_AsciiCircum: k = XK_asciicircum;break;
1064 case Qt::Key_Underscore: k = XK_underscore;break;
1065 case Qt::Key_QuoteLeft: k = XK_quoteleft;break;
1066 case Qt::Key_BraceLeft: k = XK_braceleft;break;
1067 case Qt::Key_Bar: k = XK_bar; break;
1068 case Qt::Key_BraceRight: k = XK_braceright;break;
1069 case Qt::Key_AsciiTilde: k = XK_asciitilde;break;
1070 case Qt::Key_nobreakspace: k = XK_nobreakspace;break;
1071 case Qt::Key_exclamdown: k = XK_exclamdown;break;
1072 case Qt::Key_cent: k = XK_cent;break;
1073 case Qt::Key_sterling: k = XK_sterling;break;
1074 case Qt::Key_currency: k = XK_currency;break;
1075 case Qt::Key_yen: k = XK_yen;break;
1076 case Qt::Key_brokenbar: k = XK_brokenbar;break;
1077 case Qt::Key_section: k = XK_section;break;
1078 case Qt::Key_diaeresis: k = XK_diaeresis;break;
1079 case Qt::Key_copyright: k = XK_copyright; break;
1080 case Qt::Key_ordfeminine: k = XK_ordfeminine; break;
1081 case Qt::Key_guillemotleft: k = XK_guillemotleft; break;
1082 case Qt::Key_guillemotright: k = XK_guillemotright; break;
1083 case Qt::Key_notsign: k = XK_notsign; break;
1084 case Qt::Key_hyphen: k = XK_hyphen; break;
1085 case Qt::Key_registered: k = XK_registered; break;
1086
1087 case Qt::Key_Up: k = XK_Up; break;
1088 case Qt::Key_Down: k = XK_Down; break;
1089 case Qt::Key_Right: k = XK_Right; break;
1090 case Qt::Key_Left: k = XK_Left; break;
1091 case Qt::Key_Insert: k = XK_Insert; break;
1092 case Qt::Key_Home: k = XK_Home; break;
1093 case Qt::Key_End: k = XK_End; break;
1094 case Qt::Key_PageUp: k = XK_Page_Up; break;
1095 case Qt::Key_PageDown: k = XK_Page_Down; break;
1096 case Qt::Key_MediaPrevious: k = XK_Prior; break;
1097 case Qt::Key_MediaNext: k = XK_Next; break;
1098 case Qt::Key_MediaPlay: k = XK_Begin; break;
1099
1100 /* Misc Functions */
1101 case Qt::Key_Select: k = XK_Select; break;
1102 case Qt::Key_Printer: k = XK_Print; break;
1103 case Qt::Key_Execute: k = XK_Execute; break;
1104 case Qt::Key_Undo: k = XK_Undo; break;
1105 case Qt::Key_Redo: k = XK_Redo; break;
1106 case Qt::Key_Menu: k = XK_Menu; break;
1107 case Qt::Key_Find: k = XK_Find; break;
1108 case Qt::Key_Exit:
1109 case Qt::Key_Cancel:
1110 case Qt::Key_Stop:
1111 k = XK_Cancel;
1112 break;
1113 case Qt::Key_Mode_switch: k = XK_Mode_switch; break;
1114
1115 case Qt::Key_F1: k = XK_F1; break;
1116 case Qt::Key_F2: k = XK_F2; break;
1117 case Qt::Key_F3: k = XK_F3; break;
1118 case Qt::Key_F4: k = XK_F4; break;
1119 case Qt::Key_F5: k = XK_F5; break;
1120 case Qt::Key_F6: k = XK_F6; break;
1121 case Qt::Key_F7: k = XK_F7; break;
1122 case Qt::Key_F8: k = XK_F8; break;
1123 case Qt::Key_F9: k = XK_F9; break;
1124 case Qt::Key_F10: k = XK_F10; break;
1125 case Qt::Key_F11: k = XK_F11; break;
1126 case Qt::Key_F12: k = XK_F12; break;
1127 case Qt::Key_F13: k = XK_F13; break;
1128 case Qt::Key_F14: k = XK_F14; break;
1129 case Qt::Key_F15: k = XK_F15; break;
1130 case Qt::Key_F16: k = XK_F16; break;
1131 case Qt::Key_F17: k = XK_F17; break;
1132 case Qt::Key_F18: k = XK_F18; break;
1133 case Qt::Key_F19: k = XK_F19; break;
1134 case Qt::Key_F20: k = XK_F20; break;
1135 case Qt::Key_F21: k = XK_F21; break;
1136 case Qt::Key_F22: k = XK_F22; break;
1137 case Qt::Key_F23: k = XK_F23; break;
1138 case Qt::Key_F24: k = XK_F24; break;
1139 case Qt::Key_F25: k = XK_F25; break;
1140 case Qt::Key_F26: k = XK_F26; break;
1141 case Qt::Key_F27: k = XK_F27; break;
1142 case Qt::Key_F28: k = XK_F28; break;
1143 case Qt::Key_F29: k = XK_F29; break;
1144 case Qt::Key_F30: k = XK_F30; break;
1145 case Qt::Key_F31: k = XK_F31; break;
1146 case Qt::Key_F32: k = XK_F32; break;
1147 case Qt::Key_F33: k = XK_F33; break;
1148 case Qt::Key_F34: k = XK_F34; break;
1149 case Qt::Key_F35: k = XK_F35; break;
1150
1151 case Qt::Key_NumLock: k = XK_Num_Lock; break;
1152 case Qt::Key_CapsLock: k = XK_Caps_Lock; break;
1153 case Qt::Key_ScrollLock: k = XK_Scroll_Lock; break;
1154
1155 case Qt::Key_Shift: k = XK_Shift_R; break; //k = XK_Shift_L; break;
1156 case Qt::Key_Control: k = XK_Control_R; break;// k = XK_Control_L; break;
1157 case Qt::Key_Alt: k = XK_Alt_R; break;//k = XK_Alt_L; break;
1158 case Qt::Key_Meta: k = XK_Meta_R; break;//k = XK_Meta_L; break;*/
1159
1160 case Qt::Key_Super_L: k = XK_Super_L; break; /* left "windows" key */
1161 case Qt::Key_Super_R: k = XK_Super_R; break; /* right "windows" key */
1162
1163 case Qt::Key_Hyper_L: k = XK_Hyper_L; break;
1164 case Qt::Key_Hyper_R: k = XK_Hyper_R; break;
1165
1166 case Qt::Key_Help: k = XK_Help; break;
1167 case Qt::Key_Print: k = XK_Print; break;
1168 case Qt::Key_SysReq: k = XK_Sys_Req; break;
1169 case Qt::Key_0: k = XK_0;break;
1170 case Qt::Key_1: k = XK_1;break;
1171 case Qt::Key_2: k = XK_2;break;
1172 case Qt::Key_3: k = XK_3;break;
1173 case Qt::Key_4: k = XK_4;break;
1174 case Qt::Key_5: k = XK_5;break;
1175 case Qt::Key_6: k = XK_6;break;
1176 case Qt::Key_7: k = XK_7;break;
1177 case Qt::Key_8: k = XK_8;break;
1178 case Qt::Key_9: k = XK_9;break;
1179 }
1180
1181 if (k == 5000)
1182 {
1183
1184 if (!modifier)
1185 {
1186 switch (inkey)
1187 {
1188 case Qt::Key_A: k = XK_a;break;
1189 case Qt::Key_B: k = XK_b;break;
1190 case Qt::Key_C: k = XK_c;break;
1191 case Qt::Key_D: k = XK_d;break;
1192 case Qt::Key_E: k = XK_e;break;
1193 case Qt::Key_F: k = XK_f;break;
1194 case Qt::Key_G: k = XK_g;break;
1195 case Qt::Key_H: k = XK_h;break;
1196 case Qt::Key_I: k = XK_i;break;
1197 case Qt::Key_J: k = XK_j;break;
1198 case Qt::Key_K: k = XK_k;break;
1199 case Qt::Key_L: k = XK_l;break;
1200 case Qt::Key_M: k = XK_m;break;
1201 case Qt::Key_N: k = XK_n;break;
1202 case Qt::Key_O: k = XK_o;break;
1203 case Qt::Key_P: k = XK_p;break;
1204 case Qt::Key_Q: k = XK_q;break;
1205 case Qt::Key_R: k = XK_r;break;
1206 case Qt::Key_S: k = XK_s;break;
1207 case Qt::Key_T: k = XK_t;break;
1208 case Qt::Key_U: k = XK_u;break;
1209 case Qt::Key_V: k = XK_v;break;
1210 case Qt::Key_W: k = XK_w;break;
1211 case Qt::Key_X: k = XK_x;break;
1212 case Qt::Key_Y: k = XK_y;break;
1213 case Qt::Key_Z: k = XK_z;break;
1214 }
1215 }
1216 else
1217 {
1218 switch (inkey)
1219 {
1220 case Qt::Key_A: k = XK_A;break;
1221 case Qt::Key_B: k = XK_B;break;
1222 case Qt::Key_C: k = XK_C;break;
1223 case Qt::Key_D: k = XK_D;break;
1224 case Qt::Key_E: k = XK_E;break;
1225 case Qt::Key_F: k = XK_F;break;
1226 case Qt::Key_G: k = XK_G;break;
1227 case Qt::Key_H: k = XK_H;break;
1228 case Qt::Key_I: k = XK_I;break;
1229 case Qt::Key_J: k = XK_J;break;
1230 case Qt::Key_K: k = XK_K;break;
1231 case Qt::Key_L: k = XK_L;break;
1232 case Qt::Key_M: k = XK_M;break;
1233 case Qt::Key_N: k = XK_N;break;
1234 case Qt::Key_O: k = XK_O;break;
1235 case Qt::Key_P: k = XK_P;break;
1236 case Qt::Key_Q: k = XK_Q;break;
1237 case Qt::Key_R: k = XK_R;break;
1238 case Qt::Key_S: k = XK_S;break;
1239 case Qt::Key_T: k = XK_T;break;
1240 case Qt::Key_U: k = XK_U;break;
1241 case Qt::Key_V: k = XK_V;break;
1242 case Qt::Key_W: k = XK_W;break;
1243 case Qt::Key_X: k = XK_X;break;
1244 case Qt::Key_Y: k = XK_Y;break;
1245 case Qt::Key_Z: k = XK_Z;break;
1246 }
1247 }
1248 }
1249
1250 return k;
1251
1252}
1253
1254void CBackendVnc::slotClipBoardChanged()
1255{
1256 //qDebug(log) << "CConnectVnc::slotClipBoardChanged()";
1257 if(!m_pPara->GetClipboard() || !getOutStream() || !writer()) return;
1258 QClipboard* pClip = QApplication::clipboard();
1259 if(pClip->ownsClipboard()) return;
1260 announceClipboard(true);
1261}
1262
1263void CBackendVnc::handleClipboardRequest()
1264{
1265 //qDebug(log) << "CConnectVnc::handleClipboardRequest";
1266 if(!m_pPara->GetClipboard() || !getOutStream() || !writer()) return;
1267 const QClipboard *clipboard = QApplication::clipboard();
1268 const QMimeData *mimeData = clipboard->mimeData();
1269
1270 /*if (mimeData->hasImage()) {
1271 // setPixmap(qvariant_cast<QPixmap>(mimeData->imageData()));
1272 } else */if (mimeData->hasText()) {
1273 QString szText = mimeData->text();
1274 qDebug(log)
1275 << "CConnectVnc::handleClipboardRequest:szText:" << szText;
1276 try{
1277 sendClipboardData(szText.toStdString().c_str());
1278 } catch (rdr::Exception& e) {
1279 qCritical(log) << "sendClipboardData exception" << e.str();
1280 }
1281 } /*else if (mimeData->hasHtml()) {
1282 QString szHtml = mimeData->html();
1283 qDebug(log)
1284 << "CConnectVnc::handleClipboardRequest:html:" << szHtml;
1285 try{
1286 sendClipboardData(mimeData->html().toStdString().c_str());
1287 } catch (rdr::Exception& e) {
1288 qCritical(log) << "sendClipboardData exception" << e.str();
1289 }
1290 }*/ else {
1291 qCritical(log) << "Cannot display data";
1292 }
1293}
1294
1295void CBackendVnc::handleClipboardAnnounce(bool available)
1296{
1297 //qDebug(log) << "CConnectVnc::handleClipboardAnnounce";
1298 if(!m_pPara->GetClipboard() || !getOutStream() || !writer()) return;
1299 if(available)
1300 this->requestClipboard();
1301}
1302
1303void CBackendVnc::handleClipboardData(const char *data)
1304{
1305 //qDebug(log) << "CConnectVnc::handleClipboardData";
1306 if(!m_pPara->GetClipboard() || !getOutStream() || !writer()) return;
1307
1308 QMimeData* pData = new QMimeData();
1309 pData->setText(QString::fromUtf8(data));
1310 emit sigSetClipboard(pData);
1311}
1312
1313void CBackendVnc::authSuccess()
1314{
1315 qDebug(log) << "CConnectVnc::authSuccess";
1316}
远程桌面接口。它由协议插件实现。
void sigUpdateRect(const QRect &r, const QImage &image)
通知视图,图像更新
quint32 TranslateRfbKey(quint32 inkey, bool modifier)
CBackendVnc::TranslateRfbKey
virtual int OnClean() override
清理
virtual int WakeUp() override
唤醒后台线程
virtual OnInitReturnValue OnInit() override
初始化
virtual int OnProcess() override
插件连接的具体操作处理。因为此插件是非Qt事件,所以在此函数中等待。
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 sigBlockShowMessageBox(const QString &szTitle, const QString &szMessage, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton &nRet, bool &checkBox, QString checkBoxContext=QString())
阻塞后台线程,并在前台线程中显示消息对话框(QMessageBox)
void sigRunning()
当插件开始成功后触发。仅由插件触发
void sigSecurityLevel(CSecurityLevel::Levels level)
当安全级别改变时触发
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
阻塞后台线程,并在前台线程中显示窗口。
ICE 通道类。此类实现一个 ICE 的通道。
Definition ChannelIce.h:27
通道接口类。此类默认实现一个 TCP 的通道。
Definition Channel.h:28
static CICE * Instance()
Single instance
Definition Ice.cpp:55
ICE 信令接口类
Definition IceSignal.h:26
远程桌面操作接口
virtual CParameterBase * GetParameter() const
Get parameter
virtual CStats * GetStats()
得到统计信息。如果有,其派生类则需要重载此函数提供统计信息。
Definition Operate.cpp:124
CParameterUser m_User
[Instance user]
@ OnlyPasswordX509None
Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile
安全级别
Definition Stats.h:79