Skip to content
Commits on Source (5)
......@@ -503,7 +503,7 @@ The RPM spec files and patches used to create the nightly builds
and releases can be found in the "contrib/rpm/el{5,6}" directories
of the TigerVNC subversion trunk. All external source tarballs
must be fetched manually and placed into the 'SOURCES' directory
under the rpmbuild root. Additonally, the following macros need
under the rpmbuild root. Additionally, the following macros need
to be defined:
EL6:
......
......@@ -21,10 +21,10 @@ include(CheckCSourceRuns)
include(CMakeMacroLibtoolFile)
project(tigervnc)
set(VERSION 1.7.0)
set(VERSION 1.8.0)
# The RC version must always be four comma-separated numbers
set(RCVERSION 1,7,0,0)
set(RCVERSION 1,8,0,0)
# Installation paths
set(BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin")
......@@ -104,8 +104,9 @@ else()
message(STATUS "32-bit build")
endif()
# CMake doesn't properly support resource compilation with MinGW. Boo!
if(MINGW)
# Versions of CMake before 2.8.7 do not properly support resource compilation
# with MinGW. Boo!
if(MINGW AND "${CMAKE_VERSION}" VERSION_LESS "2.8.7")
if(NOT DEFINED RC)
set(CMAKE_RC_COMPILER_INIT windres)
else()
......
......@@ -34,7 +34,7 @@ Incomplete and generally out of date copyright list:
Copyright (C) 2009-2011 D. R. Commander
Copyright (C) 2009-2011 Pierre Ossman for Cendio AB
Copyright (C) 2004, 2009-2011 Red Hat, Inc.
Copyright (C) 2009-2016 TigerVNC Team
Copyright (C) 2009-2017 TigerVNC Team
All Rights Reserved.
This software is distributed under the GNU General Public Licence as published
......@@ -64,9 +64,8 @@ The Windows version of TigerVNC contains the following programs:
winvnc - the TigerVNC Server for Windows. winvnc allows a Windows desktop to
be accessed remotely using a VNC viewer.
The Windows version of TigerVNC should work on Windows 2000 and later. On
Windows XP and later, winvnc may not work if the Fast User Switching or Remote
Desktop features are in use.
winvnc may not work if the Fast User Switching or Remote Desktop features are
in use.
Unix/Linux-Specific (not Mac)
......
......@@ -89,7 +89,7 @@ macro(libtool_create_control_file _target)
endif()
else()
# Detected a static library. Check whether the library pathname is
# absolute and, if not, use find_library() to get the abolute path.
# absolute and, if not, use find_library() to get the absolute path.
get_filename_component(_name ${library} NAME)
string(REPLACE "${_name}" "" _path ${library})
if(NOT "${_path}" STREQUAL "")
......@@ -132,6 +132,10 @@ macro(libtool_create_control_file _target)
file(APPEND ${_laname} "dlpreopen=''\n\n")
file(APPEND ${_laname} "libdir='/usr/lib'\n\n")
# Make sure the timestamp is updated to trigger other make invocations
add_custom_command(TARGET ${_target} POST_BUILD COMMAND
"${CMAKE_COMMAND}" -E touch "${_laname}")
# Add custom command to symlink the static library so that autotools finds
# the library in .libs. These are executed after the specified target build.
......
......@@ -9,7 +9,7 @@ add_subdirectory(rfb)
# because PIC code does not exist on that platform and MinGW complains if -fPIC
# is passed (additionally, libvnc is not used on Windows.)
if(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32)
if(NOT WIN32)
set_target_properties(os rdr network Xregion rfb
PROPERTIES COMPILE_FLAGS -fPIC)
endif()
......@@ -1310,7 +1310,7 @@ miSubtractO (
else if (r2->x1 <= x1)
{
/*
* Subtrahend preceeds minuend: nuke left edge of minuend.
* Subtrahend preceds minuend: nuke left edge of minuend.
*/
x1 = r2->x2;
if (x1 >= r1->x2)
......
......@@ -21,6 +21,8 @@
#ifndef __NETWORK_SOCKET_H__
#define __NETWORK_SOCKET_H__
#include <list>
#include <limits.h>
#include <rdr/FdInStream.h>
#include <rdr/FdOutStream.h>
......@@ -125,6 +127,10 @@ namespace network {
// resources to be freed.
virtual void removeSocket(network::Socket* sock) = 0;
// getSockets() gets a list of sockets. This can be used to generate an
// fd_set for calling select().
virtual void getSockets(std::list<network::Socket*>* sockets) = 0;
// processSocketReadEvent() tells the server there is a Socket read event.
// The implementation can indicate that the Socket is no longer active
// by calling shutdown() on it. The caller will then call removeSocket()
......
......@@ -17,7 +17,9 @@
*/
#ifndef __OS_THREAD_H__
#define __OP_THREAD_H__
#define __OS_THREAD_H__
#include <stddef.h>
namespace os {
class Mutex;
......
......@@ -101,8 +101,13 @@ void FdOutStream::flush()
blocking? timeoutms : 0);
// Timeout?
if ((n == 0) && blocking)
if (n == 0) {
// If non-blocking then we're done here
if (!blocking)
break;
throw TimedOut();
}
sentUpTo += n;
offset += n;
......
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2017 Pierre Ossman 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
......@@ -43,7 +44,6 @@ CConnection::CConnection()
state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false),
framebuffer(NULL), decoder(this)
{
security = new SecurityClient();
}
CConnection::~CConnection()
......@@ -86,7 +86,7 @@ void CConnection::setFramebuffer(ModifiablePixelBuffer* fb)
if (fb->width() > framebuffer->width()) {
rect.setXYWH(framebuffer->width(), 0,
fb->width() - fb->width(),
fb->width() - framebuffer->width(),
fb->height());
fb->fillRect(rect, black);
}
......@@ -166,7 +166,7 @@ void CConnection::processSecurityTypesMsg()
int secType = secTypeInvalid;
std::list<rdr::U8> secTypes;
secTypes = security->GetEnabledSecTypes();
secTypes = security.GetEnabledSecTypes();
if (cp.isVersion(3,3)) {
......@@ -234,7 +234,7 @@ void CConnection::processSecurityTypesMsg()
}
state_ = RFBSTATE_SECURITY;
csecurity = security->GetCSecurity(secType);
csecurity = security.GetCSecurity(secType);
processSecurityMsg();
}
......@@ -320,6 +320,13 @@ void CConnection::setExtendedDesktopSize(unsigned reason,
CMsgHandler::setExtendedDesktopSize(reason, result, w, h, layout);
}
void CConnection::readAndDecodeRect(const Rect& r, int encoding,
ModifiablePixelBuffer* pb)
{
decoder.decodeRect(r, encoding, pb);
decoder.flush();
}
void CConnection::framebufferUpdateStart()
{
CMsgHandler::framebufferUpdateStart();
......
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2017 Pierre Ossman 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
......@@ -25,6 +26,7 @@
#include <rfb/CMsgHandler.h>
#include <rfb/DecodeManager.h>
#include <rfb/SecurityClient.h>
#include <rfb/util.h>
namespace rfb {
......@@ -33,7 +35,6 @@ namespace rfb {
class CMsgWriter;
class CSecurity;
class IdentityVerifier;
class SecurityClient;
class CConnection : public CMsgHandler {
public:
......@@ -99,6 +100,9 @@ namespace rfb {
int w, int h,
const ScreenSet& layout);
virtual void readAndDecodeRect(const Rect& r, int encoding,
ModifiablePixelBuffer* pb);
virtual void framebufferUpdateStart();
virtual void framebufferUpdateEnd();
virtual void dataRect(const Rect& r, int encoding);
......@@ -144,7 +148,7 @@ namespace rfb {
stateEnum state() { return state_; }
CSecurity *csecurity;
SecurityClient *security;
SecurityClient security;
protected:
void setState(stateEnum s) { state_ = s; }
......
......@@ -50,13 +50,16 @@ namespace rfb {
int w, int h,
const ScreenSet& layout);
virtual void setCursor(int width, int height, const Point& hotspot,
void* data, void* mask) = 0;
const rdr::U8* data) = 0;
virtual void setPixelFormat(const PixelFormat& pf);
virtual void setName(const char* name);
virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
virtual void endOfContinuousUpdates();
virtual void serverInit() = 0;
virtual void readAndDecodeRect(const Rect& r, int encoding,
ModifiablePixelBuffer* pb) = 0;
virtual void framebufferUpdateStart();
virtual void framebufferUpdateEnd();
virtual void dataRect(const Rect& r, int encoding) = 0;
......
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2009-2014 Pierre Ossman for Cendio AB
* Copyright 2009-2017 Pierre Ossman 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
......@@ -16,7 +16,10 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include <assert.h>
#include <stdio.h>
#include <rfb/msgTypes.h>
#include <rdr/InStream.h>
#include <rfb/Exception.h>
......@@ -88,9 +91,15 @@ void CMsgReader::readMsg()
case pseudoEncodingLastRect:
nUpdateRectsLeft = 1; // this rectangle is the last one
break;
case pseudoEncodingXCursor:
readSetXCursor(w, h, Point(x,y));
break;
case pseudoEncodingCursor:
readSetCursor(w, h, Point(x,y));
break;
case pseudoEncodingCursorWithAlpha:
readSetCursorWithAlpha(w, h, Point(x,y));
break;
case pseudoEncodingDesktopName:
readSetDesktopName(x, y, w, h);
break;
......@@ -191,17 +200,150 @@ void CMsgReader::readRect(const Rect& r, int encoding)
handler->dataRect(r, encoding);
}
void CMsgReader::readSetXCursor(int width, int height, const Point& hotspot)
{
if (width > maxCursorSize || height > maxCursorSize)
throw Exception("Too big cursor");
rdr::U8 pr, pg, pb;
rdr::U8 sr, sg, sb;
int data_len = ((width+7)/8) * height;
int mask_len = ((width+7)/8) * height;
rdr::U8Array data(data_len);
rdr::U8Array mask(mask_len);
int x, y;
rdr::U8 buf[width*height*4];
rdr::U8* out;
if (width * height) {
pr = is->readU8();
pg = is->readU8();
pb = is->readU8();
sr = is->readU8();
sg = is->readU8();
sb = is->readU8();
is->readBytes(data.buf, data_len);
is->readBytes(mask.buf, mask_len);
}
int maskBytesPerRow = (width+7)/8;
out = buf;
for (y = 0;y < height;y++) {
for (x = 0;x < width;x++) {
int byte = y * maskBytesPerRow + x / 8;
int bit = 7 - x % 8;
if (data.buf[byte] & (1 << bit)) {
out[0] = pr;
out[1] = pg;
out[2] = pb;
} else {
out[0] = sr;
out[1] = sg;
out[2] = sb;
}
if (mask.buf[byte] & (1 << bit))
out[3] = 255;
else
out[3] = 0;
out += 4;
}
}
handler->setCursor(width, height, hotspot, buf);
}
void CMsgReader::readSetCursor(int width, int height, const Point& hotspot)
{
if (width > maxCursorSize || height > maxCursorSize)
throw Exception("Too big cursor");
int data_len = width * height * (handler->cp.pf().bpp/8);
int mask_len = ((width+7)/8) * height;
rdr::U8Array data(data_len);
rdr::U8Array mask(mask_len);
int x, y;
rdr::U8 buf[width*height*4];
rdr::U8* in;
rdr::U8* out;
is->readBytes(data.buf, data_len);
is->readBytes(mask.buf, mask_len);
handler->setCursor(width, height, hotspot, data.buf, mask.buf);
int maskBytesPerRow = (width+7)/8;
in = data.buf;
out = buf;
for (y = 0;y < height;y++) {
for (x = 0;x < width;x++) {
int byte = y * maskBytesPerRow + x / 8;
int bit = 7 - x % 8;
handler->cp.pf().rgbFromBuffer(out, in, 1);
if (mask.buf[byte] & (1 << bit))
out[3] = 255;
else
out[3] = 0;
in += handler->cp.pf().bpp/8;
out += 4;
}
}
handler->setCursor(width, height, hotspot, buf);
}
void CMsgReader::readSetCursorWithAlpha(int width, int height, const Point& hotspot)
{
if (width > maxCursorSize || height > maxCursorSize)
throw Exception("Too big cursor");
int encoding;
const PixelFormat rgbaPF(32, 32, false, true, 255, 255, 255, 16, 8, 0);
ManagedPixelBuffer pb(rgbaPF, width, height);
PixelFormat origPF;
rdr::U8* buf;
int stride;
encoding = is->readS32();
origPF = handler->cp.pf();
handler->cp.setPF(rgbaPF);
handler->readAndDecodeRect(pb.getRect(), encoding, &pb);
handler->cp.setPF(origPF);
// On-wire data has pre-multiplied alpha, but we store it
// non-pre-multiplied
buf = pb.getBufferRW(pb.getRect(), &stride);
assert(stride == width);
for (int i = 0;i < pb.area();i++) {
rdr::U8 alpha;
alpha = buf[3];
if (alpha == 0)
alpha = 1; // Avoid division by zero
buf[0] = (unsigned)buf[0] * 255/alpha;
buf[1] = (unsigned)buf[1] * 255/alpha;
buf[2] = (unsigned)buf[2] * 255/alpha;
buf[3] = alpha;
buf += 4;
}
pb.commitBufferRW(pb.getRect());
handler->setCursor(width, height, hotspot,
pb.getBuffer(pb.getRect(), &stride));
}
void CMsgReader::readSetDesktopName(int x, int y, int w, int h)
......
......@@ -60,13 +60,17 @@ namespace rfb {
void readRect(const Rect& r, int encoding);
void readSetXCursor(int width, int height, const Point& hotspot);
void readSetCursor(int width, int height, const Point& hotspot);
void readSetCursorWithAlpha(int width, int height, const Point& hotspot);
void readSetDesktopName(int x, int y, int w, int h);
void readExtendedDesktopSize(int x, int y, int w, int h);
CMsgHandler* handler;
rdr::InStream* is;
int nUpdateRectsLeft;
static const int maxCursorSize = 256;
};
}
#endif
......@@ -71,8 +71,11 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect)
int nEncodings = 0;
rdr::U32 encodings[encodingMax+3];
if (cp->supportsLocalCursor)
if (cp->supportsLocalCursor) {
encodings[nEncodings++] = pseudoEncodingXCursor;
encodings[nEncodings++] = pseudoEncodingCursor;
encodings[nEncodings++] = pseudoEncodingCursorWithAlpha;
}
if (cp->supportsDesktopResize)
encodings[nEncodings++] = pseudoEncodingDesktopSize;
if (cp->supportsExtendedDesktopSize)
......
......@@ -20,12 +20,16 @@
#include <vector>
#include <rdr/types.h>
#include <rfb/Exception.h>
#include <rfb/LogWriter.h>
#include <rfb/ComparingUpdateTracker.h>
using namespace rfb;
static LogWriter vlog("ComparingUpdateTracker");
ComparingUpdateTracker::ComparingUpdateTracker(PixelBuffer* buffer)
: fb(buffer), oldFb(fb->getPF(), 0, 0), firstCompare(true), enabled(true)
: fb(buffer), oldFb(fb->getPF(), 0, 0), firstCompare(true),
enabled(true), totalPixels(0), missedPixels(0)
{
changed.assign_union(fb->getRect());
}
......@@ -72,6 +76,13 @@ bool ComparingUpdateTracker::compare()
for (i = rects.begin(); i != rects.end(); i++)
compareRect(*i, &newChanged);
changed.get_rects(&rects);
for (i = rects.begin(); i != rects.end(); i++)
totalPixels += i->area();
newChanged.get_rects(&rects);
for (i = rects.begin(); i != rects.end(); i++)
missedPixels += i->area();
if (changed.equals(newChanged))
return false;
......@@ -165,3 +176,19 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)
newChanged->assign_union(temp);
}
}
void ComparingUpdateTracker::logStats()
{
double ratio;
char a[1024], b[1024];
siPrefix(totalPixels, "pixels", a, sizeof(a));
siPrefix(missedPixels, "pixels", b, sizeof(b));
ratio = (double)totalPixels / missedPixels;
vlog.info("%s in / %s out", a, b);
vlog.info("(1:%g ratio)", ratio);
totalPixels = missedPixels = 0;
}
......@@ -40,12 +40,17 @@ namespace rfb {
virtual void enable();
virtual void disable();
void logStats();
private:
void compareRect(const Rect& r, Region* newchanged);
PixelBuffer* fb;
ManagedPixelBuffer oldFb;
bool firstCompare;
bool enabled;
rdr::U32 totalPixels, missedPixels;
};
}
......
......@@ -23,24 +23,14 @@
#include <ctype.h>
#include <string.h>
#include <os/Mutex.h>
#include <rfb/util.h>
#include <rfb/Configuration.h>
#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
#include <rfb/Threading.h>
#ifdef __RFB_THREADING_IMPL
// On platforms that support Threading, we use Locks to make getData safe
#define LOCK_CONFIG Lock l(*configLock())
rfb::Mutex* configLock_ = 0;
static rfb::Mutex* configLock() {
if (!configLock_)
configLock_ = new rfb::Mutex;
return configLock_;
}
#else
#define LOCK_CONFIG
#endif
#define LOCK_CONFIG os::AutoMutex a(mutex)
#include <rdr/HexOutStream.h>
#include <rdr/HexInStream.h>
......@@ -195,9 +185,12 @@ VoidParameter::VoidParameter(const char* name_, const char* desc_,
_next = conf->head;
conf->head = this;
mutex = new os::Mutex();
}
VoidParameter::~VoidParameter() {
delete mutex;
}
const char*
......
......@@ -45,6 +45,8 @@
#include <rfb/util.h>
namespace os { class Mutex; }
namespace rfb {
class VoidParameter;
struct ParameterIterator;
......@@ -174,6 +176,8 @@ namespace rfb {
bool immutable;
const char* name;
const char* description;
os::Mutex* mutex;
};
class AliasParameter : public VoidParameter {
......
......@@ -31,6 +31,7 @@ ConnParams::ConnParams()
: majorVersion(0), minorVersion(0),
width(0), height(0), useCopyRect(false),
supportsLocalCursor(false), supportsLocalXCursor(false),
supportsLocalCursorWithAlpha(false),
supportsDesktopResize(false), supportsExtendedDesktopSize(false),
supportsDesktopRename(false), supportsLastRect(false),
supportsSetDesktopSize(false), supportsFence(false),
......@@ -39,11 +40,13 @@ ConnParams::ConnParams()
subsampling(subsampleUndefined), name_(0), verStrPos(0)
{
setName("");
cursor_ = new Cursor(0, 0, Point(), NULL);
}
ConnParams::~ConnParams()
{
delete [] name_;
delete cursor_;
}
bool ConnParams::readVersion(rdr::InStream* is, bool* done)
......@@ -86,17 +89,8 @@ void ConnParams::setName(const char* name)
void ConnParams::setCursor(const Cursor& other)
{
const rdr::U8* data;
int stride;
cursor_.hotspot = other.hotspot;
cursor_.setPF(other.getPF());
cursor_.setSize(other.width(), other.height());
data = other.getBuffer(other.getRect(), &stride);
cursor_.imageRect(cursor_.getRect(), data, stride);
memcpy(cursor_.mask.buf, other.mask.buf, cursor_.maskLen());
delete cursor_;
cursor_ = new Cursor(other);
}
bool ConnParams::supportsEncoding(rdr::S32 encoding) const
......@@ -108,6 +102,7 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
{
useCopyRect = false;
supportsLocalCursor = false;
supportsLocalCursorWithAlpha = false;
supportsDesktopResize = false;
supportsExtendedDesktopSize = false;
supportsLocalXCursor = false;
......@@ -131,6 +126,9 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
case pseudoEncodingXCursor:
supportsLocalXCursor = true;
break;
case pseudoEncodingCursorWithAlpha:
supportsLocalCursorWithAlpha = true;
break;
case pseudoEncodingDesktopSize:
supportsDesktopResize = true;
break;
......