@@ -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(); |
@@ -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; | |||
} |
@@ -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; | |||
}; |
@@ -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(); | |||
} | |||
@@ -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 { |
@@ -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); | |||
} | |||
@@ -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 */ |
@@ -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 |
@@ -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]; | |||
}; | |||
} | |||
@@ -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; |
@@ -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]; | |||
}; | |||
}; | |||
@@ -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; | |||
} | |||
@@ -50,7 +50,7 @@ namespace rdr { | |||
private: | |||
size_t bufSize; | |||
size_t offset; | |||
U8* start; | |||
uint8_t* start; | |||
struct timeval lastSizeCheck; | |||
size_t peakUsage; |
@@ -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; |
@@ -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); |
@@ -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> |
@@ -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(); | |||
@@ -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); | |||
@@ -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); |
@@ -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); |
@@ -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(); | |||
@@ -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; |
@@ -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(); |
@@ -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; | |||
}; | |||
} |
@@ -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; | |||
}; | |||
@@ -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; | |||
}; | |||
} |
@@ -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; | |||
}; |
@@ -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; |
@@ -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; | |||
@@ -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; |
@@ -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; | |||
@@ -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; |
@@ -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); |
@@ -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 |
@@ -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); | |||
} |
@@ -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; | |||
}; | |||
@@ -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); |
@@ -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; | |||
}; |
@@ -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) |
@@ -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*/) | |||
{ | |||
} |
@@ -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; | |||
}; |
@@ -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; |
@@ -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; |
@@ -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; |
@@ -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); |
@@ -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(); | |||
} |
@@ -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; |
@@ -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; | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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; |
@@ -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"); | |||
@@ -58,8 +58,6 @@ namespace rfb { | |||
gnutls_certificate_credentials_t cert_cred; | |||
bool anon; | |||
char *cafile, *crlfile; | |||
rdr::InStream* tlsis; | |||
rdr::OutStream* tlsos; | |||
@@ -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(); | |||
@@ -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 |
@@ -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); |
@@ -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; | |||
@@ -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,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; |
@@ -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; | |||
} |
@@ -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; | |||
}; | |||
@@ -38,6 +38,7 @@ | |||
#endif | |||
#include <assert.h> | |||
#include <string.h> | |||
#include <sys/time.h> | |||
#ifdef __linux__ |
@@ -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); |
@@ -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); | |||
@@ -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) |
@@ -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; | |||
} |
@@ -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; |
@@ -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; | |||
} |
@@ -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; | |||
} | |||
@@ -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 |
@@ -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) |
@@ -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: |
@@ -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) | |||
{ |
@@ -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; | |||
}; | |||
} | |||
@@ -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; |
@@ -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); | |||
}; | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} |
@@ -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 |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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 |
@@ -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; |
@@ -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*/) { } |
@@ -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; | |||
} | |||
@@ -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); | |||
@@ -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); | |||
@@ -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: |
@@ -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); |
@@ -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; | |||
}; | |||
@@ -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, ¶ms.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; |
@@ -28,7 +28,6 @@ | |||
#include <rfb/Logger.h> | |||
#include <rfb/LogWriter.h> | |||
#include <rfb/util.h> | |||
using namespace rfb; | |||
@@ -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; | |||
} | |||
} | |||
@@ -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; |
@@ -26,7 +26,6 @@ | |||
#include <string.h> | |||
#include <syslog.h> | |||
#include <rfb/util.h> | |||
#include <rfb/Logger_syslog.h> | |||
#include <rfb/LogWriter.h> | |||
@@ -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; | |||
@@ -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 |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
}; | |||
@@ -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; | |||
} | |||
} |
@@ -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 *); | |||
}; | |||
} | |||
@@ -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; |