sconnection.cxx
来自「linux可以运行程序源码」· CXX 代码 · 共 323 行
CXX
323 行
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */#include <stdio.h>#include <string.h>#include <rfb/Exception.h>#include <rfb/secTypes.h>#include <rfb/SMsgReaderV3.h>#include <rfb/SMsgWriterV3.h>#include <rfb/SConnection.h>#include <rfb/ServerCore.h>#include <rfb/LogWriter.h>using namespace rfb;static LogWriter vlog("SConnection");// AccessRights valuesconst SConnection::AccessRights SConnection::AccessView = 0x0001;const SConnection::AccessRights SConnection::AccessKeyEvents = 0x0002;const SConnection::AccessRights SConnection::AccessPtrEvents = 0x0004;const SConnection::AccessRights SConnection::AccessCutText = 0x0008;const SConnection::AccessRights SConnection::AccessDefault = 0x03ff;const SConnection::AccessRights SConnection::AccessNoQuery = 0x0400;const SConnection::AccessRights SConnection::AccessFull = 0xffff;SConnection::SConnection(SSecurityFactory* secFact, bool reverseConnection_) : readyForSetColourMapEntries(false), is(0), os(0), reader_(0), writer_(0), security(0), securityFactory(secFact), state_(RFBSTATE_UNINITIALISED), reverseConnection(reverseConnection_){ defaultMajorVersion = 3; defaultMinorVersion = 8; if (rfb::Server::protocol3_3) defaultMinorVersion = 3; cp.setVersion(defaultMajorVersion, defaultMinorVersion);}SConnection::~SConnection(){ if (security) security->destroy(); deleteReaderAndWriter();}void SConnection::deleteReaderAndWriter(){ delete reader_; reader_ = 0; delete writer_; writer_ = 0;}void SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_){ is = is_; os = os_;}void SConnection::initialiseProtocol(){ cp.writeVersion(os); state_ = RFBSTATE_PROTOCOL_VERSION;}void SConnection::processMsg(){ switch (state_) { case RFBSTATE_PROTOCOL_VERSION: processVersionMsg(); break; case RFBSTATE_SECURITY_TYPE: processSecurityTypeMsg(); break; case RFBSTATE_SECURITY: processSecurityMsg(); break; case RFBSTATE_INITIALISATION: processInitMsg(); break; case RFBSTATE_NORMAL: reader_->readMsg(); break; case RFBSTATE_QUERYING: throw Exception("SConnection::processMsg: bogus data from client while " "querying"); case RFBSTATE_UNINITIALISED: throw Exception("SConnection::processMsg: not initialised yet?"); default: throw Exception("SConnection::processMsg: invalid state"); }}void SConnection::processVersionMsg(){ vlog.debug("reading protocol version"); bool done; if (!cp.readVersion(is, &done)) { state_ = RFBSTATE_INVALID; throw Exception("reading version failed: not an RFB client?"); } if (!done) return; vlog.info("Client needs protocol version %d.%d", cp.majorVersion, cp.minorVersion); if (cp.majorVersion != 3) { // unknown protocol version char msg[256]; sprintf(msg,"Error: client needs protocol version %d.%d, server has %d.%d", cp.majorVersion, cp.minorVersion, defaultMajorVersion, defaultMinorVersion); throwConnFailedException(msg); } if (cp.minorVersion != 3 && cp.minorVersion != 7 && cp.minorVersion != 8) { vlog.error("Client uses unofficial protocol version %d.%d", cp.majorVersion,cp.minorVersion); if (cp.minorVersion >= 8) cp.minorVersion = 8; else if (cp.minorVersion == 7) cp.minorVersion = 7; else cp.minorVersion = 3; vlog.error("Assuming compatibility with version %d.%d", cp.majorVersion,cp.minorVersion); } versionReceived(); std::list<rdr::U8> secTypes; std::list<rdr::U8>::iterator i; securityFactory->getSecTypes(&secTypes, reverseConnection); if (cp.isVersion(3,3)) { // cope with legacy 3.3 client only if "no authentication" or "vnc // authentication" is supported. for (i=secTypes.begin(); i!=secTypes.end(); i++) { if (*i == secTypeNone || *i == secTypeVncAuth) break; } if (i == secTypes.end()) { char msg[256]; sprintf(msg,"No supported security type for %d.%d client", cp.majorVersion, cp.minorVersion); throwConnFailedException(msg); } os->writeU32(*i); if (*i == secTypeNone) os->flush(); state_ = RFBSTATE_SECURITY; security = securityFactory->getSSecurity(*i, reverseConnection); processSecurityMsg(); return; } // list supported security types for >=3.7 clients if (secTypes.empty()) throwConnFailedException("No supported security types"); os->writeU8(secTypes.size()); for (i=secTypes.begin(); i!=secTypes.end(); i++) os->writeU8(*i); os->flush(); state_ = RFBSTATE_SECURITY_TYPE;}void SConnection::processSecurityTypeMsg(){ vlog.debug("processing security type message"); int secType = is->readU8(); // Verify that the requested security type should be offered std::list<rdr::U8> secTypes; std::list<rdr::U8>::iterator i; securityFactory->getSecTypes(&secTypes, reverseConnection); for (i=secTypes.begin(); i!=secTypes.end(); i++) if (*i == secType) break; if (i == secTypes.end()) throw Exception("Requested security type not available"); vlog.info("Client requests security type %s(%d)", secTypeName(secType),secType); try { state_ = RFBSTATE_SECURITY; security = securityFactory->getSSecurity(secType, reverseConnection); } catch (rdr::Exception& e) { throwConnFailedException(e.str()); } processSecurityMsg();}void SConnection::processSecurityMsg(){ vlog.debug("processing security message"); try { bool done = security->processMsg(this); if (done) { state_ = RFBSTATE_QUERYING; queryConnection(security->getUserName()); } } catch (AuthFailureException& e) { vlog.error("AuthFailureException: %s", e.str()); os->writeU32(secResultFailed); if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message os->writeString(e.str()); os->flush(); throw; }}void SConnection::processInitMsg(){ vlog.debug("reading client initialisation"); reader_->readClientInit();}void SConnection::throwConnFailedException(const char* msg){ vlog.info(msg); if (state_ == RFBSTATE_PROTOCOL_VERSION) { if (cp.majorVersion == 3 && cp.minorVersion == 3) { os->writeU32(0); os->writeString(msg); os->flush(); } else { os->writeU8(0); os->writeString(msg); os->flush(); } } state_ = RFBSTATE_INVALID; throw ConnFailedException(msg);}void SConnection::writeConnFailedFromScratch(const char* msg, rdr::OutStream* os){ os->writeBytes("RFB 003.003\n", 12); os->writeU32(0); os->writeString(msg); os->flush();}void SConnection::versionReceived(){}void SConnection::authSuccess(){}void SConnection::queryConnection(const char* userName){ approveConnection(true);}void SConnection::approveConnection(bool accept, const char* reason){ if (state_ != RFBSTATE_QUERYING) throw Exception("SConnection::approveConnection: invalid state"); if (!reason) reason = "Authentication failure"; if (!cp.beforeVersion(3,8) || security->getType() != secTypeNone) { if (accept) { os->writeU32(secResultOK); } else { os->writeU32(secResultFailed); if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message os->writeString(reason); } os->flush(); } if (accept) { state_ = RFBSTATE_INITIALISATION; reader_ = new SMsgReaderV3(this, is); writer_ = new SMsgWriterV3(&cp, os); authSuccess(); } else { state_ = RFBSTATE_INVALID; throw AuthFailureException(reason); }}void SConnection::setInitialColourMap(){}void SConnection::clientInit(bool shared){ writer_->writeServerInit(); state_ = RFBSTATE_NORMAL;}void SConnection::setPixelFormat(const PixelFormat& pf){ SMsgHandler::setPixelFormat(pf); readyForSetColourMapEntries = true;}void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental){ if (!readyForSetColourMapEntries) { readyForSetColourMapEntries = true; if (!cp.pf().trueColour) { setInitialColourMap(); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?