瀏覽代碼

Merge branches 'meta' and 'tlscrash' of https://github.com/CendioOssman/tigervnc

tags/v1.9.90
Pierre Ossman 5 年之前
父節點
當前提交
20041a2924
共有 44 個文件被更改,包括 349 次插入167 次删除
  1. 1
    4
      cmake/StaticBuild.cmake
  2. 4
    3
      common/rfb/CConnection.cxx
  3. 5
    2
      common/rfb/CSecurity.h
  4. 2
    1
      common/rfb/CSecurityNone.h
  5. 1
    1
      common/rfb/CSecurityPlain.cxx
  6. 2
    2
      common/rfb/CSecurityPlain.h
  7. 6
    6
      common/rfb/CSecurityStack.cxx
  8. 3
    2
      common/rfb/CSecurityStack.h
  9. 28
    15
      common/rfb/CSecurityTLS.cxx
  10. 8
    4
      common/rfb/CSecurityTLS.h
  11. 5
    4
      common/rfb/CSecurityVeNCrypt.cxx
  12. 2
    2
      common/rfb/CSecurityVeNCrypt.h
  13. 1
    1
      common/rfb/CSecurityVncAuth.cxx
  14. 2
    2
      common/rfb/CSecurityVncAuth.h
  15. 11
    2
      common/rfb/Congestion.cxx
  16. 79
    13
      common/rfb/EncodeManager.cxx
  17. 10
    1
      common/rfb/EncodeManager.h
  18. 4
    2
      common/rfb/Encoder.cxx
  19. 9
    1
      common/rfb/Encoder.h
  20. 1
    1
      common/rfb/HextileEncoder.cxx
  21. 1
    1
      common/rfb/RREEncoder.cxx
  22. 1
    1
      common/rfb/RawEncoder.cxx
  23. 5
    4
      common/rfb/SConnection.cxx
  24. 5
    2
      common/rfb/SSecurity.h
  25. 2
    1
      common/rfb/SSecurityNone.h
  26. 2
    2
      common/rfb/SSecurityPlain.cxx
  27. 2
    2
      common/rfb/SSecurityPlain.h
  28. 8
    5
      common/rfb/SSecurityStack.cxx
  29. 3
    2
      common/rfb/SSecurityStack.h
  30. 32
    19
      common/rfb/SSecurityTLS.cxx
  31. 7
    4
      common/rfb/SSecurityTLS.h
  32. 5
    4
      common/rfb/SSecurityVeNCrypt.cxx
  33. 2
    2
      common/rfb/SSecurityVeNCrypt.h
  34. 4
    3
      common/rfb/SSecurityVncAuth.cxx
  35. 2
    2
      common/rfb/SSecurityVncAuth.h
  36. 27
    17
      common/rfb/SecurityClient.cxx
  37. 1
    1
      common/rfb/SecurityClient.h
  38. 11
    11
      common/rfb/SecurityServer.cxx
  39. 3
    2
      common/rfb/SecurityServer.h
  40. 7
    1
      common/rfb/TightJPEGEncoder.cxx
  41. 2
    0
      common/rfb/TightJPEGEncoder.h
  42. 1
    1
      common/rfb/Timer.cxx
  43. 31
    11
      common/rfb/VNCSConnectionST.cxx
  44. 1
    0
      common/rfb/VNCSConnectionST.h

+ 1
- 4
cmake/StaticBuild.cmake 查看文件

@@ -19,10 +19,7 @@ if(BUILD_STATIC)
set(BUILD_STATIC_GCC 1)

set(JPEG_LIBRARIES "-Wl,-Bstatic -ljpeg -Wl,-Bdynamic")

if(WIN32)
set(ZLIB_LIBRARIES "-Wl,-Bstatic -lz -Wl,-Bdynamic")
endif()
set(ZLIB_LIBRARIES "-Wl,-Bstatic -lz -Wl,-Bdynamic")

# gettext is included in libc on many unix systems
if(NOT LIBC_HAS_DGETTEXT)

+ 4
- 3
common/rfb/CConnection.cxx 查看文件

@@ -49,7 +49,8 @@ CConnection::CConnection()
CConnection::~CConnection()
{
setFramebuffer(NULL);
if (csecurity) csecurity->destroy();
if (csecurity)
delete csecurity;
delete reader_;
reader_ = 0;
delete writer_;
@@ -234,14 +235,14 @@ void CConnection::processSecurityTypesMsg()
}

state_ = RFBSTATE_SECURITY;
csecurity = security.GetCSecurity(secType);
csecurity = security.GetCSecurity(this, secType);
processSecurityMsg();
}

void CConnection::processSecurityMsg()
{
vlog.debug("processing security message");
if (csecurity->processMsg(this)) {
if (csecurity->processMsg()) {
state_ = RFBSTATE_SECURITY_RESULT;
processSecurityResultMsg();
}

+ 5
- 2
common/rfb/CSecurity.h 查看文件

@@ -44,9 +44,9 @@ namespace rfb {
class CConnection;
class CSecurity {
public:
CSecurity(CConnection* cc) { this->cc = cc; }
virtual ~CSecurity() {}
virtual bool processMsg(CConnection* cc)=0;
virtual void destroy() { delete this; }
virtual bool processMsg() = 0;
virtual int getType() const = 0;
virtual const char* description() const = 0;
virtual bool isSecure() const { return false; }
@@ -56,6 +56,9 @@ namespace rfb {
* It MUST be set by viewer.
*/
static UserPasswdGetter *upg;

protected:
CConnection* cc;
};
}
#endif

+ 2
- 1
common/rfb/CSecurityNone.h 查看文件

@@ -29,7 +29,8 @@ namespace rfb {

class CSecurityNone : public CSecurity {
public:
virtual bool processMsg(CConnection* cc) { return true; }
CSecurityNone(CConnection* cc) : CSecurity(cc) {}
virtual bool processMsg() { return true; }
virtual int getType() const {return secTypeNone;}
virtual const char* description() const {return "No Encryption";}
};

+ 1
- 1
common/rfb/CSecurityPlain.cxx 查看文件

@@ -26,7 +26,7 @@

using namespace rfb;

bool CSecurityPlain::processMsg(CConnection* cc)
bool CSecurityPlain::processMsg()
{
rdr::OutStream* os = cc->getOutStream();


+ 2
- 2
common/rfb/CSecurityPlain.h 查看文件

@@ -26,8 +26,8 @@ namespace rfb {

class CSecurityPlain : public CSecurity {
public:
CSecurityPlain() {}
virtual bool processMsg(CConnection* cc);
CSecurityPlain(CConnection* cc) : CSecurity(cc) {}
virtual bool processMsg();
virtual int getType() const { return secTypePlain; }
virtual const char* description() const { return "ask for username and password"; }
};

+ 6
- 6
common/rfb/CSecurityStack.cxx 查看文件

@@ -21,9 +21,9 @@

using namespace rfb;

CSecurityStack::CSecurityStack(int Type, const char*Name, CSecurity* s0,
CSecurity* s1)
:name(Name),type(Type)
CSecurityStack::CSecurityStack(CConnection* cc, int Type, const char* Name,
CSecurity* s0, CSecurity* s1)
: CSecurity(cc), name(Name), type(Type)
{
state = 0;
state0 = s0;
@@ -38,12 +38,12 @@ CSecurityStack::~CSecurityStack()
delete state1;
}

bool CSecurityStack::processMsg(CConnection* cc)
bool CSecurityStack::processMsg()
{
bool res=true;
if (state == 0) {
if (state0)
res = state0->processMsg(cc);
res = state0->processMsg();

if (!res)
return res;
@@ -53,7 +53,7 @@ bool CSecurityStack::processMsg(CConnection* cc)

if (state == 1) {
if(state1)
res = state1->processMsg(cc);
res = state1->processMsg();

if(!res)
return res;

+ 3
- 2
common/rfb/CSecurityStack.h 查看文件

@@ -27,9 +27,10 @@ namespace rfb {

class CSecurityStack : public CSecurity {
public:
CSecurityStack(int Type, const char *Name, CSecurity* s0 = 0, CSecurity* s1 = 0);
CSecurityStack(CConnection* cc, int Type, const char *Name,
CSecurity* s0 = NULL, CSecurity* s1 = NULL);
~CSecurityStack();
virtual bool processMsg(CConnection* cc);
virtual bool processMsg();
virtual int getType() const {return type;};
virtual const char* description() const {return name;}
virtual bool isSecure() const;

+ 28
- 15
common/rfb/CSecurityTLS.cxx 查看文件

@@ -67,8 +67,9 @@ StringParameter CSecurityTLS::X509CRL("X509CRL", "X509 CRL file", "", ConfViewer

static LogWriter vlog("TLS");

CSecurityTLS::CSecurityTLS(bool _anon) : session(0), anon_cred(0),
anon(_anon), fis(0), fos(0)
CSecurityTLS::CSecurityTLS(CConnection* cc, bool _anon)
: CSecurity(cc), session(NULL), anon_cred(NULL), cert_cred(NULL),
anon(_anon), tlsis(NULL), tlsos(NULL), rawis(NULL), rawos(NULL)
{
cafile = X509CA.getData();
crlfile = X509CRL.getData();
@@ -115,6 +116,21 @@ void CSecurityTLS::shutdown(bool needbye)
cert_cred = 0;
}

if (rawis && rawos) {
cc->setStreams(rawis, rawos);
rawis = NULL;
rawos = NULL;
}

if (tlsis) {
delete tlsis;
tlsis = NULL;
}
if (tlsos) {
delete tlsos;
tlsos = NULL;
}

if (session) {
gnutls_deinit(session);
session = 0;
@@ -126,18 +142,13 @@ CSecurityTLS::~CSecurityTLS()
{
shutdown(true);

if (fis)
delete fis;
if (fos)
delete fos;

delete[] cafile;
delete[] crlfile;

gnutls_global_deinit();
}

bool CSecurityTLS::processMsg(CConnection* cc)
bool CSecurityTLS::processMsg()
{
rdr::InStream* is = cc->getInStream();
rdr::OutStream* os = cc->getOutStream();
@@ -164,17 +175,19 @@ bool CSecurityTLS::processMsg(CConnection* cc)
throw AuthFailureException("gnutls_set_default_priority failed");

setParam();
}

rdr::TLSInStream *tlsis = new rdr::TLSInStream(is, session);
rdr::TLSOutStream *tlsos = new rdr::TLSOutStream(os, session);
// Create these early as they set up the push/pull functions
// for GnuTLS
tlsis = new rdr::TLSInStream(is, session);
tlsos = new rdr::TLSOutStream(os, session);

rawis = is;
rawos = os;
}

int err;
err = gnutls_handshake(session);
if (err != GNUTLS_E_SUCCESS) {
delete tlsis;
delete tlsos;

if (!gnutls_error_is_fatal(err))
return false;

@@ -185,7 +198,7 @@ bool CSecurityTLS::processMsg(CConnection* cc)

checkSession();

cc->setStreams(fis = tlsis, fos = tlsos);
cc->setStreams(tlsis, tlsos);

return true;
}

+ 8
- 4
common/rfb/CSecurityTLS.h 查看文件

@@ -42,9 +42,9 @@ namespace rfb {
class UserMsgBox;
class CSecurityTLS : public CSecurity {
public:
CSecurityTLS(bool _anon);
CSecurityTLS(CConnection* cc, bool _anon);
virtual ~CSecurityTLS();
virtual bool processMsg(CConnection* cc);
virtual bool processMsg();
virtual int getType() const { return anon ? secTypeTLSNone : secTypeX509None; }
virtual const char* description() const
{ return anon ? "TLS Encryption without VncAuth" : "X509 Encryption without VncAuth"; }
@@ -69,8 +69,12 @@ namespace rfb {
bool anon;

char *cafile, *crlfile;
rdr::InStream* fis;
rdr::OutStream* fos;

rdr::InStream* tlsis;
rdr::OutStream* tlsos;

rdr::InStream* rawis;
rdr::OutStream* rawos;
};
}


+ 5
- 4
common/rfb/CSecurityVeNCrypt.cxx 查看文件

@@ -36,7 +36,8 @@ using namespace std;

static LogWriter vlog("CVeNCrypt");

CSecurityVeNCrypt::CSecurityVeNCrypt(SecurityClient* sec) : csecurity(NULL), security(sec)
CSecurityVeNCrypt::CSecurityVeNCrypt(CConnection* cc, SecurityClient* sec)
: CSecurity(cc), csecurity(NULL), security(sec)
{
haveRecvdMajorVersion = false;
haveRecvdMinorVersion = false;
@@ -59,7 +60,7 @@ CSecurityVeNCrypt::~CSecurityVeNCrypt()
delete[] availableTypes;
}

bool CSecurityVeNCrypt::processMsg(CConnection* cc)
bool CSecurityVeNCrypt::processMsg()
{
InStream* is = cc->getInStream();
OutStream* os = cc->getOutStream();
@@ -171,7 +172,7 @@ bool CSecurityVeNCrypt::processMsg(CConnection* cc)
if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)
throw AuthFailureException("No valid VeNCrypt sub-type");

csecurity = security->GetCSecurity(chosenType);
csecurity = security->GetCSecurity(cc, chosenType);

/* send chosen type to server */
os->writeU32(chosenType);
@@ -188,7 +189,7 @@ bool CSecurityVeNCrypt::processMsg(CConnection* cc)
throw AuthFailureException("The server reported 0 VeNCrypt sub-types");
}

return csecurity->processMsg(cc);
return csecurity->processMsg();
}

const char* CSecurityVeNCrypt::description() const

+ 2
- 2
common/rfb/CSecurityVeNCrypt.h 查看文件

@@ -34,9 +34,9 @@ namespace rfb {
class CSecurityVeNCrypt : public CSecurity {
public:

CSecurityVeNCrypt(SecurityClient* sec);
CSecurityVeNCrypt(CConnection* cc, SecurityClient* sec);
~CSecurityVeNCrypt();
virtual bool processMsg(CConnection* cc);// { return true; }
virtual bool processMsg();
int getType() const {return chosenType;}
virtual const char* description() const;
virtual bool isSecure() const;

+ 1
- 1
common/rfb/CSecurityVncAuth.cxx 查看文件

@@ -40,7 +40,7 @@ using namespace rfb;

static const int vncAuthChallengeSize = 16;

bool CSecurityVncAuth::processMsg(CConnection* cc)
bool CSecurityVncAuth::processMsg()
{
rdr::InStream* is = cc->getInStream();
rdr::OutStream* os = cc->getOutStream();

+ 2
- 2
common/rfb/CSecurityVncAuth.h 查看文件

@@ -25,9 +25,9 @@ namespace rfb {

class CSecurityVncAuth : public CSecurity {
public:
CSecurityVncAuth(void) {}
CSecurityVncAuth(CConnection* cc) : CSecurity(cc) {}
virtual ~CSecurityVncAuth() {}
virtual bool processMsg(CConnection* cc);
virtual bool processMsg();
virtual int getType() const {return secTypeVncAuth;};
virtual const char* description() const {return "No Encryption";}
};

+ 11
- 2
common/rfb/Congestion.cxx 查看文件

@@ -291,11 +291,20 @@ int Congestion::getUncongestedETA()

size_t Congestion::getBandwidth()
{
size_t bandwidth;

// No measurements yet? Guess RTT of 60 ms
if (safeBaseRTT == (unsigned)-1)
return congWindow * 1000 / 60;
bandwidth = congWindow * 1000 / 60;
else
bandwidth = congWindow * 1000 / safeBaseRTT;

// We're still probing so guess actual bandwidth is halfway between
// the current guess and the next one (slow start doubles each time)
if (inSlowStart)
bandwidth = bandwidth + bandwidth / 2;

return congWindow * 1000 / safeBaseRTT;
return bandwidth;
}

void Congestion::debugTrace(const char* filename, int fd)

+ 79
- 13
common/rfb/EncodeManager.cxx 查看文件

@@ -1,6 +1,7 @@
/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved.
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
* Copyright 2014-2018 Pierre Ossman for Cendio AB
* Copyright 2018 Peter Astrand for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -50,6 +51,9 @@ static const int SolidSearchBlock = 16;
// Don't bother with blocks smaller than this
static const int SolidBlockMinArea = 2048;

// How long we consider a region recently changed (in ms)
static const int RecentChangeTimeout = 50;

namespace rfb {

enum EncoderClass {
@@ -123,7 +127,8 @@ static const char *encoderTypeName(EncoderType type)
return "Unknown Encoder Type";
}

EncodeManager::EncodeManager(SConnection* conn_) : conn(conn_)
EncodeManager::EncodeManager(SConnection* conn_)
: conn(conn_), recentChangeTimer(this)
{
StatsVector::iterator iter;

@@ -253,23 +258,57 @@ bool EncodeManager::needsLosslessRefresh(const Region& req)
return !lossyRegion.intersect(req).is_empty();
}

int EncodeManager::getNextLosslessRefresh(const Region& req)
{
// Do we have something we can send right away?
if (!pendingRefreshRegion.intersect(req).is_empty())
return 0;

assert(needsLosslessRefresh(req));
assert(recentChangeTimer.isStarted());

return recentChangeTimer.getNextTimeout();
}

void EncodeManager::pruneLosslessRefresh(const Region& limits)
{
lossyRegion.assign_intersect(limits);
pendingRefreshRegion.assign_intersect(limits);
}

void EncodeManager::writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb,
const RenderedCursor* renderedCursor)
{
doUpdate(true, ui.changed, ui.copied, ui.copy_delta, pb, renderedCursor);
doUpdate(true, ui.changed, ui.copied, ui.copy_delta, pb, renderedCursor);

recentlyChangedRegion.assign_union(ui.changed);
recentlyChangedRegion.assign_union(ui.copied);
if (!recentChangeTimer.isStarted())
recentChangeTimer.start(RecentChangeTimeout);
}

void EncodeManager::writeLosslessRefresh(const Region& req, const PixelBuffer* pb,
const RenderedCursor* renderedCursor,
size_t maxUpdateSize)
{
doUpdate(false, getLosslessRefresh(req, maxUpdateSize),
Region(), Point(), pb, renderedCursor);
doUpdate(false, getLosslessRefresh(req, maxUpdateSize),
Region(), Point(), pb, renderedCursor);
}

bool EncodeManager::handleTimeout(Timer* t)
{
if (t == &recentChangeTimer) {
// Any lossy region that wasn't recently updated can
// now be scheduled for a refresh
pendingRefreshRegion.assign_union(lossyRegion.subtract(recentlyChangedRegion));
recentlyChangedRegion.clear();

// Will there be more to do? (i.e. do we need another round)
if (!lossyRegion.subtract(pendingRefreshRegion).is_empty())
return true;
}

return false;
}

void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
@@ -325,6 +364,8 @@ void EncodeManager::prepareEncoders(bool allowLossy)
enum EncoderClass solid, bitmap, bitmapRLE;
enum EncoderClass indexed, indexedRLE, fullColour;

bool allowJPEG;

rdr::S32 preferred;

std::vector<int>::iterator iter;
@@ -332,6 +373,12 @@ void EncodeManager::prepareEncoders(bool allowLossy)
solid = bitmap = bitmapRLE = encoderRaw;
indexed = indexedRLE = fullColour = encoderRaw;

allowJPEG = conn->cp.pf().bpp >= 16;
if (!allowLossy) {
if (encoders[encoderTightJPEG]->losslessQuality == -1)
allowJPEG = false;
}

// Try to respect the client's wishes
preferred = conn->getPreferredEncoding();
switch (preferred) {
@@ -344,8 +391,7 @@ void EncodeManager::prepareEncoders(bool allowLossy)
bitmapRLE = indexedRLE = fullColour = encoderHextile;
break;
case encodingTight:
if (encoders[encoderTightJPEG]->isSupported() &&
(conn->cp.pf().bpp >= 16) && allowLossy)
if (encoders[encoderTightJPEG]->isSupported() && allowJPEG)
fullColour = encoderTightJPEG;
else
fullColour = encoderTight;
@@ -362,8 +408,7 @@ void EncodeManager::prepareEncoders(bool allowLossy)
// Any encoders still unassigned?

if (fullColour == encoderRaw) {
if (encoders[encoderTightJPEG]->isSupported() &&
(conn->cp.pf().bpp >= 16) && allowLossy)
if (encoders[encoderTightJPEG]->isSupported() && allowJPEG)
fullColour = encoderTightJPEG;
else if (encoders[encoderZRLE]->isSupported())
fullColour = encoderZRLE;
@@ -421,9 +466,17 @@ void EncodeManager::prepareEncoders(bool allowLossy)
encoder = encoders[*iter];

encoder->setCompressLevel(conn->cp.compressLevel);
encoder->setQualityLevel(conn->cp.qualityLevel);
encoder->setFineQualityLevel(conn->cp.fineQualityLevel,
conn->cp.subsampling);

if (allowLossy) {
encoder->setQualityLevel(conn->cp.qualityLevel);
encoder->setFineQualityLevel(conn->cp.fineQualityLevel,
conn->cp.subsampling);
} else {
int level = __rfbmax(conn->cp.qualityLevel,
encoder->losslessQuality);
encoder->setQualityLevel(level);
encoder->setFineQualityLevel(-1, subsampleUndefined);
}
}
}

@@ -437,8 +490,11 @@ Region EncodeManager::getLosslessRefresh(const Region& req,
// We make a conservative guess at the compression ratio at 2:1
maxUpdateSize *= 2;

// We will measure pixels, not bytes (assume 32 bpp)
maxUpdateSize /= 4;

area = 0;
lossyRegion.intersect(req).get_rects(&rects);
pendingRefreshRegion.intersect(req).get_rects(&rects);
while (!rects.empty()) {
size_t idx;
Rect rect;
@@ -525,11 +581,17 @@ Encoder *EncodeManager::startRect(const Rect& rect, int type)
encoder = encoders[klass];
conn->writer()->startRect(rect, encoder->encoding);

if (encoder->flags & EncoderLossy)
if ((encoder->flags & EncoderLossy) &&
((encoder->losslessQuality == -1) ||
(encoder->getQualityLevel() < encoder->losslessQuality)))
lossyRegion.assign_union(Region(rect));
else
lossyRegion.assign_subtract(Region(rect));

// This was either a rect getting refreshed, or a rect that just got
// new content. Either way we should not try to refresh it anymore.
pendingRefreshRegion.assign_subtract(Region(rect));

return encoder;
}

@@ -574,6 +636,10 @@ void EncodeManager::writeCopyRects(const Region& copied, const Point& delta)
lossyCopy.translate(delta);
lossyCopy.assign_intersect(copied);
lossyRegion.assign_union(lossyCopy);

// Stop any pending refresh as a copy is enough that we consider
// this region to be recently changed
pendingRefreshRegion.assign_subtract(copied);
}

void EncodeManager::writeSolidRects(Region *changed, const PixelBuffer* pb)

+ 10
- 1
common/rfb/EncodeManager.h 查看文件

@@ -25,6 +25,7 @@
#include <rdr/types.h>
#include <rfb/PixelBuffer.h>
#include <rfb/Region.h>
#include <rfb/Timer.h>

namespace rfb {
class SConnection;
@@ -36,7 +37,7 @@ namespace rfb {

struct RectInfo;

class EncodeManager {
class EncodeManager : public Timer::Callback {
public:
EncodeManager(SConnection* conn);
~EncodeManager();
@@ -47,6 +48,8 @@ namespace rfb {
static bool supported(int encoding);

bool needsLosslessRefresh(const Region& req);
int getNextLosslessRefresh(const Region& req);

void pruneLosslessRefresh(const Region& limits);

void writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb,
@@ -57,6 +60,8 @@ namespace rfb {
size_t maxUpdateSize);

protected:
virtual bool handleTimeout(Timer* t);

void doUpdate(bool allowLossy, const Region& changed,
const Region& copied, const Point& copy_delta,
const PixelBuffer* pb,
@@ -117,6 +122,10 @@ namespace rfb {
std::vector<int> activeEncoders;

Region lossyRegion;
Region recentlyChangedRegion;
Region pendingRefreshRegion;

Timer recentChangeTimer;

struct EncoderStats {
unsigned rects;

+ 4
- 2
common/rfb/Encoder.cxx 查看文件

@@ -24,9 +24,11 @@
using namespace rfb;

Encoder::Encoder(SConnection *conn_, int encoding_,
enum EncoderFlags flags_, unsigned int maxPaletteSize_) :
enum EncoderFlags flags_,
unsigned int maxPaletteSize_, int losslessQuality_) :
encoding(encoding_), flags(flags_),
maxPaletteSize(maxPaletteSize_), conn(conn_)
maxPaletteSize(maxPaletteSize_), losslessQuality(losslessQuality_),
conn(conn_)
{
}


+ 9
- 1
common/rfb/Encoder.h 查看文件

@@ -42,7 +42,8 @@ namespace rfb {
class Encoder {
public:
Encoder(SConnection* conn, int encoding,
enum EncoderFlags flags, unsigned int maxPaletteSize);
enum EncoderFlags flags, unsigned int maxPaletteSize=-1,
int losslessQuality=-1);
virtual ~Encoder();

// isSupported() should return a boolean indicating if this encoder
@@ -54,6 +55,9 @@ namespace rfb {
virtual void setQualityLevel(int level) {};
virtual void setFineQualityLevel(int quality, int subsampling) {};

virtual int getCompressLevel() { return -1; };
virtual int getQualityLevel() { return -1; };

// writeRect() is the main interface that encodes the given rectangle
// with data from the PixelBuffer onto the SConnection given at
// encoder creation.
@@ -92,6 +96,10 @@ namespace rfb {
// Maximum size of the palette per rect
const unsigned int maxPaletteSize;

// Minimum level where the quality loss will not be noticed by
// most users (only relevant with EncoderLossy flag)
const int losslessQuality;

protected:
SConnection* conn;
};

+ 1
- 1
common/rfb/HextileEncoder.cxx 查看文件

@@ -45,7 +45,7 @@ BoolParameter improvedHextile("ImprovedHextile",
#undef BPP

HextileEncoder::HextileEncoder(SConnection* conn) :
Encoder(conn, encodingHextile, EncoderPlain, -1)
Encoder(conn, encodingHextile, EncoderPlain)
{
}


+ 1
- 1
common/rfb/RREEncoder.cxx 查看文件

@@ -37,7 +37,7 @@ using namespace rfb;
#undef BPP

RREEncoder::RREEncoder(SConnection* conn) :
Encoder(conn, encodingRRE, EncoderPlain, -1)
Encoder(conn, encodingRRE, EncoderPlain)
{
}


+ 1
- 1
common/rfb/RawEncoder.cxx 查看文件

@@ -25,7 +25,7 @@
using namespace rfb;

RawEncoder::RawEncoder(SConnection* conn) :
Encoder(conn, encodingRaw, EncoderPlain, -1)
Encoder(conn, encodingRaw, EncoderPlain)
{
}


+ 5
- 4
common/rfb/SConnection.cxx 查看文件

@@ -64,7 +64,8 @@ SConnection::SConnection()

SConnection::~SConnection()
{
if (ssecurity) ssecurity->destroy();
if (ssecurity)
delete ssecurity;
delete reader_;
reader_ = 0;
delete writer_;
@@ -155,7 +156,7 @@ void SConnection::processVersionMsg()
os->writeU32(*i);
if (*i == secTypeNone) os->flush();
state_ = RFBSTATE_SECURITY;
ssecurity = security.GetSSecurity(*i);
ssecurity = security.GetSSecurity(this, *i);
processSecurityMsg();
return;
}
@@ -198,7 +199,7 @@ void SConnection::processSecurityType(int secType)

try {
state_ = RFBSTATE_SECURITY;
ssecurity = security.GetSSecurity(secType);
ssecurity = security.GetSSecurity(this, secType);
} catch (rdr::Exception& e) {
throwConnFailedException("%s", e.str());
}
@@ -210,7 +211,7 @@ void SConnection::processSecurityMsg()
{
vlog.debug("processing security message");
try {
bool done = ssecurity->processMsg(this);
bool done = ssecurity->processMsg();
if (done) {
state_ = RFBSTATE_QUERYING;
setAccessRights(ssecurity->getAccessRights());

+ 5
- 2
common/rfb/SSecurity.h 查看文件

@@ -52,9 +52,9 @@ namespace rfb {

class SSecurity {
public:
SSecurity(SConnection* sc) { this->sc = sc; }
virtual ~SSecurity() {}
virtual bool processMsg(SConnection* sc)=0;
virtual void destroy() { delete this; }
virtual bool processMsg() = 0;
virtual int getType() const = 0;

// getUserName() gets the name of the user attempting authentication. The
@@ -64,6 +64,9 @@ namespace rfb {
virtual const char* getUserName() const = 0;

virtual SConnection::AccessRights getAccessRights() const { return SConnection::AccessDefault; }

protected:
SConnection* sc;
};

}

+ 2
- 1
common/rfb/SSecurityNone.h 查看文件

@@ -28,7 +28,8 @@ namespace rfb {

class SSecurityNone : public SSecurity {
public:
virtual bool processMsg(SConnection* sc) { return true; }
SSecurityNone(SConnection* sc) : SSecurity(sc) {}
virtual bool processMsg() { return true; }
virtual int getType() const {return secTypeNone;}
virtual const char* getUserName() const {return 0;}
};

+ 2
- 2
common/rfb/SSecurityPlain.cxx 查看文件

@@ -60,7 +60,7 @@ bool PasswordValidator::validUser(const char* username)
return false;
}

SSecurityPlain::SSecurityPlain()
SSecurityPlain::SSecurityPlain(SConnection* sc) : SSecurity(sc)
{
#ifdef HAVE_PAM
valid = new UnixPasswordValidator();
@@ -73,7 +73,7 @@ SSecurityPlain::SSecurityPlain()
state = 0;
}

bool SSecurityPlain::processMsg(SConnection* sc)
bool SSecurityPlain::processMsg()
{
rdr::InStream* is = sc->getInStream();
char* pw;

+ 2
- 2
common/rfb/SSecurityPlain.h 查看文件

@@ -47,8 +47,8 @@ namespace rfb {

class SSecurityPlain : public SSecurity {
public:
SSecurityPlain();
virtual bool processMsg(SConnection* sc);
SSecurityPlain(SConnection* sc);
virtual bool processMsg();
virtual int getType() const { return secTypePlain; };
virtual const char* getUserName() const { return username.buf; }


+ 8
- 5
common/rfb/SSecurityStack.cxx 查看文件

@@ -20,8 +20,11 @@

using namespace rfb;

SSecurityStack::SSecurityStack(int Type, SSecurity* s0, SSecurity* s1)
:state(0), state0(s0), state1(s1), type(Type) {}
SSecurityStack::SSecurityStack(SConnection* sc, int Type,
SSecurity* s0, SSecurity* s1)
: SSecurity(sc), state(0), state0(s0), state1(s1), type(Type)
{
}

SSecurityStack::~SSecurityStack()
{
@@ -31,13 +34,13 @@ SSecurityStack::~SSecurityStack()
delete state1;
}

bool SSecurityStack::processMsg(SConnection* cc)
bool SSecurityStack::processMsg()
{
bool res = true;

if (state == 0) {
if (state0)
res = state0->processMsg(cc);
res = state0->processMsg();
if (!res)
return res;
state++;
@@ -45,7 +48,7 @@ bool SSecurityStack::processMsg(SConnection* cc)

if (state == 1) {
if (state1)
res = state1->processMsg(cc);
res = state1->processMsg();
if (!res)
return res;
state++;

+ 3
- 2
common/rfb/SSecurityStack.h 查看文件

@@ -26,9 +26,10 @@ namespace rfb {

class SSecurityStack : public SSecurity {
public:
SSecurityStack(int Type, SSecurity* s0 = 0, SSecurity* s1 = 0);
SSecurityStack(SConnection* sc, int Type,
SSecurity* s0 = NULL, SSecurity* s1 = NULL);
~SSecurityStack();
virtual bool processMsg(SConnection* cc);
virtual bool processMsg();
virtual int getType() const { return type; };
virtual const char* getUserName() const;
virtual SConnection::AccessRights getAccessRights() const;

+ 32
- 19
common/rfb/SSecurityTLS.cxx 查看文件

@@ -49,9 +49,10 @@ StringParameter SSecurityTLS::X509_KeyFile

static LogWriter vlog("TLS");

SSecurityTLS::SSecurityTLS(bool _anon) : session(0), dh_params(0),
anon_cred(0), cert_cred(0),
anon(_anon), fis(0), fos(0)
SSecurityTLS::SSecurityTLS(SConnection* sc, bool _anon)
: SSecurity(sc), session(NULL), dh_params(NULL), anon_cred(NULL),
cert_cred(NULL), anon(_anon), tlsis(NULL), tlsos(NULL),
rawis(NULL), rawos(NULL)
{
certfile = X509_CertFile.getData();
keyfile = X509_KeyFile.getData();
@@ -84,6 +85,21 @@ void SSecurityTLS::shutdown()
cert_cred = 0;
}

if (rawis && rawos) {
sc->setStreams(rawis, rawos);
rawis = NULL;
rawos = NULL;
}

if (tlsis) {
delete tlsis;
tlsis = NULL;
}
if (tlsos) {
delete tlsos;
tlsos = NULL;
}

if (session) {
gnutls_deinit(session);
session = 0;
@@ -95,25 +111,20 @@ SSecurityTLS::~SSecurityTLS()
{
shutdown();

if (fis)
delete fis;
if (fos)
delete fos;

delete[] keyfile;
delete[] certfile;

gnutls_global_deinit();
}

bool SSecurityTLS::processMsg(SConnection *sc)
bool SSecurityTLS::processMsg()
{
rdr::InStream* is = sc->getInStream();
rdr::OutStream* os = sc->getOutStream();

vlog.debug("Process security message (session %p)", session);

if (!session) {
rdr::InStream* is = sc->getInStream();
rdr::OutStream* os = sc->getOutStream();

if (gnutls_init(&session, GNUTLS_SERVER) != GNUTLS_E_SUCCESS)
throw AuthFailureException("gnutls_init failed");

@@ -130,17 +141,19 @@ bool SSecurityTLS::processMsg(SConnection *sc)

os->writeU8(1);
os->flush();
}

rdr::TLSInStream *tlsis = new rdr::TLSInStream(is, session);
rdr::TLSOutStream *tlsos = new rdr::TLSOutStream(os, session);
// Create these early as they set up the push/pull functions
// for GnuTLS
tlsis = new rdr::TLSInStream(is, session);
tlsos = new rdr::TLSOutStream(os, session);

rawis = is;
rawos = os;
}

int err;
err = gnutls_handshake(session);
if (err != GNUTLS_E_SUCCESS) {
delete tlsis;
delete tlsos;

if (!gnutls_error_is_fatal(err)) {
vlog.debug("Deferring completion of TLS handshake: %s", gnutls_strerror(err));
return false;
@@ -152,7 +165,7 @@ bool SSecurityTLS::processMsg(SConnection *sc)

vlog.debug("Handshake completed");

sc->setStreams(fis = tlsis, fos = tlsos);
sc->setStreams(tlsis, tlsos);

return true;
}

+ 7
- 4
common/rfb/SSecurityTLS.h 查看文件

@@ -40,9 +40,9 @@ namespace rfb {

class SSecurityTLS : public SSecurity {
public:
SSecurityTLS(bool _anon);
SSecurityTLS(SConnection* sc, bool _anon);
virtual ~SSecurityTLS();
virtual bool processMsg(SConnection* sc);
virtual bool processMsg();
virtual const char* getUserName() const {return 0;}
virtual int getType() const { return anon ? secTypeTLSNone : secTypeX509None;}

@@ -63,8 +63,11 @@ namespace rfb {
int type;
bool anon;

rdr::InStream* fis;
rdr::OutStream* fos;
rdr::InStream* tlsis;
rdr::OutStream* tlsos;

rdr::InStream* rawis;
rdr::OutStream* rawos;
};

}

+ 5
- 4
common/rfb/SSecurityVeNCrypt.cxx 查看文件

@@ -38,7 +38,8 @@ using namespace std;

static LogWriter vlog("SVeNCrypt");

SSecurityVeNCrypt::SSecurityVeNCrypt(SecurityServer *sec) : security(sec)
SSecurityVeNCrypt::SSecurityVeNCrypt(SConnection* sc, SecurityServer *sec)
: SSecurity(sc), security(sec)
{
ssecurity = NULL;
haveSentVersion = false;
@@ -63,7 +64,7 @@ SSecurityVeNCrypt::~SSecurityVeNCrypt()
}
}

bool SSecurityVeNCrypt::processMsg(SConnection* sc)
bool SSecurityVeNCrypt::processMsg()
{
rdr::InStream* is = sc->getInStream();
rdr::OutStream* os = sc->getOutStream();
@@ -166,11 +167,11 @@ bool SSecurityVeNCrypt::processMsg(SConnection* sc)
if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)
throw AuthFailureException("No valid VeNCrypt sub-type");

ssecurity = security->GetSSecurity(chosenType);
ssecurity = security->GetSSecurity(sc, chosenType);
}

/* continue processing the messages */
return ssecurity->processMsg(sc);
return ssecurity->processMsg();
}

const char* SSecurityVeNCrypt::getUserName() const

+ 2
- 2
common/rfb/SSecurityVeNCrypt.h 查看文件

@@ -36,9 +36,9 @@ namespace rfb {

class SSecurityVeNCrypt : public SSecurity {
public:
SSecurityVeNCrypt(SecurityServer *sec);
SSecurityVeNCrypt(SConnection* sc, SecurityServer *sec);
~SSecurityVeNCrypt();
virtual bool processMsg(SConnection* sc);// { return true; }
virtual bool processMsg();
virtual int getType() const { return chosenType; }
virtual const char* getUserName() const;
virtual SConnection::AccessRights getAccessRights() const;

+ 4
- 3
common/rfb/SSecurityVncAuth.cxx 查看文件

@@ -48,8 +48,9 @@ VncAuthPasswdParameter SSecurityVncAuth::vncAuthPasswd
("Password", "Obfuscated binary encoding of the password which clients must supply to "
"access the server", &SSecurityVncAuth::vncAuthPasswdFile);

SSecurityVncAuth::SSecurityVncAuth(void)
: sentChallenge(false), responsePos(0), pg(&vncAuthPasswd), accessRights(0)
SSecurityVncAuth::SSecurityVncAuth(SConnection* sc)
: SSecurity(sc), sentChallenge(false), responsePos(0),
pg(&vncAuthPasswd), accessRights(0)
{
}

@@ -70,7 +71,7 @@ bool SSecurityVncAuth::verifyResponse(const PlainPasswd &password)
return memcmp(response, expectedResponse, vncAuthChallengeSize) == 0;
}

bool SSecurityVncAuth::processMsg(SConnection* sc)
bool SSecurityVncAuth::processMsg()
{
rdr::InStream* is = sc->getInStream();
rdr::OutStream* os = sc->getOutStream();

+ 2
- 2
common/rfb/SSecurityVncAuth.h 查看文件

@@ -51,8 +51,8 @@ namespace rfb {

class SSecurityVncAuth : public SSecurity {
public:
SSecurityVncAuth(void);
virtual bool processMsg(SConnection* sc);
SSecurityVncAuth(SConnection* sc);
virtual bool processMsg();
virtual int getType() const {return secTypeVncAuth;}
virtual const char* getUserName() const {return 0;}
virtual SConnection::AccessRights getAccessRights() const { return accessRights; }

+ 27
- 17
common/rfb/SecurityClient.cxx 查看文件

@@ -55,7 +55,7 @@ StringParameter SecurityClient::secTypes
#endif
ConfViewer);

CSecurity* SecurityClient::GetCSecurity(U32 secType)
CSecurity* SecurityClient::GetCSecurity(CConnection* cc, U32 secType)
{
assert (CSecurity::upg != NULL); /* (upg == NULL) means bug in the viewer */
#ifdef HAVE_GNUTLS
@@ -66,29 +66,39 @@ CSecurity* SecurityClient::GetCSecurity(U32 secType)
goto bail;

switch (secType) {
case secTypeNone: return new CSecurityNone();
case secTypeVncAuth: return new CSecurityVncAuth();
case secTypeVeNCrypt: return new CSecurityVeNCrypt(this);
case secTypePlain: return new CSecurityPlain();
case secTypeNone: return new CSecurityNone(cc);
case secTypeVncAuth: return new CSecurityVncAuth(cc);
case secTypeVeNCrypt: return new CSecurityVeNCrypt(cc, this);
case secTypePlain: return new CSecurityPlain(cc);
#ifdef HAVE_GNUTLS
case secTypeTLSNone:
return new CSecurityStack(secTypeTLSNone, "TLS with no password",
new CSecurityTLS(true));
return new CSecurityStack(cc, secTypeTLSNone,
"TLS with no password",
new CSecurityTLS(cc, true));
case secTypeTLSVnc:
return new CSecurityStack(secTypeTLSVnc, "TLS with VNCAuth",
new CSecurityTLS(true), new CSecurityVncAuth());
return new CSecurityStack(cc, secTypeTLSVnc,
"TLS with VNCAuth",
new CSecurityTLS(cc, true),
new CSecurityVncAuth(cc));
case secTypeTLSPlain:
return new CSecurityStack(secTypeTLSPlain, "TLS with Username/Password",
new CSecurityTLS(true), new CSecurityPlain());
return new CSecurityStack(cc, secTypeTLSPlain,
"TLS with Username/Password",
new CSecurityTLS(cc, true),
new CSecurityPlain(cc));
case secTypeX509None:
return new CSecurityStack(secTypeX509None, "X509 with no password",
new CSecurityTLS(false));
return new CSecurityStack(cc, secTypeX509None,
"X509 with no password",
new CSecurityTLS(cc, false));
case secTypeX509Vnc:
return new CSecurityStack(secTypeX509Vnc, "X509 with VNCAuth",
new CSecurityTLS(false), new CSecurityVncAuth());
return new CSecurityStack(cc, secTypeX509Vnc,
"X509 with VNCAuth",
new CSecurityTLS(cc, false),
new CSecurityVncAuth(cc));
case secTypeX509Plain:
return new CSecurityStack(secTypeX509Plain, "X509 with Username/Password",
new CSecurityTLS(false), new CSecurityPlain());
return new CSecurityStack(cc, secTypeX509Plain,
"X509 with Username/Password",
new CSecurityTLS(cc, false),
new CSecurityPlain(cc));
#endif
}


+ 1
- 1
common/rfb/SecurityClient.h 查看文件

@@ -33,7 +33,7 @@ namespace rfb {
SecurityClient(void) : Security(secTypes) {}

/* Create client side CSecurity class instance */
CSecurity* GetCSecurity(rdr::U32 secType);
CSecurity* GetCSecurity(CConnection* cc, rdr::U32 secType);

static void setDefaults(void);


+ 11
- 11
common/rfb/SecurityServer.cxx 查看文件

@@ -49,29 +49,29 @@ StringParameter SecurityServer::secTypes
#endif
ConfServer);

SSecurity* SecurityServer::GetSSecurity(U32 secType)
SSecurity* SecurityServer::GetSSecurity(SConnection* sc, U32 secType)
{
if (!IsSupported(secType))
goto bail;

switch (secType) {
case secTypeNone: return new SSecurityNone();
case secTypeVncAuth: return new SSecurityVncAuth();
case secTypeVeNCrypt: return new SSecurityVeNCrypt(this);
case secTypePlain: return new SSecurityPlain();
case secTypeNone: return new SSecurityNone(sc);
case secTypeVncAuth: return new SSecurityVncAuth(sc);
case secTypeVeNCrypt: return new SSecurityVeNCrypt(sc, this);
case secTypePlain: return new SSecurityPlain(sc);
#ifdef HAVE_GNUTLS
case secTypeTLSNone:
return new SSecurityStack(secTypeTLSNone, new SSecurityTLS(true));
return new SSecurityStack(sc, secTypeTLSNone, new SSecurityTLS(sc, true));
case secTypeTLSVnc:
return new SSecurityStack(secTypeTLSVnc, new SSecurityTLS(true), new SSecurityVncAuth());
return new SSecurityStack(sc, secTypeTLSVnc, new SSecurityTLS(sc, true), new SSecurityVncAuth(sc));
case secTypeTLSPlain:
return new SSecurityStack(secTypeTLSPlain, new SSecurityTLS(true), new SSecurityPlain());
return new SSecurityStack(sc, secTypeTLSPlain, new SSecurityTLS(sc, true), new SSecurityPlain(sc));
case secTypeX509None:
return new SSecurityStack(secTypeX509None, new SSecurityTLS(false));
return new SSecurityStack(sc, secTypeX509None, new SSecurityTLS(sc, false));
case secTypeX509Vnc:
return new SSecurityStack(secTypeX509None, new SSecurityTLS(false), new SSecurityVncAuth());
return new SSecurityStack(sc, secTypeX509None, new SSecurityTLS(sc, false), new SSecurityVncAuth(sc));
case secTypeX509Plain:
return new SSecurityStack(secTypeX509Plain, new SSecurityTLS(false), new SSecurityPlain());
return new SSecurityStack(sc, secTypeX509Plain, new SSecurityTLS(sc, false), new SSecurityPlain(sc));
#endif
}


+ 3
- 2
common/rfb/SecurityServer.h 查看文件

@@ -24,7 +24,8 @@
#include <rfb/Security.h>

namespace rfb {

class SConnection;
class SSecurity;

class SecurityServer : public Security {
@@ -32,7 +33,7 @@ namespace rfb {
SecurityServer(void) : Security(secTypes) {}

/* Create server side SSecurity class instance */
SSecurity* GetSSecurity(rdr::U32 secType);
SSecurity* GetSSecurity(SConnection* sc, rdr::U32 secType);

static StringParameter secTypes;
};

+ 7
- 1
common/rfb/TightJPEGEncoder.cxx 查看文件

@@ -64,7 +64,8 @@ static const struct TightJPEGConfiguration conf[10] = {


TightJPEGEncoder::TightJPEGEncoder(SConnection* conn) :
Encoder(conn, encodingTight, (EncoderFlags)(EncoderUseNativePF | EncoderLossy), -1),
Encoder(conn, encodingTight,
(EncoderFlags)(EncoderUseNativePF | EncoderLossy), -1, 9),
qualityLevel(-1), fineQuality(-1), fineSubsampling(subsampleUndefined)
{
}
@@ -101,6 +102,11 @@ void TightJPEGEncoder::setFineQualityLevel(int quality, int subsampling)
fineSubsampling = subsampling;
}

int TightJPEGEncoder::getQualityLevel()
{
return qualityLevel;
}

void TightJPEGEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
{
const rdr::U8* buffer;

+ 2
- 0
common/rfb/TightJPEGEncoder.h 查看文件

@@ -35,6 +35,8 @@ namespace rfb {
virtual void setQualityLevel(int level);
virtual void setFineQualityLevel(int quality, int subsampling);

virtual int getQualityLevel();

virtual void writeRect(const PixelBuffer* pb, const Palette& palette);
virtual void writeSolidRect(int width, int height,
const PixelFormat& pf,

+ 1
- 1
common/rfb/Timer.cxx 查看文件

@@ -151,7 +151,7 @@ int Timer::getTimeoutMs() {
int Timer::getRemainingMs() {
timeval now;
gettimeofday(&now, 0);
return __rfbmax(0, diffTimeMillis(pending.front()->dueTime, now));
return __rfbmax(0, diffTimeMillis(dueTime, now));
}

bool Timer::isBefore(timeval other) {

+ 31
- 11
common/rfb/VNCSConnectionST.cxx 查看文件

@@ -1,5 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2009-2018 Pierre Ossman for Cendio AB
* Copyright 2018 Peter Astrand for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -48,7 +49,7 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
inProcessMessages(false),
pendingSyncFence(false), syncFence(false), fenceFlags(0),
fenceDataLen(0), fenceData(NULL), congestionTimer(this),
server(server_), updates(false),
losslessTimer(this), server(server_), updates(false),
updateRenderedCursor(false), removeRenderedCursor(false),
continuousUpdates(false), encodeManager(this), pointerEventTime(0),
clientHasCursor(false),
@@ -839,7 +840,8 @@ void VNCSConnectionST::supportsLEDState()
bool VNCSConnectionST::handleTimeout(Timer* t)
{
try {
if (t == &congestionTimer)
if ((t == &congestionTimer) ||
(t == &losslessTimer))
writeFramebufferUpdate();
} catch (rdr::Exception& e) {
close(e.str());
@@ -1065,28 +1067,46 @@ void VNCSConnectionST::writeDataUpdate()
}

// Return if there is nothing to send the client.
if (ui.is_empty() && !writer()->needFakeUpdate()) {
int eta;

if (ui.is_empty() && !writer()->needFakeUpdate() &&
!encodeManager.needsLosslessRefresh(req))
return;
// Any lossless refresh that needs handling?
if (!encodeManager.needsLosslessRefresh(req))
return;

// Now? Or later?
eta = encodeManager.getNextLosslessRefresh(req);
if (eta > 0) {
losslessTimer.start(eta);
return;
}
}

writeRTTPing();

if (!ui.is_empty())
encodeManager.writeUpdate(ui, server->getPixelBuffer(), cursor);
else {
size_t maxUpdateSize;
int nextUpdate;

// FIXME: If continuous updates aren't used then the client might
// be slower than frameRate in its requests and we could
// afford a larger update size
nextUpdate = server->msToNextUpdate();
if (nextUpdate > 0) {
size_t bandwidth, maxUpdateSize;

// FIXME: Bandwidth estimation without congestion control
maxUpdateSize = congestion.getBandwidth() *
server->msToNextUpdate() / 1000;
// FIXME: Bandwidth estimation without congestion control
bandwidth = congestion.getBandwidth();

encodeManager.writeLosslessRefresh(req, server->getPixelBuffer(),
cursor, maxUpdateSize);
// FIXME: Hard coded value for maximum CPU throughput
if (bandwidth > 5000000)
bandwidth = 5000000;

maxUpdateSize = bandwidth * nextUpdate / 1000;
encodeManager.writeLosslessRefresh(req, server->getPixelBuffer(),
cursor, maxUpdateSize);
}
}

writeRTTPing();

+ 1
- 0
common/rfb/VNCSConnectionST.h 查看文件

@@ -191,6 +191,7 @@ namespace rfb {

Congestion congestion;
Timer congestionTimer;
Timer losslessTimer;

VNCServerST* server;
SimpleUpdateTracker updates;

Loading…
取消
儲存