diff options
author | Constantin Kaplinsky <const@tightvnc.com> | 2004-10-08 09:43:57 +0000 |
---|---|---|
committer | Constantin Kaplinsky <const@tightvnc.com> | 2004-10-08 09:43:57 +0000 |
commit | 47ed8d321c32c6b741cff1f4ff686165c4f269f4 (patch) | |
tree | da413648adbff4ff10c8ee26124673f8e7cf238a /rdr | |
parent | 266bb36cd47555280fffd3aab1ed86683e26d748 (diff) | |
download | tigervnc-47ed8d321c32c6b741cff1f4ff686165c4f269f4.tar.gz tigervnc-47ed8d321c32c6b741cff1f4ff686165c4f269f4.zip |
Initial revision
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'rdr')
-rw-r--r-- | rdr/Exception.cxx | 64 | ||||
-rw-r--r-- | rdr/Exception.h | 59 | ||||
-rw-r--r-- | rdr/FdInStream.cxx | 281 | ||||
-rw-r--r-- | rdr/FdInStream.h | 77 | ||||
-rw-r--r-- | rdr/FdOutStream.cxx | 174 | ||||
-rw-r--r-- | rdr/FdOutStream.h | 56 | ||||
-rw-r--r-- | rdr/FixedMemOutStream.h | 52 | ||||
-rw-r--r-- | rdr/HexInStream.cxx | 117 | ||||
-rw-r--r-- | rdr/HexInStream.h | 50 | ||||
-rw-r--r-- | rdr/HexOutStream.cxx | 110 | ||||
-rw-r--r-- | rdr/HexOutStream.h | 51 | ||||
-rw-r--r-- | rdr/InStream.cxx | 35 | ||||
-rw-r--r-- | rdr/InStream.h | 153 | ||||
-rw-r--r-- | rdr/Makefile.in | 19 | ||||
-rw-r--r-- | rdr/MemInStream.h | 63 | ||||
-rw-r--r-- | rdr/MemOutStream.h | 82 | ||||
-rw-r--r-- | rdr/NullOutStream.cxx | 60 | ||||
-rw-r--r-- | rdr/NullOutStream.h | 42 | ||||
-rw-r--r-- | rdr/OutStream.h | 152 | ||||
-rw-r--r-- | rdr/RandomStream.cxx | 118 | ||||
-rw-r--r-- | rdr/RandomStream.h | 63 | ||||
-rw-r--r-- | rdr/SubstitutingInStream.h | 102 | ||||
-rw-r--r-- | rdr/ZlibInStream.cxx | 125 | ||||
-rw-r--r-- | rdr/ZlibInStream.h | 59 | ||||
-rw-r--r-- | rdr/ZlibOutStream.cxx | 140 | ||||
-rw-r--r-- | rdr/ZlibOutStream.h | 57 | ||||
-rw-r--r-- | rdr/msvcwarning.h | 18 | ||||
-rw-r--r-- | rdr/rdr.dsp | 231 | ||||
-rw-r--r-- | rdr/types.h | 56 |
29 files changed, 2666 insertions, 0 deletions
diff --git a/rdr/Exception.cxx b/rdr/Exception.cxx new file mode 100644 index 00000000..5f7799f1 --- /dev/null +++ b/rdr/Exception.cxx @@ -0,0 +1,64 @@ +/* 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. + */ +#include <rdr/Exception.h> +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <winsock2.h> +#endif + +using namespace rdr; + +SystemException::SystemException(const char* s, int err_) + : Exception(s, "rdr::SystemException"), 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 + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, err, 0, str_+strlen(str_), len-1-strlen(str_), 0); +#endif + } + +#else + strncat(str_, strerror(err), len-1-strlen(str_)); +#endif + strncat(str_, " (", len-1-strlen(str_)); + char buf[20]; + sprintf(buf,"%d",err); + strncat(str_, buf, len-1-strlen(str_)); + strncat(str_, ")", len-1-strlen(str_)); +} diff --git a/rdr/Exception.h b/rdr/Exception.h new file mode 100644 index 00000000..98b3f0e9 --- /dev/null +++ b/rdr/Exception.h @@ -0,0 +1,59 @@ +/* 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. + */ + +#ifndef __RDR_EXCEPTION_H__ +#define __RDR_EXCEPTION_H__ + +#include <stdio.h> +#include <string.h> + +namespace rdr { + + struct Exception { + enum { len = 256 }; + char str_[len]; + char type_[len]; + Exception(const char* s=0, const char* e="rdr::Exception") { + str_[0] = 0; + if (s) + strncat(str_, s, len-1); + else + strcat(str_, "Exception"); + type_[0] = 0; + strncat(type_, e, len-1); + } + virtual const char* str() const { return str_; } + virtual const char* type() const { return type_; } + }; + + struct SystemException : public Exception { + int err; + SystemException(const char* s, int err_); + }; + + struct TimedOut : public Exception { + TimedOut(const char* s="Timed out") : Exception(s,"rdr::TimedOut") {} + }; + + struct EndOfStream : public Exception { + EndOfStream(const char* s="End of stream") + : Exception(s,"rdr::EndOfStream") {} + }; +} + +#endif diff --git a/rdr/FdInStream.cxx b/rdr/FdInStream.cxx new file mode 100644 index 00000000..397847a4 --- /dev/null +++ b/rdr/FdInStream.cxx @@ -0,0 +1,281 @@ +/* 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. + */ + +#include <stdio.h> +#include <string.h> +#ifdef _WIN32 +#include <winsock2.h> +#ifndef _WIN32_WCE +#include <sys/timeb.h> +#endif +#define read(s,b,l) recv(s,(char*)b,l,0) +#define close closesocket +#undef errno +#define errno WSAGetLastError() +#undef EINTR +#define EINTR WSAEINTR +#else +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> +#include <sys/time.h> +#endif + +// XXX should use autoconf HAVE_SYS_SELECT_H +#ifdef _AIX +#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; + + while (end < start + itemSize) { + int n = readWithTimeoutOrCallback((U8*)end, start + bufSize - end, wait); + if (n == 0) return 0; + end += n; + } + + if (itemSize * nItems > end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; +} + +#ifdef _WIN32 +static void gettimeofday(struct timeval* tv, void*) +{ + LARGE_INTEGER counts, countsPerSec; + static double usecPerCount = 0.0; + + if (QueryPerformanceCounter(&counts)) { + if (usecPerCount == 0.0) { + QueryPerformanceFrequency(&countsPerSec); + usecPerCount = 1000000.0 / countsPerSec.QuadPart; + } + + LONGLONG usecs = (LONGLONG)(counts.QuadPart * usecPerCount); + tv->tv_usec = (long)(usecs % 1000000); + tv->tv_sec = (long)(usecs / 1000000); + + } else { +#ifndef _WIN32_WCE + struct timeb tb; + ftime(&tb); + tv->tv_sec = tb.time; + tv->tv_usec = tb.millitm * 1000; +#else + throw SystemException("QueryPerformanceCounter", GetLastError()); +#endif + } +} +#endif + +// +// 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 read() 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 read() +// 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 = ::read(fd, buf, len); + } while (n < 0 && errno == EINTR); + + if (n < 0) throw SystemException("read",errno); + if (n == 0) throw EndOfStream(); + + if (timing) { + gettimeofday(&after, 0); +// fprintf(stderr,"%d.%06d\n",(after.tv_sec - before.tv_sec), +// (after.tv_usec - before.tv_usec)); + int newTimeWaited = ((after.tv_sec - before.tv_sec) * 10000 + + (after.tv_usec - before.tv_usec) / 100); + int newKbits = n * 8 / 1000; + +// if (newTimeWaited == 0) { +// fprintf(stderr,"new kbps infinite t %d k %d\n", +// newTimeWaited, newKbits); +// } else { +// fprintf(stderr,"new kbps %d t %d k %d\n", +// newKbits * 10000 / newTimeWaited, newTimeWaited, newKbits); +// } + + // 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; +} diff --git a/rdr/FdInStream.h b/rdr/FdInStream.h new file mode 100644 index 00000000..d038b1b3 --- /dev/null +++ b/rdr/FdInStream.h @@ -0,0 +1,77 @@ +/* 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. + */ + +// +// 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; + }; + + 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 diff --git a/rdr/FdOutStream.cxx b/rdr/FdOutStream.cxx new file mode 100644 index 00000000..6795fc89 --- /dev/null +++ b/rdr/FdOutStream.cxx @@ -0,0 +1,174 @@ +/* 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. + */ + +#include <stdio.h> +#include <string.h> +#ifdef _WIN32 +#include <winsock2.h> +#define write(s,b,l) send(s,(const char*)b,l,0) +#define EWOULDBLOCK WSAEWOULDBLOCK +#undef errno +#define errno WSAGetLastError() +#undef EINTR +#define EINTR WSAEINTR +#else +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> +#include <sys/time.h> +#endif + +#include <rdr/FdOutStream.h> +#include <rdr/Exception.h> + + +using namespace rdr; + +enum { DEFAULT_BUF_SIZE = 16384, + MIN_BULK_SIZE = 1024 }; + +FdOutStream::FdOutStream(int fd_, int timeoutms_, int bufSize_) + : fd(fd_), timeoutms(timeoutms_), + bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) +{ + ptr = start = new U8[bufSize]; + end = start + bufSize; +} + +FdOutStream::~FdOutStream() +{ + try { + flush(); + } catch (Exception&) { + } + delete [] start; +} + +void FdOutStream::setTimeout(int timeoutms_) { + timeoutms = timeoutms_; +} + +void FdOutStream::writeBytes(const void* data, int length) +{ + if (length < MIN_BULK_SIZE) { + OutStream::writeBytes(data, length); + return; + } + + const U8* dataPtr = (const U8*)data; + + flush(); + + while (length > 0) { + int n = writeWithTimeout(dataPtr, length); + length -= n; + dataPtr += n; + offset += n; + } +} + +int FdOutStream::length() +{ + return offset + ptr - start; +} + +void FdOutStream::flush() +{ + U8* sentUpTo = start; + while (sentUpTo < ptr) { + int n = writeWithTimeout((const void*) sentUpTo, ptr - sentUpTo); + sentUpTo += n; + offset += n; + } + + ptr = start; +} + + +int FdOutStream::overrun(int itemSize, int nItems) +{ + if (itemSize > bufSize) + throw Exception("FdOutStream overrun: max itemSize exceeded"); + + flush(); + + 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 write() 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 write() returning EINTR. +// + +int FdOutStream::writeWithTimeout(const void* data, int length) +{ + int n; + + do { + + 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 = 0; + } + + FD_ZERO(&fds); + FD_SET(fd, &fds); +#ifdef _WIN32_WCE + // NB: This fixes a broken Winsock2 select() behaviour. select() + // never returns for non-blocking sockets, unless they're already + // ready to be written to... + u_long zero = 0; ioctlsocket(fd, FIONBIO, &zero); +#endif + n = select(fd+1, 0, &fds, 0, tvp); +#ifdef _WIN32_WCE + u_long one = 0; ioctlsocket(fd, FIONBIO, &one); +#endif + } while (n < 0 && errno == EINTR); + + if (n < 0) throw SystemException("select",errno); + + if (n == 0) throw TimedOut(); + + do { + n = ::write(fd, data, length); + } while (n < 0 && (errno == EINTR)); + + // NB: This outer loop simply fixes a broken Winsock2 EWOULDBLOCK + // condition, found only under Win98 (first edition), with slow + // network connections. Should in fact never ever happen... + } while (n < 0 && (errno == EWOULDBLOCK)); + + if (n < 0) throw SystemException("write",errno); + + return n; +} diff --git a/rdr/FdOutStream.h b/rdr/FdOutStream.h new file mode 100644 index 00000000..9c46db94 --- /dev/null +++ b/rdr/FdOutStream.h @@ -0,0 +1,56 @@ +/* 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. + */ + +// +// FdOutStream streams to a file descriptor. +// + +#ifndef __RDR_FDOUTSTREAM_H__ +#define __RDR_FDOUTSTREAM_H__ + +#include <rdr/OutStream.h> + +namespace rdr { + + class FdOutStream : public OutStream { + + public: + + FdOutStream(int fd, int timeoutms=-1, int bufSize=0); + virtual ~FdOutStream(); + + void setTimeout(int timeoutms); + int getFd() { return fd; } + + void flush(); + int length(); + void writeBytes(const void* data, int length); + + private: + int overrun(int itemSize, int nItems); + int writeWithTimeout(const void* data, int length); + int fd; + int timeoutms; + int bufSize; + int offset; + U8* start; + }; + +} + +#endif diff --git a/rdr/FixedMemOutStream.h b/rdr/FixedMemOutStream.h new file mode 100644 index 00000000..f149e600 --- /dev/null +++ b/rdr/FixedMemOutStream.h @@ -0,0 +1,52 @@ +/* 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. + */ + +// +// 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 diff --git a/rdr/HexInStream.cxx b/rdr/HexInStream.cxx new file mode 100644 index 00000000..a454ca8e --- /dev/null +++ b/rdr/HexInStream.cxx @@ -0,0 +1,117 @@ +/* Copyright (C) 2002-2004 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; +} diff --git a/rdr/HexInStream.h b/rdr/HexInStream.h new file mode 100644 index 00000000..fbfc2738 --- /dev/null +++ b/rdr/HexInStream.h @@ -0,0 +1,50 @@ +/* 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. + */ + +#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 diff --git a/rdr/HexOutStream.cxx b/rdr/HexOutStream.cxx new file mode 100644 index 00000000..f82d9f55 --- /dev/null +++ b/rdr/HexOutStream.cxx @@ -0,0 +1,110 @@ +/* Copyright (C) 2002-2004 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; +} + diff --git a/rdr/HexOutStream.h b/rdr/HexOutStream.h new file mode 100644 index 00000000..691a16bc --- /dev/null +++ b/rdr/HexOutStream.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2002-2004 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 diff --git a/rdr/InStream.cxx b/rdr/InStream.cxx new file mode 100644 index 00000000..13a6fa19 --- /dev/null +++ b/rdr/InStream.cxx @@ -0,0 +1,35 @@ +/* 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. + */ + +#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; +} diff --git a/rdr/InStream.h b/rdr/InStream.h new file mode 100644 index 00000000..2048daa6 --- /dev/null +++ b/rdr/InStream.h @@ -0,0 +1,153 @@ +/* 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::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. + + virtual 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; } + inline U32 readOpaque24A() { check(3); U32 r=0; ((U8*)&r)[0] = *ptr++; + ((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++; + return r; } + inline U32 readOpaque24B() { check(3); U32 r=0; ((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 diff --git a/rdr/Makefile.in b/rdr/Makefile.in new file mode 100644 index 00000000..9edf2842 --- /dev/null +++ b/rdr/Makefile.in @@ -0,0 +1,19 @@ + +SRCS = Exception.cxx FdInStream.cxx FdOutStream.cxx InStream.cxx \ + NullOutStream.cxx RandomStream.cxx ZlibInStream.cxx ZlibOutStream.cxx \ + HexInStream.cxx HexOutStream.cxx + +OBJS = $(SRCS:.cxx=.o) + +DIR_CPPFLAGS = -I$(top_srcdir) @ZLIB_INCLUDE@ + +library = librdr.a + +all:: $(library) + +$(library): $(OBJS) + rm -f $(library) + $(AR) $(library) $(OBJS) + $(RANLIB) $(library) + +# followed by boilerplate.mk diff --git a/rdr/MemInStream.h b/rdr/MemInStream.h new file mode 100644 index 00000000..2b05e3df --- /dev/null +++ b/rdr/MemInStream.h @@ -0,0 +1,63 @@ +/* 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::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 [] (U8*)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 diff --git a/rdr/MemOutStream.h b/rdr/MemOutStream.h new file mode 100644 index 00000000..3456f5c7 --- /dev/null +++ b/rdr/MemOutStream.h @@ -0,0 +1,82 @@ +/* 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. + */ + +// +// 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 reposition(int pos) { ptr = start + pos; } + + // data() returns a pointer to the buffer. + + const void* data() { return (const void*)start; } + + private: + + // 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 diff --git a/rdr/NullOutStream.cxx b/rdr/NullOutStream.cxx new file mode 100644 index 00000000..e940f2af --- /dev/null +++ b/rdr/NullOutStream.cxx @@ -0,0 +1,60 @@ +/* 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. + */ + +#include <rdr/NullOutStream.h> +#include <rdr/Exception.h> + +using namespace rdr; + +static const int bufferSize = 1024; + +NullOutStream::NullOutStream() + : offset(0) +{ + start = ptr = new U8[bufferSize]; + end = start + bufferSize; +} + +NullOutStream::~NullOutStream() +{ + delete [] start; +} + +int NullOutStream::length() +{ + return offset + ptr - start; +} + +void NullOutStream::writeBytes(const void* data, int length) +{ + offset += length; +} + +int NullOutStream::overrun(int itemSize, int nItems) +{ + if (itemSize > bufferSize) + throw Exception("NullOutStream overrun: max itemSize exceeded"); + + offset += ptr - start; + ptr = start; + + if (itemSize * nItems > end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; +} diff --git a/rdr/NullOutStream.h b/rdr/NullOutStream.h new file mode 100644 index 00000000..84a56e5f --- /dev/null +++ b/rdr/NullOutStream.h @@ -0,0 +1,42 @@ +/* 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. + */ + +#ifndef __RDR_NULLOUTSTREAM_H__ +#define __RDR_NULLOUTSTREAM_H__ + +#include <rdr/OutStream.h> + +namespace rdr { + + class NullOutStream : public OutStream { + + public: + NullOutStream(); + virtual ~NullOutStream(); + int length(); + void writeBytes(const void* data, int length); + + private: + int overrun(int itemSize, int nItems); + int offset; + U8* start; + }; + +} + +#endif diff --git a/rdr/OutStream.h b/rdr/OutStream.h new file mode 100644 index 00000000..a064bcc9 --- /dev/null +++ b/rdr/OutStream.h @@ -0,0 +1,152 @@ +/* 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 <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. + + virtual 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; + } + } + + // 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 writeOpaque24A(U32 u) { check(3); *ptr++ = ((U8*)&u)[0]; + *ptr++ = ((U8*)&u)[1]; + *ptr++ = ((U8*)&u)[2]; } + inline void writeOpaque24B(U32 u) { check(3); *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 diff --git a/rdr/RandomStream.cxx b/rdr/RandomStream.cxx new file mode 100644 index 00000000..7f62e091 --- /dev/null +++ b/rdr/RandomStream.cxx @@ -0,0 +1,118 @@ +/* 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. + */ + +#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() +#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 WIN32 + provider = 0; + if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, 0)) { + if (GetLastError() == 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 + fp = fopen("/dev/urandom", "r"); + if (!fp) + fp = fopen("/dev/random", "r"); + if (!fp) { +#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 WIN32 + if (provider) { + CryptReleaseContext(provider, 0); + } +#else + 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 WIN32 + if (provider) { + if (!CryptGenRandom(provider, length, (U8*)end)) + throw rdr::SystemException("unable to CryptGenRandom", GetLastError()); + end += length; +#else + 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; +#endif + } else { + 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; +} diff --git a/rdr/RandomStream.h b/rdr/RandomStream.h new file mode 100644 index 00000000..c4aaaa6a --- /dev/null +++ b/rdr/RandomStream.h @@ -0,0 +1,63 @@ +/* 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. + */ + +#ifndef __RDR_RANDOMSTREAM_H__ +#define __RDR_RANDOMSTREAM_H__ + +#include <stdio.h> +#include <rdr/InStream.h> + +#ifdef WIN32 +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <wincrypt.h> +#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 WIN32 + HCRYPTPROV provider; +#else + FILE* fp; +#endif + + }; + +} // end of namespace rdr + +#endif diff --git a/rdr/SubstitutingInStream.h b/rdr/SubstitutingInStream.h new file mode 100644 index 00000000..3a0559b7 --- /dev/null +++ b/rdr/SubstitutingInStream.h @@ -0,0 +1,102 @@ +/* Copyright (C) 2002-2004 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 diff --git a/rdr/ZlibInStream.cxx b/rdr/ZlibInStream.cxx new file mode 100644 index 00000000..52e4dd35 --- /dev/null +++ b/rdr/ZlibInStream.cxx @@ -0,0 +1,125 @@ +/* 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. + */ + +#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), + bytesIn(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 (inflateInit(zs) != Z_OK) { + delete zs; + throw Exception("ZlibInStream: inflateInit failed"); + } + ptr = end = start = new U8[bufSize]; +} + +ZlibInStream::~ZlibInStream() +{ + delete [] start; + inflateEnd(zs); + delete zs; +} + +void ZlibInStream::setUnderlying(InStream* is, int bytesIn_) +{ + underlying = is; + bytesIn = bytesIn_; + ptr = end = start; +} + +int ZlibInStream::pos() +{ + return offset + ptr - start; +} + +void ZlibInStream::reset() +{ + ptr = end = start; + if (!underlying) return; + + while (bytesIn > 0) { + decompress(true); + end = start; // throw away any data + } + underlying = 0; +} + +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; +} diff --git a/rdr/ZlibInStream.h b/rdr/ZlibInStream.h new file mode 100644 index 00000000..81eb161c --- /dev/null +++ b/rdr/ZlibInStream.h @@ -0,0 +1,59 @@ +/* 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. + */ + +// +// 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 reset(); + int pos(); + + private: + + 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 diff --git a/rdr/ZlibOutStream.cxx b/rdr/ZlibOutStream.cxx new file mode 100644 index 00000000..6aadde13 --- /dev/null +++ b/rdr/ZlibOutStream.cxx @@ -0,0 +1,140 @@ +/* Copyright (C) 2002-2004 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/ZlibOutStream.h> +#include <rdr/Exception.h> +#include <zlib.h> + +using namespace rdr; + +enum { DEFAULT_BUF_SIZE = 16384 }; + +ZlibOutStream::ZlibOutStream(OutStream* os, int bufSize_, int compressLevel) + : underlying(os), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) +{ + zs = new z_stream; + zs->zalloc = Z_NULL; + zs->zfree = Z_NULL; + zs->opaque = Z_NULL; + 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; +} + +int ZlibOutStream::length() +{ + return offset + ptr - start; +} + +void ZlibOutStream::flush() +{ + zs->next_in = start; + zs->avail_in = ptr - start; + +// fprintf(stderr,"zos flush: avail_in %d\n",zs->avail_in); + + while (zs->avail_in != 0) { + + do { + underlying->check(1); + zs->next_out = underlying->getptr(); + zs->avail_out = underlying->getend() - underlying->getptr(); + +// fprintf(stderr,"zos flush: calling deflate, avail_in %d, avail_out %d\n", +// zs->avail_in,zs->avail_out); + int rc = deflate(zs, Z_SYNC_FLUSH); + if (rc != Z_OK) throw Exception("ZlibOutStream: deflate failed"); + +// fprintf(stderr,"zos flush: after deflate: %d bytes\n", +// zs->next_out-underlying->getptr()); + + underlying->setptr(zs->next_out); + } while (zs->avail_out == 0); + } + + offset += ptr - start; + ptr = start; +} + +int ZlibOutStream::overrun(int itemSize, int nItems) +{ +// fprintf(stderr,"ZlibOutStream overrun\n"); + + if (itemSize > bufSize) + throw Exception("ZlibOutStream overrun: max itemSize exceeded"); + + while (end - ptr < itemSize) { + zs->next_in = start; + zs->avail_in = ptr - start; + + do { + underlying->check(1); + zs->next_out = underlying->getptr(); + zs->avail_out = underlying->getend() - underlying->getptr(); + +// fprintf(stderr,"zos overrun: calling deflate, avail_in %d, avail_out %d\n", +// zs->avail_in,zs->avail_out); + + int rc = deflate(zs, 0); + if (rc != Z_OK) throw Exception("ZlibOutStream: deflate failed"); + +// fprintf(stderr,"zos overrun: after deflate: %d bytes\n", +// zs->next_out-underlying->getptr()); + + underlying->setptr(zs->next_out); + } while (zs->avail_out == 0); + + // 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; +} diff --git a/rdr/ZlibOutStream.h b/rdr/ZlibOutStream.h new file mode 100644 index 00000000..e51db73b --- /dev/null +++ b/rdr/ZlibOutStream.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2002-2004 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. + */ + +// +// 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 flush(); + int length(); + + private: + + int overrun(int itemSize, int nItems); + + OutStream* underlying; + int bufSize; + int offset; + z_stream_s* zs; + U8* start; + }; + +} // end of namespace rdr + +#endif diff --git a/rdr/msvcwarning.h b/rdr/msvcwarning.h new file mode 100644 index 00000000..e93f2bbc --- /dev/null +++ b/rdr/msvcwarning.h @@ -0,0 +1,18 @@ +/* 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. + */ +#pragma warning( disable : 4800 ) // forcing bool 'true' or 'false' diff --git a/rdr/rdr.dsp b/rdr/rdr.dsp new file mode 100644 index 00000000..260f8f01 --- /dev/null +++ b/rdr/rdr.dsp @@ -0,0 +1,231 @@ +# Microsoft Developer Studio Project File - Name="rdr" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=rdr - Win32 Debug Unicode +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "rdr.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "rdr.mak" CFG="rdr - Win32 Debug Unicode" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "rdr - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "rdr - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "rdr - Win32 Debug Unicode" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "rdr - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O1 /I ".." /FI"msvcwarning.h" /D "NDEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "rdr - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "rdr - Win32 Debug Unicode" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "rdr___Win32_Debug_Unicode" +# PROP BASE Intermediate_Dir "rdr___Win32_Debug_Unicode" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_Unicode" +# PROP Intermediate_Dir "Debug_Unicode" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_LIB" /D "_DEBUG" /D "WIN32" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "rdr - Win32 Release" +# Name "rdr - Win32 Debug" +# Name "rdr - Win32 Debug Unicode" +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\Exception.h +# End Source File +# Begin Source File + +SOURCE=.\FdInStream.h +# End Source File +# Begin Source File + +SOURCE=.\FdOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\FixedMemOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\HexInStream.h +# End Source File +# Begin Source File + +SOURCE=.\HexOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\InStream.h +# End Source File +# Begin Source File + +SOURCE=.\MemInStream.h +# End Source File +# Begin Source File + +SOURCE=.\MemOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\msvcwarning.h +# End Source File +# Begin Source File + +SOURCE=.\NullOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\OutStream.h +# End Source File +# Begin Source File + +SOURCE=.\RandomStream.h +# End Source File +# Begin Source File + +SOURCE=.\SubstitutingInStream.h +# End Source File +# Begin Source File + +SOURCE=.\types.h +# End Source File +# Begin Source File + +SOURCE=.\ZlibInStream.h +# End Source File +# Begin Source File + +SOURCE=.\ZlibOutStream.h +# End Source File +# End Group +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Exception.cxx +# End Source File +# Begin Source File + +SOURCE=.\FdInStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# Begin Source File + +SOURCE=.\FdOutStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# Begin Source File + +SOURCE=.\HexInStream.cxx +# End Source File +# Begin Source File + +SOURCE=.\HexOutStream.cxx +# End Source File +# Begin Source File + +SOURCE=.\InStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# Begin Source File + +SOURCE=.\NullOutStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# Begin Source File + +SOURCE=.\RandomStream.cxx +# End Source File +# Begin Source File + +SOURCE=.\ZlibInStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# Begin Source File + +SOURCE=.\ZlibOutStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# End Group +# End Target +# End Project diff --git a/rdr/types.h b/rdr/types.h new file mode 100644 index 00000000..3798c975 --- /dev/null +++ b/rdr/types.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2002-2004 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 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; + }; + +} // end of namespace rdr + +#endif |