* rdr/Exception.h, rdr/FdInStream.cxx, rdr/FdInStream.h, rdr/FdOutStream.cxx, rdr/FdOutStream.h, rdr/FixedMemOutStream.h, rdr/InStream.cxx, rdr/InStream.h, rdr/MemInStream.h, rdr/MemOutStream.h, rdr/NullOutStream.cxx, rdr/NullOutStream.h, rdr/OutStream.h, rdr/ZlibInStream.cxx, rdr/ZlibInStream.h, rdr/ZlibOutStream.cxx, rdr/ZlibOutStream.h, rdr/types.h, zrle.cxx, zrleDecode.h, zrleEncode.h: remove original C++ ZRLE implementation. Its been ported to C. * NEWS: copy the existing ChangeLog to here and make this a more detailed ChangeLog.pull/1/head
parent
937b906f0d
commit
9edf7e56bb
@ -1,147 +1,13 @@
|
||||
Mark sent me patches to no longer need C++ for ZRLE encoding!
|
||||
added --disable-cxx Option for configure
|
||||
x11vnc changes from Karl Runge:
|
||||
- Changed all those whimpy printf(...)'s into manly fprintf(stdxxx,...)'s.
|
||||
|
||||
- Added -q switch (quiet) to suppress printing all the debug-looking output.
|
||||
|
||||
- Added -bg switch to fork into background after everything is set up.
|
||||
(checks for LIBVNCSERVER_HAVE_FORK and LIBVNCSERVER_HAVE_SETSID)
|
||||
|
||||
- Print this string out to stdout: 'PORT=XXXX' (usually XXXX = 5900).
|
||||
Combining with -bg, easy to write a ssh/rsh wrapper with something like:
|
||||
port=`ssh $host "x11vnc -bg .."` then run vncviewer based on $port output.
|
||||
(tunneling the vnc traffic thru ssh a bit more messy, but doable)
|
||||
|
||||
- Quite a bit of code to be more careful when doing 8bpp indexed color, e.g.
|
||||
not assuming NCOLORS is 256, handling 8bit TrueColor and Direct Color, etc
|
||||
(I did all this probably in April, not quite clear in my mind now, but
|
||||
I did test it out a fair amount on my old Sparcstation 20 wrt a user's
|
||||
questions).
|
||||
introduce rfbErr for Errors (Erik)
|
||||
make rfbLog overridable (suggested by Erik)
|
||||
don't reutrn on EINTR in WriteExact()/ReadExact() (suggested by Erik)
|
||||
use AX_PREFIX_CONFIG_H to prefix constants in config.h to avoid
|
||||
name clashes (also suggested by Erik)
|
||||
transformed Bool, KeySym, Pixel to rfbBool, rfbKeySym, rfbPixel
|
||||
(as suggested by Erik)
|
||||
purged exit() calls (suggested by Erik)
|
||||
fixed bug with maxRectsPerUpdate and Tight Encoding (these are incompatible)
|
||||
checked sync with TightVNC 1.2.8:
|
||||
viewonly/full passwords; if given a list, only the first is a full one
|
||||
vncRandomBytes is a little more secure now
|
||||
new weights for tight encoding
|
||||
checked sync with RealVNC 3.3.7
|
||||
introduced maxRectsPerUpdate
|
||||
added first alpha version of LibVNCClient
|
||||
added simple and simple15 example (really simple examples)
|
||||
finally got around to fix configure in CVS
|
||||
long standing http bug (.jar was sent twice) fixed by a friend of Karl named Mike
|
||||
http options in cargs
|
||||
when closing a client and no longer listening for new ones, don't crash
|
||||
fixed a bug with ClientConnectionGone
|
||||
endianness is checked at configure time
|
||||
fixed a bug that prevented the first client from being closed
|
||||
fixed that annoying "libvncserver-config --link" bug
|
||||
make rfbReverseByte public (for rdp2vnc)
|
||||
fixed compilation on OS X, IRIX, Solaris
|
||||
install target for headers is now ${prefix}/include/rfb ("#include <rfb/rfb.h>")
|
||||
renamed "sraRegion.h" to "rfbregion.h"
|
||||
CARD{8,16,32} are more standard uint{8,16,32}_t now
|
||||
fixed LinuxVNC colour handling
|
||||
fixed a bug with pthreads where the connection was not closed
|
||||
moved vncterm to main package (LinuxVNC included)
|
||||
portability fixes (IRIX, OSX, Solaris)
|
||||
more portable way to determine endianness and types of a given size
|
||||
through autoconf based methods
|
||||
0.5
|
||||
rpm packaging through autoconf
|
||||
autoconf'ed the whole package (including optional support for zlib,
|
||||
pthreads and libjpeg as well as zrle/c++)
|
||||
moved appropriate files to contrib/ and examples/ respectively
|
||||
fixed long standing cargs bug (Justin "Zippy" Dearing)
|
||||
Even better x11vnc from Karl J. Runge! (supports different kbd layouts of
|
||||
client/server)
|
||||
Better x11vnc from Karl J. Runge!
|
||||
fixed severe bug (Const Kaplinsky)
|
||||
got patch from Const Kaplisnky with CursorPosUpdate encoding and some Docs
|
||||
sync'ed with newest RealVNC (ZRLE encoding)
|
||||
a HTTP request for tunnelling was added (to fool strict web proxies)
|
||||
sync'ed with TightVNC 1.2.5
|
||||
0.4
|
||||
support for NewFB from Const Kaplinsky
|
||||
memory leaks squashed (localtime pseudo leak is still there :-)
|
||||
small improvements for OSXvnc (still not working correctly)
|
||||
synced with TightVNC 1.2.3
|
||||
solaris compile cleanups
|
||||
many x11vnc improvements
|
||||
added backchannel, an encoding which needs special clients to pass
|
||||
arbitrary data to the client
|
||||
changes from Tim Jansen regarding multi threading and client blocking
|
||||
as well as C++ compliancy
|
||||
x11vnc can be controlled by starting again with special options if compiling
|
||||
with LOCAL_CONTROL defined
|
||||
0.3
|
||||
added x11vnc, a x0rfbserver clone
|
||||
regard deferUpdateTime in processEvents, if usec<0
|
||||
initialize deferUpdateTime (memory "leak"!)
|
||||
changed command line handling (arguments are parsed and then removed)
|
||||
added very simple example: zippy
|
||||
added rfbDrawLine, rfbDrawPixel
|
||||
0.2
|
||||
inserted a deferUpdate mechanism (X11 independent).
|
||||
removed deletion of requestedRegion
|
||||
added rfbLoadConsoleFont
|
||||
fixed font colour handling.
|
||||
added rfbSelectBox
|
||||
added rfbDrawCharWithClip to allow for clipping and a background colour.
|
||||
fixed font colours
|
||||
added rfbFillRect
|
||||
added IO function to check password.
|
||||
rfbNewClient now sets the socket in the fd_set (for the select() call)
|
||||
when compiling the library with HAVE_PTHREADS and an application
|
||||
which includes "rfb.h" without, the structures got mixed up.
|
||||
So, the pthreads section is now always at the end, and also
|
||||
you get a linker error for rfbInitServer when using two different
|
||||
pthread setups.
|
||||
fixed two deadlocks: when setting a cursor and when using CopyRect
|
||||
fixed CopyRect when copying modified regions (they lost the modified
|
||||
property)
|
||||
WIN32 target compiles and works for example :-)
|
||||
fixed CopyRect (was using the wrong order of rectangles...)
|
||||
should also work with pthreads, because copyrects are
|
||||
always sent immediately (so that two consecutive copy rects
|
||||
cannot conflict).
|
||||
changed rfbUndrawCursor(rfbClientPtr) to (rfbScreenInfoPtr), because
|
||||
this makes more sense!
|
||||
flag backgroundLoop in rfbScreenInfo (if having pthreads)
|
||||
CopyRect & CopyRegion were implemented.
|
||||
if you use a rfbDoCopyR* function, it copies the data in the
|
||||
framebuffer. If you prefer to do that yourself, use rfbScheduleCopyR*
|
||||
instead; this doesn't modify the frameBuffer.
|
||||
added flag to optionally not send XCursor updates, but only RichCursor,
|
||||
or if that is not possible, fall back to server side cursor.
|
||||
This is useful if your cursor has many nice colours.
|
||||
fixed java viewer on server side:
|
||||
SendCursorUpdate would send data even before the client pixel format
|
||||
was set, but the java applet doesn't like the server's format.
|
||||
fixed two pthread issues:
|
||||
rfbSendFramebuffer was sent by a ProcessClientMessage function
|
||||
(unprotected by updateMutex).
|
||||
cursor coordinates were set without protection by cursorMutex
|
||||
source is now equivalent to TridiaVNC 1.2.1
|
||||
pthreads now work (use iterators!)
|
||||
cursors are supported (rfbSetCursor automatically undraws cursor)
|
||||
support for 3 bytes/pixel (slow!)
|
||||
server side colourmap support
|
||||
fixed rfbCloseClient not to close the connection (pthreads!)
|
||||
this is done lazily (and with proper signalling).
|
||||
cleaned up mac.c (from original OSXvnc); now compiles (untested!)
|
||||
compiles cleanly on Linux, IRIX, BSD, Apple (Darwin)
|
||||
fixed prototypes
|
||||
0.1
|
||||
rewrote API to use pseudo-methods instead of required functions.
|
||||
lots of clean up.
|
||||
Example can show symbols now.
|
||||
All encodings
|
||||
HTTP
|
||||
2003-09-11 Mark McLoughlin <mark@skynet.ie>
|
||||
|
||||
* rdr/Exception.h, rdr/FdInStream.cxx, rdr/FdInStream.h,
|
||||
rdr/FdOutStream.cxx, rdr/FdOutStream.h, rdr/FixedMemOutStream.h,
|
||||
rdr/InStream.cxx, rdr/InStream.h, rdr/MemInStream.h,
|
||||
rdr/MemOutStream.h, rdr/NullOutStream.cxx, rdr/NullOutStream.h,
|
||||
rdr/OutStream.h, rdr/ZlibInStream.cxx, rdr/ZlibInStream.h,
|
||||
rdr/ZlibOutStream.cxx, rdr/ZlibOutStream.h, rdr/types.h,
|
||||
zrle.cxx, zrleDecode.h, zrleEncode.h: remove original
|
||||
C++ ZRLE implementation. Its been ported to C.
|
||||
|
||||
* NEWS: copy the existing ChangeLog to here and make
|
||||
this a more detailed ChangeLog.
|
||||
|
@ -1,39 +1,147 @@
|
||||
Question: Why the *&!"/(§ did you change so many things in the API?
|
||||
Answer: It was necessary to make this library slightly less
|
||||
painful to use with other libraries.
|
||||
Mark sent me patches to no longer need C++ for ZRLE encoding!
|
||||
added --disable-cxx Option for configure
|
||||
x11vnc changes from Karl Runge:
|
||||
- Changed all those whimpy printf(...)'s into manly fprintf(stdxxx,...)'s.
|
||||
|
||||
Anyway, most changes are just search-and-replace:
|
||||
- Added -q switch (quiet) to suppress printing all the debug-looking output.
|
||||
|
||||
#include "rfb.h" -> #include <rfb/rfb.h>
|
||||
CARD8 -> uint8_t
|
||||
CARD16 -> uint16_t
|
||||
CARD32 -> uint32_t
|
||||
Pixel -> rfbPixel
|
||||
KeySym -> rfbKeySym
|
||||
Bool -> rfbBool
|
||||
- Added -bg switch to fork into background after everything is set up.
|
||||
(checks for LIBVNCSERVER_HAVE_FORK and LIBVNCSERVER_HAVE_SETSID)
|
||||
|
||||
also, rfbUsage doesn't exit any longer, but returns FALSE
|
||||
- Print this string out to stdout: 'PORT=XXXX' (usually XXXX = 5900).
|
||||
Combining with -bg, easy to write a ssh/rsh wrapper with something like:
|
||||
port=`ssh $host "x11vnc -bg .."` then run vncviewer based on $port output.
|
||||
(tunneling the vnc traffic thru ssh a bit more messy, but doable)
|
||||
|
||||
If you used some constants defined in rfbconfig.h, you now
|
||||
have to prefix LIBVNCSERVER_ to the constants.
|
||||
|
||||
Upcoming 0.6 release!
|
||||
|
||||
lots of bugs fixed.
|
||||
|
||||
|
||||
Version 5.0:
|
||||
|
||||
The library just got autoconf && automake support as well as a real install
|
||||
target!
|
||||
|
||||
x11vnc was much improved thanks to Karl Runge!
|
||||
|
||||
CursorPosUpdate encoding supported thanks to Const Kaplinsky!
|
||||
|
||||
ZRLE encoding, if you have a c++ compiler!
|
||||
|
||||
HTTP now optionally handles HTTP proxy functions to connect to the same
|
||||
server only.
|
||||
|
||||
Of course, a lot of bugs fixed since last release...
|
||||
- Quite a bit of code to be more careful when doing 8bpp indexed color, e.g.
|
||||
not assuming NCOLORS is 256, handling 8bit TrueColor and Direct Color, etc
|
||||
(I did all this probably in April, not quite clear in my mind now, but
|
||||
I did test it out a fair amount on my old Sparcstation 20 wrt a user's
|
||||
questions).
|
||||
introduce rfbErr for Errors (Erik)
|
||||
make rfbLog overridable (suggested by Erik)
|
||||
don't reutrn on EINTR in WriteExact()/ReadExact() (suggested by Erik)
|
||||
use AX_PREFIX_CONFIG_H to prefix constants in config.h to avoid
|
||||
name clashes (also suggested by Erik)
|
||||
transformed Bool, KeySym, Pixel to rfbBool, rfbKeySym, rfbPixel
|
||||
(as suggested by Erik)
|
||||
purged exit() calls (suggested by Erik)
|
||||
fixed bug with maxRectsPerUpdate and Tight Encoding (these are incompatible)
|
||||
checked sync with TightVNC 1.2.8:
|
||||
viewonly/full passwords; if given a list, only the first is a full one
|
||||
vncRandomBytes is a little more secure now
|
||||
new weights for tight encoding
|
||||
checked sync with RealVNC 3.3.7
|
||||
introduced maxRectsPerUpdate
|
||||
added first alpha version of LibVNCClient
|
||||
added simple and simple15 example (really simple examples)
|
||||
finally got around to fix configure in CVS
|
||||
long standing http bug (.jar was sent twice) fixed by a friend of Karl named Mike
|
||||
http options in cargs
|
||||
when closing a client and no longer listening for new ones, don't crash
|
||||
fixed a bug with ClientConnectionGone
|
||||
endianness is checked at configure time
|
||||
fixed a bug that prevented the first client from being closed
|
||||
fixed that annoying "libvncserver-config --link" bug
|
||||
make rfbReverseByte public (for rdp2vnc)
|
||||
fixed compilation on OS X, IRIX, Solaris
|
||||
install target for headers is now ${prefix}/include/rfb ("#include <rfb/rfb.h>")
|
||||
renamed "sraRegion.h" to "rfbregion.h"
|
||||
CARD{8,16,32} are more standard uint{8,16,32}_t now
|
||||
fixed LinuxVNC colour handling
|
||||
fixed a bug with pthreads where the connection was not closed
|
||||
moved vncterm to main package (LinuxVNC included)
|
||||
portability fixes (IRIX, OSX, Solaris)
|
||||
more portable way to determine endianness and types of a given size
|
||||
through autoconf based methods
|
||||
0.5
|
||||
rpm packaging through autoconf
|
||||
autoconf'ed the whole package (including optional support for zlib,
|
||||
pthreads and libjpeg as well as zrle/c++)
|
||||
moved appropriate files to contrib/ and examples/ respectively
|
||||
fixed long standing cargs bug (Justin "Zippy" Dearing)
|
||||
Even better x11vnc from Karl J. Runge! (supports different kbd layouts of
|
||||
client/server)
|
||||
Better x11vnc from Karl J. Runge!
|
||||
fixed severe bug (Const Kaplinsky)
|
||||
got patch from Const Kaplisnky with CursorPosUpdate encoding and some Docs
|
||||
sync'ed with newest RealVNC (ZRLE encoding)
|
||||
a HTTP request for tunnelling was added (to fool strict web proxies)
|
||||
sync'ed with TightVNC 1.2.5
|
||||
0.4
|
||||
support for NewFB from Const Kaplinsky
|
||||
memory leaks squashed (localtime pseudo leak is still there :-)
|
||||
small improvements for OSXvnc (still not working correctly)
|
||||
synced with TightVNC 1.2.3
|
||||
solaris compile cleanups
|
||||
many x11vnc improvements
|
||||
added backchannel, an encoding which needs special clients to pass
|
||||
arbitrary data to the client
|
||||
changes from Tim Jansen regarding multi threading and client blocking
|
||||
as well as C++ compliancy
|
||||
x11vnc can be controlled by starting again with special options if compiling
|
||||
with LOCAL_CONTROL defined
|
||||
0.3
|
||||
added x11vnc, a x0rfbserver clone
|
||||
regard deferUpdateTime in processEvents, if usec<0
|
||||
initialize deferUpdateTime (memory "leak"!)
|
||||
changed command line handling (arguments are parsed and then removed)
|
||||
added very simple example: zippy
|
||||
added rfbDrawLine, rfbDrawPixel
|
||||
0.2
|
||||
inserted a deferUpdate mechanism (X11 independent).
|
||||
removed deletion of requestedRegion
|
||||
added rfbLoadConsoleFont
|
||||
fixed font colour handling.
|
||||
added rfbSelectBox
|
||||
added rfbDrawCharWithClip to allow for clipping and a background colour.
|
||||
fixed font colours
|
||||
added rfbFillRect
|
||||
added IO function to check password.
|
||||
rfbNewClient now sets the socket in the fd_set (for the select() call)
|
||||
when compiling the library with HAVE_PTHREADS and an application
|
||||
which includes "rfb.h" without, the structures got mixed up.
|
||||
So, the pthreads section is now always at the end, and also
|
||||
you get a linker error for rfbInitServer when using two different
|
||||
pthread setups.
|
||||
fixed two deadlocks: when setting a cursor and when using CopyRect
|
||||
fixed CopyRect when copying modified regions (they lost the modified
|
||||
property)
|
||||
WIN32 target compiles and works for example :-)
|
||||
fixed CopyRect (was using the wrong order of rectangles...)
|
||||
should also work with pthreads, because copyrects are
|
||||
always sent immediately (so that two consecutive copy rects
|
||||
cannot conflict).
|
||||
changed rfbUndrawCursor(rfbClientPtr) to (rfbScreenInfoPtr), because
|
||||
this makes more sense!
|
||||
flag backgroundLoop in rfbScreenInfo (if having pthreads)
|
||||
CopyRect & CopyRegion were implemented.
|
||||
if you use a rfbDoCopyR* function, it copies the data in the
|
||||
framebuffer. If you prefer to do that yourself, use rfbScheduleCopyR*
|
||||
instead; this doesn't modify the frameBuffer.
|
||||
added flag to optionally not send XCursor updates, but only RichCursor,
|
||||
or if that is not possible, fall back to server side cursor.
|
||||
This is useful if your cursor has many nice colours.
|
||||
fixed java viewer on server side:
|
||||
SendCursorUpdate would send data even before the client pixel format
|
||||
was set, but the java applet doesn't like the server's format.
|
||||
fixed two pthread issues:
|
||||
rfbSendFramebuffer was sent by a ProcessClientMessage function
|
||||
(unprotected by updateMutex).
|
||||
cursor coordinates were set without protection by cursorMutex
|
||||
source is now equivalent to TridiaVNC 1.2.1
|
||||
pthreads now work (use iterators!)
|
||||
cursors are supported (rfbSetCursor automatically undraws cursor)
|
||||
support for 3 bytes/pixel (slow!)
|
||||
server side colourmap support
|
||||
fixed rfbCloseClient not to close the connection (pthreads!)
|
||||
this is done lazily (and with proper signalling).
|
||||
cleaned up mac.c (from original OSXvnc); now compiles (untested!)
|
||||
compiles cleanly on Linux, IRIX, BSD, Apple (Darwin)
|
||||
fixed prototypes
|
||||
0.1
|
||||
rewrote API to use pseudo-methods instead of required functions.
|
||||
lots of clean up.
|
||||
Example can show symbols now.
|
||||
All encodings
|
||||
HTTP
|
||||
|
@ -1,71 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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];
|
||||
Exception(const char* s=0, const char* e="rdr::Exception") {
|
||||
str_[0] = 0;
|
||||
strncat(str_, e, len-1);
|
||||
if (s) {
|
||||
strncat(str_, ": ", len-1-strlen(str_));
|
||||
strncat(str_, s, len-1-strlen(str_));
|
||||
}
|
||||
}
|
||||
virtual const char* str() const { return str_; }
|
||||
};
|
||||
|
||||
struct SystemException : public Exception {
|
||||
int err;
|
||||
SystemException(const char* s, int err_) : err(err_) {
|
||||
str_[0] = 0;
|
||||
strncat(str_, "rdr::SystemException: ", len-1);
|
||||
strncat(str_, s, len-1-strlen(str_));
|
||||
strncat(str_, ": ", len-1-strlen(str_));
|
||||
strncat(str_, strerror(err), len-1-strlen(str_));
|
||||
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_));
|
||||
}
|
||||
};
|
||||
|
||||
struct TimedOut : public Exception {
|
||||
TimedOut(const char* s=0) : Exception(s,"rdr::TimedOut") {}
|
||||
};
|
||||
|
||||
struct EndOfStream : public Exception {
|
||||
EndOfStream(const char* s=0) : Exception(s,"rdr::EndOfStream") {}
|
||||
};
|
||||
|
||||
struct FrameException : public Exception {
|
||||
FrameException(const char* s=0) : Exception(s,"rdr::FrameException") {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,251 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock.h>
|
||||
#include <sys/timeb.h>
|
||||
#define read(s,b,l) recv(s,(char*)b,l,0)
|
||||
#undef errno
|
||||
#define errno WSAGetLastError()
|
||||
#else
|
||||
#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>
|
||||
|
||||
extern "C" {
|
||||
extern void rfbLog(const char *format, ...);
|
||||
}
|
||||
|
||||
using namespace rdr;
|
||||
|
||||
enum { DEFAULT_BUF_SIZE = 8192,
|
||||
MIN_BULK_SIZE = 1024 };
|
||||
|
||||
FdInStream::FdInStream(int fd_, int timeout_, int bufSize_)
|
||||
: fd(fd_), timeout(timeout_), blockCallback(0), blockCallbackArg(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_, void (*blockCallback_)(void*),
|
||||
void* blockCallbackArg_, int bufSize_)
|
||||
: fd(fd_), timeout(0), blockCallback(blockCallback_),
|
||||
blockCallbackArg(blockCallbackArg_),
|
||||
timing(false), timeWaitedIn100us(5), timedKbits(0),
|
||||
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
||||
{
|
||||
ptr = end = start = new U8[bufSize];
|
||||
}
|
||||
|
||||
FdInStream::~FdInStream()
|
||||
{
|
||||
delete [] start;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
end += n;
|
||||
}
|
||||
|
||||
if (itemSize * nItems > end - ptr)
|
||||
nItems = (end - ptr) / itemSize;
|
||||
|
||||
return nItems;
|
||||
}
|
||||
|
||||
int FdInStream::checkReadable(int fd, int timeout)
|
||||
{
|
||||
while (true) {
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd, &rfds);
|
||||
int n = select(fd+1, &rfds, 0, 0, &tv);
|
||||
if (n != -1 || errno != EINTR)
|
||||
return n;
|
||||
rfbLog("select returned EINTR\n");
|
||||
}
|
||||
}
|
||||
|
||||
#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 {
|
||||
struct timeb tb;
|
||||
ftime(&tb);
|
||||
tv->tv_sec = tb.time;
|
||||
tv->tv_usec = tb.millitm * 1000;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int FdInStream::readWithTimeoutOrCallback(void* buf, int len)
|
||||
{
|
||||
struct timeval before, after;
|
||||
if (timing)
|
||||
gettimeofday(&before, 0);
|
||||
|
||||
int n = checkReadable(fd, timeout);
|
||||
|
||||
if (n < 0) throw SystemException("select",errno);
|
||||
|
||||
if (n == 0) {
|
||||
if (timeout) throw TimedOut();
|
||||
if (blockCallback) (*blockCallback)(blockCallbackArg);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
n = ::read(fd, buf, len);
|
||||
if (n != -1 || errno != EINTR)
|
||||
break;
|
||||
rfbLog("read returned EINTR\n");
|
||||
}
|
||||
|
||||
if (n < 0) throw SystemException("read",errno);
|
||||
if (n == 0) throw EndOfStream();
|
||||
|
||||
if (timing) {
|
||||
gettimeofday(&after, 0);
|
||||
// rfbLog("%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) {
|
||||
// rfbLog("new kbps infinite t %d k %d\n",
|
||||
// newTimeWaited, newKbits);
|
||||
// } else {
|
||||
// rfbLog("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;
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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 FdInStream : public InStream {
|
||||
|
||||
public:
|
||||
|
||||
FdInStream(int fd, int timeout=0, int bufSize=0);
|
||||
FdInStream(int fd, void (*blockCallback)(void*), void* blockCallbackArg=0,
|
||||
int bufSize=0);
|
||||
virtual ~FdInStream();
|
||||
|
||||
int getFd() { return fd; }
|
||||
int pos();
|
||||
void readBytes(void* data, int length);
|
||||
int bytesInBuf() { return end - ptr; }
|
||||
|
||||
void startTiming();
|
||||
void stopTiming();
|
||||
unsigned int kbitsPerSecond();
|
||||
unsigned int timeWaited() { return timeWaitedIn100us; }
|
||||
|
||||
protected:
|
||||
int overrun(int itemSize, int nItems);
|
||||
|
||||
private:
|
||||
int checkReadable(int fd, int timeout);
|
||||
int readWithTimeoutOrCallback(void* buf, int len);
|
||||
|
||||
int fd;
|
||||
int timeout;
|
||||
void (*blockCallback)(void*);
|
||||
void* blockCallbackArg;
|
||||
|
||||
bool timing;
|
||||
unsigned int timeWaitedIn100us;
|
||||
unsigned int timedKbits;
|
||||
|
||||
int bufSize;
|
||||
int offset;
|
||||
U8* start;
|
||||
};
|
||||
|
||||
} // end of namespace rdr
|
||||
|
||||
#endif
|
@ -1,113 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock.h>
|
||||
#define write(s,b,l) send(s,(const char*)b,l,0)
|
||||
#undef errno
|
||||
#define errno WSAGetLastError()
|
||||
#else
|
||||
#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 bufSize_)
|
||||
: fd(fd_), 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::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 = write(fd, dataPtr, length);
|
||||
|
||||
if (n < 0) throw SystemException("write",errno);
|
||||
|
||||
length -= n;
|
||||
dataPtr += n;
|
||||
offset += n;
|
||||
}
|
||||
}
|
||||
|
||||
int FdOutStream::length()
|
||||
{
|
||||
return offset + ptr - start;
|
||||
}
|
||||
|
||||
void FdOutStream::flush()
|
||||
{
|
||||
U8* sentUpTo = start;
|
||||
while (sentUpTo < ptr) {
|
||||
int n = write(fd, (const void*) sentUpTo, ptr - sentUpTo);
|
||||
|
||||
if (n < 0) throw SystemException("write",errno);
|
||||
|
||||
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;
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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 bufSize=0);
|
||||
virtual ~FdOutStream();
|
||||
|
||||
int getFd() { return fd; }
|
||||
|
||||
void flush();
|
||||
int length();
|
||||
void writeBytes(const void* data, int length);
|
||||
|
||||
private:
|
||||
int overrun(int itemSize, int nItems);
|
||||
int fd;
|
||||
int bufSize;
|
||||
int offset;
|
||||
U8* start;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,52 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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
|
@ -1,35 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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;
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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).
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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).
|
||||
|
||||
virtual int overrun(int itemSize, int nItems) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
InStream() {}
|
||||
const U8* ptr;
|
||||
const U8* end;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,47 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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_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) {
|
||||
ptr = start = (const U8*)data;
|
||||
end = start + len;
|
||||
}
|
||||
|
||||
int pos() { return ptr - start; }
|
||||
void reposition(int pos) { ptr = start + pos; }
|
||||
|
||||
private:
|
||||
|
||||
int overrun(int itemSize, int nItems) { throw EndOfStream(); }
|
||||
const U8* start;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,82 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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
|
@ -1,60 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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;
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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
|
@ -1,152 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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
|
@ -1,121 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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();
|
||||
end = start; // throw away any data
|
||||
}
|
||||
underlying = 0;
|
||||
}
|
||||
|
||||
int ZlibInStream::overrun(int itemSize, int nItems)
|
||||
{
|
||||
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) {
|
||||
decompress();
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
void ZlibInStream::decompress()
|
||||
{
|
||||
zs->next_out = (U8*)end;
|
||||
zs->avail_out = start + bufSize - end;
|
||||
|
||||
underlying->check(1);
|
||||
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);
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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);
|
||||
void decompress();
|
||||
|
||||
InStream* underlying;
|
||||
int bufSize;
|
||||
int offset;
|
||||
z_stream_s* zs;
|
||||
int bytesIn;
|
||||
U8* start;
|
||||
};
|
||||
|
||||
} // end of namespace rdr
|
||||
|
||||
#endif
|
@ -1,144 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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>
|
||||
|
||||
extern "C" {
|
||||
extern void rfbLog(const char *format, ...);
|
||||
}
|
||||
|
||||
using namespace rdr;
|
||||
|
||||
enum { DEFAULT_BUF_SIZE = 16384 };
|
||||
|
||||
ZlibOutStream::ZlibOutStream(OutStream* os, int bufSize_)
|
||||
: 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, Z_DEFAULT_COMPRESSION) != 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;
|
||||
|
||||
// rfbLog("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();
|
||||
|
||||
// rfbLog("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");
|
||||
|
||||
// rfbLog("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)
|
||||
{
|
||||
// rfbLog("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();
|
||||
|
||||
// rfbLog("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");
|
||||
|
||||
// rfbLog("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.
|
||||
rfbLog("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;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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);
|
||||
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
|
@ -1,33 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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;
|
||||
|
||||
} // end of namespace rdr
|
||||
|
||||
#endif
|
@ -1,179 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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.
|
||||
//
|
||||
|
||||
//
|
||||
// zrle.cc
|
||||
//
|
||||
// Routines to implement Zlib Run-length Encoding (ZRLE).
|
||||
//
|
||||
|
||||
extern "C" {
|
||||
#include <rfb/rfb.h>
|
||||
}
|
||||
#include <rdr/MemOutStream.h>
|
||||
#include <rdr/ZlibOutStream.h>
|
||||
|
||||
|
||||
#define GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf) \
|
||||
char *fbptr = (cl->screen->frameBuffer \
|
||||
+ (cl->screen->paddedWidthInBytes * ty) \
|
||||
+ (tx * (cl->screen->bitsPerPixel / 8))); \
|
||||
\
|
||||
(*cl->translateFn)(cl->translateLookupTable, &cl->screen->rfbServerFormat,\
|
||||
&cl->format, fbptr, (char*)buf, \
|
||||
cl->screen->paddedWidthInBytes, tw, th);
|
||||
|
||||
#define EXTRA_ARGS , rfbClientPtr cl
|
||||
|
||||
#define BPP 8
|
||||
#include <zrleEncode.h>
|
||||
#undef BPP
|
||||
#define BPP 16
|
||||
#include <zrleEncode.h>
|
||||
#undef BPP
|
||||
#define BPP 32
|
||||
#include <zrleEncode.h>
|
||||
#define CPIXEL 24A
|
||||
#include <zrleEncode.h>
|
||||
#undef CPIXEL
|
||||
#define CPIXEL 24B
|
||||
#include <zrleEncode.h>
|
||||
#undef CPIXEL
|
||||
#undef BPP
|
||||
|
||||
|
||||
/*
|
||||
* zrleBeforeBuf contains pixel data in the client's format. It must be at
|
||||
* least one pixel bigger than the largest tile of pixel data, since the
|
||||
* ZRLE encoding algorithm writes to the position one past the end of the pixel
|
||||
* data.
|
||||
*/
|
||||
|
||||
static char zrleBeforeBuf[rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4];
|
||||
|
||||
static rdr::MemOutStream mos;
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingZRLE - send a given rectangle using ZRLE encoding.
|
||||
*/
|
||||
|
||||
|
||||
rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
|
||||
{
|
||||
if (!cl->zrleData) cl->zrleData = new rdr::ZlibOutStream;
|
||||
rdr::ZlibOutStream* zos = (rdr::ZlibOutStream*)cl->zrleData;
|
||||
mos.clear();
|
||||
|
||||
switch (cl->format.bitsPerPixel) {
|
||||
|
||||
case 8:
|
||||
zrleEncode8( x, y, w, h, &mos, zos, zrleBeforeBuf, cl);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
zrleEncode16(x, y, w, h, &mos, zos, zrleBeforeBuf, cl);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
bool fitsInLS3Bytes
|
||||
= ((cl->format.redMax << cl->format.redShift) < (1<<24) &&
|
||||
(cl->format.greenMax << cl->format.greenShift) < (1<<24) &&
|
||||
(cl->format.blueMax << cl->format.blueShift) < (1<<24));
|
||||
|
||||
bool fitsInMS3Bytes = (cl->format.redShift > 7 &&
|
||||
cl->format.greenShift > 7 &&
|
||||
cl->format.blueShift > 7);
|
||||
|
||||
if ((fitsInLS3Bytes && !cl->format.bigEndian) ||
|
||||
(fitsInMS3Bytes && cl->format.bigEndian))
|
||||
{
|
||||
zrleEncode24A(x, y, w, h, &mos, zos, zrleBeforeBuf, cl);
|
||||
}
|
||||
else if ((fitsInLS3Bytes && cl->format.bigEndian) ||
|
||||
(fitsInMS3Bytes && !cl->format.bigEndian))
|
||||
{
|
||||
zrleEncode24B(x, y, w, h, &mos, zos, zrleBeforeBuf, cl);
|
||||
}
|
||||
else
|
||||
{
|
||||
zrleEncode32(x, y, w, h, &mos, zos, zrleBeforeBuf, cl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cl->rfbRectanglesSent[rfbEncodingZRLE]++;
|
||||
cl->rfbBytesSent[rfbEncodingZRLE] += (sz_rfbFramebufferUpdateRectHeader
|
||||
+ sz_rfbZRLEHeader + mos.length());
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader
|
||||
> UPDATE_BUF_SIZE)
|
||||
{
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingZRLE);
|
||||
|
||||
memcpy(cl->updateBuf+cl->ublen, (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
rfbZRLEHeader hdr;
|
||||
|
||||
hdr.length = Swap32IfLE(mos.length());
|
||||
|
||||
memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader);
|
||||
cl->ublen += sz_rfbZRLEHeader;
|
||||
|
||||
// copy into updateBuf and send from there. Maybe should send directly?
|
||||
|
||||
for (int i = 0; i < mos.length();) {
|
||||
|
||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
||||
|
||||
if (i + bytesToCopy > mos.length()) {
|
||||
bytesToCopy = mos.length() - i;
|
||||
}
|
||||
|
||||
memcpy(cl->updateBuf+cl->ublen, (uint8_t*)mos.data() + i, bytesToCopy);
|
||||
|
||||
cl->ublen += bytesToCopy;
|
||||
i += bytesToCopy;
|
||||
|
||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void FreeZrleData(rfbClientPtr cl)
|
||||
{
|
||||
delete (rdr::ZlibOutStream*)cl->zrleData;
|
||||
}
|
||||
|
@ -1,241 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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.
|
||||
|
||||
//
|
||||
// zrleDecode.h - zrle decoding function.
|
||||
//
|
||||
// Before including this file, you must define a number of CPP macros.
|
||||
//
|
||||
// BPP should be 8, 16 or 32 depending on the bits per pixel.
|
||||
// FILL_RECT
|
||||
// IMAGE_RECT
|
||||
|
||||
#include <rdr/ZlibInStream.h>
|
||||
#include <rdr/InStream.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace rdr;
|
||||
|
||||
/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same
|
||||
but also expands its arguments if they are macros */
|
||||
|
||||
#ifndef __RFB_CONCAT2E
|
||||
#define __RFB_CONCAT2(a,b) a##b
|
||||
#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
|
||||
#endif
|
||||
|
||||
#ifdef CPIXEL
|
||||
#define PIXEL_T __RFB_CONCAT2E(rdr::U,BPP)
|
||||
#define READ_PIXEL __RFB_CONCAT2E(readOpaque,CPIXEL)
|
||||
#define ZRLE_DECODE_BPP __RFB_CONCAT2E(zrleDecode,CPIXEL)
|
||||
#else
|
||||
#define PIXEL_T __RFB_CONCAT2E(rdr::U,BPP)
|
||||
#define READ_PIXEL __RFB_CONCAT2E(readOpaque,BPP)
|
||||
#define ZRLE_DECODE_BPP __RFB_CONCAT2E(zrleDecode,BPP)
|
||||
#endif
|
||||
|
||||
void ZRLE_DECODE_BPP (int x, int y, int w, int h, rdr::InStream* is,
|
||||
rdr::ZlibInStream* zis, PIXEL_T* buf)
|
||||
{
|
||||
int length = is->readU32();
|
||||
zis->setUnderlying(is, length);
|
||||
|
||||
for (int ty = y; ty < y+h; ty += rfbZRLETileHeight) {
|
||||
int th = rfbZRLETileHeight;
|
||||
if (th > y+h-ty) th = y+h-ty;
|
||||
for (int tx = x; tx < x+w; tx += rfbZRLETileWidth) {
|
||||
int tw = rfbZRLETileWidth;
|
||||
if (tw > x+w-tx) tw = x+w-tx;
|
||||
|
||||
int mode = zis->readU8();
|
||||
bool rle = mode & 128;
|
||||
int palSize = mode & 127;
|
||||
PIXEL_T palette[128];
|
||||
|
||||
// fprintf(stderr,"rle %d palSize %d\n",rle,palSize);
|
||||
|
||||
for (int i = 0; i < palSize; i++) {
|
||||
palette[i] = zis->READ_PIXEL();
|
||||
}
|
||||
|
||||
if (palSize == 1) {
|
||||
PIXEL_T pix = palette[0];
|
||||
FILL_RECT(tx,ty,tw,th,pix);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!rle) {
|
||||
if (palSize == 0) {
|
||||
|
||||
// raw
|
||||
|
||||
#ifdef CPIXEL
|
||||
for (PIXEL_T* ptr = buf; ptr < buf+tw*th; ptr++) {
|
||||
*ptr = zis->READ_PIXEL();
|
||||
}
|
||||
#else
|
||||
zis->readBytes(buf, tw * th * (BPP / 8));
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
// packed pixels
|
||||
int bppp = ((palSize > 16) ? 8 :
|
||||
((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1)));
|
||||
|
||||
PIXEL_T* ptr = buf;
|
||||
|
||||
for (int i = 0; i < th; i++) {
|
||||
PIXEL_T* eol = ptr + tw;
|
||||
U8 byte = 0;
|
||||
U8 nbits = 0;
|
||||
|
||||
while (ptr < eol) {
|
||||
if (nbits == 0) {
|
||||
byte = zis->readU8();
|
||||
nbits = 8;
|
||||
}
|
||||
nbits -= bppp;
|
||||
U8 index = (byte >> nbits) & ((1 << bppp) - 1) & 127;
|
||||
*ptr++ = palette[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FAVOUR_FILL_RECT
|
||||
//fprintf(stderr,"copying data to screen %dx%d at %d,%d\n",tw,th,tx,ty);
|
||||
IMAGE_RECT(tx,ty,tw,th,buf);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
if (palSize == 0) {
|
||||
|
||||
// plain RLE
|
||||
|
||||
PIXEL_T* ptr = buf;
|
||||
PIXEL_T* end = ptr + th * tw;
|
||||
while (ptr < end) {
|
||||
PIXEL_T pix = zis->READ_PIXEL();
|
||||
int len = 1;
|
||||
int b;
|
||||
do {
|
||||
b = zis->readU8();
|
||||
len += b;
|
||||
} while (b == 255);
|
||||
|
||||
assert(len <= end - ptr);
|
||||
|
||||
#ifdef FAVOUR_FILL_RECT
|
||||
int i = ptr - buf;
|
||||
ptr += len;
|
||||
|
||||
int runX = i % tw;
|
||||
int runY = i / tw;
|
||||
|
||||
if (runX + len > tw) {
|
||||
if (runX != 0) {
|
||||
FILL_RECT(tx+runX, ty+runY, tw-runX, 1, pix);
|
||||
len -= tw-runX;
|
||||
runX = 0;
|
||||
runY++;
|
||||
}
|
||||
|
||||
if (len > tw) {
|
||||
FILL_RECT(tx, ty+runY, tw, len/tw, pix);
|
||||
runY += len / tw;
|
||||
len = len % tw;
|
||||
}
|
||||
}
|
||||
|
||||
if (len != 0) {
|
||||
FILL_RECT(tx+runX, ty+runY, len, 1, pix);
|
||||
}
|
||||
#else
|
||||
while (len-- > 0) *ptr++ = pix;
|
||||
#endif
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
// palette RLE
|
||||
|
||||
PIXEL_T* ptr = buf;
|
||||
PIXEL_T* end = ptr + th * tw;
|
||||
while (ptr < end) {
|
||||
int index = zis->readU8();
|
||||
int len = 1;
|
||||
if (index & 128) {
|
||||
int b;
|
||||
do {
|
||||
b = zis->readU8();
|
||||
len += b;
|
||||
} while (b == 255);
|
||||
|
||||
assert(len <= end - ptr);
|
||||
}
|
||||
|
||||
index &= 127;
|
||||
|
||||
PIXEL_T pix = palette[index];
|
||||
|
||||
#ifdef FAVOUR_FILL_RECT
|
||||
int i = ptr - buf;
|
||||
ptr += len;
|
||||
|
||||
int runX = i % tw;
|
||||
int runY = i / tw;
|
||||
|
||||
if (runX + len > tw) {
|
||||
if (runX != 0) {
|
||||
FILL_RECT(tx+runX, ty+runY, tw-runX, 1, pix);
|
||||
len -= tw-runX;
|
||||
runX = 0;
|
||||
runY++;
|
||||
}
|
||||
|
||||
if (len > tw) {
|
||||
FILL_RECT(tx, ty+runY, tw, len/tw, pix);
|
||||
runY += len / tw;
|
||||
len = len % tw;
|
||||
}
|
||||
}
|
||||
|
||||
if (len != 0) {
|
||||
FILL_RECT(tx+runX, ty+runY, len, 1, pix);
|
||||
}
|
||||
#else
|
||||
while (len-- > 0) *ptr++ = pix;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef FAVOUR_FILL_RECT
|
||||
//fprintf(stderr,"copying data to screen %dx%d at %d,%d\n",tw,th,tx,ty);
|
||||
IMAGE_RECT(tx,ty,tw,th,buf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
zis->reset();
|
||||
}
|
||||
|
||||
#undef ZRLE_DECODE_BPP
|
||||
#undef READ_PIXEL
|
||||
#undef PIXEL_T
|
@ -1,310 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2002 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.
|
||||
|
||||
//
|
||||
// zrleEncode.h - zrle encoding function.
|
||||
//
|
||||
// Before including this file, you must define a number of CPP macros.
|
||||
//
|
||||
// BPP should be 8, 16 or 32 depending on the bits per pixel.
|
||||
// GET_IMAGE_INTO_BUF should be some code which gets a rectangle of pixel data
|
||||
// into the given buffer. EXTRA_ARGS can be defined to pass any other
|
||||
// arguments needed by GET_IMAGE_INTO_BUF.
|
||||
//
|
||||
// Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel
|
||||
// bigger than the largest tile of pixel data, since the ZRLE encoding
|
||||
// algorithm writes to the position one past the end of the pixel data.
|
||||
//
|
||||
|
||||
#include <rdr/OutStream.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace rdr;
|
||||
|
||||
/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same
|
||||
but also expands its arguments if they are macros */
|
||||
|
||||
#ifndef __RFB_CONCAT2E
|
||||
#define __RFB_CONCAT2(a,b) a##b
|
||||
#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
|
||||
#endif
|
||||
|
||||
#ifdef CPIXEL
|
||||
#define PIXEL_T __RFB_CONCAT2E(rdr::U,BPP)
|
||||
#define WRITE_PIXEL __RFB_CONCAT2E(writeOpaque,CPIXEL)
|
||||
#define ZRLE_ENCODE __RFB_CONCAT2E(zrleEncode,CPIXEL)
|
||||
#define ZRLE_ENCODE_TILE __RFB_CONCAT2E(zrleEncodeTile,CPIXEL)
|
||||
#define BPPOUT 24
|
||||
#else
|
||||
#define PIXEL_T __RFB_CONCAT2E(rdr::U,BPP)
|
||||
#define WRITE_PIXEL __RFB_CONCAT2E(writeOpaque,BPP)
|
||||
#define ZRLE_ENCODE __RFB_CONCAT2E(zrleEncode,BPP)
|
||||
#define ZRLE_ENCODE_TILE __RFB_CONCAT2E(zrleEncodeTile,BPP)
|
||||
#define BPPOUT BPP
|
||||
#endif
|
||||
|
||||
#ifndef ZRLE_ONCE
|
||||
#define ZRLE_ONCE
|
||||
static const int bitsPerPackedPixel[] = {
|
||||
0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
|
||||
};
|
||||
|
||||
// The PaletteHelper class helps us build up the palette from pixel data by
|
||||
// storing a reverse index using a simple hash-table
|
||||
|
||||
class PaletteHelper {
|
||||
public:
|
||||
enum { MAX_SIZE = 127 };
|
||||
|
||||
PaletteHelper()
|
||||
{
|
||||
memset(index, 255, sizeof(index));
|
||||
size = 0;
|
||||
}
|
||||
|
||||
inline int hash(rdr::U32 pix)
|
||||
{
|
||||
return (pix ^ (pix >> 17)) & 4095;
|
||||
}
|
||||
|
||||
inline void insert(rdr::U32 pix)
|
||||
{
|
||||
if (size < MAX_SIZE) {
|
||||
int i = hash(pix);
|
||||
while (index[i] != 255 && key[i] != pix)
|
||||
i++;
|
||||
if (index[i] != 255) return;
|
||||
|
||||
index[i] = size;
|
||||
key[i] = pix;
|
||||
palette[size] = pix;
|
||||
}
|
||||
size++;
|
||||
}
|
||||
|
||||
inline int lookup(rdr::U32 pix)
|
||||
{
|
||||
assert(size <= MAX_SIZE);
|
||||
int i = hash(pix);
|
||||
while (index[i] != 255 && key[i] != pix)
|
||||
i++;
|
||||
if (index[i] != 255) return index[i];
|
||||
return -1;
|
||||
}
|
||||
|
||||
rdr::U32 palette[MAX_SIZE];
|
||||
rdr::U8 index[4096+MAX_SIZE];
|
||||
rdr::U32 key[4096+MAX_SIZE];
|
||||
int size;
|
||||
};
|
||||
#endif
|
||||
|
||||
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os);
|
||||
|
||||
void ZRLE_ENCODE (int x, int y, int w, int h, rdr::OutStream* os,
|
||||
rdr::ZlibOutStream* zos, void* buf
|
||||
EXTRA_ARGS
|
||||
)
|
||||
{
|
||||
zos->setUnderlying(os);
|
||||
|
||||
for (int ty = y; ty < y+h; ty += rfbZRLETileHeight) {
|
||||
int th = rfbZRLETileHeight;
|
||||
if (th > y+h-ty) th = y+h-ty;
|
||||
for (int tx = x; tx < x+w; tx += rfbZRLETileWidth) {
|
||||
int tw = rfbZRLETileWidth;
|
||||
if (tw > x+w-tx) tw = x+w-tx;
|
||||
|
||||
GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf);
|
||||
|
||||
ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, zos);
|
||||
}
|
||||
}
|
||||
zos->flush();
|
||||
}
|
||||
|
||||
|
||||
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
|
||||
{
|
||||
// First find the palette and the number of runs
|
||||
|
||||
PaletteHelper ph;
|
||||
|
||||
int runs = 0;
|
||||
int singlePixels = 0;
|
||||
|
||||
PIXEL_T* ptr = data;
|
||||
PIXEL_T* end = ptr + h * w;
|
||||
*end = ~*(end-1); // one past the end is different so the while loop ends
|
||||
|
||||
while (ptr < end) {
|
||||
PIXEL_T pix = *ptr;
|
||||
if (*++ptr != pix) {
|
||||
singlePixels++;
|
||||
} else {
|
||||
while (*++ptr == pix) ;
|
||||
runs++;
|
||||
}
|
||||
ph.insert(pix);
|
||||
}
|
||||
|
||||
//fprintf(stderr,"runs %d, single pixels %d, paletteSize %d\n",
|
||||
// runs, singlePixels, ph.size);
|
||||
|
||||
// Solid tile is a special case
|
||||
|
||||
if (ph.size == 1) {
|
||||
os->writeU8(1);
|
||||
os->WRITE_PIXEL(ph.palette[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to work out whether to use RLE and/or a palette. We do this by
|
||||
// estimating the number of bytes which will be generated and picking the
|
||||
// method which results in the fewest bytes. Of course this may not result
|
||||
// in the fewest bytes after compression...
|
||||
|
||||
bool useRle = false;
|
||||
bool usePalette = false;
|
||||
|
||||
int estimatedBytes = w * h * (BPPOUT/8); // start assuming raw
|
||||
|
||||
int plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels);
|
||||
|
||||
if (plainRleBytes < estimatedBytes) {
|
||||
useRle = true;
|
||||
estimatedBytes = plainRleBytes;
|
||||
}
|
||||
|
||||
if (ph.size < 128) {
|
||||
int paletteRleBytes = (BPPOUT/8) * ph.size + 2 * runs + singlePixels;
|
||||
|
||||
if (paletteRleBytes < estimatedBytes) {
|
||||
useRle = true;
|
||||
usePalette = true;
|
||||
estimatedBytes = paletteRleBytes;
|
||||
}
|
||||
|
||||
if (ph.size < 17) {
|
||||
int packedBytes = ((BPPOUT/8) * ph.size +
|
||||
w * h * bitsPerPackedPixel[ph.size-1] / 8);
|
||||
|
||||
if (packedBytes < estimatedBytes) {
|
||||
useRle = false;
|
||||
usePalette = true;
|
||||
estimatedBytes = packedBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!usePalette) ph.size = 0;
|
||||
|
||||
os->writeU8((useRle ? 128 : 0) | ph.size);
|
||||
|
||||
for (int i = 0; i < ph.size; i++) {
|
||||
os->WRITE_PIXEL(ph.palette[i]);
|
||||
}
|
||||
|
||||
if (useRle) {
|
||||
|
||||
PIXEL_T* ptr = data;
|
||||
PIXEL_T* end = ptr + w * h;
|
||||
PIXEL_T* runStart;
|
||||
PIXEL_T pix;
|
||||
while (ptr < end) {
|
||||
runStart = ptr;
|
||||
pix = *ptr++;
|
||||
while (*ptr == pix && ptr < end)
|
||||
ptr++;
|
||||
int len = ptr - runStart;
|
||||
if (len <= 2 && usePalette) {
|
||||
int index = ph.lookup(pix);
|
||||
if (len == 2)
|
||||
os->writeU8(index);
|
||||
os->writeU8(index);
|
||||
continue;
|
||||
}
|
||||
if (usePalette) {
|
||||
int index = ph.lookup(pix);
|
||||
os->writeU8(index | 128);
|
||||
} else {
|
||||
os->WRITE_PIXEL(pix);
|
||||
}
|
||||
len -= 1;
|
||||
while (len >= 255) {
|
||||
os->writeU8(255);
|
||||
len -= 255;
|
||||
}
|
||||
os->writeU8(len);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// no RLE
|
||||
|
||||
if (usePalette) {
|
||||
|
||||
// packed pixels
|
||||
|
||||
assert (ph.size < 17);
|
||||
|
||||
int bppp = bitsPerPackedPixel[ph.size-1];
|
||||
|
||||
PIXEL_T* ptr = data;
|
||||
|
||||
for (int i = 0; i < h; i++) {
|
||||
U8 nbits = 0;
|
||||
U8 byte = 0;
|
||||
|
||||
PIXEL_T* eol = ptr + w;
|
||||
|
||||
while (ptr < eol) {
|
||||
PIXEL_T pix = *ptr++;
|
||||
U8 index = ph.lookup(pix);
|
||||
byte = (byte << bppp) | index;
|
||||
nbits += bppp;
|
||||
if (nbits >= 8) {
|
||||
os->writeU8(byte);
|
||||
nbits = 0;
|
||||
}
|
||||
}
|
||||
if (nbits > 0) {
|
||||
byte <<= 8 - nbits;
|
||||
os->writeU8(byte);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// raw
|
||||
|
||||
#ifdef CPIXEL
|
||||
for (PIXEL_T* ptr = data; ptr < data+w*h; ptr++) {
|
||||
os->WRITE_PIXEL(*ptr);
|
||||
}
|
||||
#else
|
||||
os->writeBytes(data, w*h*(BPP/8));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef PIXEL_T
|
||||
#undef WRITE_PIXEL
|
||||
#undef ZRLE_ENCODE
|
||||
#undef ZRLE_ENCODE_TILE
|
||||
#undef BPPOUT
|
Loading…
Reference in new issue