Browse Source

Merge branch 'types' of https://github.com/CendioOssman/tigervnc

pull/1611/head
Pierre Ossman 1 year ago
parent
commit
15a0da6157
100 changed files with 1950 additions and 1529 deletions
  1. 2
    2
      common/network/Socket.h
  2. 61
    60
      common/network/TcpSocket.cxx
  3. 5
    4
      common/network/TcpSocket.h
  4. 8
    8
      common/network/UnixSocket.cxx
  5. 2
    2
      common/network/UnixSocket.h
  6. 48
    53
      common/os/os.cxx
  7. 21
    26
      common/os/os.h
  8. 10
    9
      common/rdr/AESInStream.cxx
  9. 2
    2
      common/rdr/AESInStream.h
  10. 4
    3
      common/rdr/AESOutStream.cxx
  11. 4
    4
      common/rdr/AESOutStream.h
  12. 4
    4
      common/rdr/BufferedInStream.cxx
  13. 1
    1
      common/rdr/BufferedInStream.h
  14. 4
    4
      common/rdr/BufferedOutStream.cxx
  15. 2
    2
      common/rdr/BufferedOutStream.h
  16. 0
    1
      common/rdr/Exception.cxx
  17. 7
    7
      common/rdr/FdInStream.cxx
  18. 6
    6
      common/rdr/FdOutStream.cxx
  19. 1
    1
      common/rdr/FileInStream.cxx
  20. 6
    46
      common/rdr/HexInStream.cxx
  21. 0
    3
      common/rdr/HexInStream.h
  22. 5
    29
      common/rdr/HexOutStream.cxx
  23. 0
    3
      common/rdr/HexOutStream.h
  24. 30
    22
      common/rdr/InStream.h
  25. 4
    4
      common/rdr/MemInStream.h
  26. 3
    3
      common/rdr/MemOutStream.h
  27. 26
    20
      common/rdr/OutStream.h
  28. 3
    3
      common/rdr/RandomStream.cxx
  29. 2
    2
      common/rdr/TLSInStream.cxx
  30. 1
    1
      common/rdr/TLSInStream.h
  31. 1
    1
      common/rdr/TLSOutStream.cxx
  32. 1
    1
      common/rdr/TLSOutStream.h
  33. 2
    2
      common/rdr/ZlibInStream.cxx
  34. 0
    77
      common/rdr/types.h
  35. 2
    11
      common/rfb/Blacklist.cxx
  36. 2
    7
      common/rfb/Blacklist.h
  37. 35
    42
      common/rfb/CConnection.cxx
  38. 13
    11
      common/rfb/CConnection.h
  39. 1
    1
      common/rfb/CMakeLists.txt
  40. 8
    10
      common/rfb/CMsgHandler.cxx
  41. 11
    11
      common/rfb/CMsgHandler.h
  42. 77
    75
      common/rfb/CMsgReader.cxx
  43. 3
    3
      common/rfb/CMsgReader.h
  44. 11
    11
      common/rfb/CMsgWriter.cxx
  45. 10
    10
      common/rfb/CMsgWriter.h
  46. 26
    27
      common/rfb/CSecurityDH.cxx
  47. 20
    21
      common/rfb/CSecurityMSLogonII.cxx
  48. 7
    8
      common/rfb/CSecurityPlain.cxx
  49. 56
    59
      common/rfb/CSecurityRSAAES.cxx
  50. 11
    11
      common/rfb/CSecurityRSAAES.h
  51. 67
    52
      common/rfb/CSecurityTLS.cxx
  52. 0
    2
      common/rfb/CSecurityTLS.h
  53. 6
    5
      common/rfb/CSecurityVeNCrypt.cxx
  54. 6
    5
      common/rfb/CSecurityVeNCrypt.h
  55. 6
    9
      common/rfb/CSecurityVncAuth.cxx
  56. 6
    8
      common/rfb/ClientParams.cxx
  57. 13
    11
      common/rfb/ClientParams.h
  58. 23
    23
      common/rfb/ComparingUpdateTracker.cxx
  59. 52
    59
      common/rfb/Configuration.cxx
  60. 28
    29
      common/rfb/Configuration.h
  61. 1
    0
      common/rfb/Congestion.cxx
  62. 37
    36
      common/rfb/Cursor.cxx
  63. 9
    7
      common/rfb/Cursor.h
  64. 10
    13
      common/rfb/DecodeManager.cxx
  65. 111
    50
      common/rfb/EncodeManager.cxx
  66. 13
    21
      common/rfb/EncodeManager.h
  67. 0
    98
      common/rfb/EncodeManagerBPP.cxx
  68. 12
    12
      common/rfb/Encoder.cxx
  69. 3
    2
      common/rfb/Encoder.h
  70. 4
    4
      common/rfb/H264Decoder.cxx
  71. 5
    4
      common/rfb/H264DecoderContext.h
  72. 7
    7
      common/rfb/H264LibavDecoderContext.cxx
  73. 4
    4
      common/rfb/H264LibavDecoderContext.h
  74. 5
    5
      common/rfb/H264WinDecoderContext.cxx
  75. 8
    8
      common/rfb/H264WinDecoderContext.h
  76. 87
    15
      common/rfb/HextileDecoder.cxx
  77. 10
    0
      common/rfb/HextileDecoder.h
  78. 503
    21
      common/rfb/HextileEncoder.cxx
  79. 16
    2
      common/rfb/HextileEncoder.h
  80. 7
    9
      common/rfb/Hostname.h
  81. 3
    3
      common/rfb/InputHandler.h
  82. 9
    9
      common/rfb/JpegCompressor.cxx
  83. 1
    1
      common/rfb/JpegCompressor.h
  84. 10
    10
      common/rfb/JpegDecompressor.cxx
  85. 1
    1
      common/rfb/JpegDecompressor.h
  86. 4
    3
      common/rfb/KeyRemapper.cxx
  87. 4
    3
      common/rfb/KeyRemapper.h
  88. 17
    15
      common/rfb/LogWriter.cxx
  89. 0
    1
      common/rfb/Logger.cxx
  90. 20
    15
      common/rfb/Logger_file.cxx
  91. 3
    1
      common/rfb/Logger_file.h
  92. 0
    1
      common/rfb/Logger_syslog.cxx
  93. 10
    11
      common/rfb/Palette.h
  94. 0
    47
      common/rfb/Password.h
  95. 28
    26
      common/rfb/PixelBuffer.cxx
  96. 8
    10
      common/rfb/PixelBuffer.h
  97. 165
    69
      common/rfb/PixelFormat.cxx
  98. 31
    40
      common/rfb/PixelFormat.h
  99. 8
    8
      common/rfb/PixelFormat.inl
  100. 0
    0
      common/rfb/PixelFormatBPP.cxx

+ 2
- 2
common/network/Socket.h View File

@@ -49,8 +49,8 @@ namespace network {
void cork(bool enable) { outstream->cork(enable); }

// information about the remote end of the socket
virtual char* getPeerAddress() = 0; // a string e.g. "192.168.0.1"
virtual char* getPeerEndpoint() = 0; // <address>::<port>
virtual const char* getPeerAddress() = 0; // a string e.g. "192.168.0.1"
virtual const char* getPeerEndpoint() = 0; // <address>::<port>

// Was there a "?" in the ConnectionFilter used to accept this Socket?
void setRequiresQuery();

+ 61
- 60
common/network/TcpSocket.cxx View File

@@ -41,6 +41,7 @@
#include <network/TcpSocket.h>
#include <rfb/LogWriter.h>
#include <rfb/Configuration.h>
#include <rfb/util.h>

#ifdef WIN32
#include <os/winerrno.h>
@@ -211,17 +212,17 @@ TcpSocket::TcpSocket(const char *host, int port)
enableNagles(false);
}

char* TcpSocket::getPeerAddress() {
const char* TcpSocket::getPeerAddress() {
vnc_sockaddr_t sa;
socklen_t sa_size = sizeof(sa);

if (getpeername(getFd(), &sa.u.sa, &sa_size) != 0) {
vlog.error("unable to get peer name for socket");
return rfb::strDup("");
return "(N/A)";
}

if (sa.u.sa.sa_family == AF_INET6) {
char buffer[INET6_ADDRSTRLEN + 2];
static char buffer[INET6_ADDRSTRLEN + 2];
int ret;

buffer[0] = '[';
@@ -231,12 +232,12 @@ char* TcpSocket::getPeerAddress() {
NI_NUMERICHOST);
if (ret != 0) {
vlog.error("unable to convert peer name to a string");
return rfb::strDup("");
return "(N/A)";
}

strcat(buffer, "]");

return rfb::strDup(buffer);
return buffer;
}

if (sa.u.sa.sa_family == AF_INET) {
@@ -245,18 +246,18 @@ char* TcpSocket::getPeerAddress() {
name = inet_ntoa(sa.u.sin.sin_addr);
if (name == NULL) {
vlog.error("unable to convert peer name to a string");
return rfb::strDup("");
return "(N/A)";
}

return rfb::strDup(name);
return name;
}

vlog.error("unknown address family for socket");
return rfb::strDup("");
return "";
}

char* TcpSocket::getPeerEndpoint() {
rfb::CharArray address; address.buf = getPeerAddress();
const char* TcpSocket::getPeerEndpoint() {
static char buffer[INET6_ADDRSTRLEN + 2 + 32];
vnc_sockaddr_t sa;
socklen_t sa_size = sizeof(sa);
int port;
@@ -270,9 +271,8 @@ char* TcpSocket::getPeerEndpoint() {
else
port = 0;

int buflen = strlen(address.buf) + 32;
char* buffer = new char[buflen];
sprintf(buffer, "%s::%d", address.buf, port);
sprintf(buffer, "%s::%d", getPeerAddress(), port);

return buffer;
}

@@ -342,8 +342,9 @@ Socket* TcpListener::createSocket(int fd) {
return new TcpSocket(fd);
}

void TcpListener::getMyAddresses(std::list<char*>* result) {
std::list<std::string> TcpListener::getMyAddresses() {
struct addrinfo *ai, *current, hints;
std::list<std::string> result;

initSockets();

@@ -357,9 +358,11 @@ void TcpListener::getMyAddresses(std::list<char*>* result) {

// Windows doesn't like NULL for service, so specify something
if ((getaddrinfo(NULL, "1", &hints, &ai)) != 0)
return;
return result;

for (current= ai; current != NULL; current = current->ai_next) {
char addr[INET6_ADDRSTRLEN];

switch (current->ai_family) {
case AF_INET:
if (!UseIPv4)
@@ -373,15 +376,15 @@ void TcpListener::getMyAddresses(std::list<char*>* result) {
continue;
}

char *addr = new char[INET6_ADDRSTRLEN];

getnameinfo(current->ai_addr, current->ai_addrlen, addr, INET6_ADDRSTRLEN,
NULL, 0, NI_NUMERICHOST);

result->push_back(addr);
result.push_back(addr);
}

freeaddrinfo(ai);

return result;
}

int TcpListener::getMyPort() {
@@ -502,13 +505,13 @@ void network::createTcpListeners(std::list<SocketListener*> *listeners,


TcpFilter::TcpFilter(const char* spec) {
rfb::CharArray tmp;
tmp.buf = rfb::strDup(spec);
while (tmp.buf) {
rfb::CharArray first;
rfb::strSplit(tmp.buf, ',', &first.buf, &tmp.buf);
if (strlen(first.buf))
filter.push_back(parsePattern(first.buf));
std::vector<std::string> patterns;
patterns = rfb::split(spec, ',');
for (size_t i = 0; i < patterns.size(); i++) {
if (!patterns[i].empty())
filter.push_back(parsePattern(patterns[i].c_str()));
}
}

@@ -569,33 +572,31 @@ patternMatchIP(const TcpFilter::Pattern& pattern, vnc_sockaddr_t *sa) {

bool
TcpFilter::verifyConnection(Socket* s) {
rfb::CharArray name;
vnc_sockaddr_t sa;
socklen_t sa_size = sizeof(sa);

if (getpeername(s->getFd(), &sa.u.sa, &sa_size) != 0)
return false;

name.buf = s->getPeerAddress();
std::list<TcpFilter::Pattern>::iterator i;
for (i=filter.begin(); i!=filter.end(); i++) {
if (patternMatchIP(*i, &sa)) {
switch ((*i).action) {
case Accept:
vlog.debug("ACCEPT %s", name.buf);
vlog.debug("ACCEPT %s", s->getPeerAddress());
return true;
case Query:
vlog.debug("QUERY %s", name.buf);
vlog.debug("QUERY %s", s->getPeerAddress());
s->setRequiresQuery();
return true;
case Reject:
vlog.debug("REJECT %s", name.buf);
vlog.debug("REJECT %s", s->getPeerAddress());
return false;
}
}
}

vlog.debug("[REJECT] %s", name.buf);
vlog.debug("[REJECT] %s", s->getPeerAddress());
return false;
}

@@ -603,14 +604,16 @@ TcpFilter::verifyConnection(Socket* s) {
TcpFilter::Pattern TcpFilter::parsePattern(const char* p) {
TcpFilter::Pattern pattern;

rfb::CharArray addr, pref;
bool prefix_specified;
std::vector<std::string> parts;
int family;

initSockets();

prefix_specified = rfb::strSplit(&p[1], '/', &addr.buf, &pref.buf);
if (addr.buf[0] == '\0') {
parts = rfb::split(&p[1], '/');
if (parts.size() > 2)
throw Exception("invalid filter specified");

if (parts[0].empty()) {
// Match any address
memset (&pattern.address, 0, sizeof (pattern.address));
pattern.address.u.sa.sa_family = AF_UNSPEC;
@@ -618,22 +621,19 @@ TcpFilter::Pattern TcpFilter::parsePattern(const char* p) {
} else {
struct addrinfo hints;
struct addrinfo *ai;
char *p = addr.buf;
int result;
memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_NUMERICHOST;

// Take out brackets, if present
if (*p == '[') {
size_t len;
p++;
len = strlen (p);
if (len > 0 && p[len - 1] == ']')
p[len - 1] = '\0';
if (parts[0][0] == '[') {
parts[0].erase(0, 1);
if (!parts[0].empty() && parts[0][parts.size()-1] == ']')
parts[0].erase(parts.size()-1, 1);
}

if ((result = getaddrinfo (p, NULL, &hints, &ai)) != 0) {
if ((result = getaddrinfo (parts[0].c_str(), NULL, &hints, &ai)) != 0) {
throw GAIException("unable to resolve host by name", result);
}

@@ -642,14 +642,14 @@ TcpFilter::Pattern TcpFilter::parsePattern(const char* p) {

family = pattern.address.u.sa.sa_family;

if (prefix_specified) {
if (parts.size() > 1) {
if (family == AF_INET &&
rfb::strContains(pref.buf, '.')) {
(parts[1].find('.') != std::string::npos)) {
throw Exception("mask no longer supported for filter, "
"use prefix instead");
}

pattern.prefixlen = (unsigned int) atoi(pref.buf);
pattern.prefixlen = (unsigned int) atoi(parts[1].c_str());
} else {
switch (family) {
case AF_INET:
@@ -710,22 +710,19 @@ TcpFilter::Pattern TcpFilter::parsePattern(const char* p) {
return pattern;
}

char* TcpFilter::patternToStr(const TcpFilter::Pattern& p) {
rfb::CharArray addr;
char buffer[INET6_ADDRSTRLEN + 2];
std::string TcpFilter::patternToStr(const TcpFilter::Pattern& p) {
char addr[INET6_ADDRSTRLEN + 2];

if (p.address.u.sa.sa_family == AF_INET) {
getnameinfo(&p.address.u.sa, sizeof(p.address.u.sin),
buffer, sizeof (buffer), NULL, 0, NI_NUMERICHOST);
addr.buf = rfb::strDup(buffer);
addr, sizeof(addr), NULL, 0, NI_NUMERICHOST);
} else if (p.address.u.sa.sa_family == AF_INET6) {
buffer[0] = '[';
addr[0] = '[';
getnameinfo(&p.address.u.sa, sizeof(p.address.u.sin6),
buffer + 1, sizeof (buffer) - 2, NULL, 0, NI_NUMERICHOST);
strcat(buffer, "]");
addr.buf = rfb::strDup(buffer);
addr + 1, sizeof(addr) - 2, NULL, 0, NI_NUMERICHOST);
strcat(addr, "]");
} else
addr.buf = rfb::strDup("");
addr[0] = '\0';

char action;
switch (p.action) {
@@ -735,15 +732,19 @@ char* TcpFilter::patternToStr(const TcpFilter::Pattern& p) {
case Query: action = '?'; break;
};
size_t resultlen = (1 // action
+ strlen (addr.buf) // address
+ strlen (addr) // address
+ 1 // slash
+ 3 // prefix length, max 128
+ 1); // terminating nul
char* result = new char[resultlen];
if (addr.buf[0] == '\0')
if (addr[0] == '\0')
snprintf(result, resultlen, "%c", action);
else
snprintf(result, resultlen, "%c%s/%u", action, addr.buf, p.prefixlen);
snprintf(result, resultlen, "%c%s/%u", action, addr, p.prefixlen);

return result;
std::string out = result;

delete [] result;

return out;
}

+ 5
- 4
common/network/TcpSocket.h View File

@@ -39,6 +39,7 @@
#endif

#include <list>
#include <string>

/* Tunnelling support. */
#define TUNNEL_PORT_OFFSET 5500
@@ -55,8 +56,8 @@ namespace network {
TcpSocket(int sock);
TcpSocket(const char *name, int port);

virtual char* getPeerAddress();
virtual char* getPeerEndpoint();
virtual const char* getPeerAddress();
virtual const char* getPeerEndpoint();

protected:
bool enableNagles(bool enable);
@@ -69,7 +70,7 @@ namespace network {

virtual int getMyPort();

static void getMyAddresses(std::list<char*>* result);
static std::list<std::string> getMyAddresses();

protected:
virtual Socket* createSocket(int fd);
@@ -107,7 +108,7 @@ namespace network {
vnc_sockaddr_t mask; // computed from address and prefix
};
static Pattern parsePattern(const char* s);
static char* patternToStr(const Pattern& p);
static std::string patternToStr(const Pattern& p);
protected:
std::list<Pattern> filter;
};

+ 8
- 8
common/network/UnixSocket.cxx View File

@@ -74,8 +74,8 @@ UnixSocket::UnixSocket(const char *path)
setFd(sock);
}

char* UnixSocket::getPeerAddress() {
struct sockaddr_un addr;
const char* UnixSocket::getPeerAddress() {
static struct sockaddr_un addr;
socklen_t salen;

// AF_UNIX only has a single address (the server side).
@@ -85,27 +85,27 @@ char* UnixSocket::getPeerAddress() {
salen = sizeof(addr);
if (getpeername(getFd(), (struct sockaddr *)&addr, &salen) != 0) {
vlog.error("unable to get peer name for socket");
return rfb::strDup("");
return "";
}

if (salen > offsetof(struct sockaddr_un, sun_path))
return rfb::strDup(addr.sun_path);
return addr.sun_path;

salen = sizeof(addr);
if (getsockname(getFd(), (struct sockaddr *)&addr, &salen) != 0) {
vlog.error("unable to get local name for socket");
return rfb::strDup("");
return "";
}

if (salen > offsetof(struct sockaddr_un, sun_path))
return rfb::strDup(addr.sun_path);
return addr.sun_path;

// socketpair() will create unnamed sockets

return rfb::strDup("(unnamed UNIX socket)");
return "(unnamed UNIX socket)";
}

char* UnixSocket::getPeerEndpoint() {
const char* UnixSocket::getPeerEndpoint() {
return getPeerAddress();
}


+ 2
- 2
common/network/UnixSocket.h View File

@@ -38,8 +38,8 @@ namespace network {
UnixSocket(int sock);
UnixSocket(const char *name);

virtual char* getPeerAddress();
virtual char* getPeerEndpoint();
virtual const char* getPeerAddress();
virtual const char* getPeerEndpoint();
};

class UnixListener : public SocketListener {

+ 48
- 53
common/os/os.cxx View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2010 TightVNC Team. All Rights Reserved.
* Copyright 2021-2023 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
@@ -26,6 +27,8 @@

#ifndef WIN32
#include <pwd.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
@@ -36,72 +39,64 @@
#include <shlobj.h>
#endif

static int gethomedir(char **dirp, bool userDir)
static const char* gethomedir(bool userDir)
{
static char dir[PATH_MAX];

#ifndef WIN32
char *homedir, *dir;
size_t len;
uid_t uid;
struct passwd *passwd;
char *homedir;
uid_t uid;
struct passwd *passwd;
#else
TCHAR *dir;
BOOL ret;
BOOL ret;
#endif

assert(dirp != NULL && *dirp == NULL);

#ifndef WIN32
homedir = getenv("HOME");
if (homedir == NULL) {
uid = getuid();
passwd = getpwuid(uid);
if (passwd == NULL) {
/* Do we want emit error msg here? */
return -1;
}
homedir = passwd->pw_dir;
}

len = strlen(homedir);
dir = new char[len+7];
if (dir == NULL)
return -1;

memcpy(dir, homedir, len);
if (userDir)
dir[len]='\0';
else
memcpy(dir + len, "/.vnc/\0", 7);
homedir = getenv("HOME");
if (homedir == NULL) {
uid = getuid();
passwd = getpwuid(uid);
if (passwd == NULL) {
/* Do we want emit error msg here? */
return NULL;
}
homedir = passwd->pw_dir;
}

if (userDir)
return homedir;

snprintf(dir, sizeof(dir), "%s/.vnc", homedir);

return dir;
#else
dir = new TCHAR[MAX_PATH];
if (dir == NULL)
return -1;
if (userDir)
ret = SHGetSpecialFolderPath(NULL, dir, CSIDL_PROFILE, FALSE);
else
ret = SHGetSpecialFolderPath(NULL, dir, CSIDL_APPDATA, FALSE);
if (ret == FALSE) {
delete [] dir;
return -1;
}
if (userDir)
dir[strlen(dir)+1] = '\0';
else
memcpy(dir+strlen(dir), (TCHAR *)"\\vnc\\\0", 6);
if (userDir)
ret = SHGetSpecialFolderPath(NULL, dir, CSIDL_PROFILE, FALSE);
else
ret = SHGetSpecialFolderPath(NULL, dir, CSIDL_APPDATA, FALSE);
if (ret == FALSE)
return NULL;
if (userDir)
return dir;
if (strlen(dir) + strlen("\\vnc") >= sizeof(dir))
return NULL;
strcat(dir, "\\vnc");
return dir;
#endif
*dirp = dir;
return 0;
}

int getvnchomedir(char **dirp)
const char* os::getvnchomedir()
{
return gethomedir(dirp, false);
return gethomedir(false);
}

int getuserhomedir(char **dirp)
const char* os::getuserhomedir()
{
return gethomedir(dirp, true);
return gethomedir(true);
}


+ 21
- 26
common/os/os.h View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2010 TightVNC Team. All Rights Reserved.
* Copyright 2021-2023 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
@@ -19,32 +20,26 @@
#ifndef OS_OS_H
#define OS_OS_H

/*
* Get VNC home directory ($HOME/.vnc or %APPDATA%/vnc/).
* If HOME environment variable is set then it is used.
* Otherwise home directory is obtained via getpwuid function.
*
* Note for Windows:
* This functions returns array of TCHARs, not array of chars.
*
* Returns:
* 0 - Success
* -1 - Failure
*/
int getvnchomedir(char **dirp);
namespace os {

/*
* Get user home directory.
* If HOME environment variable is set then it is used.
* Otherwise home directory is obtained via getpwuid function.
*
* Note for Windows:
* This functions returns array of TCHARs, not array of chars.
*
* Returns:
* 0 - Success
* -1 - Failure
*/
int getuserhomedir(char **dirp);
/*
* Get VNC home directory ($HOME/.vnc or %APPDATA%/vnc/).
* If HOME environment variable is set then it is used.
* Otherwise home directory is obtained via getpwuid function.
*
* Returns NULL on failure.
*/
const char* getvnchomedir();

/*
* Get user home directory.
* If HOME environment variable is set then it is used.
* Otherwise home directory is obtained via getpwuid function.
*
* Returns NULL on failure.
*/
const char* getuserhomedir();

}

#endif /* OS_OS_H */

+ 10
- 9
common/rdr/AESInStream.cxx View File

@@ -27,7 +27,8 @@
#ifdef HAVE_NETTLE
using namespace rdr;

AESInStream::AESInStream(InStream* _in, const U8* key, int _keySize)
AESInStream::AESInStream(InStream* _in, const uint8_t* key,
int _keySize)
: keySize(_keySize), in(_in), counter()
{
if (keySize == 128)
@@ -44,26 +45,26 @@ bool AESInStream::fillBuffer()
{
if (!in->hasData(2))
return false;
const U8* ptr = in->getptr(2);
const uint8_t* ptr = in->getptr(2);
size_t length = ((int)ptr[0] << 8) | (int)ptr[1];
if (!in->hasData(2 + length + 16))
return false;
ensureSpace(length);
ptr = in->getptr(2 + length + 16);
const U8* ad = ptr;
const U8* data = ptr + 2;
const U8* mac = ptr + 2 + length;
U8 macComputed[16];
const uint8_t* ad = ptr;
const uint8_t* data = ptr + 2;
const uint8_t* mac = ptr + 2 + length;
uint8_t macComputed[16];

if (keySize == 128) {
EAX_SET_NONCE(&eaxCtx128, aes128_encrypt, 16, counter);
EAX_UPDATE(&eaxCtx128, aes128_encrypt, 2, ad);
EAX_DECRYPT(&eaxCtx128, aes128_encrypt, length, (rdr::U8*)end, data);
EAX_DECRYPT(&eaxCtx128, aes128_encrypt, length, (uint8_t*)end, data);
EAX_DIGEST(&eaxCtx128, aes128_encrypt, 16, macComputed);
} else {
EAX_SET_NONCE(&eaxCtx256, aes256_encrypt, 16, counter);
EAX_UPDATE(&eaxCtx256, aes256_encrypt, 2, ad);
EAX_DECRYPT(&eaxCtx256, aes256_encrypt, length, (rdr::U8*)end, data);
EAX_DECRYPT(&eaxCtx256, aes256_encrypt, length, (uint8_t*)end, data);
EAX_DIGEST(&eaxCtx256, aes256_encrypt, 16, macComputed);
}
if (memcmp(mac, macComputed, 16) != 0)
@@ -82,4 +83,4 @@ bool AESInStream::fillBuffer()
return true;
}

#endif
#endif

+ 2
- 2
common/rdr/AESInStream.h View File

@@ -29,7 +29,7 @@ namespace rdr {

class AESInStream : public BufferedInStream {
public:
AESInStream(InStream* in, const U8* key, int keySize);
AESInStream(InStream* in, const uint8_t* key, int keySize);
virtual ~AESInStream();

private:
@@ -41,7 +41,7 @@ namespace rdr {
struct EAX_CTX(aes128_ctx) eaxCtx128;
struct EAX_CTX(aes256_ctx) eaxCtx256;
};
U8 counter[16];
uint8_t counter[16];
};
}


+ 4
- 3
common/rdr/AESOutStream.cxx View File

@@ -29,10 +29,11 @@ using namespace rdr;

const int MaxMessageSize = 8192;

AESOutStream::AESOutStream(OutStream* _out, const U8* key, int _keySize)
AESOutStream::AESOutStream(OutStream* _out, const uint8_t* key,
int _keySize)
: keySize(_keySize), out(_out), counter()
{
msg = new U8[MaxMessageSize + 16 + 2];
msg = new uint8_t[MaxMessageSize + 16 + 2];
if (keySize == 128)
EAX_SET_KEY(&eaxCtx128, aes128_set_encrypt_key, aes128_encrypt, key);
else if (keySize == 256)
@@ -71,7 +72,7 @@ bool AESOutStream::flushBuffer()
}


void AESOutStream::writeMessage(const U8* data, size_t length)
void AESOutStream::writeMessage(const uint8_t* data, size_t length)
{
msg[0] = (length & 0xff00) >> 8;
msg[1] = length & 0xff;

+ 4
- 4
common/rdr/AESOutStream.h View File

@@ -28,7 +28,7 @@ namespace rdr {

class AESOutStream : public BufferedOutStream {
public:
AESOutStream(OutStream* out, const U8* key, int keySize);
AESOutStream(OutStream* out, const uint8_t* key, int keySize);
virtual ~AESOutStream();

virtual void flush();
@@ -36,16 +36,16 @@ namespace rdr {

private:
virtual bool flushBuffer();
void writeMessage(const U8* data, size_t length);
void writeMessage(const uint8_t* data, size_t length);

int keySize;
OutStream* out;
U8* msg;
uint8_t* msg;
union {
struct EAX_CTX(aes128_ctx) eaxCtx128;
struct EAX_CTX(aes256_ctx) eaxCtx256;
};
U8 counter[16];
uint8_t counter[16];
};
};


+ 4
- 4
common/rdr/BufferedInStream.cxx View File

@@ -34,7 +34,7 @@ static const size_t MAX_BUF_SIZE = 32 * 1024 * 1024;
BufferedInStream::BufferedInStream()
: bufSize(DEFAULT_BUF_SIZE), offset(0)
{
ptr = end = start = new U8[bufSize];
ptr = end = start = new uint8_t[bufSize];
gettimeofday(&lastSizeCheck, NULL);
peakUsage = 0;
}
@@ -60,7 +60,7 @@ void BufferedInStream::ensureSpace(size_t needed)

if (needed > bufSize) {
size_t newSize;
U8* newBuffer;
uint8_t* newBuffer;

if (needed > MAX_BUF_SIZE)
throw Exception("BufferedInStream overrun: requested size of "
@@ -71,7 +71,7 @@ void BufferedInStream::ensureSpace(size_t needed)
while (newSize < needed)
newSize *= 2;

newBuffer = new U8[newSize];
newBuffer = new uint8_t[newSize];
memcpy(newBuffer, ptr, end - ptr);
delete [] start;
bufSize = newSize;
@@ -101,7 +101,7 @@ void BufferedInStream::ensureSpace(size_t needed)

// We know the buffer is empty, so just reset everything
delete [] start;
ptr = end = start = new U8[newSize];
ptr = end = start = new uint8_t[newSize];
bufSize = newSize;
}


+ 1
- 1
common/rdr/BufferedInStream.h View File

@@ -50,7 +50,7 @@ namespace rdr {
private:
size_t bufSize;
size_t offset;
U8* start;
uint8_t* start;

struct timeval lastSizeCheck;
size_t peakUsage;

+ 4
- 4
common/rdr/BufferedOutStream.cxx View File

@@ -34,7 +34,7 @@ static const size_t MAX_BUF_SIZE = 32 * 1024 * 1024;
BufferedOutStream::BufferedOutStream(bool emulateCork)
: bufSize(DEFAULT_BUF_SIZE), offset(0), emulateCork(emulateCork)
{
ptr = start = sentUpTo = new U8[bufSize];
ptr = start = sentUpTo = new uint8_t[bufSize];
end = start + bufSize;
gettimeofday(&lastSizeCheck, NULL);
peakUsage = 0;
@@ -88,7 +88,7 @@ void BufferedOutStream::flush()

// We know the buffer is empty, so just reset everything
delete [] start;
ptr = start = sentUpTo = new U8[newSize];
ptr = start = sentUpTo = new uint8_t[newSize];
end = start + newSize;
bufSize = newSize;
}
@@ -107,7 +107,7 @@ void BufferedOutStream::overrun(size_t needed)
{
bool oldCorked;
size_t totalNeeded, newSize;
U8* newBuffer;
uint8_t* newBuffer;

// First try to get rid of the data we have
// (use corked to make things a bit more efficient since we're not
@@ -147,7 +147,7 @@ void BufferedOutStream::overrun(size_t needed)
while (newSize < totalNeeded)
newSize *= 2;

newBuffer = new U8[newSize];
newBuffer = new uint8_t[newSize];
memcpy(newBuffer, sentUpTo, ptr - sentUpTo);
delete [] start;
bufSize = newSize;

+ 2
- 2
common/rdr/BufferedOutStream.h View File

@@ -54,7 +54,7 @@ namespace rdr {
private:
size_t bufSize;
size_t offset;
U8* start;
uint8_t* start;

struct timeval lastSizeCheck;
size_t peakUsage;
@@ -62,7 +62,7 @@ namespace rdr {
bool emulateCork;

protected:
U8* sentUpTo;
uint8_t* sentUpTo;

protected:
BufferedOutStream(bool emulateCork=true);

+ 0
- 1
common/rdr/Exception.cxx View File

@@ -28,7 +28,6 @@
#include <rdr/Exception.h>
#include <rdr/TLSException.h>
#ifdef _WIN32
#include <tchar.h>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>

+ 7
- 7
common/rdr/FdInStream.cxx View File

@@ -26,14 +26,14 @@
#include <sys/time.h>
#ifdef _WIN32
#include <winsock2.h>
#define errorNumber WSAGetLastError()
#define close closesocket
#undef errno
#define errno WSAGetLastError()
#include <os/winerrno.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#define errorNumber errno
#endif

/* Old systems have select() in sys/time.h */
@@ -59,7 +59,7 @@ FdInStream::~FdInStream()

bool FdInStream::fillBuffer()
{
size_t n = readFd((U8*)end, availSpace());
size_t n = readFd((uint8_t*)end, availSpace());
if (n == 0)
return false;
end += n;
@@ -89,20 +89,20 @@ size_t FdInStream::readFd(void* buf, size_t len)
FD_ZERO(&fds);
FD_SET(fd, &fds);
n = select(fd+1, &fds, 0, 0, &tv);
} while (n < 0 && errno == EINTR);
} while (n < 0 && errorNumber == EINTR);

if (n < 0)
throw SystemException("select",errno);
throw SystemException("select", errorNumber);

if (n == 0)
return 0;

do {
n = ::recv(fd, (char*)buf, len, 0);
} while (n < 0 && errno == EINTR);
} while (n < 0 && errorNumber == EINTR);

if (n < 0)
throw SystemException("read",errno);
throw SystemException("read", errorNumber);
if (n == 0)
throw EndOfStream();


+ 6
- 6
common/rdr/FdOutStream.cxx View File

@@ -27,8 +27,7 @@
#include <errno.h>
#ifdef _WIN32
#include <winsock2.h>
#undef errno
#define errno WSAGetLastError()
#define errorNumber WSAGetLastError()
#include <os/winerrno.h>
#else
#include <sys/types.h>
@@ -37,6 +36,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#define errorNumber errno
#endif

/* Old systems have select() in sys/time.h */
@@ -109,10 +109,10 @@ size_t FdOutStream::writeFd(const void* data, size_t length)
FD_ZERO(&fds);
FD_SET(fd, &fds);
n = select(fd+1, 0, &fds, 0, &tv);
} while (n < 0 && errno == EINTR);
} while (n < 0 && errorNumber == EINTR);

if (n < 0)
throw SystemException("select", errno);
throw SystemException("select", errorNumber);

if (n == 0)
return 0;
@@ -126,10 +126,10 @@ size_t FdOutStream::writeFd(const void* data, size_t length)
#else
n = ::send(fd, (const char*)data, length, MSG_DONTWAIT);
#endif
} while (n < 0 && (errno == EINTR));
} while (n < 0 && (errorNumber == EINTR));

if (n < 0)
throw SystemException("write", errno);
throw SystemException("write", errorNumber);

gettimeofday(&lastWrite, NULL);


+ 1
- 1
common/rdr/FileInStream.cxx View File

@@ -45,7 +45,7 @@ FileInStream::~FileInStream(void) {

bool FileInStream::fillBuffer()
{
size_t n = fread((U8 *)end, 1, availSpace(), file);
size_t n = fread((uint8_t*)end, 1, availSpace(), file);
if (n == 0) {
if (ferror(file))
throw SystemException("fread", errno);

+ 6
- 46
common/rdr/HexInStream.cxx View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2019-2022 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
@@ -22,9 +23,7 @@

#include <rdr/HexInStream.h>
#include <rdr/Exception.h>

#include <stdlib.h>
#include <ctype.h>
#include <rfb/util.h>

using namespace rdr;

@@ -39,56 +38,17 @@ HexInStream::~HexInStream() {
}


bool HexInStream::readHexAndShift(char c, int* v) {
c=tolower(c);
if ((c >= '0') && (c <= '9'))
*v = (*v << 4) + (c - '0');
else if ((c >= 'a') && (c <= 'f'))
*v = (*v << 4) + (c - 'a' + 10);
else
return false;
return true;
}

bool HexInStream::hexStrToBin(const char* s, char** data, size_t* length) {
size_t l=strlen(s);
if ((l % 2) == 0) {
delete [] *data;
*data = 0; *length = 0;
if (l == 0)
return true;
*data = new char[l/2];
*length = l/2;
for(size_t i=0;i<l;i+=2) {
int byte = 0;
if (!readHexAndShift(s[i], &byte) ||
!readHexAndShift(s[i+1], &byte))
goto decodeError;
(*data)[i/2] = byte;
}
return true;
}
decodeError:
delete [] *data;
*data = 0;
*length = 0;
return false;
}


bool HexInStream::fillBuffer() {
if (!in_stream.hasData(2))
return false;

size_t length = min(in_stream.avail()/2, availSpace());
const U8* iptr = in_stream.getptr(length*2);
const uint8_t* iptr = in_stream.getptr(length*2);

U8* optr = (U8*) end;
uint8_t* optr = (uint8_t*) end;
for (size_t i=0; i<length; i++) {
int v = 0;
readHexAndShift(iptr[i*2], &v);
readHexAndShift(iptr[i*2+1], &v);
optr[i] = v;
if (!rfb::hexToBin((const char*)&iptr[i*2], 2, &optr[i], 1))
throw Exception("HexInStream: Invalid input data");
}

in_stream.setptr(length*2);

+ 0
- 3
common/rdr/HexInStream.h View File

@@ -29,9 +29,6 @@ namespace rdr {
HexInStream(InStream& is);
virtual ~HexInStream();

static bool readHexAndShift(char c, int* v);
static bool hexStrToBin(const char* s, char** data, size_t* length);

private:
virtual bool fillBuffer();


+ 5
- 29
common/rdr/HexOutStream.cxx View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2019-2022 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
@@ -21,7 +22,7 @@
#endif

#include <rdr/HexOutStream.h>
#include <rdr/Exception.h>
#include <rfb/util.h>

using namespace rdr;

@@ -36,39 +37,14 @@ HexOutStream::~HexOutStream()
{
}

char HexOutStream::intToHex(int i) {
if ((i>=0) && (i<=9))
return '0'+i;
else if ((i>=10) && (i<=15))
return 'a'+(i-10);
else
throw rdr::Exception("intToHex failed");
}

char* HexOutStream::binToHexStr(const char* data, size_t length) {
char* buffer = new char[length*2+1];
for (size_t i=0; i<length; i++) {
buffer[i*2] = intToHex((data[i] >> 4) & 15);
buffer[i*2+1] = intToHex((data[i] & 15));
if (!buffer[i*2] || !buffer[i*2+1]) {
delete [] buffer;
return 0;
}
}
buffer[length*2] = 0;
return buffer;
}

bool HexOutStream::flushBuffer()
{
while (sentUpTo != ptr) {
U8* optr = out_stream.getptr(2);
uint8_t* optr = out_stream.getptr(2);
size_t length = min(ptr-sentUpTo, out_stream.avail()/2);

for (size_t i=0; i<length; i++) {
optr[i*2] = intToHex((sentUpTo[i] >> 4) & 0xf);
optr[i*2+1] = intToHex(sentUpTo[i] & 0xf);
}
for (size_t i=0; i<length; i++)
rfb::binToHex(&sentUpTo[i], 1, (char*)&optr[i*2], 2);

out_stream.setptr(length*2);
sentUpTo += length;

+ 0
- 3
common/rdr/HexOutStream.h View File

@@ -32,9 +32,6 @@ namespace rdr {
virtual void flush();
virtual void cork(bool enable);

static char intToHex(int i);
static char* binToHexStr(const char* data, size_t length);

private:
virtual bool flushBuffer();
void writeBuffer();

+ 30
- 22
common/rdr/InStream.h View File

@@ -25,10 +25,11 @@
#ifndef __RDR_INSTREAM_H__
#define __RDR_INSTREAM_H__

#include <rdr/types.h>
#include <rdr/Exception.h>
#include <stdint.h>
#include <string.h> // for memcpy

#include <rdr/Exception.h>

// Check that callers are using InStream properly,
// useful when writing new protocol handling
#ifdef _DEBUG
@@ -122,16 +123,18 @@ namespace rdr {

// readU/SN() methods read unsigned and signed N-bit integers.

inline U8 readU8() { check(1); return *ptr++; }
inline U16 readU16() { check(2); int b0 = *ptr++; int b1 = *ptr++;
return b0 << 8 | b1; }
inline U32 readU32() { check(4); int b0 = *ptr++; int b1 = *ptr++;
int b2 = *ptr++; int b3 = *ptr++;
return b0 << 24 | b1 << 16 | b2 << 8 | b3; }
inline uint8_t readU8() { check(1); return *ptr++; }
inline uint16_t readU16() { check(2);
int b0 = *ptr++; int b1 = *ptr++;
return b0 << 8 | b1; }
inline uint32_t readU32() { check(4);
int b0 = *ptr++; int b1 = *ptr++;
int b2 = *ptr++; int b3 = *ptr++;
return b0 << 24 | b1 << 16 | b2 << 8 | b3; }

inline S8 readS8() { return (S8) readU8(); }
inline S16 readS16() { return (S16)readU16(); }
inline S32 readS32() { return (S32)readU32(); }
inline int8_t readS8() { return (int8_t) readU8(); }
inline int16_t readS16() { return (int16_t)readU16(); }
inline int32_t readS32() { return (int32_t)readU32(); }

// skip() ignores a number of bytes on the stream

@@ -150,12 +153,17 @@ namespace rdr {

// readOpaqueN() reads a quantity without byte-swapping.

inline U8 readOpaque8() { return readU8(); }
inline U16 readOpaque16() { check(2); U16 r; ((U8*)&r)[0] = *ptr++;
((U8*)&r)[1] = *ptr++; return r; }
inline U32 readOpaque32() { check(4); U32 r; ((U8*)&r)[0] = *ptr++;
((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++;
((U8*)&r)[3] = *ptr++; return r; }
inline uint8_t readOpaque8() { return readU8(); }
inline uint16_t readOpaque16() { check(2); uint16_t r;
((uint8_t*)&r)[0] = *ptr++;
((uint8_t*)&r)[1] = *ptr++;
return r; }
inline uint32_t readOpaque32() { check(4); uint32_t r;
((uint8_t*)&r)[0] = *ptr++;
((uint8_t*)&r)[1] = *ptr++;
((uint8_t*)&r)[2] = *ptr++;
((uint8_t*)&r)[3] = *ptr++;
return r; }

// pos() returns the position in the stream.

@@ -165,15 +173,15 @@ namespace rdr {
// to the buffer. This is useful for a stream which is a wrapper around an
// some other stream API.

inline const U8* getptr(size_t length) { check(length);
return ptr; }
inline const uint8_t* getptr(size_t length) { check(length);
return ptr; }
inline void setptr(size_t length) { if (length > avail())
throw Exception("Input stream overflow");
skip(length); }

private:

const U8* restorePoint;
const uint8_t* restorePoint;
#ifdef RFB_INSTREAM_CHECK
size_t checkedBytes;
#endif
@@ -201,8 +209,8 @@ namespace rdr {
,checkedBytes(0)
#endif
{}
const U8* ptr;
const U8* end;
const uint8_t* ptr;
const uint8_t* end;
};

}

+ 4
- 4
common/rdr/MemInStream.h View File

@@ -19,8 +19,8 @@
//
// rdr::MemInStream is an InStream which streams from a given memory buffer.
// If the deleteWhenDone parameter is true then the buffer will be delete[]d in
// the destructor. Note that it is delete[]d as a U8* - strictly speaking this
// means it ought to be new[]ed as a U8* as well, but on most platforms this
// the destructor. Note that it is delete[]d as a uint8_t* - strictly speaking this
// means it ought to be new[]ed as a uint8_t* as well, but on most platforms this
// doesn't matter.
//

@@ -37,7 +37,7 @@ namespace rdr {
public:

MemInStream(const void* data, size_t len, bool deleteWhenDone_=false)
: start((const U8*)data), deleteWhenDone(deleteWhenDone_)
: start((const uint8_t*)data), deleteWhenDone(deleteWhenDone_)
{
ptr = start;
end = start + len;
@@ -60,7 +60,7 @@ namespace rdr {
private:

bool overrun(size_t /*needed*/) { throw EndOfStream(); }
const U8* start;
const uint8_t* start;
bool deleteWhenDone;
};


+ 3
- 3
common/rdr/MemOutStream.h View File

@@ -33,7 +33,7 @@ namespace rdr {
public:

MemOutStream(int len=1024) {
start = ptr = new U8[len];
start = ptr = new uint8_t[len];
end = start + len;
}

@@ -63,7 +63,7 @@ namespace rdr {
if (len < (size_t)(end - start))
throw Exception("Overflow in MemOutStream::overrun()");

U8* newStart = new U8[len];
uint8_t* newStart = new uint8_t[len];
memcpy(newStart, start, ptr - start);
ptr = newStart + (ptr - start);
delete [] start;
@@ -71,7 +71,7 @@ namespace rdr {
end = newStart + len;
}

U8* start;
uint8_t* start;
};

}

+ 26
- 20
common/rdr/OutStream.h View File

@@ -24,10 +24,11 @@
#ifndef __RDR_OUTSTREAM_H__
#define __RDR_OUTSTREAM_H__

#include <rdr/types.h>
#include <stdint.h>
#include <string.h> // for memcpy

#include <rdr/Exception.h>
#include <rdr/InStream.h>
#include <string.h> // for memcpy

namespace rdr {

@@ -51,14 +52,17 @@ namespace rdr {

// writeU/SN() methods write unsigned and signed N-bit integers.

inline void writeU8( U8 u) { check(1); *ptr++ = u; }
inline void writeU16(U16 u) { check(2); *ptr++ = u >> 8; *ptr++ = (U8)u; }
inline void writeU32(U32 u) { check(4); *ptr++ = u >> 24; *ptr++ = u >> 16;
*ptr++ = u >> 8; *ptr++ = u; }
inline void writeU8( uint8_t u) { check(1); *ptr++ = u; }
inline void writeU16(uint16_t u) { check(2); *ptr++ = u >> 8;
*ptr++ = (uint8_t)u; }
inline void writeU32(uint32_t u) { check(4); *ptr++ = u >> 24;
*ptr++ = u >> 16;
*ptr++ = u >> 8;
*ptr++ = u; }

inline void writeS8( S8 s) { writeU8((U8)s); }
inline void writeS16(S16 s) { writeU16((U16)s); }
inline void writeS32(S32 s) { writeU32((U32)s); }
inline void writeS8( int8_t s) { writeU8((uint8_t)s); }
inline void writeS16(int16_t s) { writeU16((uint16_t)s); }
inline void writeS32(int32_t s) { writeU32((uint32_t)s); }

inline void pad(size_t bytes) {
while (bytes-- > 0) writeU8(0);
@@ -74,7 +78,7 @@ namespace rdr {
n = avail();
memcpy(ptr, data, n);
ptr += n;
data = (U8*)data + n;
data = (uint8_t*)data + n;
length -= n;
}
}
@@ -95,13 +99,15 @@ namespace rdr {

// writeOpaqueN() writes a quantity without byte-swapping.

inline void writeOpaque8( U8 u) { writeU8(u); }
inline void writeOpaque16(U16 u) { check(2); *ptr++ = ((U8*)&u)[0];
*ptr++ = ((U8*)&u)[1]; }
inline void writeOpaque32(U32 u) { check(4); *ptr++ = ((U8*)&u)[0];
*ptr++ = ((U8*)&u)[1];
*ptr++ = ((U8*)&u)[2];
*ptr++ = ((U8*)&u)[3]; }
inline void writeOpaque8( uint8_t u) { writeU8(u); }
inline void writeOpaque16(uint16_t u) { check(2);
*ptr++ = ((uint8_t*)&u)[0];
*ptr++ = ((uint8_t*)&u)[1]; }
inline void writeOpaque32(uint32_t u) { check(4);
*ptr++ = ((uint8_t*)&u)[0];
*ptr++ = ((uint8_t*)&u)[1];
*ptr++ = ((uint8_t*)&u)[2];
*ptr++ = ((uint8_t*)&u)[3]; }

// length() returns the length of the stream.

@@ -121,7 +127,7 @@ namespace rdr {
// larger than the bytes actually written as doing so can result in
// security issues. Use pad() in such cases instead.

inline U8* getptr(size_t length) { check(length); return ptr; }
inline uint8_t* getptr(size_t length) { check(length); return ptr; }
inline void setptr(size_t length) { if (length > avail())
throw Exception("Output stream overflow");
ptr += length; }
@@ -141,8 +147,8 @@ namespace rdr {

protected:

U8* ptr;
U8* end;
uint8_t* ptr;
uint8_t* end;

bool corked;
};

+ 3
- 3
common/rdr/RandomStream.cxx View File

@@ -86,14 +86,14 @@ RandomStream::~RandomStream() {
bool RandomStream::fillBuffer() {
#ifdef RFB_HAVE_WINCRYPT
if (provider) {
if (!CryptGenRandom(provider, availSpace(), (U8*)end))
if (!CryptGenRandom(provider, availSpace(), (uint8_t*)end))
throw rdr::SystemException("unable to CryptGenRandom", GetLastError());
end += availSpace();
} else {
#else
#ifndef WIN32
if (fp) {
size_t n = fread((U8*)end, 1, availSpace(), fp);
size_t n = fread((uint8_t*)end, 1, availSpace(), fp);
if (n <= 0)
throw rdr::SystemException("reading /dev/urandom or /dev/random failed",
errno);
@@ -104,7 +104,7 @@ bool RandomStream::fillBuffer() {
#endif
#endif
for (size_t i=availSpace(); i>0; i--)
*(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0));
*(uint8_t*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0));
}

return true;

+ 2
- 2
common/rdr/TLSInStream.cxx View File

@@ -90,7 +90,7 @@ TLSInStream::~TLSInStream()

bool TLSInStream::fillBuffer()
{
size_t n = readTLS((U8*) end, availSpace());
size_t n = readTLS((uint8_t*) end, availSpace());
if (n == 0)
return false;
end += n;
@@ -98,7 +98,7 @@ bool TLSInStream::fillBuffer()
return true;
}

size_t TLSInStream::readTLS(U8* buf, size_t len)
size_t TLSInStream::readTLS(uint8_t* buf, size_t len)
{
int n;


+ 1
- 1
common/rdr/TLSInStream.h View File

@@ -34,7 +34,7 @@ namespace rdr {

private:
virtual bool fillBuffer();
size_t readTLS(U8* buf, size_t len);
size_t readTLS(uint8_t* buf, size_t len);
static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size);

gnutls_session_t session;

+ 1
- 1
common/rdr/TLSOutStream.cxx View File

@@ -106,7 +106,7 @@ bool TLSOutStream::flushBuffer()
return true;
}

size_t TLSOutStream::writeTLS(const U8* data, size_t length)
size_t TLSOutStream::writeTLS(const uint8_t* data, size_t length)
{
int n;


+ 1
- 1
common/rdr/TLSOutStream.h View File

@@ -36,7 +36,7 @@ namespace rdr {

private:
virtual bool flushBuffer();
size_t writeTLS(const U8* data, size_t length);
size_t writeTLS(const uint8_t* data, size_t length);
static ssize_t push(gnutls_transport_ptr_t str, const void* data, size_t size);

gnutls_session_t session;

+ 2
- 2
common/rdr/ZlibInStream.cxx View File

@@ -94,7 +94,7 @@ bool ZlibInStream::fillBuffer()
if (!underlying)
throw Exception("ZlibInStream overrun: no underlying stream");

zs->next_out = (U8*)end;
zs->next_out = (uint8_t*)end;
zs->avail_out = availSpace();

if (!underlying->hasData(1))
@@ -102,7 +102,7 @@ bool ZlibInStream::fillBuffer()
size_t length = underlying->avail();
if (length > bytesIn)
length = bytesIn;
zs->next_in = (U8*)underlying->getptr(length);
zs->next_in = (uint8_t*)underlying->getptr(length);
zs->avail_in = length;

int rc = inflate(zs, Z_SYNC_FLUSH);

+ 0
- 77
common/rdr/types.h View File

@@ -1,77 +0,0 @@
/* 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.
*/

#ifndef __RDR_TYPES_H__
#define __RDR_TYPES_H__

namespace rdr {

typedef unsigned char U8;
typedef unsigned short U16;
typedef unsigned int U32;
typedef unsigned long long U64;
typedef signed char S8;
typedef signed short S16;
typedef signed int S32;

class U8Array {
public:
U8Array() : buf(0) {}
U8Array(U8* a) : buf(a) {} // note: assumes ownership
U8Array(int len) : buf(new U8[len]) {}
~U8Array() { delete [] buf; }

// Get the buffer pointer & clear it (i.e. caller takes ownership)
U8* takeBuf() { U8* tmp = buf; buf = 0; return tmp; }

U8* buf;
};

class U16Array {
public:
U16Array() : buf(0) {}
U16Array(U16* a) : buf(a) {} // note: assumes ownership
U16Array(int len) : buf(new U16[len]) {}
~U16Array() { delete [] buf; }
U16* takeBuf() { U16* tmp = buf; buf = 0; return tmp; }
U16* buf;
};

class U32Array {
public:
U32Array() : buf(0) {}
U32Array(U32* a) : buf(a) {} // note: assumes ownership
U32Array(int len) : buf(new U32[len]) {}
~U32Array() { delete [] buf; }
U32* takeBuf() { U32* tmp = buf; buf = 0; return tmp; }
U32* buf;
};

class S32Array {
public:
S32Array() : buf(0) {}
S32Array(S32* a) : buf(a) {} // note: assumes ownership
S32Array(int len) : buf(new S32[len]) {}
~S32Array() { delete [] buf; }
S32* takeBuf() { S32* tmp = buf; buf = 0; return tmp; }
S32* buf;
};

} // end of namespace rdr

#endif

+ 2
- 11
common/rfb/Blacklist.cxx View File

@@ -45,11 +45,6 @@ Blacklist::Blacklist() {
}

Blacklist::~Blacklist() {
// Free the map keys
BlacklistMap::iterator i;
for (i=blm.begin(); i!=blm.end(); i++) {
strFree((char*)(*i).first);
}
}

bool Blacklist::isBlackmarked(const char* name) {
@@ -65,7 +60,7 @@ bool Blacklist::isBlackmarked(const char* name) {
bi.marks = 1;
bi.blockUntil = 0;
bi.blockTimeout = initialTimeout;
blm[strDup(name)] = bi;
blm[name] = bi;
i = blm.find(name);
}

@@ -92,9 +87,5 @@ bool Blacklist::isBlackmarked(const char* name) {
}

void Blacklist::clearBlackmark(const char* name) {
BlacklistMap::iterator i = blm.find(name);
if (i != blm.end()) {
strFree((char*)(*i).first);
blm.erase(i);
}
blm.erase(name);
}

+ 2
- 7
common/rfb/Blacklist.h View File

@@ -30,9 +30,9 @@
#include <string.h>
#include <time.h>
#include <map>
#include <string>

#include <rfb/Configuration.h>
#include <rfb/util.h>

namespace rfb {

@@ -68,17 +68,12 @@ namespace rfb {
void clearBlackmark(const char* name);

protected:
struct ltStr {
bool operator()(const char* s1, const char* s2) const {
return strcmp(s1, s2) < 0;
};
};
struct BlacklistInfo {
int marks;
time_t blockUntil;
unsigned int blockTimeout;
};
typedef std::map<const char*,BlacklistInfo,ltStr> BlacklistMap;
typedef std::map<std::string,BlacklistInfo> BlacklistMap;
BlacklistMap blm;
};


+ 35
- 42
common/rfb/CConnection.cxx View File

@@ -52,14 +52,14 @@ CConnection::CConnection()
supportsDesktopResize(false), supportsLEDState(false),
is(0), os(0), reader_(0), writer_(0),
shared(false),
state_(RFBSTATE_UNINITIALISED), serverName(strDup("")),
state_(RFBSTATE_UNINITIALISED),
pendingPFChange(false), preferredEncoding(encodingTight),
compressLevel(2), qualityLevel(-1),
formatChange(false), encodingChange(false),
firstUpdate(true), pendingUpdate(false), continuousUpdates(false),
forceNonincremental(true),
framebuffer(NULL), decoder(this),
serverClipboard(NULL), hasLocalClipboard(false)
hasRemoteClipboard(false), hasLocalClipboard(false)
{
}

@@ -72,7 +72,7 @@ void CConnection::setServerName(const char* name_)
{
if (name_ == NULL)
name_ = "";
serverName.replaceBuf(strDup(name_));
serverName = name_;
}

void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
@@ -93,10 +93,10 @@ void CConnection::setFramebuffer(ModifiablePixelBuffer* fb)
if ((framebuffer != NULL) && (fb != NULL)) {
Rect rect;

const rdr::U8* data;
const uint8_t* data;
int stride;

const rdr::U8 black[4] = { 0, 0, 0, 0 };
const uint8_t black[4] = { 0, 0, 0, 0 };

// Copy still valid area

@@ -210,7 +210,7 @@ bool CConnection::processSecurityTypesMsg()

int secType = secTypeInvalid;

std::list<rdr::U8> secTypes;
std::list<uint8_t> secTypes;
secTypes = security.GetEnabledSecTypes();

if (server.isVersion(3,3)) {
@@ -225,7 +225,7 @@ bool CConnection::processSecurityTypesMsg()
state_ = RFBSTATE_SECURITY_REASON;
return true;
} else if (secType == secTypeNone || secType == secTypeVncAuth) {
std::list<rdr::U8>::iterator i;
std::list<uint8_t>::iterator i;
for (i = secTypes.begin(); i != secTypes.end(); i++)
if (*i == secType) {
secType = *i;
@@ -259,10 +259,10 @@ bool CConnection::processSecurityTypesMsg()
return true;
}

std::list<rdr::U8>::iterator j;
std::list<uint8_t>::iterator j;

for (int i = 0; i < nServerSecTypes; i++) {
rdr::U8 serverSecType = is->readU8();
uint8_t serverSecType = is->readU8();
vlog.debug("Server offers security type %s(%d)",
secTypeName(serverSecType), serverSecType);

@@ -355,17 +355,17 @@ bool CConnection::processSecurityReasonMsg()

is->setRestorePoint();

rdr::U32 len = is->readU32();
uint32_t len = is->readU32();
if (!is->hasDataOrRestore(len))
return false;
is->clearRestorePoint();

CharArray reason(len + 1);
is->readBytes(reason.buf, len);
reason.buf[len] = '\0';
std::vector<char> reason(len + 1);
is->readBytes(reason.data(), len);
reason[len] = '\0';

state_ = RFBSTATE_INVALID;
throw AuthFailureException(reason.buf);
throw AuthFailureException(reason.data());
}

bool CConnection::processInitMsg()
@@ -405,8 +405,6 @@ void CConnection::close()
reader_ = NULL;
delete writer_;
writer_ = NULL;
strFree(serverClipboard);
serverClipboard = NULL;
}

void CConnection::setDesktopSize(int w, int h)
@@ -545,18 +543,16 @@ void CConnection::serverCutText(const char* str)
{
hasLocalClipboard = false;

strFree(serverClipboard);
serverClipboard = NULL;

serverClipboard = latin1ToUTF8(str);
hasRemoteClipboard = true;

handleClipboardAnnounce(true);
}

void CConnection::handleClipboardCaps(rdr::U32 flags,
const rdr::U32* lengths)
void CConnection::handleClipboardCaps(uint32_t flags,
const uint32_t* lengths)
{
rdr::U32 sizes[] = { 0 };
uint32_t sizes[] = { 0 };

CMsgHandler::handleClipboardCaps(flags, lengths);

@@ -568,7 +564,7 @@ void CConnection::handleClipboardCaps(rdr::U32 flags,
sizes);
}

void CConnection::handleClipboardRequest(rdr::U32 flags)
void CConnection::handleClipboardRequest(uint32_t flags)
{
if (!(flags & rfb::clipboardUTF8)) {
vlog.debug("Ignoring clipboard request for unsupported formats 0x%x", flags);
@@ -587,10 +583,9 @@ void CConnection::handleClipboardPeek()
writer()->writeClipboardNotify(hasLocalClipboard ? rfb::clipboardUTF8 : 0);
}

void CConnection::handleClipboardNotify(rdr::U32 flags)
void CConnection::handleClipboardNotify(uint32_t flags)
{
strFree(serverClipboard);
serverClipboard = NULL;
hasRemoteClipboard = false;

if (flags & rfb::clipboardUTF8) {
hasLocalClipboard = false;
@@ -600,22 +595,20 @@ void CConnection::handleClipboardNotify(rdr::U32 flags)
}
}

void CConnection::handleClipboardProvide(rdr::U32 flags,
void CConnection::handleClipboardProvide(uint32_t flags,
const size_t* lengths,
const rdr::U8* const* data)
const uint8_t* const* data)
{
if (!(flags & rfb::clipboardUTF8)) {
vlog.debug("Ignoring clipboard provide with unsupported formats 0x%x", flags);
return;
}

strFree(serverClipboard);
serverClipboard = NULL;

serverClipboard = convertLF((const char*)data[0], lengths[0]);
hasRemoteClipboard = true;

// FIXME: Should probably verify that this data was actually requested
handleClipboardData(serverClipboard);
handleClipboardData(serverClipboard.c_str());
}

void CConnection::authSuccess()
@@ -645,8 +638,8 @@ void CConnection::handleClipboardData(const char* /*data*/)

void CConnection::requestClipboard()
{
if (serverClipboard != NULL) {
handleClipboardData(serverClipboard);
if (hasRemoteClipboard) {
handleClipboardData(serverClipboard.c_str());
return;
}

@@ -681,9 +674,9 @@ void CConnection::announceClipboard(bool available)
void CConnection::sendClipboardData(const char* data)
{
if (server.clipboardFlags() & rfb::clipboardProvide) {
CharArray filtered(convertCRLF(data));
size_t sizes[1] = { strlen(filtered.buf) + 1 };
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf };
std::string filtered(convertCRLF(data));
size_t sizes[1] = { filtered.size() + 1 };
const uint8_t* data[1] = { (const uint8_t*)filtered.c_str() };

if (unsolicitedClipboardAttempt) {
unsolicitedClipboardAttempt = false;
@@ -697,9 +690,9 @@ void CConnection::sendClipboardData(const char* data)

writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
} else {
CharArray latin1(utf8ToLatin1(data));
std::string latin1(utf8ToLatin1(data));

writer()->writeClientCutText(latin1.buf);
writer()->writeClientCutText(latin1.c_str());
}
}

@@ -747,14 +740,14 @@ void CConnection::setQualityLevel(int level)

void CConnection::setPF(const PixelFormat& pf)
{
if (server.pf().equal(pf) && !formatChange)
if (server.pf() == pf && !formatChange)
return;

nextPF = pf;
formatChange = true;
}

void CConnection::fence(rdr::U32 flags, unsigned len, const char data[])
void CConnection::fence(uint32_t flags, unsigned len, const char data[])
{
CMsgHandler::fence(flags, len, data);

@@ -819,7 +812,7 @@ void CConnection::requestNewUpdate()

void CConnection::updateEncodings()
{
std::list<rdr::U32> encodings;
std::list<uint32_t> encodings;

if (supportsLocalCursor) {
encodings.push_back(pseudoEncodingCursorWithAlpha);

+ 13
- 11
common/rfb/CConnection.h View File

@@ -24,10 +24,11 @@
#ifndef __RFB_CCONNECTION_H__
#define __RFB_CCONNECTION_H__

#include <string>

#include <rfb/CMsgHandler.h>
#include <rfb/DecodeManager.h>
#include <rfb/SecurityClient.h>
#include <rfb/util.h>

namespace rfb {

@@ -116,14 +117,14 @@ namespace rfb {

virtual void serverCutText(const char* str);

virtual void handleClipboardCaps(rdr::U32 flags,
const rdr::U32* lengths);
virtual void handleClipboardRequest(rdr::U32 flags);
virtual void handleClipboardCaps(uint32_t flags,
const uint32_t* lengths);
virtual void handleClipboardRequest(uint32_t flags);
virtual void handleClipboardPeek();
virtual void handleClipboardNotify(rdr::U32 flags);
virtual void handleClipboardProvide(rdr::U32 flags,
virtual void handleClipboardNotify(uint32_t flags);
virtual void handleClipboardProvide(uint32_t flags,
const size_t* lengths,
const rdr::U8* const* data);
const uint8_t* const* data);


// Methods to be overridden in a derived class
@@ -206,7 +207,7 @@ namespace rfb {

// Access method used by SSecurity implementations that can verify servers'
// Identities, to determine the unique(ish) name of the server.
const char* getServerName() const { return serverName.buf; }
const char* getServerName() const { return serverName.c_str(); }

bool isSecure() const { return csecurity ? csecurity->isSecure() : false; }

@@ -248,7 +249,7 @@ namespace rfb {
// responds to requests, stating no support for synchronisation.
// When overriding, call CMsgHandler::fence() directly in order to
// state correct support for fence flags.
virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
virtual void fence(uint32_t flags, unsigned len, const char data[]);

private:
bool processVersionMsg();
@@ -271,7 +272,7 @@ namespace rfb {
bool shared;
stateEnum state_;

CharArray serverName;
std::string serverName;

bool pendingPFChange;
rfb::PixelFormat pendingPF;
@@ -293,7 +294,8 @@ namespace rfb {
ModifiablePixelBuffer* framebuffer;
DecodeManager decoder;

char* serverClipboard;
std::string serverClipboard;
bool hasRemoteClipboard;
bool hasLocalClipboard;
bool unsolicitedClipboardAttempt;
};

+ 1
- 1
common/rfb/CMakeLists.txt View File

@@ -32,7 +32,6 @@ add_library(rfb STATIC
Logger.cxx
Logger_file.cxx
Logger_stdio.cxx
Password.cxx
PixelBuffer.cxx
PixelFormat.cxx
RREEncoder.cxx
@@ -64,6 +63,7 @@ add_library(rfb STATIC
ZRLEEncoder.cxx
ZRLEDecoder.cxx
encodings.cxx
obfuscate.cxx
util.cxx)

target_link_libraries(rfb os rdr)

+ 8
- 10
common/rfb/CMsgHandler.cxx View File

@@ -28,6 +28,7 @@
#include <rfb/CMsgHandler.h>
#include <rfb/clipboardTypes.h>
#include <rfb/screenTypes.h>
#include <rfb/util.h>

static rfb::LogWriter vlog("CMsgHandler");

@@ -68,7 +69,7 @@ void CMsgHandler::setName(const char* name)
server.setName(name);
}

void CMsgHandler::fence(rdr::U32 /*flags*/, unsigned /*len*/,
void CMsgHandler::fence(uint32_t /*flags*/, unsigned /*len*/,
const char /*data*/ [])
{
server.supportsFence = true;
@@ -106,7 +107,7 @@ void CMsgHandler::setLEDState(unsigned int state)
server.setLEDState(state);
}

void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
void CMsgHandler::handleClipboardCaps(uint32_t flags, const uint32_t* lengths)
{
int i;

@@ -139,11 +140,8 @@ void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
if (lengths[i] == 0)
vlog.debug(" %s (only notify)", type);
else {
char bytes[1024];

iecPrefix(lengths[i], "B", bytes, sizeof(bytes));
vlog.debug(" %s (automatically send up to %s)",
type, bytes);
type, iecPrefix(lengths[i], "B").c_str());
}
}
}
@@ -151,7 +149,7 @@ void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
server.setClipboardCaps(flags, lengths);
}

void CMsgHandler::handleClipboardRequest(rdr::U32 /*flags*/)
void CMsgHandler::handleClipboardRequest(uint32_t /*flags*/)
{
}

@@ -159,12 +157,12 @@ void CMsgHandler::handleClipboardPeek()
{
}

void CMsgHandler::handleClipboardNotify(rdr::U32 /*flags*/)
void CMsgHandler::handleClipboardNotify(uint32_t /*flags*/)
{
}

void CMsgHandler::handleClipboardProvide(rdr::U32 /*flags*/,
void CMsgHandler::handleClipboardProvide(uint32_t /*flags*/,
const size_t* /*lengths*/,
const rdr::U8* const* /*data*/)
const uint8_t* const* /*data*/)
{
}

+ 11
- 11
common/rfb/CMsgHandler.h View File

@@ -24,8 +24,8 @@
#ifndef __RFB_CMSGHANDLER_H__
#define __RFB_CMSGHANDLER_H__

#include <rdr/types.h>
#include <rfb/Pixel.h>
#include <stdint.h>
#include <rfb/ServerParams.h>
#include <rfb/Rect.h>
#include <rfb/ScreenSet.h>
@@ -51,11 +51,11 @@ namespace rfb {
int w, int h,
const ScreenSet& layout);
virtual void setCursor(int width, int height, const Point& hotspot,
const rdr::U8* data) = 0;
const uint8_t* data) = 0;
virtual void setCursorPos(const Point& pos) = 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 fence(uint32_t flags, unsigned len, const char data[]);
virtual void endOfContinuousUpdates();
virtual void supportsQEMUKeyEvent();
virtual void serverInit(int width, int height,
@@ -70,20 +70,20 @@ namespace rfb {
virtual bool dataRect(const Rect& r, int encoding) = 0;

virtual void setColourMapEntries(int firstColour, int nColours,
rdr::U16* rgbs) = 0;
uint16_t* rgbs) = 0;
virtual void bell() = 0;
virtual void serverCutText(const char* str) = 0;

virtual void setLEDState(unsigned int state);

virtual void handleClipboardCaps(rdr::U32 flags,
const rdr::U32* lengths);
virtual void handleClipboardRequest(rdr::U32 flags);
virtual void handleClipboardCaps(uint32_t flags,
const uint32_t* lengths);
virtual void handleClipboardRequest(uint32_t flags);
virtual void handleClipboardPeek();
virtual void handleClipboardNotify(rdr::U32 flags);
virtual void handleClipboardProvide(rdr::U32 flags,
virtual void handleClipboardNotify(uint32_t flags);
virtual void handleClipboardProvide(uint32_t flags,
const size_t* lengths,
const rdr::U8* const* data);
const uint8_t* const* data);

ServerParams server;
};

+ 77
- 75
common/rfb/CMsgReader.cxx View File

@@ -24,14 +24,16 @@
#include <assert.h>
#include <stdio.h>

#include <vector>

#include <rdr/InStream.h>
#include <rdr/ZlibInStream.h>

#include <rfb/msgTypes.h>
#include <rfb/clipboardTypes.h>
#include <rfb/util.h>
#include <rfb/Exception.h>
#include <rfb/LogWriter.h>
#include <rfb/util.h>
#include <rfb/CMsgHandler.h>
#include <rfb/CMsgReader.h>

@@ -54,7 +56,7 @@ CMsgReader::~CMsgReader()
bool CMsgReader::readServerInit()
{
int width, height;
rdr::U32 len;
uint32_t len;

if (!is->hasData(2 + 2 + 16 + 4))
return false;
@@ -71,10 +73,10 @@ bool CMsgReader::readServerInit()
if (!is->hasDataOrRestore(len))
return false;
is->clearRestorePoint();
CharArray name(len + 1);
is->readBytes(name.buf, len);
name.buf[len] = '\0';
handler->serverInit(width, height, pf, name.buf);
std::vector<char> name(len + 1);
is->readBytes(name.data(), len);
name[len] = '\0';
handler->serverInit(width, height, pf, name.data());

return true;
}
@@ -228,10 +230,10 @@ bool CMsgReader::readSetColourMapEntries()
return false;
is->clearRestorePoint();

rdr::U16Array rgbs(nColours * 3);
for (int i = 0; i < nColours * 3; i++)
rgbs.buf[i] = is->readU16();
handler->setColourMapEntries(firstColour, nColours, rgbs.buf);
std::vector<uint16_t> rgbs(nColours * 3);
for (size_t i = 0; i < rgbs.size(); i++)
rgbs[i] = is->readU16();
handler->setColourMapEntries(firstColour, nColours, rgbs.data());

return true;
}
@@ -250,10 +252,10 @@ bool CMsgReader::readServerCutText()
is->setRestorePoint();

is->skip(3);
rdr::U32 len = is->readU32();
uint32_t len = is->readU32();

if (len & 0x80000000) {
rdr::S32 slen = len;
int32_t slen = len;
slen = -slen;
if (readExtendedClipboard(slen)) {
is->clearRestorePoint();
@@ -273,18 +275,18 @@ bool CMsgReader::readServerCutText()
vlog.error("cut text too long (%d bytes) - ignoring",len);
return true;
}
CharArray ca(len);
is->readBytes(ca.buf, len);
CharArray filtered(convertLF(ca.buf, len));
handler->serverCutText(filtered.buf);
std::vector<char> ca(len);
is->readBytes(ca.data(), len);
std::string filtered(convertLF(ca.data(), len));
handler->serverCutText(filtered.c_str());

return true;
}

bool CMsgReader::readExtendedClipboard(rdr::S32 len)
bool CMsgReader::readExtendedClipboard(int32_t len)
{
rdr::U32 flags;
rdr::U32 action;
uint32_t flags;
uint32_t action;

if (!is->hasData(len))
return false;
@@ -303,7 +305,7 @@ bool CMsgReader::readExtendedClipboard(rdr::S32 len)
if (action & clipboardCaps) {
int i;
size_t num;
rdr::U32 lengths[16];
uint32_t lengths[16];

num = 0;
for (i = 0;i < 16;i++) {
@@ -311,7 +313,7 @@ bool CMsgReader::readExtendedClipboard(rdr::S32 len)
num++;
}

if (len < (rdr::S32)(4 + 4*num))
if (len < (int32_t)(4 + 4*num))
throw Exception("Invalid extended clipboard message");

num = 0;
@@ -327,7 +329,7 @@ bool CMsgReader::readExtendedClipboard(rdr::S32 len)
int i;
size_t num;
size_t lengths[16];
rdr::U8* buffers[16];
uint8_t* buffers[16];

zis.setUnderlying(is, len - 4);

@@ -368,7 +370,7 @@ bool CMsgReader::readExtendedClipboard(rdr::S32 len)
if (!zis.hasData(lengths[num]))
throw Exception("Extended clipboard decode error");

buffers[num] = new rdr::U8[lengths[num]];
buffers[num] = new uint8_t[lengths[num]];
zis.readBytes(buffers[num], lengths[num]);
num++;
}
@@ -405,8 +407,8 @@ bool CMsgReader::readExtendedClipboard(rdr::S32 len)

bool CMsgReader::readFence()
{
rdr::U32 flags;
rdr::U8 len;
uint32_t flags;
uint8_t len;
char data[64];

if (!is->hasData(3 + 4 + 1))
@@ -476,18 +478,18 @@ bool CMsgReader::readSetXCursor(int width, int height, const Point& hotspot)
if (width > maxCursorSize || height > maxCursorSize)
throw Exception("Too big cursor");

rdr::U8Array rgba(width*height*4);
std::vector<uint8_t> rgba(width*height*4);

if (width * height > 0) {
rdr::U8 pr, pg, pb;
rdr::U8 sr, sg, sb;
uint8_t pr, pg, pb;
uint8_t 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);
std::vector<uint8_t> data(data_len);
std::vector<uint8_t> mask(mask_len);

int x, y;
rdr::U8* out;
uint8_t* out;

if (!is->hasData(3 + 3 + data_len + mask_len))
return false;
@@ -500,17 +502,17 @@ bool CMsgReader::readSetXCursor(int width, int height, const Point& hotspot)
sg = is->readU8();
sb = is->readU8();

is->readBytes(data.buf, data_len);
is->readBytes(mask.buf, mask_len);
is->readBytes(data.data(), data.size());
is->readBytes(mask.data(), mask.size());

int maskBytesPerRow = (width+7)/8;
out = rgba.buf;
out = rgba.data();
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)) {
if (data[byte] & (1 << bit)) {
out[0] = pr;
out[1] = pg;
out[2] = pb;
@@ -520,7 +522,7 @@ bool CMsgReader::readSetXCursor(int width, int height, const Point& hotspot)
out[2] = sb;
}

if (mask.buf[byte] & (1 << bit))
if (mask[byte] & (1 << bit))
out[3] = 255;
else
out[3] = 0;
@@ -530,7 +532,7 @@ bool CMsgReader::readSetXCursor(int width, int height, const Point& hotspot)
}
}

handler->setCursor(width, height, hotspot, rgba.buf);
handler->setCursor(width, height, hotspot, rgba.data());

return true;
}
@@ -542,23 +544,23 @@ bool CMsgReader::readSetCursor(int width, int height, const Point& hotspot)

int data_len = width * height * (handler->server.pf().bpp/8);
int mask_len = ((width+7)/8) * height;
rdr::U8Array data(data_len);
rdr::U8Array mask(mask_len);
std::vector<uint8_t> data(data_len);
std::vector<uint8_t> mask(mask_len);

int x, y;
rdr::U8Array rgba(width*height*4);
rdr::U8* in;
rdr::U8* out;
std::vector<uint8_t> rgba(width*height*4);
uint8_t* in;
uint8_t* out;

if (!is->hasData(data_len + mask_len))
return false;

is->readBytes(data.buf, data_len);
is->readBytes(mask.buf, mask_len);
is->readBytes(data.data(), data.size());
is->readBytes(mask.data(), mask.size());

int maskBytesPerRow = (width+7)/8;
in = data.buf;
out = rgba.buf;
in = data.data();
out = rgba.data();
for (y = 0;y < height;y++) {
for (x = 0;x < width;x++) {
int byte = y * maskBytesPerRow + x / 8;
@@ -566,7 +568,7 @@ bool CMsgReader::readSetCursor(int width, int height, const Point& hotspot)

handler->server.pf().rgbFromBuffer(out, in, 1);

if (mask.buf[byte] & (1 << bit))
if (mask[byte] & (1 << bit))
out[3] = 255;
else
out[3] = 0;
@@ -576,7 +578,7 @@ bool CMsgReader::readSetCursor(int width, int height, const Point& hotspot)
}
}

handler->setCursor(width, height, hotspot, rgba.buf);
handler->setCursor(width, height, hotspot, rgba.data());

return true;
}
@@ -592,7 +594,7 @@ bool CMsgReader::readSetCursorWithAlpha(int width, int height, const Point& hots

bool ret;

rdr::U8* buf;
uint8_t* buf;
int stride;

// We can't use restore points as the decoder likely wants to as well, so
@@ -621,7 +623,7 @@ bool CMsgReader::readSetCursorWithAlpha(int width, int height, const Point& hots
assert(stride == width);

for (int i = 0;i < pb.area();i++) {
rdr::U8 alpha;
uint8_t alpha;

alpha = buf[3];
if (alpha == 0)
@@ -647,7 +649,7 @@ bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot
if (width > maxCursorSize || height > maxCursorSize)
throw Exception("Too big cursor");

rdr::U8 type;
uint8_t type;

if (!is->hasData(1 + 1))
return false;
@@ -659,26 +661,26 @@ bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot

if (type == 0) {
int len = width * height * (handler->server.pf().bpp/8);
rdr::U8Array andMask(len);
rdr::U8Array xorMask(len);
std::vector<uint8_t> andMask(len);
std::vector<uint8_t> xorMask(len);

rdr::U8Array data(width*height*4);
std::vector<uint8_t> data(width*height*4);

rdr::U8* andIn;
rdr::U8* xorIn;
rdr::U8* out;
uint8_t* andIn;
uint8_t* xorIn;
uint8_t* out;
int Bpp;

if (!is->hasDataOrRestore(len + len))
return false;
is->clearRestorePoint();

is->readBytes(andMask.buf, len);
is->readBytes(xorMask.buf, len);
is->readBytes(andMask.data(), andMask.size());
is->readBytes(xorMask.data(), xorMask.size());

andIn = andMask.buf;
xorIn = xorMask.buf;
out = data.buf;
andIn = andMask.data();
xorIn = xorMask.data();
out = data.data();
Bpp = handler->server.pf().bpp/8;
for (int y = 0;y < height;y++) {
for (int x = 0;x < width;x++) {
@@ -690,7 +692,7 @@ bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot
xorIn += Bpp;

if (andPixel == 0) {
rdr::U8 r, g, b;
uint8_t r, g, b;

// Opaque pixel

@@ -726,18 +728,18 @@ bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot
}
}

handler->setCursor(width, height, hotspot, data.buf);
handler->setCursor(width, height, hotspot, data.data());
} else if (type == 1) {
rdr::U8Array data(width*height*4);
std::vector<uint8_t> data(width*height*4);

if (!is->hasDataOrRestore(width*height*4))
return false;
is->clearRestorePoint();

// FIXME: Is alpha premultiplied?
is->readBytes(data.buf, width*height*4);
is->readBytes(data.data(), data.size());

handler->setCursor(width, height, hotspot, data.buf);
handler->setCursor(width, height, hotspot, data.data());
} else {
throw Exception("Unknown cursor type");
}
@@ -747,7 +749,7 @@ bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot

bool CMsgReader::readSetDesktopName(int x, int y, int w, int h)
{
rdr::U32 len;
uint32_t len;

if (!is->hasData(4))
return false;
@@ -760,14 +762,14 @@ bool CMsgReader::readSetDesktopName(int x, int y, int w, int h)
return false;
is->clearRestorePoint();

CharArray name(len + 1);
is->readBytes(name.buf, len);
name.buf[len] = '\0';
std::vector<char> name(len + 1);
is->readBytes(name.data(), len);
name[len] = '\0';

if (x || y || w || h) {
vlog.error("Ignoring DesktopName rect with non-zero position/size");
} else {
handler->setName(name.buf);
handler->setName(name.data());
}

return true;
@@ -776,7 +778,7 @@ bool CMsgReader::readSetDesktopName(int x, int y, int w, int h)
bool CMsgReader::readExtendedDesktopSize(int x, int y, int w, int h)
{
unsigned int screens, i;
rdr::U32 id, flags;
uint32_t id, flags;
int sx, sy, sw, sh;
ScreenSet layout;

@@ -810,7 +812,7 @@ bool CMsgReader::readExtendedDesktopSize(int x, int y, int w, int h)

bool CMsgReader::readLEDState()
{
rdr::U8 state;
uint8_t state;

if (!is->hasData(1))
return false;
@@ -824,7 +826,7 @@ bool CMsgReader::readLEDState()

bool CMsgReader::readVMwareLEDState()
{
rdr::U32 state;
uint32_t state;

if (!is->hasData(4))
return false;

+ 3
- 3
common/rfb/CMsgReader.h View File

@@ -24,7 +24,7 @@
#ifndef __RFB_CMSGREADER_H__
#define __RFB_CMSGREADER_H__

#include <rdr/types.h>
#include <stdint.h>

#include <rfb/Rect.h>
#include <rfb/encodings.h>
@@ -53,7 +53,7 @@ namespace rfb {
bool readSetColourMapEntries();
bool readBell();
bool readServerCutText();
bool readExtendedClipboard(rdr::S32 len);
bool readExtendedClipboard(int32_t len);
bool readFence();
bool readEndOfContinuousUpdates();

@@ -83,7 +83,7 @@ namespace rfb {

stateEnum state;

rdr::U8 currentMsgType;
uint8_t currentMsgType;
int nUpdateRectsLeft;
Rect dataRect;
int rectEncoding;

+ 11
- 11
common/rfb/CMsgWriter.cxx View File

@@ -62,9 +62,9 @@ void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)
endMsg();
}

void CMsgWriter::writeSetEncodings(const std::list<rdr::U32> encodings)
void CMsgWriter::writeSetEncodings(const std::list<uint32_t> encodings)
{
std::list<rdr::U32>::const_iterator iter;
std::list<uint32_t>::const_iterator iter;
startMsg(msgTypeSetEncodings);
os->pad(1);
os->writeU16(encodings.size());
@@ -130,7 +130,7 @@ void CMsgWriter::writeEnableContinuousUpdates(bool enable,
endMsg();
}

void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
void CMsgWriter::writeFence(uint32_t flags, unsigned len, const char data[])
{
if (!server->supportsFence)
throw Exception("Server does not support fences");
@@ -150,7 +150,7 @@ void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
endMsg();
}

void CMsgWriter::writeKeyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
void CMsgWriter::writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down)
{
if (!server->supportsQEMUKeyEvent || !keycode) {
/* This event isn't meaningful without a valid keysym */
@@ -204,8 +204,8 @@ void CMsgWriter::writeClientCutText(const char* str)
endMsg();
}

void CMsgWriter::writeClipboardCaps(rdr::U32 caps,
const rdr::U32* lengths)
void CMsgWriter::writeClipboardCaps(uint32_t caps,
const uint32_t* lengths)
{
size_t i, count;

@@ -233,7 +233,7 @@ void CMsgWriter::writeClipboardCaps(rdr::U32 caps,
endMsg();
}

void CMsgWriter::writeClipboardRequest(rdr::U32 flags)
void CMsgWriter::writeClipboardRequest(uint32_t flags)
{
if (!(server->clipboardFlags() & clipboardRequest))
throw Exception("Server does not support clipboard \"request\" action");
@@ -245,7 +245,7 @@ void CMsgWriter::writeClipboardRequest(rdr::U32 flags)
endMsg();
}

void CMsgWriter::writeClipboardPeek(rdr::U32 flags)
void CMsgWriter::writeClipboardPeek(uint32_t flags)
{
if (!(server->clipboardFlags() & clipboardPeek))
throw Exception("Server does not support clipboard \"peek\" action");
@@ -257,7 +257,7 @@ void CMsgWriter::writeClipboardPeek(rdr::U32 flags)
endMsg();
}

void CMsgWriter::writeClipboardNotify(rdr::U32 flags)
void CMsgWriter::writeClipboardNotify(uint32_t flags)
{
if (!(server->clipboardFlags() & clipboardNotify))
throw Exception("Server does not support clipboard \"notify\" action");
@@ -269,9 +269,9 @@ void CMsgWriter::writeClipboardNotify(rdr::U32 flags)
endMsg();
}

void CMsgWriter::writeClipboardProvide(rdr::U32 flags,
void CMsgWriter::writeClipboardProvide(uint32_t flags,
const size_t* lengths,
const rdr::U8* const* data)
const uint8_t* const* data)
{
rdr::MemOutStream mos;
rdr::ZlibOutStream zos;

+ 10
- 10
common/rfb/CMsgWriter.h View File

@@ -25,7 +25,7 @@

#include <list>

#include <rdr/types.h>
#include <stdint.h>

namespace rdr { class OutStream; }

@@ -45,25 +45,25 @@ namespace rfb {
void writeClientInit(bool shared);

void writeSetPixelFormat(const PixelFormat& pf);
void writeSetEncodings(const std::list<rdr::U32> encodings);
void writeSetEncodings(const std::list<uint32_t> encodings);
void writeSetDesktopSize(int width, int height, const ScreenSet& layout);

void writeFramebufferUpdateRequest(const Rect& r,bool incremental);
void writeEnableContinuousUpdates(bool enable, int x, int y, int w, int h);

void writeFence(rdr::U32 flags, unsigned len, const char data[]);
void writeFence(uint32_t flags, unsigned len, const char data[]);

void writeKeyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
void writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down);
void writePointerEvent(const Point& pos, int buttonMask);

void writeClientCutText(const char* str);

void writeClipboardCaps(rdr::U32 caps, const rdr::U32* lengths);
void writeClipboardRequest(rdr::U32 flags);
void writeClipboardPeek(rdr::U32 flags);
void writeClipboardNotify(rdr::U32 flags);
void writeClipboardProvide(rdr::U32 flags, const size_t* lengths,
const rdr::U8* const* data);
void writeClipboardCaps(uint32_t caps, const uint32_t* lengths);
void writeClipboardRequest(uint32_t flags);
void writeClipboardPeek(uint32_t flags);
void writeClipboardNotify(uint32_t flags);
void writeClipboardProvide(uint32_t flags, const size_t* lengths,
const uint8_t* const* data);

protected:
void startMsg(int type);

+ 26
- 27
common/rfb/CSecurityDH.cxx View File

@@ -83,7 +83,7 @@ bool CSecurityDH::readKey()
if (!is->hasData(4))
return false;
is->setRestorePoint();
rdr::U16 gen = is->readU16();
uint16_t gen = is->readU16();
keyLength = is->readU16();
if (keyLength < MinKeyLength)
throw AuthFailureException("DH key is too short");
@@ -93,38 +93,39 @@ bool CSecurityDH::readKey()
return false;
is->clearRestorePoint();
mpz_set_ui(g, gen);
rdr::U8Array pBytes(keyLength);
rdr::U8Array ABytes(keyLength);
is->readBytes(pBytes.buf, keyLength);
is->readBytes(ABytes.buf, keyLength);
nettle_mpz_set_str_256_u(p, keyLength, pBytes.buf);
nettle_mpz_set_str_256_u(A, keyLength, ABytes.buf);
std::vector<uint8_t> pBytes(keyLength);
std::vector<uint8_t> ABytes(keyLength);
is->readBytes(pBytes.data(), pBytes.size());
is->readBytes(ABytes.data(), ABytes.size());
nettle_mpz_set_str_256_u(p, pBytes.size(), pBytes.data());
nettle_mpz_set_str_256_u(A, ABytes.size(), ABytes.data());
return true;
}

void CSecurityDH::writeCredentials()
{
CharArray username;
CharArray password;
std::string username;
std::string password;
rdr::RandomStream rs;

(CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf);
rdr::U8Array bBytes(keyLength);
(CSecurity::upg)->getUserPasswd(isSecure(), &username, &password);

std::vector<uint8_t> bBytes(keyLength);
if (!rs.hasData(keyLength))
throw ConnFailedException("failed to generate DH private key");
rs.readBytes(bBytes.buf, keyLength);
nettle_mpz_set_str_256_u(b, keyLength, bBytes.buf);
rs.readBytes(bBytes.data(), bBytes.size());
nettle_mpz_set_str_256_u(b, bBytes.size(), bBytes.data());
mpz_powm(k, A, b, p);
mpz_powm(B, g, b, p);

rdr::U8Array sharedSecret(keyLength);
rdr::U8Array BBytes(keyLength);
nettle_mpz_get_str_256(keyLength, sharedSecret.buf, k);
nettle_mpz_get_str_256(keyLength, BBytes.buf, B);
rdr::U8 key[16];
std::vector<uint8_t> sharedSecret(keyLength);
std::vector<uint8_t> BBytes(keyLength);
nettle_mpz_get_str_256(sharedSecret.size(), sharedSecret.data(), k);
nettle_mpz_get_str_256(BBytes.size(), BBytes.data(), B);
uint8_t key[16];
struct md5_ctx md5Ctx;
md5_init(&md5Ctx);
md5_update(&md5Ctx, keyLength, sharedSecret.buf);
md5_update(&md5Ctx, sharedSecret.size(), sharedSecret.data());
md5_digest(&md5Ctx, 16, key);
struct aes128_ctx aesCtx;
aes128_set_encrypt_key(&aesCtx, key);
@@ -133,18 +134,16 @@ void CSecurityDH::writeCredentials()
if (!rs.hasData(128))
throw ConnFailedException("failed to generate random padding");
rs.readBytes(buf, 128);
size_t len = strlen(username.buf);
if (len >= 64)
if (username.size() >= 64)
throw AuthFailureException("username is too long");
memcpy(buf, username.buf, len + 1);
len = strlen(password.buf);
if (len >= 64)
memcpy(buf, username.c_str(), username.size() + 1);
if (password.size() >= 64)
throw AuthFailureException("password is too long");
memcpy(buf + 64, password.buf, len + 1);
aes128_encrypt(&aesCtx, 128, (rdr::U8 *)buf, (rdr::U8 *)buf);
memcpy(buf + 64, password.c_str(), password.size() + 1);
aes128_encrypt(&aesCtx, 128, (uint8_t *)buf, (uint8_t *)buf);

rdr::OutStream* os = cc->getOutStream();
os->writeBytes(buf, 128);
os->writeBytes(BBytes.buf, keyLength);
os->writeBytes(BBytes.data(), BBytes.size());
os->flush();
}

+ 20
- 21
common/rfb/CSecurityMSLogonII.cxx View File

@@ -79,9 +79,9 @@ bool CSecurityMSLogonII::readKey()
rdr::InStream* is = cc->getInStream();
if (!is->hasData(24))
return false;
rdr::U8 gBytes[8];
rdr::U8 pBytes[8];
rdr::U8 ABytes[8];
uint8_t gBytes[8];
uint8_t pBytes[8];
uint8_t ABytes[8];
is->readBytes(gBytes, 8);
is->readBytes(pBytes, 8);
is->readBytes(ABytes, 8);
@@ -93,28 +93,29 @@ bool CSecurityMSLogonII::readKey()

void CSecurityMSLogonII::writeCredentials()
{
CharArray username;
CharArray password;
std::string username;
std::string password;
rdr::RandomStream rs;

(CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf);
rdr::U8Array bBytes(8);
(CSecurity::upg)->getUserPasswd(isSecure(), &username, &password);

std::vector<uint8_t> bBytes(8);
if (!rs.hasData(8))
throw ConnFailedException("failed to generate DH private key");
rs.readBytes(bBytes.buf, 8);
nettle_mpz_set_str_256_u(b, 8, bBytes.buf);
rs.readBytes(bBytes.data(), bBytes.size());
nettle_mpz_set_str_256_u(b, bBytes.size(), bBytes.data());
mpz_powm(k, A, b, p);
mpz_powm(B, g, b, p);

rdr::U8 key[8];
rdr::U8 reversedKey[8];
rdr::U8 BBytes[8];
rdr::U8 user[256];
rdr::U8 pass[64];
uint8_t key[8];
uint8_t reversedKey[8];
uint8_t BBytes[8];
uint8_t user[256];
uint8_t pass[64];
nettle_mpz_get_str_256(8, key, k);
nettle_mpz_get_str_256(8, BBytes, B);
for (int i = 0; i < 8; ++i) {
rdr::U8 x = 0;
uint8_t x = 0;
for (int j = 0; j < 8; ++j) {
x |= ((key[i] >> j) & 1) << (7 - j);
}
@@ -125,14 +126,12 @@ void CSecurityMSLogonII::writeCredentials()
throw ConnFailedException("failed to generate random padding");
rs.readBytes(user, 256);
rs.readBytes(pass, 64);
size_t len = strlen(username.buf);
if (len >= 256)
if (username.size() >= 256)
throw AuthFailureException("username is too long");
memcpy(user, username.buf, len + 1);
len = strlen(password.buf);
if (len >= 64)
memcpy(user, username.c_str(), username.size() + 1);
if (password.size() >= 64)
throw AuthFailureException("password is too long");
memcpy(pass, password.buf, len + 1);
memcpy(pass, password.c_str(), password.size() + 1);

// DES-CBC with the original key as IV, and the reversed one as the DES key
struct CBC_CTX(struct des_ctx, DES_BLOCK_SIZE) ctx;

+ 7
- 8
common/rfb/CSecurityPlain.cxx View File

@@ -24,7 +24,6 @@
#include <rfb/CConnection.h>
#include <rfb/CSecurityPlain.h>
#include <rfb/UserPasswdGetter.h>
#include <rfb/util.h>

#include <rdr/OutStream.h>

@@ -34,16 +33,16 @@ bool CSecurityPlain::processMsg()
{
rdr::OutStream* os = cc->getOutStream();

CharArray username;
CharArray password;
std::string username;
std::string password;

(CSecurity::upg)->getUserPasswd(cc->isSecure(), &username.buf, &password.buf);
(CSecurity::upg)->getUserPasswd(cc->isSecure(), &username, &password);

// Return the response to the server
os->writeU32(strlen(username.buf));
os->writeU32(strlen(password.buf));
os->writeBytes(username.buf,strlen(username.buf));
os->writeBytes(password.buf,strlen(password.buf));
os->writeU32(username.size());
os->writeU32(password.size());
os->writeBytes(username.data(), username.size());
os->writeBytes(password.data(), password.size());
os->flush();
return true;
}

+ 56
- 59
common/rfb/CSecurityRSAAES.cxx View File

@@ -39,6 +39,7 @@
#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
#include <rfb/UserMsgBox.h>
#include <rfb/util.h>
#include <rdr/AESInStream.h>
#include <rdr/AESOutStream.h>
#include <os/os.h>
@@ -55,7 +56,7 @@ const int MaxKeyLength = 8192;

using namespace rfb;

CSecurityRSAAES::CSecurityRSAAES(CConnection* cc, rdr::U32 _secType,
CSecurityRSAAES::CSecurityRSAAES(CConnection* cc, uint32_t _secType,
int _keySize, bool _isAllEncrypted)
: CSecurity(cc), state(ReadPublicKey),
keySize(_keySize), isAllEncrypted(_isAllEncrypted), secType(_secType),
@@ -155,8 +156,8 @@ void CSecurityRSAAES::writePublicKey()
if (!rsa_generate_keypair(&clientPublicKey, &clientKey,
&rs, random_func, NULL, NULL, clientKeyLength, 0))
throw AuthFailureException("failed to generate key");
clientKeyN = new rdr::U8[rsaKeySize];
clientKeyE = new rdr::U8[rsaKeySize];
clientKeyN = new uint8_t[rsaKeySize];
clientKeyE = new uint8_t[rsaKeySize];
nettle_mpz_get_str_256(rsaKeySize, clientKeyN, clientPublicKey.n);
nettle_mpz_get_str_256(rsaKeySize, clientKeyE, clientPublicKey.e);
os->writeU32(clientKeyLength);
@@ -180,8 +181,8 @@ bool CSecurityRSAAES::readPublicKey()
if (!is->hasDataOrRestore(size * 2))
return false;
is->clearRestorePoint();
serverKeyE = new rdr::U8[size];
serverKeyN = new rdr::U8[size];
serverKeyE = new uint8_t[size];
serverKeyN = new uint8_t[size];
is->readBytes(serverKeyN, size);
is->readBytes(serverKeyE, size);
rsa_public_key_init(&serverKey);
@@ -194,13 +195,13 @@ bool CSecurityRSAAES::readPublicKey()

void CSecurityRSAAES::verifyServer()
{
rdr::U8 lenServerKey[4] = {
(rdr::U8)((serverKeyLength & 0xff000000) >> 24),
(rdr::U8)((serverKeyLength & 0xff0000) >> 16),
(rdr::U8)((serverKeyLength & 0xff00) >> 8),
(rdr::U8)(serverKeyLength & 0xff)
uint8_t lenServerKey[4] = {
(uint8_t)((serverKeyLength & 0xff000000) >> 24),
(uint8_t)((serverKeyLength & 0xff0000) >> 16),
(uint8_t)((serverKeyLength & 0xff00) >> 8),
(uint8_t)(serverKeyLength & 0xff)
};
rdr::U8 f[8];
uint8_t f[8];
struct sha1_ctx ctx;
sha1_init(&ctx);
sha1_update(&ctx, 4, lenServerKey);
@@ -208,13 +209,12 @@ void CSecurityRSAAES::verifyServer()
sha1_update(&ctx, serverKey.size, serverKeyE);
sha1_digest(&ctx, sizeof(f), f);
const char *title = "Server key fingerprint";
CharArray text;
text.format(
std::string text = format(
"The server has provided the following identifying information:\n"
"Fingerprint: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n"
"Please verify that the information is correct and press \"Yes\". "
"Otherwise press \"No\"", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]);
if (!msg->showMsgBox(UserMsgBox::M_YESNO, title, text.buf))
if (!msg->showMsgBox(UserMsgBox::M_YESNO, title, text.c_str()))
throw AuthFailureException("server key mismatch");
}

@@ -238,7 +238,7 @@ void CSecurityRSAAES::writeRandom()
mpz_clear(x);
throw AuthFailureException("failed to encrypt random");
}
rdr::U8* buffer = new rdr::U8[serverKey.size];
uint8_t* buffer = new uint8_t[serverKey.size];
nettle_mpz_get_str_256(serverKey.size, buffer, x);
mpz_clear(x);
os->writeU16(serverKey.size);
@@ -259,7 +259,7 @@ bool CSecurityRSAAES::readRandom()
if (!is->hasDataOrRestore(size))
return false;
is->clearRestorePoint();
rdr::U8* buffer = new rdr::U8[size];
uint8_t* buffer = new uint8_t[size];
is->readBytes(buffer, size);
size_t randomSize = keySize / 8;
mpz_t x;
@@ -278,7 +278,7 @@ void CSecurityRSAAES::setCipher()
{
rawis = cc->getInStream();
rawos = cc->getOutStream();
rdr::U8 key[32];
uint8_t key[32];
if (keySize == 128) {
struct sha1_ctx ctx;
sha1_init(&ctx);
@@ -310,20 +310,20 @@ void CSecurityRSAAES::setCipher()

void CSecurityRSAAES::writeHash()
{
rdr::U8 hash[32];
uint8_t hash[32];
size_t len = serverKeyLength;
rdr::U8 lenServerKey[4] = {
(rdr::U8)((len & 0xff000000) >> 24),
(rdr::U8)((len & 0xff0000) >> 16),
(rdr::U8)((len & 0xff00) >> 8),
(rdr::U8)(len & 0xff)
uint8_t lenServerKey[4] = {
(uint8_t)((len & 0xff000000) >> 24),
(uint8_t)((len & 0xff0000) >> 16),
(uint8_t)((len & 0xff00) >> 8),
(uint8_t)(len & 0xff)
};
len = clientKeyLength;
rdr::U8 lenClientKey[4] = {
(rdr::U8)((len & 0xff000000) >> 24),
(rdr::U8)((len & 0xff0000) >> 16),
(rdr::U8)((len & 0xff00) >> 8),
(rdr::U8)(len & 0xff)
uint8_t lenClientKey[4] = {
(uint8_t)((len & 0xff000000) >> 24),
(uint8_t)((len & 0xff0000) >> 16),
(uint8_t)((len & 0xff00) >> 8),
(uint8_t)(len & 0xff)
};
int hashSize;
if (keySize == 128) {
@@ -355,25 +355,25 @@ void CSecurityRSAAES::writeHash()

bool CSecurityRSAAES::readHash()
{
rdr::U8 hash[32];
rdr::U8 realHash[32];
uint8_t hash[32];
uint8_t realHash[32];
int hashSize = keySize == 128 ? 20 : 32;
if (!rais->hasData(hashSize))
return false;
rais->readBytes(hash, hashSize);
size_t len = serverKeyLength;
rdr::U8 lenServerKey[4] = {
(rdr::U8)((len & 0xff000000) >> 24),
(rdr::U8)((len & 0xff0000) >> 16),
(rdr::U8)((len & 0xff00) >> 8),
(rdr::U8)(len & 0xff)
uint8_t lenServerKey[4] = {
(uint8_t)((len & 0xff000000) >> 24),
(uint8_t)((len & 0xff0000) >> 16),
(uint8_t)((len & 0xff00) >> 8),
(uint8_t)(len & 0xff)
};
len = clientKeyLength;
rdr::U8 lenClientKey[4] = {
(rdr::U8)((len & 0xff000000) >> 24),
(rdr::U8)((len & 0xff0000) >> 16),
(rdr::U8)((len & 0xff00) >> 8),
(rdr::U8)(len & 0xff)
uint8_t lenClientKey[4] = {
(uint8_t)((len & 0xff000000) >> 24),
(uint8_t)((len & 0xff0000) >> 16),
(uint8_t)((len & 0xff00) >> 8),
(uint8_t)(len & 0xff)
};
if (keySize == 128) {
struct sha1_ctx ctx;
@@ -433,29 +433,26 @@ bool CSecurityRSAAES::readSubtype()

void CSecurityRSAAES::writeCredentials()
{
CharArray username;
CharArray password;
std::string username;
std::string password;

(CSecurity::upg)->getUserPasswd(
isSecure(),
subtype == secTypeRA2UserPass ? &username.buf : NULL, &password.buf
);
size_t len;
if (username.buf) {
len = strlen(username.buf);
if (len > 255)
if (subtype == secTypeRA2UserPass)
(CSecurity::upg)->getUserPasswd(isSecure(), &username, &password);
else
(CSecurity::upg)->getUserPasswd(isSecure(), NULL, &password);

if (subtype == secTypeRA2UserPass) {
if (username.size() > 255)
throw AuthFailureException("username is too long");
raos->writeU8(len);
if (len)
raos->writeBytes(username.buf, len);
raos->writeU8(username.size());
raos->writeBytes(username.data(), username.size());
} else {
raos->writeU8(0);
}
len = strlen(password.buf);
if (len > 255)
if (password.size() > 255)
throw AuthFailureException("password is too long");
raos->writeU8(len);
if (len)
raos->writeBytes(password.buf, len);
raos->writeU8(password.size());
raos->writeBytes(password.data(), password.size());
raos->flush();
}
}

+ 11
- 11
common/rfb/CSecurityRSAAES.h View File

@@ -36,7 +36,7 @@ namespace rfb {
class UserMsgBox;
class CSecurityRSAAES : public CSecurity {
public:
CSecurityRSAAES(CConnection* cc, rdr::U32 secType,
CSecurityRSAAES(CConnection* cc, uint32_t secType,
int keySize, bool isAllEncrypted);
virtual ~CSecurityRSAAES();
virtual bool processMsg();
@@ -62,19 +62,19 @@ namespace rfb {
int state;
int keySize;
bool isAllEncrypted;
rdr::U32 secType;
rdr::U8 subtype;
uint32_t secType;
uint8_t subtype;
struct rsa_private_key clientKey;
struct rsa_public_key clientPublicKey;
struct rsa_public_key serverKey;
rdr::U32 serverKeyLength;
rdr::U8* serverKeyN;
rdr::U8* serverKeyE;
rdr::U32 clientKeyLength;
rdr::U8* clientKeyN;
rdr::U8* clientKeyE;
rdr::U8 serverRandom[32];
rdr::U8 clientRandom[32];
uint32_t serverKeyLength;
uint8_t* serverKeyN;
uint8_t* serverKeyE;
uint32_t clientKeyLength;
uint8_t* clientKeyN;
uint8_t* clientKeyE;
uint8_t serverRandom[32];
uint8_t clientRandom[32];

rdr::InStream* rais;
rdr::OutStream* raos;

+ 67
- 52
common/rfb/CSecurityTLS.cxx View File

@@ -39,6 +39,7 @@
#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
#include <rfb/UserMsgBox.h>
#include <rfb/util.h>
#include <rdr/TLSInStream.h>
#include <rdr/TLSOutStream.h>
#include <os/os.h>
@@ -76,14 +77,13 @@ static LogWriter vlog("TLS");
static const char* homedirfn(const char* fn)
{
static char full_path[PATH_MAX];
char* homedir = NULL;
const char* homedir;

if (getvnchomedir(&homedir) == -1)
homedir = os::getvnchomedir();
if (homedir == NULL)
return "";

snprintf(full_path, sizeof(full_path), "%s%s", homedir, fn);

delete [] homedir;
snprintf(full_path, sizeof(full_path), "%s/%s", homedir, fn);

return full_path;
}
@@ -92,9 +92,6 @@ 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();

if (gnutls_global_init() != GNUTLS_E_SUCCESS)
throw AuthFailureException("gnutls_global_init failed");
}
@@ -146,9 +143,6 @@ CSecurityTLS::~CSecurityTLS()
{
shutdown();

delete[] cafile;
delete[] crlfile;

gnutls_global_deinit();
}

@@ -287,10 +281,10 @@ void CSecurityTLS::setParam()
if (gnutls_certificate_set_x509_system_trust(cert_cred) < 1)
vlog.error("Could not load system certificate trust store");

if (*cafile && gnutls_certificate_set_x509_trust_file(cert_cred,cafile,GNUTLS_X509_FMT_PEM) < 0)
if (gnutls_certificate_set_x509_trust_file(cert_cred, X509CA, GNUTLS_X509_FMT_PEM) < 0)
vlog.error("Could not load user specified certificate authority");

if (*crlfile && gnutls_certificate_set_x509_crl_file(cert_cred,crlfile,GNUTLS_X509_FMT_PEM) < 0)
if (gnutls_certificate_set_x509_crl_file(cert_cred, X509CRL, GNUTLS_X509_FMT_PEM) < 0)
vlog.error("Could not load user specified certificate revocation list");

if (gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred) != GNUTLS_E_SUCCESS)
@@ -316,7 +310,7 @@ void CSecurityTLS::checkSession()
unsigned int cert_list_size = 0;
int err;

char *homeDir;
const char *homeDir;
gnutls_datum_t info;
size_t len;

@@ -361,12 +355,14 @@ void CSecurityTLS::checkSession()
throw AuthFailureException("decoding of certificate failed");

if (gnutls_x509_crt_check_hostname(crt, client->getServerName()) == 0) {
CharArray text;
std::string text;
vlog.debug("hostname mismatch");
text.format("Hostname (%s) does not match the server certificate, "
"do you want to continue?", client->getServerName());
text = format("Hostname (%s) does not match the server "
"certificate, do you want to continue?",
client->getServerName());
if (!msg->showMsgBox(UserMsgBox::M_YESNO,
"Certificate hostname mismatch", text.buf))
"Certificate hostname mismatch",
text.c_str()))
throw AuthFailureException("Certificate hostname mismatch");
}

@@ -396,17 +392,16 @@ void CSecurityTLS::checkSession()

/* Certificate is fine, except we don't know the issuer, so TOFU time */

homeDir = NULL;
if (getvnchomedir(&homeDir) == -1) {
homeDir = os::getvnchomedir();
if (homeDir == NULL) {
throw AuthFailureException("Could not obtain VNC home directory "
"path for known hosts storage");
}

CharArray dbPath(strlen(homeDir) + 16 + 1);
sprintf(dbPath.buf, "%sx509_known_hosts", homeDir);
delete [] homeDir;
std::string dbPath;
dbPath = (std::string)homeDir + "/x509_known_hosts";

err = gnutls_verify_stored_pubkey(dbPath.buf, NULL,
err = gnutls_verify_stored_pubkey(dbPath.c_str(), NULL,
client->getServerName(), NULL,
GNUTLS_CRT_X509, &cert_list[0], 0);

@@ -433,73 +428,93 @@ void CSecurityTLS::checkSession()

/* New host */
if (err == GNUTLS_E_NO_CERTIFICATE_FOUND) {
CharArray text;
std::string text;

vlog.debug("Server host not previously known");
vlog.debug("%s", info.data);

if (status & (GNUTLS_CERT_SIGNER_NOT_FOUND |
GNUTLS_CERT_SIGNER_NOT_CA)) {
text.format("This certificate has been signed by an unknown "
"authority:\n\n%s\n\nSomeone could be trying to "
"impersonate the site and you should not "
"continue.\n\nDo you want to make an exception "
"for this server?", info.data);
text = format("This certificate has been signed by an unknown "
"authority:\n"
"\n"
"%s\n"
"\n"
"Someone could be trying to impersonate the site "
"and you should not continue.\n"
"\n"
"Do you want to make an exception for this "
"server?", info.data);

if (!msg->showMsgBox(UserMsgBox::M_YESNO,
"Unknown certificate issuer",
text.buf))
text.c_str()))
throw AuthFailureException("Unknown certificate issuer");
}

if (status & GNUTLS_CERT_EXPIRED) {
text.format("This certificate has expired:\n\n%s\n\nSomeone "
"could be trying to impersonate the site and you "
"should not continue.\n\nDo you want to make an "
"exception for this server?", info.data);
text = format("This certificate has expired:\n"
"\n"
"%s\n"
"\n"
"Someone could be trying to impersonate the site "
"and you should not continue.\n"
"\n"
"Do you want to make an exception for this "
"server?", info.data);

if (!msg->showMsgBox(UserMsgBox::M_YESNO,
"Expired certificate",
text.buf))
text.c_str()))
throw AuthFailureException("Expired certificate");
}
} else if (err == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {
CharArray text;
std::string text;

vlog.debug("Server host key mismatch");
vlog.debug("%s", info.data);

if (status & (GNUTLS_CERT_SIGNER_NOT_FOUND |
GNUTLS_CERT_SIGNER_NOT_CA)) {
text.format("This host is previously known with a different "
"certificate, and the new certificate has been "
"signed by an unknown authority:\n\n%s\n\nSomeone "
"could be trying to impersonate the site and you "
"should not continue.\n\nDo you want to make an "
"exception for this server?", info.data);
text = format("This host is previously known with a different "
"certificate, and the new certificate has been "
"signed by an unknown authority:\n"
"\n"
"%s\n"
"\n"
"Someone could be trying to impersonate the site "
"and you should not continue.\n"
"\n"
"Do you want to make an exception for this "
"server?", info.data);

if (!msg->showMsgBox(UserMsgBox::M_YESNO,
"Unexpected server certificate",
text.buf))
text.c_str()))
throw AuthFailureException("Unexpected server certificate");
}

if (status & GNUTLS_CERT_EXPIRED) {
text.format("This host is previously known with a different "
"certificate, and the new certificate has expired:"
"\n\n%s\n\nSomeone could be trying to impersonate "
"the site and you should not continue.\n\nDo you "
"want to make an exception for this server?",
info.data);
text = format("This host is previously known with a different "
"certificate, and the new certificate has "
"expired:\n"
"\n"
"%s\n"
"\n"
"Someone could be trying to impersonate the site "
"and you should not continue.\n"
"\n"
"Do you want to make an exception for this "
"server?", info.data);

if (!msg->showMsgBox(UserMsgBox::M_YESNO,
"Unexpected server certificate",
text.buf))
text.c_str()))
throw AuthFailureException("Unexpected server certificate");
}
}

if (gnutls_store_pubkey(dbPath.buf, NULL, client->getServerName(),
if (gnutls_store_pubkey(dbPath.c_str(), NULL, client->getServerName(),
NULL, GNUTLS_CRT_X509, &cert_list[0], 0, 0))
vlog.error("Failed to store server certificate to known hosts database");


+ 0
- 2
common/rfb/CSecurityTLS.h View File

@@ -58,8 +58,6 @@ namespace rfb {
gnutls_certificate_credentials_t cert_cred;
bool anon;

char *cafile, *crlfile;

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


+ 6
- 5
common/rfb/CSecurityVeNCrypt.cxx View File

@@ -86,7 +86,8 @@ bool CSecurityVeNCrypt::processMsg()
}

/* major version in upper 8 bits and minor version in lower 8 bits */
U16 Version = (((U16) majorVersion) << 8) | ((U16) minorVersion);
uint16_t Version = (((uint16_t) majorVersion) << 8) |
((uint16_t) minorVersion);
if (!haveSentVersion) {
/* Currently we don't support former VeNCrypt 0.1 */
@@ -131,7 +132,7 @@ bool CSecurityVeNCrypt::processMsg()
if (!nAvailableTypes)
throw AuthFailureException("The server reported no VeNCrypt sub-types");

availableTypes = new rdr::U32[nAvailableTypes];
availableTypes = new uint32_t[nAvailableTypes];
haveNumberOfTypes = true;
}

@@ -154,9 +155,9 @@ bool CSecurityVeNCrypt::processMsg()
/* make a choice and send it to the server, meanwhile set up the stack */
if (!haveChosenType) {
chosenType = secTypeInvalid;
U8 i;
list<U32>::iterator j;
list<U32> secTypes;
uint8_t i;
list<uint32_t>::iterator j;
list<uint32_t> secTypes;

secTypes = security->GetEnabledExtSecTypes();


+ 6
- 5
common/rfb/CSecurityVeNCrypt.h View File

@@ -25,9 +25,10 @@
#ifndef __CSECURITYVENCRYPT_H__
#define __CSECURITYVENCRYPT_H__

#include <stdint.h>

#include <rfb/CSecurity.h>
#include <rfb/SecurityClient.h>
#include <rdr/types.h>

namespace rfb {

@@ -50,10 +51,10 @@ namespace rfb {
bool haveListOfTypes;
bool haveNumberOfTypes;
bool haveChosenType;
rdr::U8 majorVersion, minorVersion;
rdr::U32 chosenType;
rdr::U8 nAvailableTypes;
rdr::U32 *availableTypes;
uint8_t majorVersion, minorVersion;
uint32_t chosenType;
uint8_t nAvailableTypes;
uint32_t *availableTypes;
};
}
#endif

+ 6
- 9
common/rfb/CSecurityVncAuth.cxx View File

@@ -29,9 +29,7 @@
#include <stdio.h>

#include <rfb/CConnection.h>
#include <rfb/Password.h>
#include <rfb/CSecurityVncAuth.h>
#include <rfb/util.h>
#include <rfb/Security.h>
extern "C" {
#include <rfb/d3des.h>
@@ -53,16 +51,15 @@ bool CSecurityVncAuth::processMsg()
return false;

// Read the challenge & obtain the user's password
rdr::U8 challenge[vncAuthChallengeSize];
uint8_t challenge[vncAuthChallengeSize];
is->readBytes(challenge, vncAuthChallengeSize);
PlainPasswd passwd;
(CSecurity::upg)->getUserPasswd(cc->isSecure(), 0, &passwd.buf);
std::string passwd;
(CSecurity::upg)->getUserPasswd(cc->isSecure(), 0, &passwd);

// Calculate the correct response
rdr::U8 key[8];
int pwdLen = strlen(passwd.buf);
for (int i=0; i<8; i++)
key[i] = i<pwdLen ? passwd.buf[i] : 0;
uint8_t key[8];
for (size_t i=0; i<8; i++)
key[i] = i<passwd.size() ? passwd[i] : 0;
deskey(key, EN0);
for (int j = 0; j < vncAuthChallengeSize; j += 8)
des(challenge+j, challenge+j);

+ 6
- 8
common/rfb/ClientParams.cxx View File

@@ -34,7 +34,7 @@ ClientParams::ClientParams()
: majorVersion(0), minorVersion(0),
compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),
subsampling(subsampleUndefined),
width_(0), height_(0), name_(0),
width_(0), height_(0),
cursorPos_(0, 0), ledState_(ledUnknown)
{
setName("");
@@ -49,7 +49,6 @@ ClientParams::ClientParams()

ClientParams::~ClientParams()
{
delete [] name_;
delete cursor_;
}

@@ -80,8 +79,7 @@ void ClientParams::setPF(const PixelFormat& pf)

void ClientParams::setName(const char* name)
{
delete [] name_;
name_ = strDup(name);
name_ = name;
}

void ClientParams::setCursor(const Cursor& other)
@@ -95,12 +93,12 @@ void ClientParams::setCursorPos(const Point& pos)
cursorPos_ = pos;
}

bool ClientParams::supportsEncoding(rdr::S32 encoding) const
bool ClientParams::supportsEncoding(int32_t encoding) const
{
return encodings_.count(encoding) != 0;
}

void ClientParams::setEncodings(int nEncodings, const rdr::S32* encodings)
void ClientParams::setEncodings(int nEncodings, const int32_t* encodings)
{
compressLevel = -1;
qualityLevel = -1;
@@ -153,7 +151,7 @@ void ClientParams::setLEDState(unsigned int state)
ledState_ = state;
}

rdr::U32 ClientParams::clipboardSize(unsigned int format) const
uint32_t ClientParams::clipboardSize(unsigned int format) const
{
int i;

@@ -165,7 +163,7 @@ rdr::U32 ClientParams::clipboardSize(unsigned int format) const
throw Exception("Invalid clipboard format 0x%x", format);
}

void ClientParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
void ClientParams::setClipboardCaps(uint32_t flags, const uint32_t* lengths)
{
int i, num;


+ 13
- 11
common/rfb/ClientParams.h View File

@@ -24,8 +24,10 @@
#define __RFB_CLIENTPARAMS_H__

#include <set>
#include <string>

#include <stdint.h>

#include <rdr/types.h>
#include <rfb/Cursor.h>
#include <rfb/PixelFormat.h>
#include <rfb/ScreenSet.h>
@@ -71,7 +73,7 @@ namespace rfb {
const PixelFormat& pf() const { return pf_; }
void setPF(const PixelFormat& pf);

const char* name() const { return name_; }
const char* name() const { return name_.c_str(); }
void setName(const char* name);

const Cursor& cursor() const { return *cursor_; }
@@ -80,16 +82,16 @@ namespace rfb {
const Point& cursorPos() const { return cursorPos_; }
void setCursorPos(const Point& pos);

bool supportsEncoding(rdr::S32 encoding) const;
bool supportsEncoding(int32_t encoding) const;

void setEncodings(int nEncodings, const rdr::S32* encodings);
void setEncodings(int nEncodings, const int32_t* encodings);

unsigned int ledState() { return ledState_; }
void setLEDState(unsigned int state);

rdr::U32 clipboardFlags() const { return clipFlags; }
rdr::U32 clipboardSize(unsigned int format) const;
void setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths);
uint32_t clipboardFlags() const { return clipFlags; }
uint32_t clipboardSize(unsigned int format) const;
void setClipboardCaps(uint32_t flags, const uint32_t* lengths);

// Wrappers to check for functionality rather than specific
// encodings
@@ -112,13 +114,13 @@ namespace rfb {
ScreenSet screenLayout_;

PixelFormat pf_;
char* name_;
std::string name_;
Cursor* cursor_;
Point cursorPos_;
std::set<rdr::S32> encodings_;
std::set<int32_t> encodings_;
unsigned int ledState_;
rdr::U32 clipFlags;
rdr::U32 clipSizes[16];
uint32_t clipFlags;
uint32_t clipSizes[16];
};
}
#endif

+ 23
- 23
common/rfb/ComparingUpdateTracker.cxx View File

@@ -23,9 +23,11 @@
#include <stdio.h>
#include <string.h>
#include <vector>
#include <rdr/types.h>
#include <rfb/Exception.h>
#include <rfb/LogWriter.h>
#include <rfb/util.h>

#include <rfb/ComparingUpdateTracker.h>

using namespace rfb;
@@ -62,7 +64,7 @@ bool ComparingUpdateTracker::compare()
for (int y=0; y<fb->height(); y+=BLOCK_SIZE) {
Rect pos(0, y, fb->width(), __rfbmin(fb->height(), y+BLOCK_SIZE));
int srcStride;
const rdr::U8* srcData = fb->getBuffer(pos, &srcStride);
const uint8_t* srcData = fb->getBuffer(pos, &srcStride);
oldFb.imageRect(pos, srcData, srcStride);
}

@@ -88,7 +90,7 @@ bool ComparingUpdateTracker::compare()
for (i = rects.begin(); i != rects.end(); i++)
missedPixels += i->area();

if (changed.equals(newChanged))
if (changed == newChanged)
return false;

changed = newChanged;
@@ -122,7 +124,7 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)

int bytesPerPixel = fb->getPF().bpp/8;
int oldStride;
rdr::U8* oldData = oldFb.getBufferRW(r, &oldStride);
uint8_t* oldData = oldFb.getBufferRW(r, &oldStride);
int oldStrideBytes = oldStride * bytesPerPixel;

// Used to efficiently crop the left and right of the change rectangle
@@ -134,16 +136,16 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)
// Get a strip of the source buffer
Rect pos(r.tl.x, blockTop, r.br.x, __rfbmin(r.br.y, blockTop+BLOCK_SIZE));
int fbStride;
const rdr::U8* newBlockPtr = fb->getBuffer(pos, &fbStride);
const uint8_t* newBlockPtr = fb->getBuffer(pos, &fbStride);
int newStrideBytes = fbStride * bytesPerPixel;

rdr::U8* oldBlockPtr = oldData;
uint8_t* oldBlockPtr = oldData;
int blockBottom = __rfbmin(blockTop+BLOCK_SIZE, r.br.y);

for (int blockLeft = r.tl.x; blockLeft < r.br.x; blockLeft += BLOCK_SIZE)
{
const rdr::U8* newPtr = newBlockPtr;
rdr::U8* oldPtr = oldBlockPtr;
const uint8_t* newPtr = newBlockPtr;
uint8_t* oldPtr = oldBlockPtr;

int blockRight = __rfbmin(blockLeft+BLOCK_SIZE, r.br.x);
int blockWidthInBytes = (blockRight-blockLeft) * bytesPerPixel;
@@ -160,8 +162,8 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)

// For every unchanged row at the bottom of the block, decrement change height
{
const rdr::U8* newRowPtr = newPtr + ((changeHeight - 1) * newStrideBytes);
const rdr::U8* oldRowPtr = oldPtr + ((changeHeight - 1) * oldStrideBytes);
const uint8_t* newRowPtr = newPtr + ((changeHeight - 1) * newStrideBytes);
const uint8_t* oldRowPtr = oldPtr + ((changeHeight - 1) * oldStrideBytes);
while (changeHeight > 1 && memcmp(oldRowPtr, newRowPtr, blockWidthInBytes) == 0)
{
newRowPtr -= newStrideBytes;
@@ -173,12 +175,12 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)

// For every unchanged column at the left of the block, increment change left
{
const rdr::U8* newColumnPtr = newPtr;
const rdr::U8* oldColumnPtr = oldPtr;
const uint8_t* newColumnPtr = newPtr;
const uint8_t* oldColumnPtr = oldPtr;
while (changeLeft + minCompareWidthInPixels < changeRight)
{
const rdr::U8* newRowPtr = newColumnPtr;
const rdr::U8* oldRowPtr = oldColumnPtr;
const uint8_t* newRowPtr = newColumnPtr;
const uint8_t* oldRowPtr = oldColumnPtr;
for (int row = 0; row < changeHeight; row++)
{
if (memcmp(oldRowPtr, newRowPtr, minCompareWidthInBytes) != 0)
@@ -198,15 +200,15 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)

// For every unchanged column at the right of the block, decrement change right
{
const rdr::U8* newColumnPtr = newPtr + blockWidthInBytes;
const rdr::U8* oldColumnPtr = oldPtr + blockWidthInBytes;
const uint8_t* newColumnPtr = newPtr + blockWidthInBytes;
const uint8_t* oldColumnPtr = oldPtr + blockWidthInBytes;
while (changeLeft + minCompareWidthInPixels < changeRight)
{
newColumnPtr -= minCompareWidthInBytes;
oldColumnPtr -= minCompareWidthInBytes;

const rdr::U8* newRowPtr = newColumnPtr;
const rdr::U8* oldRowPtr = oldColumnPtr;
const uint8_t* newRowPtr = newColumnPtr;
const uint8_t* oldRowPtr = oldColumnPtr;
for (int row = 0; row < changeHeight; row++)
{
if (memcmp(oldRowPtr, newRowPtr, minCompareWidthInBytes) != 0)
@@ -253,14 +255,12 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)
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("%s in / %s out",
siPrefix(totalPixels, "pixels").c_str(),
siPrefix(missedPixels, "pixels").c_str());
vlog.info("(1:%g ratio)", ratio);

totalPixels = missedPixels = 0;

+ 52
- 59
common/rfb/Configuration.cxx View File

@@ -1,6 +1,7 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2004-2005 Cendio AB.
* Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
* Copyright 2011-2022 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
@@ -24,6 +25,7 @@
#include <config.h>
#endif

#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
@@ -131,9 +133,9 @@ VoidParameter* Configuration::get(const char* param)
void Configuration::list(int width, int nameWidth) {
VoidParameter* current = head;

fprintf(stderr, "%s Parameters:\n", name.buf);
fprintf(stderr, "%s Parameters:\n", name.c_str());
while (current) {
char* def_str = current->getDefaultStr();
std::string def_str = current->getDefaultStr();
const char* desc = current->getDescription();
fprintf(stderr," %-*s -", nameWidth, current->getName());
int column = strlen(current->getName());
@@ -155,11 +157,10 @@ void Configuration::list(int width, int nameWidth) {
if (!s) break;
}

if (def_str) {
if (column + (int)strlen(def_str) + 11 > width)
if (!def_str.empty()) {
if (column + (int)def_str.size() + 11 > width)
fprintf(stderr,"\n%*s",nameWidth+4,"");
fprintf(stderr," (default=%s)\n",def_str);
strFree(def_str);
fprintf(stderr," (default=%s)\n",def_str.c_str());
} else {
fprintf(stderr,"\n");
}
@@ -255,12 +256,11 @@ bool AliasParameter::setParam() {
return param->setParam();
}

char*
AliasParameter::getDefaultStr() const {
return 0;
std::string AliasParameter::getDefaultStr() const {
return "";
}

char* AliasParameter::getValueStr() const {
std::string AliasParameter::getValueStr() const {
return param->getValueStr();
}

@@ -288,16 +288,15 @@ BoolParameter::setParam(const char* v) {

if (*v == 0 || strcasecmp(v, "1") == 0 || strcasecmp(v, "on") == 0
|| strcasecmp(v, "true") == 0 || strcasecmp(v, "yes") == 0)
value = 1;
setParam(true);
else if (strcasecmp(v, "0") == 0 || strcasecmp(v, "off") == 0
|| strcasecmp(v, "false") == 0 || strcasecmp(v, "no") == 0)
value = 0;
setParam(false);
else {
vlog.error("Bool parameter %s: invalid value '%s'", getName(), v);
return false;
}

vlog.debug("set %s(Bool) to %s(%d)", getName(), v, value);
return true;
}

@@ -312,13 +311,12 @@ void BoolParameter::setParam(bool b) {
vlog.debug("set %s(Bool) to %d", getName(), value);
}

char*
BoolParameter::getDefaultStr() const {
return strDup(def_value ? "1" : "0");
std::string BoolParameter::getDefaultStr() const {
return def_value ? "1" : "0";
}

char* BoolParameter::getValueStr() const {
return strDup(value ? "1" : "0");
std::string BoolParameter::getValueStr() const {
return value ? "1" : "0";
}

bool BoolParameter::isBool() const {
@@ -341,12 +339,7 @@ IntParameter::IntParameter(const char* name_, const char* desc_, int v,
bool
IntParameter::setParam(const char* v) {
if (immutable) return true;
vlog.debug("set %s(Int) to %s", getName(), v);
int i = strtol(v, NULL, 0);
if (i < minValue || i > maxValue)
return false;
value = i;
return true;
return setParam(strtol(v, NULL, 0));
}

bool
@@ -359,15 +352,14 @@ IntParameter::setParam(int v) {
return true;
}

char*
IntParameter::getDefaultStr() const {
char* result = new char[16];
std::string IntParameter::getDefaultStr() const {
char result[16];
sprintf(result, "%d", def_value);
return result;
}

char* IntParameter::getValueStr() const {
char* result = new char[16];
std::string IntParameter::getValueStr() const {
char result[16];
sprintf(result, "%d", value);
return result;
}
@@ -380,7 +372,7 @@ IntParameter::operator int() const {

StringParameter::StringParameter(const char* name_, const char* desc_,
const char* v, ConfigurationObject co)
: VoidParameter(name_, desc_, co), value(strDup(v)), def_value(strDup(v))
: VoidParameter(name_, desc_, co), value(v), def_value(v)
{
if (!v) {
vlog.error("Default value <null> for %s not allowed",name_);
@@ -389,8 +381,6 @@ StringParameter::StringParameter(const char* name_, const char* desc_,
}

StringParameter::~StringParameter() {
strFree(value);
strFree(def_value);
}

bool StringParameter::setParam(const char* v) {
@@ -399,34 +389,34 @@ bool StringParameter::setParam(const char* v) {
if (!v)
throw rfb::Exception("setParam(<null>) not allowed");
vlog.debug("set %s(String) to %s", getName(), v);
CharArray oldValue(value);
value = strDup(v);
return value != 0;
value = v;
return true;
}

char* StringParameter::getDefaultStr() const {
return strDup(def_value);
std::string StringParameter::getDefaultStr() const {
return def_value;
}

char* StringParameter::getValueStr() const {
std::string StringParameter::getValueStr() const {
LOCK_CONFIG;
return strDup(value);
return value;
}

StringParameter::operator const char *() const {
return value;
return value.c_str();
}

// -=- BinaryParameter

BinaryParameter::BinaryParameter(const char* name_, const char* desc_,
const void* v, size_t l, ConfigurationObject co)
const uint8_t* v, size_t l, ConfigurationObject co)
: VoidParameter(name_, desc_, co), value(0), length(0), def_value(0), def_length(0) {
if (l) {
value = new char[l];
assert(v);
value = new uint8_t[l];
length = l;
memcpy(value, v, l);
def_value = new char[l];
def_value = new uint8_t[l];
def_length = l;
memcpy(def_value, v, l);
}
@@ -437,38 +427,41 @@ BinaryParameter::~BinaryParameter() {
}

bool BinaryParameter::setParam(const char* v) {
LOCK_CONFIG;
if (immutable) return true;
vlog.debug("set %s(Binary) to %s", getName(), v);
return rdr::HexInStream::hexStrToBin(v, &value, &length);
std::vector<uint8_t> newValue = hexToBin(v, strlen(v));
if (newValue.empty() && strlen(v) > 0)
return false;
setParam(newValue.data(), newValue.size());
return true;
}

void BinaryParameter::setParam(const void* v, size_t len) {
void BinaryParameter::setParam(const uint8_t* v, size_t len) {
LOCK_CONFIG;
if (immutable) return;
vlog.debug("set %s(Binary)", getName());
delete [] value; value = 0;
delete [] value;
value = NULL;
length = 0;
if (len) {
value = new char[len];
assert(v);
value = new uint8_t[len];
length = len;
memcpy(value, v, len);
}
}

char* BinaryParameter::getDefaultStr() const {
return rdr::HexOutStream::binToHexStr(def_value, def_length);
std::string BinaryParameter::getDefaultStr() const {
return binToHex(def_value, def_length);
}

char* BinaryParameter::getValueStr() const {
std::string BinaryParameter::getValueStr() const {
LOCK_CONFIG;
return rdr::HexOutStream::binToHexStr(value, length);
return binToHex(value, length);
}

void BinaryParameter::getData(void** data_, size_t* length_) const {
std::vector<uint8_t> BinaryParameter::getData() const {
LOCK_CONFIG;
if (length_) *length_ = length;
if (data_) {
*data_ = new char[length];
memcpy(*data_, value, length);
}
std::vector<uint8_t> out(length);
memcpy(out.data(), value, length);
return out;
}

+ 28
- 29
common/rfb/Configuration.h View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2022 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,11 @@
#ifndef __RFB_CONFIGURATION_H__
#define __RFB_CONFIGURATION_H__

#include <rfb/util.h>
#include <limits.h>
#include <stdint.h>

#include <string>
#include <vector>

namespace os { class Mutex; }

@@ -59,10 +64,10 @@ namespace rfb {
class Configuration {
public:
// - Create a new Configuration object
Configuration(const char* name_) : name(strDup(name_)), head(0), _next(0) {}
Configuration(const char* name_) : name(name_), head(0), _next(0) {}

// - Return the buffer containing the Configuration's name
const char* getName() const { return name.buf; }
const char* getName() const { return name.c_str(); }

// - Set named parameter to value
bool set(const char* param, const char* value, bool immutable=false);
@@ -128,7 +133,7 @@ namespace rfb {
friend struct ParameterIterator;

// Name for this Configuration
CharArray name;
std::string name;

// - Pointer to first Parameter in this group
VoidParameter* head;
@@ -168,8 +173,8 @@ namespace rfb {

virtual bool setParam(const char* value) = 0;
virtual bool setParam();
virtual char* getDefaultStr() const = 0;
virtual char* getValueStr() const = 0;
virtual std::string getDefaultStr() const = 0;
virtual std::string getValueStr() const = 0;
virtual bool isBool() const;

virtual void setImmutable();
@@ -192,8 +197,8 @@ namespace rfb {
ConfigurationObject co=ConfGlobal);
virtual bool setParam(const char* value);
virtual bool setParam();
virtual char* getDefaultStr() const;
virtual char* getValueStr() const;
virtual std::string getDefaultStr() const;
virtual std::string getValueStr() const;
virtual bool isBool() const;
virtual void setImmutable();
private:
@@ -207,8 +212,8 @@ namespace rfb {
virtual bool setParam(const char* value);
virtual bool setParam();
virtual void setParam(bool b);
virtual char* getDefaultStr() const;
virtual char* getValueStr() const;
virtual std::string getDefaultStr() const;
virtual std::string getValueStr() const;
virtual bool isBool() const;
operator bool() const;
protected:
@@ -224,8 +229,8 @@ namespace rfb {
using VoidParameter::setParam;
virtual bool setParam(const char* value);
virtual bool setParam(int v);
virtual char* getDefaultStr() const;
virtual char* getValueStr() const;
virtual std::string getDefaultStr() const;
virtual std::string getValueStr() const;
operator int() const;
protected:
int value;
@@ -241,38 +246,32 @@ namespace rfb {
ConfigurationObject co=ConfGlobal);
virtual ~StringParameter();
virtual bool setParam(const char* value);
virtual char* getDefaultStr() const;
virtual char* getValueStr() const;
virtual std::string getDefaultStr() const;
virtual std::string getValueStr() const;
operator const char*() const;

// getData() returns a copy of the data - it must be delete[]d by the
// caller.
char* getData() const { return getValueStr(); }
protected:
char* value;
char* def_value;
std::string value;
std::string def_value;
};

class BinaryParameter : public VoidParameter {
public:
BinaryParameter(const char* name_, const char* desc_,
const void* v, size_t l,
const uint8_t* v, size_t l,
ConfigurationObject co=ConfGlobal);
using VoidParameter::setParam;
virtual ~BinaryParameter();
virtual bool setParam(const char* value);
virtual void setParam(const void* v, size_t l);
virtual char* getDefaultStr() const;
virtual char* getValueStr() const;
virtual void setParam(const uint8_t* v, size_t l);
virtual std::string getDefaultStr() const;
virtual std::string getValueStr() const;

// getData() will return length zero if there is no data
// NB: data may be set to zero, OR set to a zero-length buffer
void getData(void** data, size_t* length) const;
std::vector<uint8_t> getData() const;

protected:
char* value;
uint8_t* value;
size_t length;
char* def_value;
uint8_t* def_value;
size_t def_length;
};


+ 1
- 0
common/rfb/Congestion.cxx View File

@@ -38,6 +38,7 @@
#endif

#include <assert.h>
#include <string.h>
#include <sys/time.h>

#ifdef __linux__

+ 37
- 36
common/rfb/Cursor.cxx View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2014-2017 Pierre Ossman for Cendio AB
* Copyright 2014-2023 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
@@ -23,6 +23,7 @@

#include <assert.h>
#include <string.h>

#include <rfb/Cursor.h>
#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
@@ -32,10 +33,10 @@ using namespace rfb;
static LogWriter vlog("Cursor");

Cursor::Cursor(int width, int height, const Point& hotspot,
const rdr::U8* data) :
const uint8_t* data) :
width_(width), height_(height), hotspot_(hotspot)
{
this->data = new rdr::U8[width_*height_*4];
this->data = new uint8_t[width_*height_*4];
memcpy(this->data, data, width_*height_*4);
}

@@ -43,7 +44,7 @@ Cursor::Cursor(const Cursor& other) :
width_(other.width_), height_(other.height_),
hotspot_(other.hotspot_)
{
data = new rdr::U8[width_*height_*4];
data = new uint8_t[width_*height_*4];
memcpy(data, other.data, width_*height_*4);
}

@@ -81,7 +82,7 @@ static unsigned short srgb_to_lin(unsigned char srgb)
}

// Floyd-Steinberg dithering
static void dither(int width, int height, rdr::S32* data)
static void dither(int width, int height, int32_t* data)
{
for (int y = 0; y < height; y++) {
for (int x_ = 0; x_ < width; x_++) {
@@ -124,21 +125,21 @@ static void dither(int width, int height, rdr::S32* data)
}
}

rdr::U8* Cursor::getBitmap() const
std::vector<uint8_t> Cursor::getBitmap() const
{
// First step is converting to luminance
rdr::S32Array luminance(width()*height());
rdr::S32 *lum_ptr = luminance.buf;
const rdr::U8 *data_ptr = data;
std::vector<int32_t> luminance(width()*height());
int32_t *lum_ptr = luminance.data();
const uint8_t *data_ptr = data;
for (int y = 0; y < height(); y++) {
for (int x = 0; x < width(); x++) {
rdr::S32 lum;
int32_t lum;

// Use BT.709 coefficients for grayscale
lum = 0;
lum += (rdr::U32)srgb_to_lin(data_ptr[0]) * 6947; // 0.2126
lum += (rdr::U32)srgb_to_lin(data_ptr[1]) * 23436; // 0.7152
lum += (rdr::U32)srgb_to_lin(data_ptr[2]) * 2366; // 0.0722
lum += (uint32_t)srgb_to_lin(data_ptr[0]) * 6947; // 0.2126
lum += (uint32_t)srgb_to_lin(data_ptr[1]) * 23436; // 0.7152
lum += (uint32_t)srgb_to_lin(data_ptr[2]) * 2366; // 0.0722
lum /= 32768;

*lum_ptr++ = lum;
@@ -147,62 +148,62 @@ rdr::U8* Cursor::getBitmap() const
}

// Then diterhing
dither(width(), height(), luminance.buf);
dither(width(), height(), luminance.data());

// Then conversion to a bit mask
rdr::U8Array source((width()+7)/8*height());
memset(source.buf, 0, (width()+7)/8*height());
std::vector<uint8_t> source((width()+7)/8*height());
memset(source.data(), 0, source.size());
int maskBytesPerRow = (width() + 7) / 8;
lum_ptr = luminance.buf;
lum_ptr = luminance.data();
data_ptr = data;
for (int y = 0; y < height(); y++) {
for (int x = 0; x < width(); x++) {
int byte = y * maskBytesPerRow + x / 8;
int bit = 7 - x % 8;
if (*lum_ptr > 32767)
source.buf[byte] |= (1 << bit);
source[byte] |= (1 << bit);
lum_ptr++;
data_ptr += 4;
}
}

return source.takeBuf();
return source;
}

rdr::U8* Cursor::getMask() const
std::vector<uint8_t> Cursor::getMask() const
{
// First step is converting to integer array
rdr::S32Array alpha(width()*height());
rdr::S32 *alpha_ptr = alpha.buf;
const rdr::U8 *data_ptr = data;
std::vector<int32_t> alpha(width()*height());
int32_t *alpha_ptr = alpha.data();
const uint8_t *data_ptr = data;
for (int y = 0; y < height(); y++) {
for (int x = 0; x < width(); x++) {
*alpha_ptr++ = (rdr::U32)data_ptr[3] * 65535 / 255;
*alpha_ptr++ = (uint32_t)data_ptr[3] * 65535 / 255;
data_ptr += 4;
}
}

// Then diterhing
dither(width(), height(), alpha.buf);
dither(width(), height(), alpha.data());

// Then conversion to a bit mask
rdr::U8Array mask((width()+7)/8*height());
memset(mask.buf, 0, (width()+7)/8*height());
std::vector<uint8_t> mask((width()+7)/8*height());
memset(mask.data(), 0, mask.size());
int maskBytesPerRow = (width() + 7) / 8;
alpha_ptr = alpha.buf;
alpha_ptr = alpha.data();
data_ptr = data;
for (int y = 0; y < height(); y++) {
for (int x = 0; x < width(); x++) {
int byte = y * maskBytesPerRow + x / 8;
int bit = 7 - x % 8;
if (*alpha_ptr > 32767)
mask.buf[byte] |= (1 << bit);
mask[byte] |= (1 << bit);
alpha_ptr++;
data_ptr += 4;
}
}

return mask.takeBuf();
return mask;
}

// crop() determines the "busy" rectangle for the cursor - the minimum bounding
@@ -217,7 +218,7 @@ void Cursor::crop()
busy = busy.intersect(Rect(hotspot_.x, hotspot_.y,
hotspot_.x+1, hotspot_.y+1));
int x, y;
rdr::U8 *data_ptr = data;
uint8_t *data_ptr = data;
for (y = 0; y < height(); y++) {
for (x = 0; x < width(); x++) {
if (data_ptr[3] > 0) {
@@ -234,7 +235,7 @@ void Cursor::crop()

// Copy the pixel data
int newDataLen = busy.area() * 4;
rdr::U8* newData = new rdr::U8[newDataLen];
uint8_t* newData = new uint8_t[newDataLen];
data_ptr = newData;
for (y = busy.tl.y; y < busy.br.y; y++) {
memcpy(data_ptr, data + y*width()*4 + busy.tl.x*4, busy.width()*4);
@@ -253,7 +254,7 @@ RenderedCursor::RenderedCursor()
{
}

const rdr::U8* RenderedCursor::getBuffer(const Rect& _r, int* stride) const
const uint8_t* RenderedCursor::getBuffer(const Rect& _r, int* stride) const
{
Rect r;

@@ -270,7 +271,7 @@ void RenderedCursor::update(PixelBuffer* framebuffer,
Point rawOffset, diff;
Rect clippedRect;

const rdr::U8* data;
const uint8_t* data;
int stride;

assert(framebuffer);
@@ -300,8 +301,8 @@ void RenderedCursor::update(PixelBuffer* framebuffer,
for (int y = 0;y < buffer.height();y++) {
for (int x = 0;x < buffer.width();x++) {
size_t idx;
rdr::U8 bg[4], fg[4];
rdr::U8 rgb[3];
uint8_t bg[4], fg[4];
uint8_t rgb[3];

idx = (y+diff.y)*cursor->width() + (x+diff.x);
memcpy(fg, cursor->getBuffer() + idx*4, 4);

+ 9
- 7
common/rfb/Cursor.h View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2014-2017 Pierre Ossman for Cendio AB
* Copyright 2014-2023 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
@@ -24,25 +24,27 @@
#ifndef __RFB_CURSOR_H__
#define __RFB_CURSOR_H__

#include <vector>

#include <rfb/PixelBuffer.h>

namespace rfb {

class Cursor {
public:
Cursor(int width, int height, const Point& hotspot, const rdr::U8* data);
Cursor(int width, int height, const Point& hotspot, const uint8_t* data);
Cursor(const Cursor& other);
~Cursor();

int width() const { return width_; };
int height() const { return height_; };
const Point& hotspot() const { return hotspot_; };
const rdr::U8* getBuffer() const { return data; };
const uint8_t* getBuffer() const { return data; };

// getBitmap() returns a monochrome version of the cursor
rdr::U8* getBitmap() const;
std::vector<uint8_t> getBitmap() const;
// getMask() returns a simple mask version of the alpha channel
rdr::U8* getMask() const;
std::vector<uint8_t> getMask() const;

// crop() crops the cursor down to the smallest possible size, based on the
// mask.
@@ -51,7 +53,7 @@ namespace rfb {
protected:
int width_, height_;
Point hotspot_;
rdr::U8* data;
uint8_t* data;
};

class RenderedCursor : public PixelBuffer {
@@ -60,7 +62,7 @@ namespace rfb {

Rect getEffectiveRect() const { return buffer.getRect(offset); }

virtual const rdr::U8* getBuffer(const Rect& r, int* stride) const;
virtual const uint8_t* getBuffer(const Rect& r, int* stride) const;

void update(PixelBuffer* framebuffer, Cursor* cursor, const Point& pos);


+ 10
- 13
common/rfb/DecodeManager.cxx View File

@@ -28,8 +28,8 @@
#include <rfb/Decoder.h>
#include <rfb/Exception.h>
#include <rfb/Region.h>

#include <rfb/LogWriter.h>
#include <rfb/util.h>

#include <rdr/Exception.h>
#include <rdr/MemOutStream.h>
@@ -211,8 +211,6 @@ void DecodeManager::logStats()

double ratio;

char a[1024], b[1024];

rects = 0;
pixels = bytes = equivalent = 0;

@@ -228,22 +226,21 @@ void DecodeManager::logStats()

ratio = (double)stats[i].equivalent / stats[i].bytes;

siPrefix(stats[i].rects, "rects", a, sizeof(a));
siPrefix(stats[i].pixels, "pixels", b, sizeof(b));
vlog.info(" %s: %s, %s", encodingName(i), a, b);
iecPrefix(stats[i].bytes, "B", a, sizeof(a));
vlog.info(" %s: %s, %s", encodingName(i),
siPrefix(stats[i].rects, "rects").c_str(),
siPrefix(stats[i].pixels, "pixels").c_str());
vlog.info(" %*s %s (1:%g ratio)",
(int)strlen(encodingName(i)), "",
a, ratio);
iecPrefix(stats[i].bytes, "B").c_str(), ratio);
}

ratio = (double)equivalent / bytes;

siPrefix(rects, "rects", a, sizeof(a));
siPrefix(pixels, "pixels", b, sizeof(b));
vlog.info(" Total: %s, %s", a, b);
iecPrefix(bytes, "B", a, sizeof(a));
vlog.info(" %s (1:%g ratio)", a, ratio);
vlog.info(" Total: %s, %s",
siPrefix(rects, "rects").c_str(),
siPrefix(pixels, "pixels").c_str());
vlog.info(" %s (1:%g ratio)",
iecPrefix(bytes, "B").c_str(), ratio);
}

void DecodeManager::setThreadException(const rdr::Exception& e)

+ 111
- 50
common/rfb/EncodeManager.cxx View File

@@ -1,6 +1,6 @@
/* 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 2014-2022 Pierre Ossman for Cendio AB
* Copyright 2018 Peter Astrand for Cendio AB
*
* This is free software; you can redistribute it and/or modify
@@ -33,6 +33,7 @@
#include <rfb/UpdateTracker.h>
#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
#include <rfb/util.h>

#include <rfb/RawEncoder.h>
#include <rfb/RREEncoder.h>
@@ -177,8 +178,6 @@ void EncodeManager::logStats()

double ratio;

char a[1024], b[1024];

rects = 0;
pixels = bytes = equivalent = 0;

@@ -194,13 +193,12 @@ void EncodeManager::logStats()

ratio = (double)copyStats.equivalent / copyStats.bytes;

siPrefix(copyStats.rects, "rects", a, sizeof(a));
siPrefix(copyStats.pixels, "pixels", b, sizeof(b));
vlog.info(" %s: %s, %s", "Copies", a, b);
iecPrefix(copyStats.bytes, "B", a, sizeof(a));
vlog.info(" %s: %s, %s", "Copies",
siPrefix(copyStats.rects, "rects").c_str(),
siPrefix(copyStats.pixels, "pixels").c_str());
vlog.info(" %*s %s (1:%g ratio)",
(int)strlen("Copies"), "",
a, ratio);
iecPrefix(copyStats.bytes, "B").c_str(), ratio);
}

for (i = 0;i < stats.size();i++) {
@@ -225,23 +223,22 @@ void EncodeManager::logStats()

ratio = (double)stats[i][j].equivalent / stats[i][j].bytes;

siPrefix(stats[i][j].rects, "rects", a, sizeof(a));
siPrefix(stats[i][j].pixels, "pixels", b, sizeof(b));
vlog.info(" %s: %s, %s", encoderTypeName((EncoderType)j), a, b);
iecPrefix(stats[i][j].bytes, "B", a, sizeof(a));
vlog.info(" %s: %s, %s", encoderTypeName((EncoderType)j),
siPrefix(stats[i][j].rects, "rects").c_str(),
siPrefix(stats[i][j].pixels, "pixels").c_str());
vlog.info(" %*s %s (1:%g ratio)",
(int)strlen(encoderTypeName((EncoderType)j)), "",
a, ratio);
iecPrefix(stats[i][j].bytes, "B").c_str(), ratio);
}
}

ratio = (double)equivalent / bytes;

siPrefix(rects, "rects", a, sizeof(a));
siPrefix(pixels, "pixels", b, sizeof(b));
vlog.info(" Total: %s, %s", a, b);
iecPrefix(bytes, "B", a, sizeof(a));
vlog.info(" %s (1:%g ratio)", a, ratio);
vlog.info(" Total: %s, %s",
siPrefix(rects, "rects").c_str(),
siPrefix(pixels, "pixels").c_str());
vlog.info(" %s (1:%g ratio)",
iecPrefix(bytes, "B").c_str(), ratio);
}

bool EncodeManager::supported(int encoding)
@@ -377,7 +374,7 @@ void EncodeManager::prepareEncoders(bool allowLossy)

bool allowJPEG;

rdr::S32 preferred;
int32_t preferred;

std::vector<int>::iterator iter;

@@ -678,8 +675,8 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed,

for (dx = rect.tl.x; dx < rect.br.x; dx += SolidSearchBlock) {
// We define it like this to guarantee alignment
rdr::U32 _buffer;
rdr::U8* colourValue = (rdr::U8*)&_buffer;
uint32_t _buffer;
uint8_t* colourValue = (uint8_t*)&_buffer;

dw = SolidSearchBlock;
if (dx + dw > rect.br.x)
@@ -700,7 +697,7 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed,
extendSolidAreaByBlock(sr, colourValue, pb, &erb);

// Did we end up getting the entire rectangle?
if (erb.equals(rect))
if (erb == rect)
erp = erb;
else {
// Don't bother with sending tiny rectangles
@@ -718,8 +715,8 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed,
encoder->writeSolidRect(erp.width(), erp.height(),
pb->getPF(), colourValue);
} else {
rdr::U32 _buffer2;
rdr::U8* converted = (rdr::U8*)&_buffer2;
uint32_t _buffer2;
uint8_t* converted = (uint8_t*)&_buffer2;

conn->client.pf().bufferFromBuffer(converted, pb->getPF(),
colourValue, 1);
@@ -886,21 +883,21 @@ void EncodeManager::writeSubRect(const Rect& rect, const PixelBuffer *pb)
endRect();
}

bool EncodeManager::checkSolidTile(const Rect& r, const rdr::U8* colourValue,
bool EncodeManager::checkSolidTile(const Rect& r, const uint8_t* colourValue,
const PixelBuffer *pb)
{
switch (pb->getPF().bpp) {
case 32:
return checkSolidTile(r, *(const rdr::U32*)colourValue, pb);
return checkSolidTile(r, *(const uint32_t*)colourValue, pb);
case 16:
return checkSolidTile(r, *(const rdr::U16*)colourValue, pb);
return checkSolidTile(r, *(const uint16_t*)colourValue, pb);
default:
return checkSolidTile(r, *(const rdr::U8*)colourValue, pb);
return checkSolidTile(r, *(const uint8_t*)colourValue, pb);
}
}

void EncodeManager::extendSolidAreaByBlock(const Rect& r,
const rdr::U8* colourValue,
const uint8_t* colourValue,
const PixelBuffer *pb, Rect* er)
{
int dx, dy, dw, dh;
@@ -956,7 +953,7 @@ void EncodeManager::extendSolidAreaByBlock(const Rect& r,
}

void EncodeManager::extendSolidAreaByPixel(const Rect& r, const Rect& sr,
const rdr::U8* colourValue,
const uint8_t* colourValue,
const PixelBuffer *pb, Rect* er)
{
int cx, cy;
@@ -999,11 +996,11 @@ PixelBuffer* EncodeManager::preparePixelBuffer(const Rect& rect,
const PixelBuffer *pb,
bool convert)
{
const rdr::U8* buffer;
const uint8_t* buffer;
int stride;

// Do wo need to convert the data?
if (convert && !conn->client.pf().equal(pb->getPF())) {
if (convert && conn->client.pf() != pb->getPF()) {
convertedPixelBuffer.setPF(conn->client.pf());
convertedPixelBuffer.setSize(rect.width(), rect.height());

@@ -1029,7 +1026,7 @@ PixelBuffer* EncodeManager::preparePixelBuffer(const Rect& rect,
bool EncodeManager::analyseRect(const PixelBuffer *pb,
struct RectInfo *info, int maxColours)
{
const rdr::U8* buffer;
const uint8_t* buffer;
int stride;

buffer = pb->getBuffer(pb->getRect(), &stride);
@@ -1037,42 +1034,106 @@ bool EncodeManager::analyseRect(const PixelBuffer *pb,
switch (pb->getPF().bpp) {
case 32:
return analyseRect(pb->width(), pb->height(),
(const rdr::U32*)buffer, stride,
(const uint32_t*)buffer, stride,
info, maxColours);
case 16:
return analyseRect(pb->width(), pb->height(),
(const rdr::U16*)buffer, stride,
(const uint16_t*)buffer, stride,
info, maxColours);
default:
return analyseRect(pb->width(), pb->height(),
(const rdr::U8*)buffer, stride,
(const uint8_t*)buffer, stride,
info, maxColours);
}
}

void EncodeManager::OffsetPixelBuffer::update(const PixelFormat& pf,
int width, int height,
const rdr::U8* data_,
const uint8_t* data_,
int stride_)
{
format = pf;
// Forced cast. We never write anything though, so it should be safe.
setBuffer(width, height, (rdr::U8*)data_, stride_);
setBuffer(width, height, (uint8_t*)data_, stride_);
}

rdr::U8* EncodeManager::OffsetPixelBuffer::getBufferRW(const Rect& /*r*/, int* /*stride*/)
uint8_t* EncodeManager::OffsetPixelBuffer::getBufferRW(const Rect& /*r*/, int* /*stride*/)
{
throw rfb::Exception("Invalid write attempt to OffsetPixelBuffer");
}

// Preprocessor generated, optimised methods

#define BPP 8
#include "EncodeManagerBPP.cxx"
#undef BPP
#define BPP 16
#include "EncodeManagerBPP.cxx"
#undef BPP
#define BPP 32
#include "EncodeManagerBPP.cxx"
#undef BPP
template<class T>
inline bool EncodeManager::checkSolidTile(const Rect& r,
const T colourValue,
const PixelBuffer *pb)
{
int w, h;
const T* buffer;
int stride, pad;

w = r.width();
h = r.height();

buffer = (const T*)pb->getBuffer(r, &stride);
pad = stride - w;

while (h--) {
int w_ = w;
while (w_--) {
if (*buffer != colourValue)
return false;
buffer++;
}
buffer += pad;
}

return true;
}

template<class T>
inline bool EncodeManager::analyseRect(int width, int height,
const T* buffer, int stride,
struct RectInfo *info, int maxColours)
{
int pad;

T colour;
int count;

info->rleRuns = 0;
info->palette.clear();

pad = stride - width;

// For efficiency, we only update the palette on changes in colour
colour = buffer[0];
count = 0;
while (height--) {
int w_ = width;
while (w_--) {
if (*buffer != colour) {
if (!info->palette.insert(colour, count))
return false;
if (info->palette.size() > maxColours)
return false;

// FIXME: This doesn't account for switching lines
info->rleRuns++;

colour = *buffer;
count = 0;
}
buffer++;
count++;
}
buffer += pad;
}

// Make sure the final pixels also get counted
if (!info->palette.insert(colour, count))
return false;
if (info->palette.size() > maxColours)
return false;

return true;
}

+ 13
- 21
common/rfb/EncodeManager.h View File

@@ -1,6 +1,6 @@
/* 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 2014-2022 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
@@ -22,7 +22,8 @@

#include <vector>

#include <rdr/types.h>
#include <stdint.h>

#include <rfb/PixelBuffer.h>
#include <rfb/Region.h>
#include <rfb/Timer.h>
@@ -82,12 +83,12 @@ namespace rfb {

void writeSubRect(const Rect& rect, const PixelBuffer *pb);

bool checkSolidTile(const Rect& r, const rdr::U8* colourValue,
bool checkSolidTile(const Rect& r, const uint8_t* colourValue,
const PixelBuffer *pb);
void extendSolidAreaByBlock(const Rect& r, const rdr::U8* colourValue,
void extendSolidAreaByBlock(const Rect& r, const uint8_t* colourValue,
const PixelBuffer *pb, Rect* er);
void extendSolidAreaByPixel(const Rect& r, const Rect& sr,
const rdr::U8* colourValue,
const uint8_t* colourValue,
const PixelBuffer *pb, Rect* er);

PixelBuffer* preparePixelBuffer(const Rect& rect,
@@ -97,22 +98,13 @@ namespace rfb {
struct RectInfo *info, int maxColours);

protected:
// Preprocessor generated, optimised methods
inline bool checkSolidTile(const Rect& r, rdr::U8 colourValue,
const PixelBuffer *pb);
inline bool checkSolidTile(const Rect& r, rdr::U16 colourValue,
// Templated, optimised methods
template<class T>
inline bool checkSolidTile(const Rect& r, const T,
const PixelBuffer *pb);
inline bool checkSolidTile(const Rect& r, rdr::U32 colourValue,
const PixelBuffer *pb);

inline bool analyseRect(int width, int height,
const rdr::U8* buffer, int stride,
struct RectInfo *info, int maxColours);
inline bool analyseRect(int width, int height,
const rdr::U16* buffer, int stride,
struct RectInfo *info, int maxColours);
template<class T>
inline bool analyseRect(int width, int height,
const rdr::U32* buffer, int stride,
const T* buffer, int stride,
struct RectInfo *info, int maxColours);

protected:
@@ -147,10 +139,10 @@ namespace rfb {
virtual ~OffsetPixelBuffer() {}

void update(const PixelFormat& pf, int width, int height,
const rdr::U8* data_, int stride);
const uint8_t* data_, int stride);

private:
virtual rdr::U8* getBufferRW(const Rect& r, int* stride);
virtual uint8_t* getBufferRW(const Rect& r, int* stride);
};

OffsetPixelBuffer offsetPixelBuffer;

+ 0
- 98
common/rfb/EncodeManagerBPP.cxx View File

@@ -1,98 +0,0 @@
/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved.
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
* Copyright 2014 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
* 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.
*/

#define CONCAT2(a,b) a##b
#define CONCAT2E(a,b) CONCAT2(a,b)

#define UBPP CONCAT2E(U,BPP)

inline bool EncodeManager::checkSolidTile(const Rect& r,
rdr::UBPP colourValue,
const PixelBuffer *pb)
{
int w, h;
const rdr::UBPP* buffer;
int stride, pad;

w = r.width();
h = r.height();

buffer = (const rdr::UBPP*)pb->getBuffer(r, &stride);
pad = stride - w;

while (h--) {
int w_ = w;
while (w_--) {
if (*buffer != colourValue)
return false;
buffer++;
}
buffer += pad;
}

return true;
}

inline bool EncodeManager::analyseRect(int width, int height,
const rdr::UBPP* buffer, int stride,
struct RectInfo *info, int maxColours)
{
int pad;

rdr::UBPP colour;
int count;

info->rleRuns = 0;
info->palette.clear();

pad = stride - width;

// For efficiency, we only update the palette on changes in colour
colour = buffer[0];
count = 0;
while (height--) {
int w_ = width;
while (w_--) {
if (*buffer != colour) {
if (!info->palette.insert(colour, count))
return false;
if (info->palette.size() > maxColours)
return false;

// FIXME: This doesn't account for switching lines
info->rleRuns++;

colour = *buffer;
count = 0;
}
buffer++;
count++;
}
buffer += pad;
}

// Make sure the final pixels also get counted
if (!info->palette.insert(colour, count))
return false;
if (info->palette.size() > maxColours)
return false;

return true;
}

+ 12
- 12
common/rfb/Encoder.cxx View File

@@ -41,12 +41,12 @@ Encoder::~Encoder()
}

void Encoder::writeSolidRect(int width, int height,
const PixelFormat& pf, const rdr::U8* colour)
const PixelFormat& pf, const uint8_t* colour)
{
ManagedPixelBuffer buffer(pf, width, height);

Palette palette;
rdr::U32 palcol;
uint32_t palcol;

buffer.fillRect(buffer.getRect(), colour);

@@ -59,27 +59,27 @@ void Encoder::writeSolidRect(int width, int height,

void Encoder::writeSolidRect(const PixelBuffer* pb, const Palette& palette)
{
rdr::U32 col32;
rdr::U16 col16;
rdr::U8 col8;
uint32_t col32;
uint16_t col16;
uint8_t col8;

rdr::U8* buffer;
uint8_t* buffer;

assert(palette.size() == 1);

// The Palette relies on implicit up and down conversion
switch (pb->getPF().bpp) {
case 32:
col32 = (rdr::U32)palette.getColour(0);
buffer = (rdr::U8*)&col32;
col32 = (uint32_t)palette.getColour(0);
buffer = (uint8_t*)&col32;
break;
case 16:
col16 = (rdr::U16)palette.getColour(0);
buffer = (rdr::U8*)&col16;
col16 = (uint16_t)palette.getColour(0);
buffer = (uint8_t*)&col16;
break;
default:
col8 = (rdr::U8)palette.getColour(0);
buffer = (rdr::U8*)&col8;
col8 = (uint8_t)palette.getColour(0);
buffer = (uint8_t*)&col8;
break;
}


+ 3
- 2
common/rfb/Encoder.h View File

@@ -20,7 +20,8 @@
#ifndef __RFB_ENCODER_H__
#define __RFB_ENCODER_H__

#include <rdr/types.h>
#include <stdint.h>

#include <rfb/Rect.h>

namespace rfb {
@@ -83,7 +84,7 @@ namespace rfb {
// efficient short cut.
virtual void writeSolidRect(int width, int height,
const PixelFormat& pf,
const rdr::U8* colour)=0;
const uint8_t* colour)=0;

protected:
// Helper method for redirecting a single colour palette to the

+ 4
- 4
common/rfb/H264Decoder.cxx View File

@@ -70,7 +70,7 @@ bool H264Decoder::readRect(const Rect& /*r*/,
const ServerParams& /*server*/,
rdr::OutStream* os)
{
rdr::U32 len;
uint32_t len;

if (!is->hasData(8))
return false;
@@ -79,7 +79,7 @@ bool H264Decoder::readRect(const Rect& /*r*/,

len = is->readU32();
os->writeU32(len);
rdr::U32 flags = is->readU32();
uint32_t flags = is->readU32();

os->writeU32(flags);

@@ -99,8 +99,8 @@ void H264Decoder::decodeRect(const Rect& r, const void* buffer,
ModifiablePixelBuffer* pb)
{
rdr::MemInStream is(buffer, buflen);
rdr::U32 len = is.readU32();
rdr::U32 flags = is.readU32();
uint32_t len = is.readU32();
uint32_t flags = is.readU32();

H264DecoderContext* ctx = NULL;
if (flags & resetAllContexts)

+ 5
- 4
common/rfb/H264DecoderContext.h View File

@@ -21,8 +21,9 @@
#ifndef __RFB_H264DECODERCONTEXT_H__
#define __RFB_H264DECODERCONTEXT_H__

#include <stdint.h>

#include <os/Mutex.h>
#include <rdr/types.h>
#include <rfb/Rect.h>
#include <rfb/Decoder.h>

@@ -33,12 +34,12 @@ namespace rfb {

virtual ~H264DecoderContext() = 0;

virtual void decode(const rdr::U8* /*h264_buffer*/,
rdr::U32 /*len*/,
virtual void decode(const uint8_t* /*h264_buffer*/,
uint32_t /*len*/,
ModifiablePixelBuffer* /*pb*/) {}
void reset();

inline bool isEqualRect(const Rect &r) const { return r.equals(rect); }
inline bool isEqualRect(const Rect &r) const { return r == rect; }
bool isReady();

protected:

+ 7
- 7
common/rfb/H264LibavDecoderContext.cxx View File

@@ -110,13 +110,13 @@ void H264LibavDecoderContext::freeCodec() {
// We need to reallocate buffer because AVPacket uses non-const pointer.
// We don't want to const_cast our buffer somewhere. So we would rather to maintain context's own buffer
// Also avcodec requires a right padded buffer
rdr::U8* H264LibavDecoderContext::makeH264WorkBuffer(const rdr::U8* buffer, rdr::U32 len)
uint8_t* H264LibavDecoderContext::makeH264WorkBuffer(const uint8_t* buffer, uint32_t len)
{
rdr::U32 reserve_len = len + len % AV_INPUT_BUFFER_PADDING_SIZE;
uint32_t reserve_len = len + len % AV_INPUT_BUFFER_PADDING_SIZE;

if (!h264WorkBuffer || reserve_len > h264WorkBufferLength)
{
h264WorkBuffer = (rdr::U8*)realloc(h264WorkBuffer, reserve_len);
h264WorkBuffer = (uint8_t*)realloc(h264WorkBuffer, reserve_len);
if (h264WorkBuffer == NULL) {
throw Exception("H264LibavDecoderContext: Unable to allocate memory");
}
@@ -128,13 +128,13 @@ rdr::U8* H264LibavDecoderContext::makeH264WorkBuffer(const rdr::U8* buffer, rdr:
return h264WorkBuffer;
}

void H264LibavDecoderContext::decode(const rdr::U8* h264_in_buffer,
rdr::U32 len,
void H264LibavDecoderContext::decode(const uint8_t* h264_in_buffer,
uint32_t len,
ModifiablePixelBuffer* pb) {
os::AutoMutex lock(&mutex);
if (!initialized)
return;
rdr::U8* h264_work_buffer = makeH264WorkBuffer(h264_in_buffer, len);
uint8_t* h264_work_buffer = makeH264WorkBuffer(h264_in_buffer, len);

#ifdef FFMPEG_INIT_PACKET_DEPRECATED
AVPacket *packet = av_packet_alloc();
@@ -154,7 +154,7 @@ void H264LibavDecoderContext::decode(const rdr::U8* h264_in_buffer,
break;
}
// We need to slap on tv to make it work here (don't ask me why)
if (!packet->size && len == static_cast<rdr::U32>(ret))
if (!packet->size && len == static_cast<uint32_t>(ret))
ret = av_parser_parse2(parser, avctx, &packet->data, &packet->size, h264_work_buffer, len, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (ret < 0)
{

+ 4
- 4
common/rfb/H264LibavDecoderContext.h View File

@@ -34,7 +34,7 @@ namespace rfb {
H264LibavDecoderContext(const Rect &r) : H264DecoderContext(r) {}
~H264LibavDecoderContext() { freeCodec(); }

virtual void decode(const rdr::U8* h264_buffer, rdr::U32 len,
virtual void decode(const uint8_t* h264_buffer, uint32_t len,
ModifiablePixelBuffer* pb);

protected:
@@ -42,15 +42,15 @@ namespace rfb {
virtual void freeCodec();

private:
rdr::U8* makeH264WorkBuffer(const rdr::U8* buffer, rdr::U32 len);
uint8_t* makeH264WorkBuffer(const uint8_t* buffer, uint32_t len);

AVCodecContext *avctx;
AVCodecParserContext *parser;
AVFrame* frame;
SwsContext* sws;
uint8_t* swsBuffer;
rdr::U8* h264WorkBuffer;
rdr::U32 h264WorkBufferLength;
uint8_t* h264WorkBuffer;
uint32_t h264WorkBufferLength;
};
}


+ 5
- 5
common/rfb/H264WinDecoderContext.cxx View File

@@ -154,8 +154,8 @@ void H264WinDecoderContext::freeCodec() {
initialized = false;
}

void H264WinDecoderContext::decode(const rdr::U8* h264_buffer,
rdr::U32 len,
void H264WinDecoderContext::decode(const uint8_t* h264_buffer,
uint32_t len,
ModifiablePixelBuffer* pb) {
os::AutoMutex lock(&mutex);
if (!initialized)
@@ -351,7 +351,7 @@ void H264WinDecoderContext::decode(const rdr::U8* h264_buffer,
}

// "7.3.2.1.1 Sequence parameter set data syntax" on page 66 of https://www.itu.int/rec/T-REC-H.264-202108-I/en
void H264WinDecoderContext::ParseSPS(const rdr::U8* buffer, int length)
void H264WinDecoderContext::ParseSPS(const uint8_t* buffer, int length)
{
#define EXPECT(cond) if (!(cond)) return;

@@ -404,14 +404,14 @@ void H264WinDecoderContext::ParseSPS(const rdr::U8* buffer, int length)

// NAL unit type
EXPECT(length > 1);
rdr::U8 type = buffer[0];
uint8_t type = buffer[0];
EXPECT((type & 0x80) == 0); // forbidden zero bit
EXPECT((type & 0x1f) == 7); // SPS NAL unit type
buffer++;
length--;

int available = 0;
rdr::U8 byte = 0;
uint8_t byte = 0;

unsigned profile_idc;
unsigned seq_parameter_set_id;

+ 8
- 8
common/rfb/H264WinDecoderContext.h View File

@@ -33,7 +33,7 @@ namespace rfb {
H264WinDecoderContext(const Rect &r) : H264DecoderContext(r) {};
~H264WinDecoderContext() { freeCodec(); }

virtual void decode(const rdr::U8* h264_buffer, rdr::U32 len,
virtual void decode(const uint8_t* h264_buffer, uint32_t len,
ModifiablePixelBuffer* pb);

protected:
@@ -42,12 +42,12 @@ namespace rfb {

private:
LONG stride;
rdr::U32 full_width = 0;
rdr::U32 full_height = 0;
rdr::U32 crop_width = 0;
rdr::U32 crop_height = 0;
rdr::U32 offset_x = 0;
rdr::U32 offset_y = 0;
uint32_t full_width = 0;
uint32_t full_height = 0;
uint32_t crop_width = 0;
uint32_t crop_height = 0;
uint32_t offset_x = 0;
uint32_t offset_y = 0;
IMFTransform *decoder = NULL;
IMFTransform *converter = NULL;
IMFSample *input_sample = NULL;
@@ -57,7 +57,7 @@ namespace rfb {
IMFMediaBuffer *decoded_buffer = NULL;
IMFMediaBuffer *converted_buffer = NULL;

void ParseSPS(const rdr::U8* buffer, int length);
void ParseSPS(const uint8_t* buffer, int length);
};
}


+ 87
- 15
common/rfb/HextileDecoder.cxx View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2014-2022 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
@@ -24,22 +25,14 @@
#include <rdr/MemInStream.h>
#include <rdr/OutStream.h>

#include <rfb/Exception.h>
#include <rfb/ServerParams.h>
#include <rfb/PixelBuffer.h>
#include <rfb/HextileDecoder.h>
#include <rfb/hextileConstants.h>

using namespace rfb;

#define BPP 8
#include <rfb/hextileDecode.h>
#undef BPP
#define BPP 16
#include <rfb/hextileDecode.h>
#undef BPP
#define BPP 32
#include <rfb/hextileDecode.h>
#undef BPP

HextileDecoder::HextileDecoder() : Decoder(DecoderPlain)
{
}
@@ -63,7 +56,7 @@ bool HextileDecoder::readRect(const Rect& r, rdr::InStream* is,
t.br.y = __rfbmin(r.br.y, t.tl.y + 16);

for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {
rdr::U8 tileType;
uint8_t tileType;

t.br.x = __rfbmin(r.br.x, t.tl.x + 16);

@@ -94,7 +87,7 @@ bool HextileDecoder::readRect(const Rect& r, rdr::InStream* is,
}

if (tileType & hextileAnySubrects) {
rdr::U8 nSubrects;
uint8_t nSubrects;

if (!is->hasDataOrRestore(1))
return false;
@@ -127,8 +120,87 @@ void HextileDecoder::decodeRect(const Rect& r, const void* buffer,
rdr::MemInStream is(buffer, buflen);
const PixelFormat& pf = server.pf();
switch (pf.bpp) {
case 8: hextileDecode8 (r, &is, pf, pb); break;
case 16: hextileDecode16(r, &is, pf, pb); break;
case 32: hextileDecode32(r, &is, pf, pb); break;
case 8: hextileDecode<uint8_t >(r, &is, pf, pb); break;
case 16: hextileDecode<uint16_t>(r, &is, pf, pb); break;
case 32: hextileDecode<uint32_t>(r, &is, pf, pb); break;
}
}

template<class T>
inline T HextileDecoder::readPixel(rdr::InStream* is)
{
if (sizeof(T) == 1)
return is->readOpaque8();
if (sizeof(T) == 2)
return is->readOpaque16();
if (sizeof(T) == 4)
return is->readOpaque32();
}

template<class T>
void HextileDecoder::hextileDecode(const Rect& r, rdr::InStream* is,
const PixelFormat& pf,
ModifiablePixelBuffer* pb)
{
Rect t;
T bg = 0;
T fg = 0;
T buf[16 * 16];

for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {

t.br.y = __rfbmin(r.br.y, t.tl.y + 16);

for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {

t.br.x = __rfbmin(r.br.x, t.tl.x + 16);

int tileType = is->readU8();

if (tileType & hextileRaw) {
is->readBytes(buf, t.area() * sizeof(T));
pb->imageRect(pf, t, buf);
continue;
}

if (tileType & hextileBgSpecified)
bg = readPixel<T>(is);

int len = t.area();
T* ptr = buf;
while (len-- > 0) *ptr++ = bg;

if (tileType & hextileFgSpecified)
fg = readPixel<T>(is);

if (tileType & hextileAnySubrects) {
int nSubrects = is->readU8();

for (int i = 0; i < nSubrects; i++) {

if (tileType & hextileSubrectsColoured)
fg = readPixel<T>(is);

int xy = is->readU8();
int wh = is->readU8();

int x = ((xy >> 4) & 15);
int y = (xy & 15);
int w = ((wh >> 4) & 15) + 1;
int h = (wh & 15) + 1;
if (x + w > 16 || y + h > 16) {
throw rfb::Exception("HEXTILE_DECODE: Hextile out of bounds");
}
T* ptr = buf + y * t.width() + x;
int rowAdd = t.width() - w;
while (h-- > 0) {
int len = w;
while (len-- > 0) *ptr++ = fg;
ptr += rowAdd;
}
}
}
pb->imageRect(pf, t, buf);
}
}
}

+ 10
- 0
common/rfb/HextileDecoder.h View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2014-2022 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
@@ -22,6 +23,8 @@

namespace rfb {

class PixelFormat;

class HextileDecoder : public Decoder {
public:
HextileDecoder();
@@ -31,6 +34,13 @@ namespace rfb {
virtual void decodeRect(const Rect& r, const void* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb);
private:
template<class T>
inline T readPixel(rdr::InStream* is);
template<class T>
void hextileDecode(const Rect& r, rdr::InStream* is,
const PixelFormat& pf,
ModifiablePixelBuffer* pb);
};
}
#endif

+ 503
- 21
common/rfb/HextileEncoder.cxx View File

@@ -1,6 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2005 Constantin Kaplinsky. All Rights Reserved.
* Copyright 2014 Pierre Ossman for Cendio AB
* Copyright 2014-2022 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,8 +25,10 @@
#include <rfb/encodings.h>
#include <rfb/SConnection.h>
#include <rfb/HextileEncoder.h>
#include <rfb/Palette.h>
#include <rfb/PixelBuffer.h>
#include <rfb/Configuration.h>
#include <rfb/hextileConstants.h>

using namespace rfb;

@@ -36,19 +38,6 @@ BoolParameter improvedHextile("ImprovedHextile",
"ratios by the cost of using more CPU time",
true);

#define BPP 8
#include <rfb/hextileEncode.h>
#include <rfb/hextileEncodeBetter.h>
#undef BPP
#define BPP 16
#include <rfb/hextileEncode.h>
#include <rfb/hextileEncodeBetter.h>
#undef BPP
#define BPP 32
#include <rfb/hextileEncode.h>
#include <rfb/hextileEncodeBetter.h>
#undef BPP

HextileEncoder::HextileEncoder(SConnection* conn) :
Encoder(conn, encodingHextile, EncoderPlain)
{
@@ -70,23 +59,23 @@ void HextileEncoder::writeRect(const PixelBuffer* pb,
switch (pb->getPF().bpp) {
case 8:
if (improvedHextile) {
hextileEncodeBetter8(os, pb);
hextileEncodeBetter<uint8_t>(os, pb);
} else {
hextileEncode8(os, pb);
hextileEncode<uint8_t>(os, pb);
}
break;
case 16:
if (improvedHextile) {
hextileEncodeBetter16(os, pb);
hextileEncodeBetter<uint16_t>(os, pb);
} else {
hextileEncode16(os, pb);
hextileEncode<uint16_t>(os, pb);
}
break;
case 32:
if (improvedHextile) {
hextileEncodeBetter32(os, pb);
hextileEncodeBetter<uint32_t>(os, pb);
} else {
hextileEncode32(os, pb);
hextileEncode<uint32_t>(os, pb);
}
break;
}
@@ -94,7 +83,7 @@ void HextileEncoder::writeRect(const PixelBuffer* pb,

void HextileEncoder::writeSolidRect(int width, int height,
const PixelFormat& pf,
const rdr::U8* colour)
const uint8_t* colour)
{
rdr::OutStream* os;
int tiles;
@@ -110,3 +99,496 @@ void HextileEncoder::writeSolidRect(int width, int height,
while (tiles--)
os->writeU8(0);
}

template<class T>
inline void HextileEncoder::writePixel(rdr::OutStream* os, T pixel)
{
if (sizeof(T) == 1)
os->writeOpaque8(pixel);
else if (sizeof(T) == 2)
os->writeOpaque16(pixel);
else if (sizeof(T) == 4)
os->writeOpaque32(pixel);
}

template<class T>
void HextileEncoder::hextileEncode(rdr::OutStream* os,
const PixelBuffer* pb)
{
Rect t;
T buf[256];
T oldBg = 0, oldFg = 0;
bool oldBgValid = false;
bool oldFgValid = false;
uint8_t encoded[256*sizeof(T)];

for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {

t.br.y = __rfbmin(pb->height(), t.tl.y + 16);

for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {

t.br.x = __rfbmin(pb->width(), t.tl.x + 16);

pb->getImage(buf, t);

T bg = 0, fg = 0;
int tileType = testTileType(buf, t.width(), t.height(), &bg, &fg);

if (!oldBgValid || oldBg != bg) {
tileType |= hextileBgSpecified;
oldBg = bg;
oldBgValid = true;
}

int encodedLen = 0;

if (tileType & hextileAnySubrects) {

if (tileType & hextileSubrectsColoured) {
oldFgValid = false;
} else {
if (!oldFgValid || oldFg != fg) {
tileType |= hextileFgSpecified;
oldFg = fg;
oldFgValid = true;
}
}

encodedLen = hextileEncodeTile(buf, t.width(), t.height(),
tileType, encoded, bg);

if (encodedLen < 0) {
pb->getImage(buf, t);
os->writeU8(hextileRaw);
os->writeBytes(buf, t.width() * t.height() * sizeof(T));
oldBgValid = oldFgValid = false;
continue;
}
}

os->writeU8(tileType);
if (tileType & hextileBgSpecified) writePixel(os, bg);
if (tileType & hextileFgSpecified) writePixel(os, fg);
if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen);
}
}
}

template<class T>
int HextileEncoder::hextileEncodeTile(T* data, int w, int h,
int tileType, uint8_t* encoded,
T bg)
{
uint8_t* nSubrectsPtr = encoded;
*nSubrectsPtr = 0;
encoded++;

for (int y = 0; y < h; y++)
{
int x = 0;
while (x < w) {
if (*data == bg) {
x++;
data++;
continue;
}

// Find horizontal subrect first
T* ptr = data+1;
T* eol = data+w-x;
while (ptr < eol && *ptr == *data) ptr++;
int sw = ptr - data;

ptr = data + w;
int sh = 1;
while (sh < h-y) {
eol = ptr + sw;
while (ptr < eol)
if (*ptr++ != *data) goto endOfSubrect;
ptr += w - sw;
sh++;
}
endOfSubrect:

(*nSubrectsPtr)++;

if (tileType & hextileSubrectsColoured) {
if (encoded - nSubrectsPtr + sizeof(T) > w*h*sizeof(T))
return -1;

if (sizeof(T) == 1) {
*encoded++ = *data;
} else if (sizeof(T) == 2) {
*encoded++ = ((uint8_t*)data)[0];
*encoded++ = ((uint8_t*)data)[1];
} else if (sizeof(T) == 4) {
*encoded++ = ((uint8_t*)data)[0];
*encoded++ = ((uint8_t*)data)[1];
*encoded++ = ((uint8_t*)data)[2];
*encoded++ = ((uint8_t*)data)[3];
}
}

if ((size_t)(encoded - nSubrectsPtr + 2) > w*h*sizeof(T))
return -1;
*encoded++ = (x << 4) | y;
*encoded++ = ((sw-1) << 4) | (sh-1);

ptr = data+w;
T* eor = data+w*sh;
while (ptr < eor) {
eol = ptr + sw;
while (ptr < eol) *ptr++ = bg;
ptr += w - sw;
}
x += sw;
data += sw;
}
}
return encoded - nSubrectsPtr;
}

template<class T>
int HextileEncoder::testTileType(T* data, int w, int h, T* bg, T* fg)
{
T pix1 = *data;
T* end = data + w * h;

T* ptr = data + 1;
while (ptr < end && *ptr == pix1)
ptr++;

if (ptr == end) {
*bg = pix1;
return 0; // solid-color tile
}

int count1 = ptr - data;
int count2 = 1;
T pix2 = *ptr++;
int tileType = hextileAnySubrects;

for (; ptr < end; ptr++) {
if (*ptr == pix1) {
count1++;
} else if (*ptr == pix2) {
count2++;
} else {
tileType |= hextileSubrectsColoured;
break;
}
}

if (count1 >= count2) {
*bg = pix1; *fg = pix2;
} else {
*bg = pix2; *fg = pix1;
}
return tileType;
}

//
// This class analyzes a separate tile and encodes its subrectangles.
//

template<class T>
class HextileTile {

public:

HextileTile ();

//
// Initialize existing object instance with new tile data.
//
void newTile(const T *src, int w, int h);

//
// Flags can include: hextileRaw, hextileAnySubrects and
// hextileSubrectsColoured. Note that if hextileRaw is set, other
// flags make no sense. Also, hextileSubrectsColoured is meaningful
// only when hextileAnySubrects is set as well.
//
int getFlags() const { return m_flags; }

//
// Returns the size of encoded subrects data, including subrect count.
// The size is zero if flags do not include hextileAnySubrects.
//
size_t getSize() const { return m_size; }

//
// Return optimal background.
//
int getBackground() const { return m_background; }

//
// Return foreground if flags include hextileSubrectsColoured.
//
int getForeground() const { return m_foreground; }

//
// Encode subrects. This function may be called only if
// hextileAnySubrects bit is set in flags. The buffer size should be
// big enough to store at least the number of bytes returned by the
// getSize() method.
//
void encode(uint8_t* dst) const;

protected:

//
// Analyze the tile pixels, fill in all the data fields.
//
void analyze();

const T *m_tile;
int m_width;
int m_height;

size_t m_size;
int m_flags;
T m_background;
T m_foreground;

int m_numSubrects;
uint8_t m_coords[256 * 2];
T m_colors[256];

private:

bool m_processed[16][16];
Palette m_pal;
};

template<class T>
HextileTile<T>::HextileTile()
: m_tile(NULL), m_width(0), m_height(0),
m_size(0), m_flags(0), m_background(0), m_foreground(0),
m_numSubrects(0)
{
}

template<class T>
void HextileTile<T>::newTile(const T *src, int w, int h)
{
m_tile = src;
m_width = w;
m_height = h;

analyze();
}

template<class T>
void HextileTile<T>::analyze()
{
assert(m_tile && m_width && m_height);

const T *ptr = m_tile;
const T *end = &m_tile[m_width * m_height];
T color = *ptr++;
while (ptr != end && *ptr == color)
ptr++;

// Handle solid tile
if (ptr == end) {
m_background = m_tile[0];
m_flags = 0;
m_size = 0;
return;
}

// Compute number of complete rows of the same color, at the top
int y = (ptr - m_tile) / m_width;

T *colorsPtr = m_colors;
uint8_t *coordsPtr = m_coords;
m_pal.clear();
m_numSubrects = 0;

// Have we found the first subrect already?
if (y > 0) {
*colorsPtr++ = color;
*coordsPtr++ = 0;
*coordsPtr++ = (uint8_t)(((m_width - 1) << 4) | ((y - 1) & 0x0F));
m_pal.insert(color, 1);
m_numSubrects++;
}

memset(m_processed, 0, 16 * 16 * sizeof(bool));

int x, sx, sy, sw, sh, max_x;

for (; y < m_height; y++) {
for (x = 0; x < m_width; x++) {
// Skip pixels that were processed earlier
if (m_processed[y][x]) {
continue;
}
// Determine dimensions of the horizontal subrect
color = m_tile[y * m_width + x];
for (sx = x + 1; sx < m_width; sx++) {
if (m_tile[y * m_width + sx] != color)
break;
}
sw = sx - x;
max_x = sx;
for (sy = y + 1; sy < m_height; sy++) {
for (sx = x; sx < max_x; sx++) {
if (m_tile[sy * m_width + sx] != color)
goto done;
}
}
done:
sh = sy - y;

// Save properties of this subrect
*colorsPtr++ = color;
*coordsPtr++ = (uint8_t)((x << 4) | (y & 0x0F));
*coordsPtr++ = (uint8_t)(((sw - 1) << 4) | ((sh - 1) & 0x0F));

if (!m_pal.insert(color, 1) ||
((size_t)m_pal.size() > (48 + 2 * sizeof(T)*8))) {
// Handle palette overflow
m_flags = hextileRaw;
m_size = 0;
return;
}

m_numSubrects++;

// Mark pixels of this subrect as processed, below this row
for (sy = y + 1; sy < y + sh; sy++) {
for (sx = x; sx < x + sw; sx++)
m_processed[sy][sx] = true;
}

// Skip processed pixels of this row
x += (sw - 1);
}
}

// Save number of colors in this tile (should be no less than 2)
int numColors = m_pal.size();
assert(numColors >= 2);

m_background = (T)m_pal.getColour(0);
m_flags = hextileAnySubrects;
int numSubrects = m_numSubrects - m_pal.getCount(0);

if (numColors == 2) {
// Monochrome tile
m_foreground = (T)m_pal.getColour(1);
m_size = 1 + 2 * numSubrects;
} else {
// Colored tile
m_flags |= hextileSubrectsColoured;
m_size = 1 + (2 + sizeof(T)) * numSubrects;
}
}

template<class T>
void HextileTile<T>::encode(uint8_t *dst) const
{
assert(m_numSubrects && (m_flags & hextileAnySubrects));

// Zero subrects counter
uint8_t *numSubrectsPtr = dst;
*dst++ = 0;

for (int i = 0; i < m_numSubrects; i++) {
if (m_colors[i] == m_background)
continue;

if (m_flags & hextileSubrectsColoured) {
if (sizeof(T) == 1) {
*dst++ = m_colors[i];
} else if (sizeof(T) == 2) {
*dst++ = ((uint8_t*)&m_colors[i])[0];
*dst++ = ((uint8_t*)&m_colors[i])[1];
} else if (sizeof(T) == 4) {
*dst++ = ((uint8_t*)&m_colors[i])[0];
*dst++ = ((uint8_t*)&m_colors[i])[1];
*dst++ = ((uint8_t*)&m_colors[i])[2];
*dst++ = ((uint8_t*)&m_colors[i])[3];
}
}
*dst++ = m_coords[i * 2];
*dst++ = m_coords[i * 2 + 1];

(*numSubrectsPtr)++;
}

assert((size_t)(dst - numSubrectsPtr) == m_size);
}

//
// Main encoding function.
//

template<class T>
void HextileEncoder::hextileEncodeBetter(rdr::OutStream* os,
const PixelBuffer* pb)
{
Rect t;
T buf[256];
T oldBg = 0, oldFg = 0;
bool oldBgValid = false;
bool oldFgValid = false;
uint8_t encoded[256*sizeof(T)];

HextileTile<T> tile;

for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {

t.br.y = __rfbmin(pb->height(), t.tl.y + 16);

for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {

t.br.x = __rfbmin(pb->width(), t.tl.x + 16);

pb->getImage(buf, t);

tile.newTile(buf, t.width(), t.height());
int tileType = tile.getFlags();
size_t encodedLen = tile.getSize();

if ( (tileType & hextileRaw) != 0 ||
encodedLen >= t.width() * t.height() * sizeof(T)) {
os->writeU8(hextileRaw);
os->writeBytes(buf, t.width() * t.height() * sizeof(T));
oldBgValid = oldFgValid = false;
continue;
}

T bg = tile.getBackground();
T fg = 0;

if (!oldBgValid || oldBg != bg) {
tileType |= hextileBgSpecified;
oldBg = bg;
oldBgValid = true;
}

if (tileType & hextileAnySubrects) {
if (tileType & hextileSubrectsColoured) {
oldFgValid = false;
} else {
fg = tile.getForeground();
if (!oldFgValid || oldFg != fg) {
tileType |= hextileFgSpecified;
oldFg = fg;
oldFgValid = true;
}
}
tile.encode(encoded);
}

os->writeU8(tileType);
if (tileType & hextileBgSpecified) writePixel(os, bg);
if (tileType & hextileFgSpecified) writePixel(os, fg);
if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen);
}
}
}

+ 16
- 2
common/rfb/HextileEncoder.h View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2014 Pierre Ossman for Cendio AB
* Copyright 2014-2022 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
@@ -31,7 +31,21 @@ namespace rfb {
virtual void writeRect(const PixelBuffer* pb, const Palette& palette);
virtual void writeSolidRect(int width, int height,
const PixelFormat& pf,
const rdr::U8* colour);
const uint8_t* colour);
private:
template<class T>
inline void writePixel(rdr::OutStream* os, T pixel);

template<class T>
void hextileEncode(rdr::OutStream* os, const PixelBuffer* pb);
template<class T>
int hextileEncodeTile(T* data, int w, int h, int tileType,
uint8_t* encoded, T bg);
template<class T>
int testTileType(T* data, int w, int h, T* bg, T* fg);

template<class T>
void hextileEncodeBetter(rdr::OutStream* os, const PixelBuffer* pb);
};
}
#endif

+ 7
- 9
common/rfb/Hostname.h View File

@@ -22,6 +22,7 @@
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <rdr/Exception.h>
#include <rfb/util.h>

@@ -38,7 +39,9 @@ namespace rfb {
return true;
}

static void getHostAndPort(const char* hi, char** host, int* port, int basePort=5900) {
static void getHostAndPort(const char* hi, std::string* host,
int* port, int basePort=5900)
{
const char* hostStart;
const char* hostEnd;
const char* portStart;
@@ -86,14 +89,9 @@ namespace rfb {
hostEnd--;

if (hostStart == hostEnd)
*host = strDup("localhost");
else {
size_t len;
len = hostEnd - hostStart + 1;
*host = new char[len];
strncpy(*host, hostStart, len-1);
(*host)[len-1] = '\0';
}
*host = "localhost";
else
*host = std::string(hostStart, hostEnd - hostStart);

if (portStart == NULL)
*port = basePort;

+ 3
- 3
common/rfb/InputHandler.h View File

@@ -23,16 +23,16 @@
#ifndef __RFB_INPUTHANDLER_H__
#define __RFB_INPUTHANDLER_H__

#include <rdr/types.h>
#include <stdint.h>

#include <rfb/Rect.h>
#include <rfb/util.h>

namespace rfb {

class InputHandler {
public:
virtual ~InputHandler() {}
virtual void keyEvent(rdr::U32 /*keysym*/, rdr::U32 /*keycode*/,
virtual void keyEvent(uint32_t /*keysym*/, uint32_t /*keycode*/,
bool /*down*/) { }
virtual void pointerEvent(const Point& /*pos*/,
int /*buttonMask*/) { }

+ 9
- 9
common/rfb/JpegCompressor.cxx View File

@@ -155,14 +155,14 @@ JpegCompressor::~JpegCompressor(void)
delete cinfo;
}

void JpegCompressor::compress(const rdr::U8 *buf, volatile int stride,
void JpegCompressor::compress(const uint8_t *buf, volatile int stride,
const Rect& r, const PixelFormat& pf,
int quality, int subsamp)
{
int w = r.width();
int h = r.height();
int pixelsize;
rdr::U8 * volatile srcBuf = NULL;
uint8_t * volatile srcBuf = NULL;
volatile bool srcBufIsTemp = false;
JSAMPROW * volatile rowPointer = NULL;

@@ -182,17 +182,17 @@ void JpegCompressor::compress(const rdr::U8 *buf, volatile int stride,
#ifdef JCS_EXTENSIONS
// Try to have libjpeg output directly to our native format
// libjpeg can only handle some "standard" formats
if (pfRGBX.equal(pf))
if (pfRGBX == pf)
cinfo->in_color_space = JCS_EXT_RGBX;
else if (pfBGRX.equal(pf))
else if (pfBGRX == pf)
cinfo->in_color_space = JCS_EXT_BGRX;
else if (pfXRGB.equal(pf))
else if (pfXRGB == pf)
cinfo->in_color_space = JCS_EXT_XRGB;
else if (pfXBGR.equal(pf))
else if (pfXBGR == pf)
cinfo->in_color_space = JCS_EXT_XBGR;

if (cinfo->in_color_space != JCS_RGB) {
srcBuf = (rdr::U8 *)buf;
srcBuf = (uint8_t *)buf;
pixelsize = 4;
}
#endif
@@ -201,9 +201,9 @@ void JpegCompressor::compress(const rdr::U8 *buf, volatile int stride,
stride = w;

if (cinfo->in_color_space == JCS_RGB) {
srcBuf = new rdr::U8[w * h * pixelsize];
srcBuf = new uint8_t[w * h * pixelsize];
srcBufIsTemp = true;
pf.rgbFromBuffer(srcBuf, (const rdr::U8 *)buf, w, stride, h);
pf.rgbFromBuffer(srcBuf, (const uint8_t *)buf, w, stride, h);
stride = w;
}


+ 1
- 1
common/rfb/JpegCompressor.h View File

@@ -43,7 +43,7 @@ namespace rfb {
JpegCompressor(int bufferLen = 128*1024);
virtual ~JpegCompressor();

void compress(const rdr::U8 *, int, const Rect&, const PixelFormat&, int, int);
void compress(const uint8_t *, int, const Rect&, const PixelFormat&, int, int);

void writeBytes(const void*, int);


+ 10
- 10
common/rfb/JpegDecompressor.cxx View File

@@ -150,8 +150,8 @@ JpegDecompressor::~JpegDecompressor(void)
delete dinfo;
}

void JpegDecompressor::decompress(const rdr::U8 *jpegBuf,
int jpegBufLen, rdr::U8 *buf,
void JpegDecompressor::decompress(const uint8_t *jpegBuf,
int jpegBufLen, uint8_t *buf,
volatile int stride,
const Rect& r, const PixelFormat& pf)
{
@@ -159,7 +159,7 @@ void JpegDecompressor::decompress(const rdr::U8 *jpegBuf,
int h = r.height();
int pixelsize;
int dstBufStride;
rdr::U8 * volatile dstBuf = NULL;
uint8_t * volatile dstBuf = NULL;
volatile bool dstBufIsTemp = false;
JSAMPROW * volatile rowPointer = NULL;

@@ -184,23 +184,23 @@ void JpegDecompressor::decompress(const rdr::U8 *jpegBuf,
#ifdef JCS_EXTENSIONS
// Try to have libjpeg output directly to our native format
// libjpeg can only handle some "standard" formats
if (pfRGBX.equal(pf))
if (pfRGBX == pf)
dinfo->out_color_space = JCS_EXT_RGBX;
else if (pfBGRX.equal(pf))
else if (pfBGRX == pf)
dinfo->out_color_space = JCS_EXT_BGRX;
else if (pfXRGB.equal(pf))
else if (pfXRGB == pf)
dinfo->out_color_space = JCS_EXT_XRGB;
else if (pfXBGR.equal(pf))
else if (pfXBGR == pf)
dinfo->out_color_space = JCS_EXT_XBGR;

if (dinfo->out_color_space != JCS_RGB) {
dstBuf = (rdr::U8 *)buf;
dstBuf = (uint8_t *)buf;
pixelsize = 4;
}
#endif

if (dinfo->out_color_space == JCS_RGB) {
dstBuf = new rdr::U8[w * h * pixelsize];
dstBuf = new uint8_t[w * h * pixelsize];
dstBufIsTemp = true;
dstBufStride = w;
}
@@ -226,7 +226,7 @@ void JpegDecompressor::decompress(const rdr::U8 *jpegBuf,
}

if (dinfo->out_color_space == JCS_RGB)
pf.bufferFromRGB((rdr::U8*)buf, dstBuf, w, stride, h);
pf.bufferFromRGB((uint8_t*)buf, dstBuf, w, stride, h);

jpeg_finish_decompress(dinfo);


+ 1
- 1
common/rfb/JpegDecompressor.h View File

@@ -43,7 +43,7 @@ namespace rfb {
JpegDecompressor(void);
virtual ~JpegDecompressor();

void decompress(const rdr::U8 *, int, rdr::U8 *, int, const Rect&,
void decompress(const uint8_t *, int, uint8_t *, int, const Rect&,
const PixelFormat&);

private:

+ 4
- 3
common/rfb/KeyRemapper.cxx View File

@@ -21,6 +21,7 @@
#endif

#include <stdio.h>
#include <string.h>

#include <os/Mutex.h>

@@ -72,10 +73,10 @@ void KeyRemapper::setMapping(const char* m) {
}
}

rdr::U32 KeyRemapper::remapKey(rdr::U32 key) const {
uint32_t KeyRemapper::remapKey(uint32_t key) const {
os::AutoMutex a(mutex);

std::map<rdr::U32,rdr::U32>::const_iterator i = mapping.find(key);
std::map<uint32_t,uint32_t>::const_iterator i = mapping.find(key);
if (i != mapping.end())
return i->second;
return key;
@@ -86,7 +87,7 @@ class KeyMapParameter : public StringParameter {
public:
KeyMapParameter()
: StringParameter("RemapKeys", "Comma-separated list of incoming keysyms to remap. Mappings are expressed as two hex values, prefixed by 0x, and separated by ->", "") {
setParam(value);
KeyRemapper::defInstance.setMapping("");
}
bool setParam(const char* v) {
KeyRemapper::defInstance.setMapping(v);

+ 4
- 3
common/rfb/KeyRemapper.h View File

@@ -20,7 +20,8 @@
#define __RFB_KEYREMAPPER_H__

#include <map>
#include <rdr/types.h>

#include <stdint.h>

namespace os { class Mutex; }

@@ -31,10 +32,10 @@ namespace rfb {
KeyRemapper(const char* m="");
~KeyRemapper();
void setMapping(const char* m);
rdr::U32 remapKey(rdr::U32 key) const;
uint32_t remapKey(uint32_t key) const;
static KeyRemapper defInstance;
private:
std::map<rdr::U32,rdr::U32> mapping;
std::map<uint32_t,uint32_t> mapping;
os::Mutex* mutex;
};


+ 17
- 15
common/rfb/LogWriter.cxx View File

@@ -76,19 +76,20 @@ LogWriter::getLogWriter(const char* name) {
}

bool LogWriter::setLogParams(const char* params) {
CharArray logwriterName, loggerName, logLevel;
if (!strSplit(params, ':', &logwriterName.buf, &loggerName.buf) ||
!strSplit(loggerName.buf, ':', &loggerName.buf, &logLevel.buf)) {
std::vector<std::string> parts;
parts = split(params, ':');
if (parts.size() != 3) {
fprintf(stderr,"failed to parse log params:%s\n",params);
return false;
}
int level = atoi(logLevel.buf);
int level = atoi(parts[2].c_str());
Logger* logger = 0;
if (strcmp("", loggerName.buf) != 0) {
logger = Logger::getLogger(loggerName.buf);
if (!logger) fprintf(stderr,"no logger found! %s\n",loggerName.buf);
if (!parts[1].empty()) {
logger = Logger::getLogger(parts[1].c_str());
if (!logger)
fprintf(stderr, "no logger found! %s\n", parts[1].c_str());
}
if (strcmp("*", logwriterName.buf) == 0) {
if (parts[0] == "*") {
LogWriter* current = log_writers;
while (current) {
current->setLog(logger);
@@ -97,9 +98,9 @@ bool LogWriter::setLogParams(const char* params) {
}
return true;
} else {
LogWriter* logwriter = getLogWriter(logwriterName.buf);
LogWriter* logwriter = getLogWriter(parts[0].c_str());
if (!logwriter) {
fprintf(stderr,"no logwriter found! %s\n",logwriterName.buf);
fprintf(stderr, "no logwriter found! %s\n", parts[0].c_str());
} else {
logwriter->setLog(logger);
logwriter->setLevel(level);
@@ -122,11 +123,12 @@ bool LogParameter::setParam(const char* v) {
if (immutable) return true;
LogWriter::setLogParams("*::0");
StringParameter::setParam(v);
CharArray logParam;
CharArray params(getData());
while (params.buf) {
strSplit(params.buf, ',', &logParam.buf, &params.buf);
if (strlen(logParam.buf) && !LogWriter::setLogParams(logParam.buf))
std::vector<std::string> parts;
parts = split(v, ',');
for (size_t i = 0; i < parts.size(); i++) {
if (parts[i].empty())
continue;
if (!LogWriter::setLogParams(parts[i].c_str()))
return false;
}
return true;

+ 0
- 1
common/rfb/Logger.cxx View File

@@ -28,7 +28,6 @@

#include <rfb/Logger.h>
#include <rfb/LogWriter.h>
#include <rfb/util.h>

using namespace rfb;


+ 20
- 15
common/rfb/Logger_file.cxx View File

@@ -22,20 +22,21 @@
#include <config.h>
#endif

#include <limits.h>
#include <stdlib.h>
#include <string.h>

#include <os/Mutex.h>

#include <rfb/util.h>
#include <rfb/Logger_file.h>

using namespace rfb;

Logger_File::Logger_File(const char* loggerName)
: Logger(loggerName), indent(13), width(79), m_filename(0), m_file(0),
: Logger(loggerName), indent(13), width(79), m_file(0),
m_lastLogTime(0)
{
m_filename[0] = '\0';
mutex = new os::Mutex();
}

@@ -50,11 +51,16 @@ void Logger_File::write(int /*level*/, const char *logname, const char *message)
os::AutoMutex a(mutex);

if (!m_file) {
if (!m_filename) return;
CharArray bakFilename(strlen(m_filename) + 1 + 4);
sprintf(bakFilename.buf, "%s.bak", m_filename);
remove(bakFilename.buf);
rename(m_filename, bakFilename.buf);
if (m_filename[0] == '\0')
return;
char bakFilename[PATH_MAX];
if (snprintf(bakFilename, sizeof(bakFilename),
"%s.bak", m_filename) >= (int)sizeof(bakFilename)) {
remove(m_filename);
} else {
remove(bakFilename);
rename(m_filename, bakFilename);
}
m_file = fopen(m_filename, "w+");
if (!m_file) return;
}
@@ -93,7 +99,10 @@ void Logger_File::write(int /*level*/, const char *logname, const char *message)
void Logger_File::setFilename(const char* filename)
{
closeFile();
m_filename = strDup(filename);
m_filename[0] = '\0';
if (strlen(filename) >= sizeof(filename))
return;
strcpy(m_filename, filename);
}

void Logger_File::setFile(FILE* file)
@@ -104,13 +113,9 @@ void Logger_File::setFile(FILE* file)

void Logger_File::closeFile()
{
if (m_filename) {
if (m_file) {
fclose(m_file);
m_file = 0;
}
strFree(m_filename);
m_filename = 0;
if (m_file) {
fclose(m_file);
m_file = 0;
}
}


+ 3
- 1
common/rfb/Logger_file.h View File

@@ -22,6 +22,8 @@
#define __RFB_LOGGER_FILE_H__

#include <time.h>
#include <limits.h>

#include <rfb/Logger.h>

namespace os { class Mutex; }
@@ -42,7 +44,7 @@ namespace rfb {

protected:
void closeFile();
char* m_filename;
char m_filename[PATH_MAX];
FILE* m_file;
time_t m_lastLogTime;
os::Mutex* mutex;

+ 0
- 1
common/rfb/Logger_syslog.cxx View File

@@ -26,7 +26,6 @@
#include <string.h>
#include <syslog.h>

#include <rfb/util.h>
#include <rfb/Logger_syslog.h>
#include <rfb/LogWriter.h>


+ 10
- 11
common/rfb/Palette.h View File

@@ -22,8 +22,7 @@

#include <assert.h>
#include <string.h>

#include <rdr/types.h>
#include <stdint.h>

namespace rfb {
class Palette {
@@ -35,13 +34,13 @@ namespace rfb {

void clear() { numColours = 0; memset(hash, 0, sizeof(hash)); }

inline bool insert(rdr::U32 colour, int numPixels);
inline unsigned char lookup(rdr::U32 colour) const;
inline rdr::U32 getColour(unsigned char index) const;
inline bool insert(uint32_t colour, int numPixels);
inline unsigned char lookup(uint32_t colour) const;
inline uint32_t getColour(unsigned char index) const;
inline int getCount(unsigned char index) const;

protected:
inline unsigned char genHash(rdr::U32 colour) const;
inline unsigned char genHash(uint32_t colour) const;

protected:
int numColours;
@@ -49,7 +48,7 @@ namespace rfb {
struct PaletteListNode {
PaletteListNode *next;
unsigned char idx;
rdr::U32 colour;
uint32_t colour;
};

struct PaletteEntry {
@@ -67,7 +66,7 @@ namespace rfb {
};
}

inline bool rfb::Palette::insert(rdr::U32 colour, int numPixels)
inline bool rfb::Palette::insert(uint32_t colour, int numPixels)
{
PaletteListNode* pnode;
PaletteListNode* prev_pnode;
@@ -145,7 +144,7 @@ inline bool rfb::Palette::insert(rdr::U32 colour, int numPixels)
return true;
}

inline unsigned char rfb::Palette::lookup(rdr::U32 colour) const
inline unsigned char rfb::Palette::lookup(uint32_t colour) const
{
unsigned char hash_key;
PaletteListNode* pnode;
@@ -165,7 +164,7 @@ inline unsigned char rfb::Palette::lookup(rdr::U32 colour) const
return 0;
}

inline rdr::U32 rfb::Palette::getColour(unsigned char index) const
inline uint32_t rfb::Palette::getColour(unsigned char index) const
{
return entry[index].listNode->colour;
}
@@ -175,7 +174,7 @@ inline int rfb::Palette::getCount(unsigned char index) const
return entry[index].numPixels;
}

inline unsigned char rfb::Palette::genHash(rdr::U32 colour) const
inline unsigned char rfb::Palette::genHash(uint32_t colour) const
{
unsigned char hash_key;


+ 0
- 47
common/rfb/Password.h View File

@@ -1,47 +0,0 @@
/* 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.
*/
#ifndef __RFB_PASSWORD_H__
#define __RFB_PASSWORD_H__

#include <rfb/util.h>

namespace rfb {

class ObfuscatedPasswd;

class PlainPasswd : public CharArray {
public:
PlainPasswd();
PlainPasswd(char* pwd);
PlainPasswd(size_t len);
PlainPasswd(const ObfuscatedPasswd& obfPwd);
~PlainPasswd();
void replaceBuf(char* b);
};

class ObfuscatedPasswd : public CharArray {
public:
ObfuscatedPasswd();
ObfuscatedPasswd(size_t l);
ObfuscatedPasswd(const PlainPasswd& plainPwd);
~ObfuscatedPasswd();
size_t length;
};

}
#endif

+ 28
- 26
common/rfb/PixelBuffer.cxx View File

@@ -26,6 +26,8 @@
#include <config.h>
#endif

#include <string.h>

#include <rfb/Exception.h>
#include <rfb/LogWriter.h>
#include <rfb/PixelBuffer.h>
@@ -63,10 +65,10 @@ void
PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) const
{
int inStride;
const U8* data;
const uint8_t* data;
int bytesPerPixel, inBytesPerRow, outBytesPerRow, bytesPerMemCpy;
U8* imageBufPos;
const U8* end;
uint8_t* imageBufPos;
const uint8_t* end;

if (!r.enclosed_by(getRect()))
throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d",
@@ -83,7 +85,7 @@ PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) const
outBytesPerRow = outStride * bytesPerPixel;
bytesPerMemCpy = r.width() * bytesPerPixel;

imageBufPos = (U8*)imageBuf;
imageBufPos = (uint8_t*)imageBuf;
end = data + (inBytesPerRow * r.height());

while (data < end) {
@@ -96,10 +98,10 @@ PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) const
void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf,
const Rect& r, int stride) const
{
const rdr::U8* srcBuffer;
const uint8_t* srcBuffer;
int srcStride;

if (format.equal(pf)) {
if (format == pf) {
getImage(imageBuf, r, stride);
return;
}
@@ -114,8 +116,8 @@ void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf,

srcBuffer = getBuffer(r, &srcStride);

pf.bufferFromBuffer((U8*)imageBuf, format, srcBuffer, r.width(), r.height(),
stride, srcStride);
pf.bufferFromBuffer((uint8_t*)imageBuf, format, srcBuffer,
r.width(), r.height(), stride, srcStride);
}

void PixelBuffer::setSize(int width, int height)
@@ -148,7 +150,7 @@ ModifiablePixelBuffer::~ModifiablePixelBuffer()
void ModifiablePixelBuffer::fillRect(const Rect& r, const void* pix)
{
int stride;
U8 *buf;
uint8_t *buf;
int w, h, b;

if (!r.enclosed_by(getRect()))
@@ -166,11 +168,11 @@ void ModifiablePixelBuffer::fillRect(const Rect& r, const void* pix)

if (b == 1) {
while (h--) {
memset(buf, *(const U8*)pix, w);
memset(buf, *(const uint8_t*)pix, w);
buf += stride * b;
}
} else {
U8 *start;
uint8_t *start;
int w1;

start = buf;
@@ -195,11 +197,11 @@ void ModifiablePixelBuffer::fillRect(const Rect& r, const void* pix)
void ModifiablePixelBuffer::imageRect(const Rect& r,
const void* pixels, int srcStride)
{
U8* dest;
uint8_t* dest;
int destStride;
int bytesPerPixel, bytesPerDestRow, bytesPerSrcRow, bytesPerFill;
const U8* src;
U8* end;
const uint8_t* src;
uint8_t* end;

if (!r.enclosed_by(getRect()))
throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
@@ -217,7 +219,7 @@ void ModifiablePixelBuffer::imageRect(const Rect& r,
bytesPerSrcRow = bytesPerPixel * srcStride;
bytesPerFill = bytesPerPixel * r.width();

src = (const U8*)pixels;
src = (const uint8_t*)pixels;
end = dest + (bytesPerDestRow * r.height());

while (dest < end) {
@@ -234,8 +236,8 @@ void ModifiablePixelBuffer::copyRect(const Rect &rect,
{
int srcStride, dstStride;
int bytesPerPixel;
const U8* srcData;
U8* dstData;
const uint8_t* srcData;
uint8_t* dstData;

Rect drect, srect;

@@ -290,15 +292,15 @@ void ModifiablePixelBuffer::copyRect(const Rect &rect,
void ModifiablePixelBuffer::fillRect(const PixelFormat& pf, const Rect &dest,
const void* pix)
{
rdr::U8 buf[4];
format.bufferFromBuffer(buf, pf, (const rdr::U8*)pix, 1);
uint8_t buf[4];
format.bufferFromBuffer(buf, pf, (const uint8_t*)pix, 1);
fillRect(dest, buf);
}

void ModifiablePixelBuffer::imageRect(const PixelFormat& pf, const Rect &dest,
const void* pixels, int stride)
{
rdr::U8* dstBuffer;
uint8_t* dstBuffer;
int dstStride;

if (!dest.enclosed_by(getRect()))
@@ -310,7 +312,7 @@ void ModifiablePixelBuffer::imageRect(const PixelFormat& pf, const Rect &dest,
stride = dest.width();

dstBuffer = getBufferRW(dest, &dstStride);
format.bufferFromBuffer(dstBuffer, pf, (const rdr::U8*)pixels,
format.bufferFromBuffer(dstBuffer, pf, (const uint8_t*)pixels,
dest.width(), dest.height(),
dstStride, stride);
commitBufferRW(dest);
@@ -319,7 +321,7 @@ void ModifiablePixelBuffer::imageRect(const PixelFormat& pf, const Rect &dest,
// -=- Simple pixel buffer with a continuous block of memory

FullFramePixelBuffer::FullFramePixelBuffer(const PixelFormat& pf, int w, int h,
rdr::U8* data_, int stride_)
uint8_t* data_, int stride_)
: ModifiablePixelBuffer(pf, w, h), data(data_), stride(stride_)
{
}
@@ -328,7 +330,7 @@ FullFramePixelBuffer::FullFramePixelBuffer() : data(0) {}

FullFramePixelBuffer::~FullFramePixelBuffer() {}

rdr::U8* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride_)
uint8_t* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride_)
{
if (!r.enclosed_by(getRect()))
throw rfb::Exception("Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d",
@@ -343,7 +345,7 @@ void FullFramePixelBuffer::commitBufferRW(const Rect& /*r*/)
{
}

const rdr::U8* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) const
const uint8_t* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) const
{
if (!r.enclosed_by(getRect()))
throw rfb::Exception("Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d",
@@ -355,7 +357,7 @@ const rdr::U8* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) cons
}

void FullFramePixelBuffer::setBuffer(int width, int height,
rdr::U8* data_, int stride_)
uint8_t* data_, int stride_)
{
if ((width < 0) || (width > maxPixelBufferWidth))
throw rfb::Exception("Invalid PixelBuffer width of %d pixels requested", width);
@@ -415,7 +417,7 @@ void ManagedPixelBuffer::setSize(int w, int h)
datasize = 0;
}
if (new_datasize) {
data_ = new U8[new_datasize];
data_ = new uint8_t[new_datasize];
datasize = new_datasize;
}
}

+ 8
- 10
common/rfb/PixelBuffer.h View File

@@ -27,8 +27,6 @@

#include <rfb/PixelFormat.h>
#include <rfb/Rect.h>
#include <rfb/Pixel.h>
#include <rfb/util.h>

namespace rfb {

@@ -66,7 +64,7 @@ namespace rfb {
// Get a pointer into the buffer
// The pointer is to the top-left pixel of the specified Rect.
// The buffer stride (in pixels) is returned.
virtual const rdr::U8* getBuffer(const Rect& r, int* stride) const = 0;
virtual const uint8_t* getBuffer(const Rect& r, int* stride) const = 0;

// Get pixel data for a given part of the buffer
// Data is copied into the supplied buffer, with the specified
@@ -112,7 +110,7 @@ namespace rfb {
// Get a writeable pointer into the buffer
// Like getBuffer(), the pointer is to the top-left pixel of the
// specified Rect and the stride in pixels is returned.
virtual rdr::U8* getBufferRW(const Rect& r, int* stride) = 0;
virtual uint8_t* getBufferRW(const Rect& r, int* stride) = 0;
// Commit the modified contents
// Ensures that the changes to the specified Rect is properly
// stored away and any temporary buffers are freed. The Rect given
@@ -149,23 +147,23 @@ namespace rfb {
class FullFramePixelBuffer : public ModifiablePixelBuffer {
public:
FullFramePixelBuffer(const PixelFormat& pf, int width, int height,
rdr::U8* data_, int stride);
uint8_t* data_, int stride);
virtual ~FullFramePixelBuffer();

public:
virtual const rdr::U8* getBuffer(const Rect& r, int* stride) const;
virtual rdr::U8* getBufferRW(const Rect& r, int* stride);
virtual const uint8_t* getBuffer(const Rect& r, int* stride) const;
virtual uint8_t* getBufferRW(const Rect& r, int* stride);
virtual void commitBufferRW(const Rect& r);

protected:
FullFramePixelBuffer();
virtual void setBuffer(int width, int height, rdr::U8* data, int stride);
virtual void setBuffer(int width, int height, uint8_t* data, int stride);

private:
virtual void setSize(int w, int h);

private:
rdr::U8* data;
uint8_t* data;
int stride;
};

@@ -183,7 +181,7 @@ namespace rfb {
virtual void setSize(int w, int h);

private:
rdr::U8* data_; // Mirrors FullFramePixelBuffer::data
uint8_t* data_; // Mirrors FullFramePixelBuffer::data
unsigned long datasize;
};


+ 165
- 69
common/rfb/PixelFormat.cxx View File

@@ -1,6 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
* Copyright 2009-2014 Pierre Ossman for Cendio AB
* Copyright 2009-2022 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
@@ -30,7 +30,6 @@
#include <rdr/OutStream.h>
#include <rfb/Exception.h>
#include <rfb/PixelFormat.h>
#include <rfb/util.h>

#ifdef _WIN32
#define strcasecmp _stricmp
@@ -38,8 +37,8 @@

using namespace rfb;

rdr::U8 PixelFormat::upconvTable[256*8];
rdr::U8 PixelFormat::downconvTable[256*8];
uint8_t PixelFormat::upconvTable[256*8];
uint8_t PixelFormat::downconvTable[256*8];

class PixelFormat::Init {
public:
@@ -59,8 +58,8 @@ PixelFormat::Init::Init()

for (bits = 1;bits <= 8;bits++) {
int i, maxVal;
rdr::U8 *subUpTable;
rdr::U8 *subDownTable;
uint8_t *subUpTable;
uint8_t *subDownTable;

maxVal = (1 << bits) - 1;
subUpTable = &upconvTable[(bits-1)*256];
@@ -100,7 +99,7 @@ PixelFormat::PixelFormat()
updateState();
}

bool PixelFormat::equal(const PixelFormat& other) const
bool PixelFormat::operator==(const PixelFormat& other) const
{
if (bpp != other.bpp || depth != other.depth)
return false;
@@ -149,6 +148,11 @@ bool PixelFormat::equal(const PixelFormat& other) const
return true;
}

bool PixelFormat::operator!=(const PixelFormat& other) const
{
return !(*this == other);
}

void PixelFormat::read(rdr::InStream* is)
{
bpp = is->readU8();
@@ -234,17 +238,17 @@ bool PixelFormat::isLittleEndian(void) const
}


void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels) const
void PixelFormat::bufferFromRGB(uint8_t *dst, const uint8_t* src, int pixels) const
{
bufferFromRGB(dst, src, pixels, pixels, 1);
}

void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
void PixelFormat::bufferFromRGB(uint8_t *dst, const uint8_t* src,
int w, int stride, int h) const
{
if (is888()) {
// Optimised common case
rdr::U8 *r, *g, *b, *x;
uint8_t *r, *g, *b, *x;

if (bigEndian) {
r = dst + (24 - redShift)/8;
@@ -283,7 +287,7 @@ void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
int w_ = w;
while (w_--) {
Pixel p;
rdr::U8 r, g, b;
uint8_t r, g, b;

r = *(src++);
g = *(src++);
@@ -300,18 +304,18 @@ void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
}


void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels) const
void PixelFormat::rgbFromBuffer(uint8_t* dst, const uint8_t* src, int pixels) const
{
rgbFromBuffer(dst, src, pixels, pixels, 1);
}


void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src,
void PixelFormat::rgbFromBuffer(uint8_t* dst, const uint8_t* src,
int w, int stride, int h) const
{
if (is888()) {
// Optimised common case
const rdr::U8 *r, *g, *b;
const uint8_t *r, *g, *b;

if (bigEndian) {
r = src + (24 - redShift)/8;
@@ -345,7 +349,7 @@ void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src,
int w_ = w;
while (w_--) {
Pixel p;
rdr::U8 r, g, b;
uint8_t r, g, b;

p = pixelFromBuffer(src);

@@ -364,25 +368,25 @@ void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src,

Pixel PixelFormat::pixelFromPixel(const PixelFormat &srcPF, Pixel src) const
{
rdr::U16 r, g, b;
uint16_t r, g, b;
srcPF.rgbFromPixel(src, &r, &g, &b);
return pixelFromRGB(r, g, b);
}


void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF,
const rdr::U8* src, int pixels) const
void PixelFormat::bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF,
const uint8_t* src, int pixels) const
{
bufferFromBuffer(dst, srcPF, src, pixels, 1, pixels, pixels);
}

#define IS_ALIGNED(v, a) (((intptr_t)v & (a-1)) == 0)

void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF,
const rdr::U8* src, int w, int h,
void PixelFormat::bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF,
const uint8_t* src, int w, int h,
int dstStride, int srcStride) const
{
if (equal(srcPF)) {
if (*this == srcPF) {
// Trivial case
while (h--) {
memcpy(dst, src, w * bpp/8);
@@ -391,7 +395,7 @@ void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF,
}
} else if (is888() && srcPF.is888()) {
// Optimised common case A: byte shuffling (e.g. endian conversion)
rdr::U8 *d[4], *s[4];
uint8_t *d[4], *s[4];
int dstPad, srcPad;

if (bigEndian) {
@@ -442,15 +446,15 @@ void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF,
// Optimised common case B: 888 source
switch (bpp) {
case 8:
directBufferFromBufferFrom888((rdr::U8*)dst, srcPF, src,
directBufferFromBufferFrom888((uint8_t*)dst, srcPF, src,
w, h, dstStride, srcStride);
break;
case 16:
directBufferFromBufferFrom888((rdr::U16*)dst, srcPF, src,
directBufferFromBufferFrom888((uint16_t*)dst, srcPF, src,
w, h, dstStride, srcStride);
break;
case 32:
directBufferFromBufferFrom888((rdr::U32*)dst, srcPF, src,
directBufferFromBufferFrom888((uint32_t*)dst, srcPF, src,
w, h, dstStride, srcStride);
break;
}
@@ -458,15 +462,15 @@ void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF,
// Optimised common case C: 888 destination
switch (srcPF.bpp) {
case 8:
directBufferFromBufferTo888(dst, srcPF, (rdr::U8*)src,
directBufferFromBufferTo888(dst, srcPF, (uint8_t*)src,
w, h, dstStride, srcStride);
break;
case 16:
directBufferFromBufferTo888(dst, srcPF, (rdr::U16*)src,
directBufferFromBufferTo888(dst, srcPF, (uint16_t*)src,
w, h, dstStride, srcStride);
break;
case 32:
directBufferFromBufferTo888(dst, srcPF, (rdr::U32*)src,
directBufferFromBufferTo888(dst, srcPF, (uint32_t*)src,
w, h, dstStride, srcStride);
break;
}
@@ -478,7 +482,7 @@ void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF,
int w_ = w;
while (w_--) {
Pixel p;
rdr::U8 r, g, b;
uint8_t r, g, b;

p = srcPF.pixelFromBuffer(src);
srcPF.rgbFromPixel(p, &r, &g, &b);
@@ -579,8 +583,8 @@ bool PixelFormat::parse(const char* str)
depth = bits1 + bits2 + bits3;
bpp = depth <= 8 ? 8 : ((depth <= 16) ? 16 : 32);
trueColour = true;
rdr::U32 endianTest = 1;
bigEndian = (*(rdr::U8*)&endianTest == 0);
uint32_t endianTest = 1;
bigEndian = (*(uint8_t*)&endianTest == 0);

greenShift = bits3;
greenMax = (1 << bits2) - 1;
@@ -607,7 +611,7 @@ bool PixelFormat::parse(const char* str)
}


static int bits(rdr::U16 value)
static int bits(uint16_t value)
{
int bits;

@@ -710,41 +714,133 @@ bool PixelFormat::isSane(void)
return true;
}

// Preprocessor generated, optimised methods

#define INBPP 8
#define OUTBPP 8
#include "PixelFormatBPP.cxx"
#undef OUTBPP
#define OUTBPP 16
#include "PixelFormatBPP.cxx"
#undef OUTBPP
#define OUTBPP 32
#include "PixelFormatBPP.cxx"
#undef OUTBPP
#undef INBPP

#define INBPP 16
#define OUTBPP 8
#include "PixelFormatBPP.cxx"
#undef OUTBPP
#define OUTBPP 16
#include "PixelFormatBPP.cxx"
#undef OUTBPP
#define OUTBPP 32
#include "PixelFormatBPP.cxx"
#undef OUTBPP
#undef INBPP

#define INBPP 32
#define OUTBPP 8
#include "PixelFormatBPP.cxx"
#undef OUTBPP
#define OUTBPP 16
#include "PixelFormatBPP.cxx"
#undef OUTBPP
#define OUTBPP 32
#include "PixelFormatBPP.cxx"
#undef OUTBPP
#undef INBPP
static inline uint8_t swap(uint8_t n)
{
return n;
}

static inline uint16_t swap(uint16_t n)
{
return (((n) & 0xff) << 8) | (((n) >> 8) & 0xff);
}

static inline uint32_t swap(uint32_t n)
{
return ((n) >> 24) | (((n) & 0x00ff0000) >> 8) |
(((n) & 0x0000ff00) << 8) | ((n) << 24);
}

template<class T>
void PixelFormat::directBufferFromBufferFrom888(T* dst,
const PixelFormat &srcPF,
const uint8_t* src,
int w, int h,
int dstStride,
int srcStride) const
{
const uint8_t *r, *g, *b;
int dstPad, srcPad;

const uint8_t *redDownTable, *greenDownTable, *blueDownTable;

redDownTable = &downconvTable[(redBits-1)*256];
greenDownTable = &downconvTable[(greenBits-1)*256];
blueDownTable = &downconvTable[(blueBits-1)*256];

if (srcPF.bigEndian) {
r = src + (24 - srcPF.redShift)/8;
g = src + (24 - srcPF.greenShift)/8;
b = src + (24 - srcPF.blueShift)/8;
} else {
r = src + srcPF.redShift/8;
g = src + srcPF.greenShift/8;
b = src + srcPF.blueShift/8;
}

dstPad = (dstStride - w);
srcPad = (srcStride - w) * 4;
while (h--) {
int w_ = w;
while (w_--) {
T d;

d = redDownTable[*r] << redShift;
d |= greenDownTable[*g] << greenShift;
d |= blueDownTable[*b] << blueShift;

if (endianMismatch)
d = swap(d);

*dst = d;

dst++;
r += 4;
g += 4;
b += 4;
}
dst += dstPad;
r += srcPad;
g += srcPad;
b += srcPad;
}
}

template<class T>
void PixelFormat::directBufferFromBufferTo888(uint8_t* dst,
const PixelFormat &srcPF,
const T* src,
int w, int h,
int dstStride,
int srcStride) const
{
uint8_t *r, *g, *b, *x;
int dstPad, srcPad;

const uint8_t *redUpTable, *greenUpTable, *blueUpTable;

redUpTable = &upconvTable[(srcPF.redBits-1)*256];
greenUpTable = &upconvTable[(srcPF.greenBits-1)*256];
blueUpTable = &upconvTable[(srcPF.blueBits-1)*256];

if (bigEndian) {
r = dst + (24 - redShift)/8;
g = dst + (24 - greenShift)/8;
b = dst + (24 - blueShift)/8;
x = dst + (24 - (48 - redShift - greenShift - blueShift))/8;
} else {
r = dst + redShift/8;
g = dst + greenShift/8;
b = dst + blueShift/8;
x = dst + (48 - redShift - greenShift - blueShift)/8;
}

dstPad = (dstStride - w) * 4;
srcPad = (srcStride - w);
while (h--) {
int w_ = w;
while (w_--) {
T s;

s = *src;

if (srcPF.endianMismatch)
s = swap(s);

*r = redUpTable[(s >> srcPF.redShift) & 0xff];
*g = greenUpTable[(s >> srcPF.greenShift) & 0xff];
*b = blueUpTable[(s >> srcPF.blueShift) & 0xff];
*x = 0;

r += 4;
g += 4;
b += 4;
x += 4;
src++;
}
r += dstPad;
g += dstPad;
b += dstPad;
x += dstPad;
src += srcPad;
}
}

+ 31
- 40
common/rfb/PixelFormat.h View File

@@ -1,6 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
* Copyright 2009-2014 Pierre Ossman for Cendio AB
* Copyright 2009-2022 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
@@ -34,12 +34,14 @@
#ifndef __RFB_PIXELFORMAT_H__
#define __RFB_PIXELFORMAT_H__

#include <rfb/Pixel.h>
#include <stdint.h>

namespace rdr { class InStream; class OutStream; }

namespace rfb {

typedef uint32_t Pixel; // must be big enough to hold any pixel value

class PixelFormat {
public:
PixelFormat(int b, int d, bool e, bool t,
@@ -49,7 +51,8 @@ namespace rfb {
// Checks if the formats have identical buffer representation.
// They might still have different pixel representation, endianness
// or true colour state.
bool equal(const PixelFormat& other) const;
bool operator==(const PixelFormat& other) const;
bool operator!=(const PixelFormat& other) const;

void read(rdr::InStream* is);
void write(rdr::OutStream* os) const;
@@ -58,29 +61,29 @@ namespace rfb {
bool isBigEndian(void) const;
bool isLittleEndian(void) const;

inline Pixel pixelFromBuffer(const rdr::U8* buffer) const;
inline void bufferFromPixel(rdr::U8* buffer, Pixel pixel) const;
inline Pixel pixelFromBuffer(const uint8_t* buffer) const;
inline void bufferFromPixel(uint8_t* buffer, Pixel pixel) const;

inline Pixel pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue) const;
inline Pixel pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue) const;
inline Pixel pixelFromRGB(uint16_t red, uint16_t green, uint16_t blue) const;
inline Pixel pixelFromRGB(uint8_t red, uint8_t green, uint8_t blue) const;

void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels) const;
void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
void bufferFromRGB(uint8_t *dst, const uint8_t* src, int pixels) const;
void bufferFromRGB(uint8_t *dst, const uint8_t* src,
int w, int stride, int h) const;

inline void rgbFromPixel(Pixel pix, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const;
inline void rgbFromPixel(Pixel pix, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const;
inline void rgbFromPixel(Pixel pix, uint16_t *r, uint16_t *g, uint16_t *b) const;
inline void rgbFromPixel(Pixel pix, uint8_t *r, uint8_t *g, uint8_t *b) const;

void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels) const;
void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src,
void rgbFromBuffer(uint8_t* dst, const uint8_t* src, int pixels) const;
void rgbFromBuffer(uint8_t* dst, const uint8_t* src,
int w, int stride, int h) const;

Pixel pixelFromPixel(const PixelFormat &srcPF, Pixel src) const;

void bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF,
const rdr::U8* src, int pixels) const;
void bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF,
const rdr::U8* src, int w, int h,
void bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF,
const uint8_t* src, int pixels) const;
void bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF,
const uint8_t* src, int w, int h,
int dstStride, int srcStride) const;

void print(char* str, int len) const;
@@ -91,26 +94,14 @@ namespace rfb {
bool isSane(void);

private:
// Preprocessor generated, optimised methods

void directBufferFromBufferFrom888(rdr::U8* dst, const PixelFormat &srcPF,
const rdr::U8* src, int w, int h,
int dstStride, int srcStride) const;
void directBufferFromBufferFrom888(rdr::U16* dst, const PixelFormat &srcPF,
const rdr::U8* src, int w, int h,
int dstStride, int srcStride) const;
void directBufferFromBufferFrom888(rdr::U32* dst, const PixelFormat &srcPF,
const rdr::U8* src, int w, int h,
// Templated, optimised methods
template<class T>
void directBufferFromBufferFrom888(T* dst, const PixelFormat &srcPF,
const uint8_t* src, int w, int h,
int dstStride, int srcStride) const;

void directBufferFromBufferTo888(rdr::U8* dst, const PixelFormat &srcPF,
const rdr::U8* src, int w, int h,
int dstStride, int srcStride) const;
void directBufferFromBufferTo888(rdr::U8* dst, const PixelFormat &srcPF,
const rdr::U16* src, int w, int h,
int dstStride, int srcStride) const;
void directBufferFromBufferTo888(rdr::U8* dst, const PixelFormat &srcPF,
const rdr::U32* src, int w, int h,
template<class T>
void directBufferFromBufferTo888(uint8_t* dst, const PixelFormat &srcPF,
const T* src, int w, int h,
int dstStride, int srcStride) const;

public:
@@ -136,18 +127,18 @@ namespace rfb {
int maxBits, minBits;
bool endianMismatch;

static rdr::U8 upconvTable[256*8];
static rdr::U8 downconvTable[256*8];
static uint8_t upconvTable[256*8];
static uint8_t downconvTable[256*8];

class Init;
friend class Init;
static Init _init;

/* Only for testing this class */
friend void makePixel(const rfb::PixelFormat &, rdr::U8 *);
friend void makePixel(const rfb::PixelFormat &, uint8_t *);
friend bool verifyPixel(const rfb::PixelFormat &,
const rfb::PixelFormat &,
const rdr::U8 *);
const uint8_t *);
};
}


+ 8
- 8
common/rfb/PixelFormat.inl View File

@@ -19,7 +19,7 @@
namespace rfb {


inline Pixel PixelFormat::pixelFromBuffer(const rdr::U8* buffer) const
inline Pixel PixelFormat::pixelFromBuffer(const uint8_t* buffer) const
{
Pixel p;

@@ -52,7 +52,7 @@ inline Pixel PixelFormat::pixelFromBuffer(const rdr::U8* buffer) const
}


inline void PixelFormat::bufferFromPixel(rdr::U8* buffer, Pixel p) const
inline void PixelFormat::bufferFromPixel(uint8_t* buffer, Pixel p) const
{
if (bigEndian) {
switch (bpp) {
@@ -79,7 +79,7 @@ inline void PixelFormat::bufferFromPixel(rdr::U8* buffer, Pixel p) const
}


inline Pixel PixelFormat::pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue) const
inline Pixel PixelFormat::pixelFromRGB(uint16_t red, uint16_t green, uint16_t blue) const
{
Pixel p;

@@ -91,7 +91,7 @@ inline Pixel PixelFormat::pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 bl
}


inline Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue) const
inline Pixel PixelFormat::pixelFromRGB(uint8_t red, uint8_t green, uint8_t blue) const
{
Pixel p;

@@ -103,9 +103,9 @@ inline Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue)
}


inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const
inline void PixelFormat::rgbFromPixel(Pixel p, uint16_t *r, uint16_t *g, uint16_t *b) const
{
rdr::U8 _r, _g, _b;
uint8_t _r, _g, _b;

_r = p >> redShift;
_g = p >> greenShift;
@@ -121,9 +121,9 @@ inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U16 *r, rdr::U16 *g, rdr::U1
}


inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const
inline void PixelFormat::rgbFromPixel(Pixel p, uint8_t *r, uint8_t *g, uint8_t *b) const
{
rdr::U8 _r, _g, _b;
uint8_t _r, _g, _b;

_r = p >> redShift;
_g = p >> greenShift;

+ 0
- 0
common/rfb/PixelFormatBPP.cxx View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save