Initial commit

This commit is contained in:
matt
2020-09-20 12:16:44 +00:00
parent 09a4460ddb
commit 408c005d3e
839 changed files with 190481 additions and 0 deletions

30
common/rdr/CMakeLists.txt Normal file
View File

@@ -0,0 +1,30 @@
include_directories(${CMAKE_SOURCE_DIR}/common ${ZLIB_INCLUDE_DIRS})
add_library(rdr STATIC
Exception.cxx
FdInStream.cxx
FdOutStream.cxx
FileInStream.cxx
HexInStream.cxx
HexOutStream.cxx
InStream.cxx
RandomStream.cxx
TLSException.cxx
TLSInStream.cxx
TLSOutStream.cxx
ZlibInStream.cxx
ZlibOutStream.cxx)
set(RDR_LIBRARIES ${ZLIB_LIBRARIES} os)
if(GNUTLS_FOUND)
set(RDR_LIBRARIES ${RDR_LIBRARIES} ${GNUTLS_LIBRARIES})
endif()
if(WIN32)
set(RDR_LIBRARIES ${RDR_LIBRARIES} ws2_32)
endif()
target_link_libraries(rdr ${RDR_LIBRARIES})
if(UNIX)
libtool_create_control_file(rdr)
endif()

99
common/rdr/Exception.cxx Normal file
View File

@@ -0,0 +1,99 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2004 Red Hat Inc.
* Copyright (C) 2010 TigerVNC Team
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdarg.h>
#include <rdr/Exception.h>
#include <rdr/TLSException.h>
#ifdef _WIN32
#include <tchar.h>
#include <winsock2.h>
#include <windows.h>
#endif
#include <string.h>
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
#endif
using namespace rdr;
Exception::Exception(const char *format, ...) {
va_list ap;
va_start(ap, format);
(void) vsnprintf(str_, len, format, ap);
va_end(ap);
}
SystemException::SystemException(const char* s, int err_)
: Exception("%s", s), err(err_)
{
strncat(str_, ": ", len-1-strlen(str_));
#ifdef _WIN32
// Windows error messages are crap, so use unix ones for common errors.
const char* msg = 0;
switch (err) {
case WSAECONNREFUSED: msg = "Connection refused"; break;
case WSAETIMEDOUT: msg = "Connection timed out"; break;
case WSAECONNRESET: msg = "Connection reset by peer"; break;
case WSAECONNABORTED: msg = "Connection aborted"; break;
}
if (msg) {
strncat(str_, msg, len-1-strlen(str_));
} else {
#ifdef UNICODE
WCHAR* tmsg = new WCHAR[len-strlen(str_)];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0, err, 0, tmsg, len-1-strlen(str_), 0);
WideCharToMultiByte(CP_ACP, 0, tmsg, wcslen(tmsg)+1,
str_+strlen(str_), len-strlen(str_), 0, 0);
delete [] tmsg;
#else
char* currStr = str_+strlen(str_);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0, err, 0, currStr, len-1-strlen(str_), 0);
#endif
int l = strlen(str_);
if ((l >= 2) && (str_[l-2] == '\r') && (str_[l-1] == '\n'))
str_[l-2] = 0;
}
#else
strncat(str_, strerror(err), len-1-strlen(str_));
#endif
strncat(str_, " (", len-1-strlen(str_));
char buf[20];
#ifdef WIN32
if (err < 0)
sprintf(buf, "%x", err);
else
#endif
sprintf(buf,"%d",err);
strncat(str_, buf, len-1-strlen(str_));
strncat(str_, ")", len-1-strlen(str_));
}

55
common/rdr/Exception.h Normal file
View File

@@ -0,0 +1,55 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2004 Red Hat Inc.
* Copyright (C) 2010 TigerVNC Team
*
* 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_EXCEPTION_H__
#define __RDR_EXCEPTION_H__
#ifdef __GNUC__
# define __printf_attr(a, b) __attribute__((__format__ (__printf__, a, b)))
#else
# define __printf_attr(a, b)
#endif // __GNUC__
namespace rdr {
struct Exception {
enum { len = 256 };
char str_[len];
Exception(const char *format = 0, ...) __printf_attr(2, 3);
virtual ~Exception() {}
virtual const char* str() const { return str_; }
};
struct SystemException : public Exception {
int err;
SystemException(const char* s, int err_);
};
struct TimedOut : public Exception {
TimedOut() : Exception("Timed out") {}
};
struct EndOfStream : public Exception {
EndOfStream() : Exception("End of stream") {}
};
}
#endif

260
common/rdr/FdInStream.cxx Normal file
View File

@@ -0,0 +1,260 @@
/* 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#ifdef _WIN32
#include <winsock2.h>
#define close closesocket
#undef errno
#define errno WSAGetLastError()
#include <os/winerrno.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
#ifndef vncmin
#define vncmin(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef vncmax
#define vncmax(a,b) (((a) > (b)) ? (a) : (b))
#endif
/* Old systems have select() in sys/time.h */
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <rdr/FdInStream.h>
#include <rdr/Exception.h>
using namespace rdr;
enum { DEFAULT_BUF_SIZE = 8192,
MIN_BULK_SIZE = 1024 };
FdInStream::FdInStream(int fd_, int timeoutms_, int bufSize_,
bool closeWhenDone_)
: fd(fd_), closeWhenDone(closeWhenDone_),
timeoutms(timeoutms_), blockCallback(0),
timing(false), timeWaitedIn100us(5), timedKbits(0),
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
{
ptr = end = start = new U8[bufSize];
}
FdInStream::FdInStream(int fd_, FdInStreamBlockCallback* blockCallback_,
int bufSize_)
: fd(fd_), timeoutms(0), blockCallback(blockCallback_),
timing(false), timeWaitedIn100us(5), timedKbits(0),
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
{
ptr = end = start = new U8[bufSize];
}
FdInStream::~FdInStream()
{
delete [] start;
if (closeWhenDone) close(fd);
}
void FdInStream::setTimeout(int timeoutms_) {
timeoutms = timeoutms_;
}
void FdInStream::setBlockCallback(FdInStreamBlockCallback* blockCallback_)
{
blockCallback = blockCallback_;
timeoutms = 0;
}
int FdInStream::pos()
{
return offset + ptr - start;
}
void FdInStream::readBytes(void* data, int length)
{
if (length < MIN_BULK_SIZE) {
InStream::readBytes(data, length);
return;
}
U8* dataPtr = (U8*)data;
int n = end - ptr;
if (n > length) n = length;
memcpy(dataPtr, ptr, n);
dataPtr += n;
length -= n;
ptr += n;
while (length > 0) {
n = readWithTimeoutOrCallback(dataPtr, length);
dataPtr += n;
length -= n;
offset += n;
}
}
int FdInStream::overrun(int itemSize, int nItems, bool wait)
{
if (itemSize > bufSize)
throw Exception("FdInStream overrun: max itemSize exceeded");
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
offset += ptr - start;
end -= ptr - start;
ptr = start;
int bytes_to_read;
while (end < start + itemSize) {
bytes_to_read = start + bufSize - end;
if (!timing) {
// When not timing, we must be careful not to read too much
// extra data into the buffer. Otherwise, the line speed
// estimation might stay at zero for a long time: All reads
// during timing=1 can be satisfied without calling
// readWithTimeoutOrCallback. However, reading only 1 or 2 bytes
// bytes is ineffecient.
bytes_to_read = vncmin(bytes_to_read, vncmax(itemSize*nItems, 8));
}
int n = readWithTimeoutOrCallback((U8*)end, bytes_to_read, wait);
if (n == 0) return 0;
end += n;
}
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}
//
// readWithTimeoutOrCallback() reads up to the given length in bytes from the
// file descriptor into a buffer. If the wait argument is false, then zero is
// returned if no bytes can be read without blocking. Otherwise if a
// blockCallback is set, it will be called (repeatedly) instead of blocking.
// If alternatively there is a timeout set and that timeout expires, it throws
// a TimedOut exception. Otherwise it returns the number of bytes read. It
// never attempts to recv() unless select() indicates that the fd is readable -
// this means it can be used on an fd which has been set non-blocking. It also
// has to cope with the annoying possibility of both select() and recv()
// returning EINTR.
//
int FdInStream::readWithTimeoutOrCallback(void* buf, int len, bool wait)
{
struct timeval before, after;
if (timing)
gettimeofday(&before, 0);
int n;
while (true) {
do {
fd_set fds;
struct timeval tv;
struct timeval* tvp = &tv;
if (!wait) {
tv.tv_sec = tv.tv_usec = 0;
} else if (timeoutms != -1) {
tv.tv_sec = timeoutms / 1000;
tv.tv_usec = (timeoutms % 1000) * 1000;
} else {
tvp = 0;
}
FD_ZERO(&fds);
FD_SET(fd, &fds);
n = select(fd+1, &fds, 0, 0, tvp);
} while (n < 0 && errno == EINTR);
if (n > 0) break;
if (n < 0) throw SystemException("select",errno);
if (!wait) return 0;
if (!blockCallback) throw TimedOut();
blockCallback->blockCallback();
}
do {
n = ::recv(fd, (char*)buf, len, 0);
} while (n < 0 && errno == EINTR);
if (n < 0) throw SystemException("read",errno);
if (n == 0) throw EndOfStream();
if (timing) {
gettimeofday(&after, 0);
int newTimeWaited = ((after.tv_sec - before.tv_sec) * 10000 +
(after.tv_usec - before.tv_usec) / 100);
int newKbits = n * 8 / 1000;
// limit rate to between 10kbit/s and 40Mbit/s
if (newTimeWaited > newKbits*1000) newTimeWaited = newKbits*1000;
if (newTimeWaited < newKbits/4) newTimeWaited = newKbits/4;
timeWaitedIn100us += newTimeWaited;
timedKbits += newKbits;
}
return n;
}
void FdInStream::startTiming()
{
timing = true;
// Carry over up to 1s worth of previous rate for smoothing.
if (timeWaitedIn100us > 10000) {
timedKbits = timedKbits * 10000 / timeWaitedIn100us;
timeWaitedIn100us = 10000;
}
}
void FdInStream::stopTiming()
{
timing = false;
if (timeWaitedIn100us < timedKbits/2)
timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
}
unsigned int FdInStream::kbitsPerSecond()
{
// The following calculation will overflow 32-bit arithmetic if we have
// received more than about 50Mbytes (400Mbits) since we started timing, so
// it should be OK for a single RFB update.
return timedKbits * 10000 / timeWaitedIn100us;
}

78
common/rdr/FdInStream.h Normal file
View File

@@ -0,0 +1,78 @@
/* 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.
*/
//
// FdInStream streams from a file descriptor.
//
#ifndef __RDR_FDINSTREAM_H__
#define __RDR_FDINSTREAM_H__
#include <rdr/InStream.h>
namespace rdr {
class FdInStreamBlockCallback {
public:
virtual void blockCallback() = 0;
virtual ~FdInStreamBlockCallback() {}
};
class FdInStream : public InStream {
public:
FdInStream(int fd, int timeoutms=-1, int bufSize=0,
bool closeWhenDone_=false);
FdInStream(int fd, FdInStreamBlockCallback* blockCallback, int bufSize=0);
virtual ~FdInStream();
void setTimeout(int timeoutms);
void setBlockCallback(FdInStreamBlockCallback* blockCallback);
int getFd() { return fd; }
int pos();
void readBytes(void* data, int length);
void startTiming();
void stopTiming();
unsigned int kbitsPerSecond();
unsigned int timeWaited() { return timeWaitedIn100us; }
protected:
int overrun(int itemSize, int nItems, bool wait);
private:
int readWithTimeoutOrCallback(void* buf, int len, bool wait=true);
int fd;
bool closeWhenDone;
int timeoutms;
FdInStreamBlockCallback* blockCallback;
bool timing;
unsigned int timeWaitedIn100us;
unsigned int timedKbits;
int bufSize;
int offset;
U8* start;
};
} // end of namespace rdr
#endif

213
common/rdr/FdOutStream.cxx Normal file
View File

@@ -0,0 +1,213 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011 Pierre Ossman for Cendio AB
* Copyright 2017 Peter Astrand <astrand@cendio.se> 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifdef _WIN32
#include <winsock2.h>
#undef errno
#define errno WSAGetLastError()
#include <os/winerrno.h>
#else
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#endif
/* Old systems have select() in sys/time.h */
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <rdr/FdOutStream.h>
#include <rdr/Exception.h>
#include <rfb/util.h>
using namespace rdr;
enum { DEFAULT_BUF_SIZE = 16384 };
FdOutStream::FdOutStream(int fd_, bool blocking_, int timeoutms_, int bufSize_)
: fd(fd_), blocking(blocking_), timeoutms(timeoutms_),
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
{
ptr = start = sentUpTo = new U8[bufSize];
end = start + bufSize;
gettimeofday(&lastWrite, NULL);
}
FdOutStream::~FdOutStream()
{
try {
blocking = true;
flush();
} catch (Exception&) {
}
delete [] start;
}
void FdOutStream::setTimeout(int timeoutms_) {
timeoutms = timeoutms_;
}
void FdOutStream::setBlocking(bool blocking_) {
blocking = blocking_;
}
int FdOutStream::length()
{
return offset + ptr - sentUpTo;
}
int FdOutStream::bufferUsage()
{
return ptr - sentUpTo;
}
unsigned FdOutStream::getIdleTime()
{
return rfb::msSince(&lastWrite);
}
void FdOutStream::flush()
{
while (sentUpTo < ptr) {
int n = writeWithTimeout((const void*) sentUpTo,
ptr - sentUpTo,
blocking? timeoutms : 0);
// Timeout?
if (n == 0) {
// If non-blocking then we're done here
if (!blocking)
break;
throw TimedOut();
}
sentUpTo += n;
offset += n;
}
// Managed to flush everything?
if (sentUpTo == ptr)
ptr = sentUpTo = start;
}
int FdOutStream::overrun(int itemSize, int nItems)
{
if (itemSize > bufSize)
throw Exception("FdOutStream overrun: max itemSize exceeded");
// First try to get rid of the data we have
flush();
// Still not enough space?
if (itemSize > end - ptr) {
// Can we shuffle things around?
// (don't do this if it gains us less than 25%)
if ((sentUpTo - start > bufSize / 4) &&
(itemSize < bufSize - (ptr - sentUpTo))) {
memmove(start, sentUpTo, ptr - sentUpTo);
ptr = start + (ptr - sentUpTo);
sentUpTo = start;
} else {
// Have to get rid of more data, so turn off non-blocking
// for a bit...
bool realBlocking;
realBlocking = blocking;
blocking = true;
flush();
blocking = realBlocking;
}
}
// Can we fit all the items asked for?
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}
//
// writeWithTimeout() writes up to the given length in bytes from the given
// buffer to the file descriptor. If there is a timeout set and that timeout
// expires, it throws a TimedOut exception. Otherwise it returns the number of
// bytes written. It never attempts to send() unless select() indicates that
// the fd is writable - this means it can be used on an fd which has been set
// non-blocking. It also has to cope with the annoying possibility of both
// select() and send() returning EINTR.
//
int FdOutStream::writeWithTimeout(const void* data, int length, int timeoutms)
{
int n;
do {
fd_set fds;
struct timeval tv;
struct timeval* tvp = &tv;
if (timeoutms != -1) {
tv.tv_sec = timeoutms / 1000;
tv.tv_usec = (timeoutms % 1000) * 1000;
} else {
tvp = NULL;
}
FD_ZERO(&fds);
FD_SET(fd, &fds);
n = select(fd+1, 0, &fds, 0, tvp);
} while (n < 0 && errno == EINTR);
if (n < 0)
throw SystemException("select", errno);
if (n == 0)
return 0;
do {
// select only guarantees that you can write SO_SNDLOWAT without
// blocking, which is normally 1. Use MSG_DONTWAIT to avoid
// blocking, when possible.
#ifndef MSG_DONTWAIT
n = ::send(fd, (const char*)data, length, 0);
#else
n = ::send(fd, (const char*)data, length, MSG_DONTWAIT);
#endif
} while (n < 0 && (errno == EINTR));
if (n < 0)
throw SystemException("write", errno);
gettimeofday(&lastWrite, NULL);
return n;
}

66
common/rdr/FdOutStream.h Normal file
View File

@@ -0,0 +1,66 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011 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.
*/
//
// FdOutStream streams to a file descriptor.
//
#ifndef __RDR_FDOUTSTREAM_H__
#define __RDR_FDOUTSTREAM_H__
#include <sys/time.h>
#include <rdr/OutStream.h>
namespace rdr {
class FdOutStream : public OutStream {
public:
FdOutStream(int fd, bool blocking=true, int timeoutms=-1, int bufSize=0);
virtual ~FdOutStream();
void setTimeout(int timeoutms);
void setBlocking(bool blocking);
int getFd() { return fd; }
void flush();
int length();
int bufferUsage();
unsigned getIdleTime();
private:
int overrun(int itemSize, int nItems);
int writeWithTimeout(const void* data, int length, int timeoutms);
int fd;
bool blocking;
int timeoutms;
int bufSize;
int offset;
U8* start;
U8* sentUpTo;
struct timeval lastWrite;
};
}
#endif

View File

@@ -0,0 +1,87 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2013 D. R. Commander. All Rights Reserved.
* Copyright 2015 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.
*/
#include <errno.h>
#include <rdr/Exception.h>
#include <rdr/FileInStream.h>
using namespace rdr;
FileInStream::FileInStream(const char *fileName)
{
file = fopen(fileName, "rb");
if (!file)
throw SystemException("fopen", errno);
ptr = end = b;
}
FileInStream::~FileInStream(void) {
if (file) {
fclose(file);
file = NULL;
}
}
void FileInStream::reset(void) {
if (!file)
throw Exception("File is not open");
if (fseek(file, 0, SEEK_SET) != 0)
throw SystemException("fseek", errno);
ptr = end = b;
}
int FileInStream::pos()
{
if (!file)
throw Exception("File is not open");
return ftell(file) + ptr - b;
}
int FileInStream::overrun(int itemSize, int nItems, bool wait)
{
if (itemSize > (int)sizeof(b))
throw Exception("FileInStream overrun: max itemSize exceeded");
if (end - ptr != 0)
memmove(b, ptr, end - ptr);
end -= ptr - b;
ptr = b;
while (end < b + itemSize) {
size_t n = fread((U8 *)end, b + sizeof(b) - end, 1, file);
if (n == 0) {
if (ferror(file))
throw SystemException("fread", errno);
if (feof(file))
throw EndOfStream();
return 0;
}
end += b + sizeof(b) - end;
}
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}

50
common/rdr/FileInStream.h Normal file
View File

@@ -0,0 +1,50 @@
/* Copyright (C) 2013 D. R. Commander. All Rights Reserved.
* Copyright 2015 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.
*/
#ifndef __RDR_FILEINSTREAM_H__
#define __RDR_FILEINSTREAM_H__
#include <stdio.h>
#include <rdr/InStream.h>
namespace rdr {
class FileInStream : public InStream {
public:
FileInStream(const char *fileName);
~FileInStream(void);
void reset(void);
int pos();
protected:
int overrun(int itemSize, int nItems, bool wait = true);
private:
U8 b[131072];
FILE *file;
};
} // end of namespace rdr
#endif

View File

@@ -0,0 +1,52 @@
/* 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.
*/
//
// A FixedMemOutStream writes to a buffer of a fixed length.
//
#ifndef __RDR_FIXEDMEMOUTSTREAM_H__
#define __RDR_FIXEDMEMOUTSTREAM_H__
#include <rdr/OutStream.h>
#include <rdr/Exception.h>
namespace rdr {
class FixedMemOutStream : public OutStream {
public:
FixedMemOutStream(void* buf, int len) {
ptr = start = (U8*)buf;
end = start + len;
}
int length() { return ptr - start; }
void reposition(int pos) { ptr = start + pos; }
const void* data() { return (const void*)start; }
private:
int overrun(int itemSize, int nItems) { throw EndOfStream(); }
U8* start;
};
}
#endif

117
common/rdr/HexInStream.cxx Normal file
View File

@@ -0,0 +1,117 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include <rdr/HexInStream.h>
#include <rdr/Exception.h>
#include <stdlib.h>
#include <ctype.h>
using namespace rdr;
const int DEFAULT_BUF_LEN = 16384;
static inline int min(int a, int b) {return a<b ? a : b;}
HexInStream::HexInStream(InStream& is, int bufSize_)
: bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_LEN), offset(0), in_stream(is)
{
ptr = end = start = new U8[bufSize];
}
HexInStream::~HexInStream() {
delete [] start;
}
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, int* length) {
int 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(int 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;
}
int HexInStream::pos() {
return offset + ptr - start;
}
int HexInStream::overrun(int itemSize, int nItems, bool wait) {
if (itemSize > bufSize)
throw Exception("HexInStream overrun: max itemSize exceeded");
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
end -= ptr - start;
offset += ptr - start;
ptr = start;
while (end < ptr + itemSize) {
int n = in_stream.check(2, 1, wait);
if (n == 0) return 0;
const U8* iptr = in_stream.getptr();
const U8* eptr = in_stream.getend();
int length = min((eptr - iptr)/2, start + bufSize - end);
U8* optr = (U8*) end;
for (int i=0; i<length; i++) {
int v = 0;
readHexAndShift(iptr[i*2], &v);
readHexAndShift(iptr[i*2+1], &v);
optr[i] = v;
}
in_stream.setptr(iptr + length*2);
end += length;
}
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}

50
common/rdr/HexInStream.h Normal file
View File

@@ -0,0 +1,50 @@
/* 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_HEX_INSTREAM_H__
#define __RDR_HEX_INSTREAM_H__
#include <rdr/InStream.h>
namespace rdr {
class HexInStream : public InStream {
public:
HexInStream(InStream& is, int bufSize=0);
virtual ~HexInStream();
int pos();
static bool readHexAndShift(char c, int* v);
static bool hexStrToBin(const char* s, char** data, int* length);
protected:
int overrun(int itemSize, int nItems, bool wait);
private:
int bufSize;
U8* start;
int offset;
InStream& in_stream;
};
} // end of namespace rdr
#endif

110
common/rdr/HexOutStream.cxx Normal file
View File

@@ -0,0 +1,110 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include <rdr/HexOutStream.h>
#include <rdr/Exception.h>
using namespace rdr;
const int DEFAULT_BUF_LEN = 16384;
static inline int min(int a, int b) {return a<b ? a : b;}
HexOutStream::HexOutStream(OutStream& os, int buflen)
: out_stream(os), offset(0), bufSize(buflen ? buflen : DEFAULT_BUF_LEN)
{
if (bufSize % 2)
bufSize--;
ptr = start = new U8[bufSize];
end = start + bufSize;
}
HexOutStream::~HexOutStream() {
delete [] start;
}
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, int length) {
char* buffer = new char[length*2+1];
for (int 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;
}
void
HexOutStream::writeBuffer() {
U8* pos = start;
while (pos != ptr) {
out_stream.check(2);
U8* optr = out_stream.getptr();
U8* oend = out_stream.getend();
int length = min(ptr-pos, (oend-optr)/2);
for (int i=0; i<length; i++) {
optr[i*2] = intToHex((pos[i] >> 4) & 0xf);
optr[i*2+1] = intToHex(pos[i] & 0xf);
}
out_stream.setptr(optr + length*2);
pos += length;
}
offset += ptr - start;
ptr = start;
}
int HexOutStream::length()
{
return offset + ptr - start;
}
void
HexOutStream::flush() {
writeBuffer();
out_stream.flush();
}
int
HexOutStream::overrun(int itemSize, int nItems) {
if (itemSize > bufSize)
throw Exception("HexOutStream overrun: max itemSize exceeded");
writeBuffer();
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}

51
common/rdr/HexOutStream.h Normal file
View File

@@ -0,0 +1,51 @@
/* 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_HEX_OUTSTREAM_H__
#define __RDR_HEX_OUTSTREAM_H__
#include <rdr/OutStream.h>
namespace rdr {
class HexOutStream : public OutStream {
public:
HexOutStream(OutStream& os, int buflen=0);
virtual ~HexOutStream();
void flush();
int length();
static char intToHex(int i);
static char* binToHexStr(const char* data, int length);
private:
void writeBuffer();
int overrun(int itemSize, int nItems);
OutStream& out_stream;
U8* start;
int offset;
int bufSize;
};
}
#endif

35
common/rdr/InStream.cxx Normal file
View File

@@ -0,0 +1,35 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include <rdr/InStream.h>
#include <rdr/Exception.h>
using namespace rdr;
U32 InStream::maxStringLength = 65535;
char* InStream::readString()
{
U32 len = readU32();
if (len > maxStringLength)
throw Exception("InStream max string length exceeded");
char* str = new char[len+1];
readBytes(str, len);
str[len] = 0;
return str;
}

147
common/rdr/InStream.h Normal file
View File

@@ -0,0 +1,147 @@
/* 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.
*/
//
// rdr::InStream marshalls data from a buffer stored in RDR (RFB Data
// Representation).
//
#ifndef __RDR_INSTREAM_H__
#define __RDR_INSTREAM_H__
#include <rdr/types.h>
#include <string.h> // for memcpy
namespace rdr {
class InStream {
public:
virtual ~InStream() {}
// check() ensures there is buffer data for at least one item of size
// itemSize bytes. Returns the number of items in the buffer (up to a
// maximum of nItems). If wait is false, then instead of blocking to wait
// for the bytes, zero is returned if the bytes are not immediately
// available.
inline int check(int itemSize, int nItems=1, bool wait=true)
{
if (ptr + itemSize * nItems > end) {
if (ptr + itemSize > end)
return overrun(itemSize, nItems, wait);
nItems = (end - ptr) / itemSize;
}
return nItems;
}
// checkNoWait() tries to make sure that the given number of bytes can
// be read without blocking. It returns true if this is the case, false
// otherwise. The length must be "small" (less than the buffer size).
inline bool checkNoWait(int length) { return check(length, 1, false)!=0; }
// 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 S8 readS8() { return (S8) readU8(); }
inline S16 readS16() { return (S16)readU16(); }
inline S32 readS32() { return (S32)readU32(); }
// readString() reads a string - a U32 length followed by the data.
// Returns a null-terminated string - the caller should delete[] it
// afterwards.
char* readString();
// maxStringLength protects against allocating a huge buffer. Set it
// higher if you need longer strings.
static U32 maxStringLength;
inline void skip(int bytes) {
while (bytes > 0) {
int n = check(1, bytes);
ptr += n;
bytes -= n;
}
}
// readBytes() reads an exact number of bytes.
void readBytes(void* data, int length) {
U8* dataPtr = (U8*)data;
U8* dataEnd = dataPtr + length;
while (dataPtr < dataEnd) {
int n = check(1, dataEnd - dataPtr);
memcpy(dataPtr, ptr, n);
ptr += n;
dataPtr += n;
}
}
// 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; }
// pos() returns the position in the stream.
virtual int pos() = 0;
// getptr(), getend() and setptr() are "dirty" methods which allow you to
// manipulate the buffer directly. This is useful for a stream which is a
// wrapper around an underlying stream.
inline const U8* getptr() const { return ptr; }
inline const U8* getend() const { return end; }
inline void setptr(const U8* p) { ptr = p; }
private:
// overrun() is implemented by a derived class to cope with buffer overrun.
// It ensures there are at least itemSize bytes of buffer data. Returns
// the number of items in the buffer (up to a maximum of nItems). itemSize
// is supposed to be "small" (a few bytes). If wait is false, then
// instead of blocking to wait for the bytes, zero is returned if the bytes
// are not immediately available.
virtual int overrun(int itemSize, int nItems, bool wait=true) = 0;
protected:
InStream() {}
const U8* ptr;
const U8* end;
};
}
#endif

63
common/rdr/MemInStream.h Normal file
View File

@@ -0,0 +1,63 @@
/* 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.
*/
//
// 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
// doesn't matter.
//
#ifndef __RDR_MEMINSTREAM_H__
#define __RDR_MEMINSTREAM_H__
#include <rdr/InStream.h>
#include <rdr/Exception.h>
namespace rdr {
class MemInStream : public InStream {
public:
MemInStream(const void* data, int len, bool deleteWhenDone_=false)
: start((const U8*)data), deleteWhenDone(deleteWhenDone_)
{
ptr = start;
end = start + len;
}
virtual ~MemInStream() {
if (deleteWhenDone)
delete [] start;
}
int pos() { return ptr - start; }
void reposition(int pos) { ptr = start + pos; }
private:
int overrun(int itemSize, int nItems, bool wait) { throw EndOfStream(); }
const U8* start;
bool deleteWhenDone;
};
}
#endif

83
common/rdr/MemOutStream.h Normal file
View File

@@ -0,0 +1,83 @@
/* 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.
*/
//
// A MemOutStream grows as needed when data is written to it.
//
#ifndef __RDR_MEMOUTSTREAM_H__
#define __RDR_MEMOUTSTREAM_H__
#include <rdr/OutStream.h>
namespace rdr {
class MemOutStream : public OutStream {
public:
MemOutStream(int len=1024) {
start = ptr = new U8[len];
end = start + len;
}
virtual ~MemOutStream() {
delete [] start;
}
void writeBytes(const void* data, int length) {
check(length);
memcpy(ptr, data, length);
ptr += length;
}
int length() { return ptr - start; }
void clear() { ptr = start; };
void clearAndZero() { memset(start, 0, ptr-start); clear(); }
void reposition(int pos) { ptr = start + pos; }
// data() returns a pointer to the buffer.
const void* data() { return (const void*)start; }
protected:
// overrun() either doubles the buffer or adds enough space for nItems of
// size itemSize bytes.
int overrun(int itemSize, int nItems) {
int len = ptr - start + itemSize * nItems;
if (len < (end - start) * 2)
len = (end - start) * 2;
U8* newStart = new U8[len];
memcpy(newStart, start, ptr - start);
ptr = newStart + (ptr - start);
delete [] start;
start = newStart;
end = newStart + len;
return nItems;
}
U8* start;
};
}
#endif

158
common/rdr/OutStream.h Normal file
View File

@@ -0,0 +1,158 @@
/* Copyright (C) 2002-2003 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.
*/
//
// rdr::OutStream marshalls data into a buffer stored in RDR (RFB Data
// Representation).
//
#ifndef __RDR_OUTSTREAM_H__
#define __RDR_OUTSTREAM_H__
#include <rdr/types.h>
#include <rdr/InStream.h>
#include <string.h> // for memcpy
namespace rdr {
class OutStream {
protected:
OutStream() {}
public:
virtual ~OutStream() {}
// check() ensures there is buffer space for at least one item of size
// itemSize bytes. Returns the number of items which fit (up to a maximum
// of nItems).
inline int check(int itemSize, int nItems=1)
{
if (ptr + itemSize * nItems > end) {
if (ptr + itemSize > end)
return overrun(itemSize, nItems);
nItems = (end - ptr) / itemSize;
}
return nItems;
}
// 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 writeS8( S8 s) { writeU8((U8)s); }
inline void writeS16(S16 s) { writeU16((U16)s); }
inline void writeS32(S32 s) { writeU32((U32)s); }
// writeString() writes a string - a U32 length followed by the data. The
// given string should be null-terminated (but the terminating null is not
// written to the stream).
inline void writeString(const char* str) {
U32 len = strlen(str);
writeU32(len);
writeBytes(str, len);
}
inline void pad(int bytes) {
while (bytes-- > 0) writeU8(0);
}
inline void skip(int bytes) {
while (bytes > 0) {
int n = check(1, bytes);
ptr += n;
bytes -= n;
}
}
// writeBytes() writes an exact number of bytes.
void writeBytes(const void* data, int length) {
const U8* dataPtr = (const U8*)data;
const U8* dataEnd = dataPtr + length;
while (dataPtr < dataEnd) {
int n = check(1, dataEnd - dataPtr);
memcpy(ptr, dataPtr, n);
ptr += n;
dataPtr += n;
}
}
// copyBytes() efficiently transfers data between streams
void copyBytes(InStream* is, int length) {
while (length > 0) {
int n = check(1, length);
is->readBytes(ptr, n);
ptr += n;
length -= n;
}
}
// 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]; }
// length() returns the length of the stream.
virtual int length() = 0;
// flush() requests that the stream be flushed.
virtual void flush() {}
// getptr(), getend() and setptr() are "dirty" methods which allow you to
// manipulate the buffer directly. This is useful for a stream which is a
// wrapper around an underlying stream.
inline U8* getptr() { return ptr; }
inline U8* getend() { return end; }
inline void setptr(U8* p) { ptr = p; }
private:
// overrun() is implemented by a derived class to cope with buffer overrun.
// It ensures there are at least itemSize bytes of buffer space. Returns
// the number of items which fit (up to a maximum of nItems). itemSize is
// supposed to be "small" (a few bytes).
virtual int overrun(int itemSize, int nItems) = 0;
protected:
U8* ptr;
U8* end;
};
}
#endif

130
common/rdr/RandomStream.cxx Normal file
View File

@@ -0,0 +1,130 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include <rdr/RandomStream.h>
#include <rdr/Exception.h>
#include <time.h>
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#include <errno.h>
#else
#define getpid() GetCurrentProcessId()
#ifndef RFB_HAVE_WINCRYPT
#pragma message(" NOTE: Not building WinCrypt-based RandomStream")
#endif
#endif
using namespace rdr;
const int DEFAULT_BUF_LEN = 256;
unsigned int RandomStream::seed;
RandomStream::RandomStream()
: offset(0)
{
ptr = end = start = new U8[DEFAULT_BUF_LEN];
#ifdef RFB_HAVE_WINCRYPT
provider = 0;
if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, 0)) {
if (GetLastError() == (DWORD)NTE_BAD_KEYSET) {
if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
fprintf(stderr, "RandomStream: unable to create keyset\n");
provider = 0;
}
} else {
fprintf(stderr, "RandomStream: unable to acquire context\n");
provider = 0;
}
}
if (!provider) {
#else
#ifndef WIN32
fp = fopen("/dev/urandom", "r");
if (!fp)
fp = fopen("/dev/random", "r");
if (!fp) {
#else
{
#endif
#endif
fprintf(stderr,"RandomStream: warning: no OS supplied random source - using rand()\n");
seed += (unsigned int) time(0) + getpid() + getpid() * 987654 + rand();
srand(seed);
}
}
RandomStream::~RandomStream() {
delete [] start;
#ifdef RFB_HAVE_WINCRYPT
if (provider)
CryptReleaseContext(provider, 0);
#endif
#ifndef WIN32
if (fp) fclose(fp);
#endif
}
int RandomStream::pos() {
return offset + ptr - start;
}
int RandomStream::overrun(int itemSize, int nItems, bool wait) {
if (itemSize > DEFAULT_BUF_LEN)
throw Exception("RandomStream overrun: max itemSize exceeded");
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
end -= ptr - start;
offset += ptr - start;
ptr = start;
int length = start + DEFAULT_BUF_LEN - end;
#ifdef RFB_HAVE_WINCRYPT
if (provider) {
if (!CryptGenRandom(provider, length, (U8*)end))
throw rdr::SystemException("unable to CryptGenRandom", GetLastError());
end += length;
} else {
#else
#ifndef WIN32
if (fp) {
int n = fread((U8*)end, length, 1, fp);
if (n != 1)
throw rdr::SystemException("reading /dev/urandom or /dev/random failed",
errno);
end += length;
} else {
#else
{
#endif
#endif
for (int i=0; i<length; i++)
*(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0));
}
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}

63
common/rdr/RandomStream.h Normal file
View File

@@ -0,0 +1,63 @@
/* 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_RANDOMSTREAM_H__
#define __RDR_RANDOMSTREAM_H__
#include <stdio.h>
#include <rdr/InStream.h>
#ifdef WIN32
#include <windows.h>
#include <wincrypt.h>
#ifdef WINCRYPT32API
#define RFB_HAVE_WINCRYPT
#endif
#endif
namespace rdr {
class RandomStream : public InStream {
public:
RandomStream();
virtual ~RandomStream();
int pos();
protected:
int overrun(int itemSize, int nItems, bool wait);
private:
U8* start;
int offset;
static unsigned int seed;
#ifdef RFB_HAVE_WINCRYPT
HCRYPTPROV provider;
#endif
#ifndef WIN32
FILE* fp;
#endif
};
} // end of namespace rdr
#endif

View File

@@ -0,0 +1,102 @@
/* 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_SUBSTITUTINGINSTREAM_H__
#define __RDR_SUBSTITUTINGINSTREAM_H__
#include <rdr/InStream.h>
#include <rdr/Exception.h>
namespace rdr {
class Substitutor {
public:
virtual char* substitute(const char* varName) = 0;
};
class SubstitutingInStream : public InStream {
public:
SubstitutingInStream(InStream* underlying_, Substitutor* s,
int maxVarNameLen_)
: underlying(underlying_), dollar(0), substitutor(s), subst(0),
maxVarNameLen(maxVarNameLen_)
{
ptr = end = underlying->getptr();
varName = new char[maxVarNameLen+1];
}
~SubstitutingInStream() {
delete underlying;
delete [] varName;
delete [] subst;
}
int pos() { return underlying->pos(); }
virtual int overrun(int itemSize, int nItems, bool wait=true) {
if (itemSize != 1)
throw new rdr::Exception("SubstitutingInStream: itemSize must be 1");
if (subst) {
delete [] subst;
subst = 0;
} else {
underlying->setptr(ptr);
}
underlying->check(1);
ptr = underlying->getptr();
end = underlying->getend();
dollar = (const U8*)memchr(ptr, '$', end-ptr);
if (dollar) {
if (dollar == ptr) {
try {
int i = 0;
while (i < maxVarNameLen) {
varName[i++] = underlying->readS8();
varName[i] = 0;
subst = substitutor->substitute(varName);
if (subst) {
ptr = (U8*)subst;
end = (U8*)subst + strlen(subst);
break;
}
}
} catch (EndOfStream&) {
}
if (!subst)
dollar = (const U8*)memchr(ptr+1, '$', end-ptr-1);
}
if (!subst && dollar) end = dollar;
}
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}
InStream* underlying;
const U8* dollar;
Substitutor* substitutor;
char* varName;
char* subst;
int maxVarNameLen;
};
}
#endif

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2004 Red Hat Inc.
* Copyright (C) 2010 TigerVNC Team
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <rdr/TLSException.h>
#include <string.h>
#include <stdio.h>
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
#endif
using namespace rdr;
#ifdef HAVE_GNUTLS
TLSException::TLSException(const char* s, int err_)
: Exception("%s: %s (%d)", s, gnutls_strerror(err_), err_), err(err_)
{
}
#endif /* HAVE_GNUTLS */

35
common/rdr/TLSException.h Normal file
View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2004 Red Hat Inc.
* Copyright (C) 2010 TigerVNC Team
*
* 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_TLSEXCEPTION_H__
#define __RDR_TLSEXCEPTION_H__
#include <rdr/Exception.h>
namespace rdr {
struct TLSException : public Exception {
int err;
TLSException(const char* s, int err_);
};
}
#endif

125
common/rdr/TLSInStream.cxx Normal file
View File

@@ -0,0 +1,125 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <rdr/Exception.h>
#include <rdr/TLSException.h>
#include <rdr/TLSInStream.h>
#include <errno.h>
#ifdef HAVE_GNUTLS
using namespace rdr;
enum { DEFAULT_BUF_SIZE = 16384 };
ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
{
TLSInStream* self= (TLSInStream*) str;
InStream *in = self->in;
try {
if (!in->check(1, 1, false)) {
gnutls_transport_set_errno(self->session, EAGAIN);
return -1;
}
if (in->getend() - in->getptr() < (ptrdiff_t)size)
size = in->getend() - in->getptr();
in->readBytes(data, size);
} catch (Exception& e) {
gnutls_transport_set_errno(self->session, EINVAL);
return -1;
}
return size;
}
TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
: session(_session), in(_in), bufSize(DEFAULT_BUF_SIZE), offset(0)
{
gnutls_transport_ptr_t recv, send;
ptr = end = start = new U8[bufSize];
gnutls_transport_set_pull_function(session, pull);
gnutls_transport_get_ptr2(session, &recv, &send);
gnutls_transport_set_ptr2(session, this, send);
}
TLSInStream::~TLSInStream()
{
gnutls_transport_set_pull_function(session, NULL);
delete[] start;
}
int TLSInStream::pos()
{
return offset + ptr - start;
}
int TLSInStream::overrun(int itemSize, int nItems, bool wait)
{
if (itemSize > bufSize)
throw Exception("TLSInStream overrun: max itemSize exceeded");
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
offset += ptr - start;
end -= ptr - start;
ptr = start;
while (end < start + itemSize) {
int n = readTLS((U8*) end, start + bufSize - end, wait);
if (!wait && n == 0)
return 0;
end += n;
}
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}
int TLSInStream::readTLS(U8* buf, int len, bool wait)
{
int n;
n = in->check(1, 1, wait);
if (n == 0)
return 0;
n = gnutls_record_recv(session, (void *) buf, len);
if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN)
return 0;
if (n < 0) throw TLSException("readTLS", n);
return n;
}
#endif

55
common/rdr/TLSInStream.h Normal file
View File

@@ -0,0 +1,55 @@
/* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
*
* 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_TLSINSTREAM_H__
#define __RDR_TLSINSTREAM_H__
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
#include <rdr/InStream.h>
namespace rdr {
class TLSInStream : public InStream {
public:
TLSInStream(InStream* in, gnutls_session_t session);
virtual ~TLSInStream();
int pos();
private:
int overrun(int itemSize, int nItems, bool wait);
int readTLS(U8* buf, int len, bool wait);
static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size);
gnutls_session_t session;
InStream* in;
int bufSize;
int offset;
U8* start;
};
};
#endif
#endif

123
common/rdr/TLSOutStream.cxx Normal file
View File

@@ -0,0 +1,123 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <rdr/Exception.h>
#include <rdr/TLSException.h>
#include <rdr/TLSOutStream.h>
#include <errno.h>
#ifdef HAVE_GNUTLS
using namespace rdr;
enum { DEFAULT_BUF_SIZE = 16384 };
ssize_t TLSOutStream::push(gnutls_transport_ptr_t str, const void* data,
size_t size)
{
TLSOutStream* self= (TLSOutStream*) str;
OutStream *out = self->out;
try {
out->writeBytes(data, size);
out->flush();
} catch (Exception& e) {
gnutls_transport_set_errno(self->session, EINVAL);
return -1;
}
return size;
}
TLSOutStream::TLSOutStream(OutStream* _out, gnutls_session_t _session)
: session(_session), out(_out), bufSize(DEFAULT_BUF_SIZE), offset(0)
{
gnutls_transport_ptr_t recv, send;
ptr = start = new U8[bufSize];
end = start + bufSize;
gnutls_transport_set_push_function(session, push);
gnutls_transport_get_ptr2(session, &recv, &send);
gnutls_transport_set_ptr2(session, recv, this);
}
TLSOutStream::~TLSOutStream()
{
#if 0
try {
// flush();
} catch (Exception&) {
}
#endif
gnutls_transport_set_push_function(session, NULL);
delete [] start;
}
int TLSOutStream::length()
{
return offset + ptr - start;
}
void TLSOutStream::flush()
{
U8* sentUpTo = start;
while (sentUpTo < ptr) {
int n = writeTLS(sentUpTo, ptr - sentUpTo);
sentUpTo += n;
offset += n;
}
ptr = start;
out->flush();
}
int TLSOutStream::overrun(int itemSize, int nItems)
{
if (itemSize > bufSize)
throw Exception("TLSOutStream overrun: max itemSize exceeded");
flush();
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}
int TLSOutStream::writeTLS(const U8* data, int length)
{
int n;
n = gnutls_record_send(session, data, length);
if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN)
return 0;
if (n < 0)
throw TLSException("writeTLS", n);
return n;
}
#endif

57
common/rdr/TLSOutStream.h Normal file
View File

@@ -0,0 +1,57 @@
/* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
*
* 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_TLSOUTSTREAM_H__
#define __RDR_TLSOUTSTREAM_H__
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
#include <rdr/OutStream.h>
namespace rdr {
class TLSOutStream : public OutStream {
public:
TLSOutStream(OutStream* out, gnutls_session_t session);
virtual ~TLSOutStream();
void flush();
int length();
protected:
int overrun(int itemSize, int nItems);
private:
int writeTLS(const U8* data, int length);
static ssize_t push(gnutls_transport_ptr_t str, const void* data, size_t size);
gnutls_session_t session;
OutStream* out;
int bufSize;
U8* start;
int offset;
};
};
#endif
#endif

149
common/rdr/ZlibInStream.cxx Normal file
View File

@@ -0,0 +1,149 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include <assert.h>
#include <rdr/ZlibInStream.h>
#include <rdr/Exception.h>
#include <zlib.h>
using namespace rdr;
enum { DEFAULT_BUF_SIZE = 16384 };
ZlibInStream::ZlibInStream(int bufSize_)
: underlying(0), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0),
zs(NULL), bytesIn(0)
{
ptr = end = start = new U8[bufSize];
init();
}
ZlibInStream::~ZlibInStream()
{
deinit();
delete [] start;
}
void ZlibInStream::setUnderlying(InStream* is, int bytesIn_)
{
underlying = is;
bytesIn = bytesIn_;
ptr = end = start;
}
int ZlibInStream::pos()
{
return offset + ptr - start;
}
void ZlibInStream::removeUnderlying()
{
ptr = end = start;
if (!underlying) return;
while (bytesIn > 0) {
decompress(true);
end = start; // throw away any data
}
underlying = 0;
}
void ZlibInStream::reset()
{
deinit();
init();
}
void ZlibInStream::init()
{
assert(zs == NULL);
zs = new z_stream;
zs->zalloc = Z_NULL;
zs->zfree = Z_NULL;
zs->opaque = Z_NULL;
zs->next_in = Z_NULL;
zs->avail_in = 0;
if (inflateInit(zs) != Z_OK) {
delete zs;
zs = NULL;
throw Exception("ZlibInStream: inflateInit failed");
}
}
void ZlibInStream::deinit()
{
assert(zs != NULL);
removeUnderlying();
inflateEnd(zs);
delete zs;
zs = NULL;
}
int ZlibInStream::overrun(int itemSize, int nItems, bool wait)
{
if (itemSize > bufSize)
throw Exception("ZlibInStream overrun: max itemSize exceeded");
if (!underlying)
throw Exception("ZlibInStream overrun: no underlying stream");
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
offset += ptr - start;
end -= ptr - start;
ptr = start;
while (end - ptr < itemSize) {
if (!decompress(wait))
return 0;
}
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}
// decompress() calls the decompressor once. Note that this won't necessarily
// generate any output data - it may just consume some input data. Returns
// false if wait is false and we would block on the underlying stream.
bool ZlibInStream::decompress(bool wait)
{
zs->next_out = (U8*)end;
zs->avail_out = start + bufSize - end;
int n = underlying->check(1, 1, wait);
if (n == 0) return false;
zs->next_in = (U8*)underlying->getptr();
zs->avail_in = underlying->getend() - underlying->getptr();
if ((int)zs->avail_in > bytesIn)
zs->avail_in = bytesIn;
int rc = inflate(zs, Z_SYNC_FLUSH);
if (rc != Z_OK) {
throw Exception("ZlibInStream: inflate failed");
}
bytesIn -= zs->next_in - underlying->getptr();
end = zs->next_out;
underlying->setptr(zs->next_in);
return true;
}

63
common/rdr/ZlibInStream.h Normal file
View File

@@ -0,0 +1,63 @@
/* 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.
*/
//
// ZlibInStream streams from a compressed data stream ("underlying"),
// decompressing with zlib on the fly.
//
#ifndef __RDR_ZLIBINSTREAM_H__
#define __RDR_ZLIBINSTREAM_H__
#include <rdr/InStream.h>
struct z_stream_s;
namespace rdr {
class ZlibInStream : public InStream {
public:
ZlibInStream(int bufSize=0);
virtual ~ZlibInStream();
void setUnderlying(InStream* is, int bytesIn);
void removeUnderlying();
int pos();
void reset();
private:
void init();
void deinit();
int overrun(int itemSize, int nItems, bool wait);
bool decompress(bool wait);
InStream* underlying;
int bufSize;
int offset;
z_stream_s* zs;
int bytesIn;
U8* start;
};
} // end of namespace rdr
#endif

View File

@@ -0,0 +1,201 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include <stdio.h>
#include <rdr/ZlibOutStream.h>
#include <rdr/Exception.h>
#include <zlib.h>
#undef ZLIBOUT_DEBUG
using namespace rdr;
enum { DEFAULT_BUF_SIZE = 16384 };
ZlibOutStream::ZlibOutStream(OutStream* os, int bufSize_, int compressLevel)
: underlying(os), compressionLevel(compressLevel), newLevel(compressLevel),
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
{
zs = new z_stream;
zs->zalloc = Z_NULL;
zs->zfree = Z_NULL;
zs->opaque = Z_NULL;
zs->next_in = Z_NULL;
zs->avail_in = 0;
if (deflateInit(zs, compressLevel) != Z_OK) {
delete zs;
throw Exception("ZlibOutStream: deflateInit failed");
}
ptr = start = new U8[bufSize];
end = start + bufSize;
}
ZlibOutStream::~ZlibOutStream()
{
try {
flush();
} catch (Exception&) {
}
delete [] start;
deflateEnd(zs);
delete zs;
}
void ZlibOutStream::setUnderlying(OutStream* os)
{
underlying = os;
}
void ZlibOutStream::setCompressionLevel(int level)
{
if (level < -1 || level > 9)
level = -1; // Z_DEFAULT_COMPRESSION
newLevel = level;
}
int ZlibOutStream::length()
{
return offset + ptr - start;
}
void ZlibOutStream::flush()
{
checkCompressionLevel();
zs->next_in = start;
zs->avail_in = ptr - start;
#ifdef ZLIBOUT_DEBUG
fprintf(stderr,"zos flush: avail_in %d\n",zs->avail_in);
#endif
// Force out everything from the zlib encoder
deflate(Z_SYNC_FLUSH);
offset += ptr - start;
ptr = start;
}
int ZlibOutStream::overrun(int itemSize, int nItems)
{
#ifdef ZLIBOUT_DEBUG
fprintf(stderr,"zos overrun\n");
#endif
if (itemSize > bufSize)
throw Exception("ZlibOutStream overrun: max itemSize exceeded");
checkCompressionLevel();
while (end - ptr < itemSize) {
zs->next_in = start;
zs->avail_in = ptr - start;
deflate(Z_NO_FLUSH);
// output buffer not full
if (zs->avail_in == 0) {
offset += ptr - start;
ptr = start;
} else {
// but didn't consume all the data? try shifting what's left to the
// start of the buffer.
fprintf(stderr,"z out buf not full, but in data not consumed\n");
memmove(start, zs->next_in, ptr - zs->next_in);
offset += zs->next_in - start;
ptr -= zs->next_in - start;
}
}
if (itemSize * nItems > end - ptr)
nItems = (end - ptr) / itemSize;
return nItems;
}
void ZlibOutStream::deflate(int flush)
{
int rc;
if (!underlying)
throw Exception("ZlibOutStream: underlying OutStream has not been set");
if ((flush == Z_NO_FLUSH) && (zs->avail_in == 0))
return;
do {
underlying->check(1);
zs->next_out = underlying->getptr();
zs->avail_out = underlying->getend() - underlying->getptr();
#ifdef ZLIBOUT_DEBUG
fprintf(stderr,"zos: calling deflate, avail_in %d, avail_out %d\n",
zs->avail_in,zs->avail_out);
#endif
rc = ::deflate(zs, flush);
if (rc != Z_OK) {
// Silly zlib returns an error if you try to flush something twice
if ((rc == Z_BUF_ERROR) && (flush != Z_NO_FLUSH))
break;
throw Exception("ZlibOutStream: deflate failed");
}
#ifdef ZLIBOUT_DEBUG
fprintf(stderr,"zos: after deflate: %d bytes\n",
zs->next_out-underlying->getptr());
#endif
underlying->setptr(zs->next_out);
} while (zs->avail_out == 0);
}
void ZlibOutStream::checkCompressionLevel()
{
int rc;
if (newLevel != compressionLevel) {
#ifdef ZLIBOUT_DEBUG
fprintf(stderr,"zos change: avail_in %d\n",zs->avail_in);
#endif
// zlib is just horribly stupid. It does an implicit flush on
// parameter changes, but the flush it does is not one that forces
// out all the data. And since you cannot flush things again, we
// cannot force out our data after the parameter change. Hence we
// need to do a more proper flush here first.
deflate(Z_SYNC_FLUSH);
rc = deflateParams (zs, newLevel, Z_DEFAULT_STRATEGY);
if (rc != Z_OK) {
// The implicit flush can result in this error, caused by the
// explicit flush we did above. It should be safe to ignore though
// as the first flush should have left things in a stable state...
if (rc != Z_BUF_ERROR)
throw Exception("ZlibOutStream: deflateParams failed");
}
compressionLevel = newLevel;
}
}

View File

@@ -0,0 +1,63 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2011 D. R. Commander. 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.
*/
//
// ZlibOutStream streams to a compressed data stream (underlying), compressing
// with zlib on the fly.
//
#ifndef __RDR_ZLIBOUTSTREAM_H__
#define __RDR_ZLIBOUTSTREAM_H__
#include <rdr/OutStream.h>
struct z_stream_s;
namespace rdr {
class ZlibOutStream : public OutStream {
public:
ZlibOutStream(OutStream* os=0, int bufSize=0, int compressionLevel=-1);
virtual ~ZlibOutStream();
void setUnderlying(OutStream* os);
void setCompressionLevel(int level=-1);
void flush();
int length();
private:
int overrun(int itemSize, int nItems);
void deflate(int flush);
void checkCompressionLevel();
OutStream* underlying;
int compressionLevel;
int newLevel;
int bufSize;
int offset;
z_stream_s* zs;
U8* start;
};
} // end of namespace rdr
#endif

77
common/rdr/types.h Normal file
View File

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