Allow subclasses to call it, instead of it being strictly internal. This is useful when a subclass can only provide data in minimum sized chunks.tags/v1.12.90
#include <config.h> | #include <config.h> | ||||
#endif | #endif | ||||
#include <assert.h> | |||||
#include <rdr/BufferedInStream.h> | #include <rdr/BufferedInStream.h> | ||||
#include <rdr/Exception.h> | #include <rdr/Exception.h> | ||||
return offset + ptr - start; | return offset + ptr - start; | ||||
} | } | ||||
bool BufferedInStream::overrun(size_t needed) | |||||
void BufferedInStream::ensureSpace(size_t needed) | |||||
{ | { | ||||
struct timeval now; | struct timeval now; | ||||
// Given argument is how much free space is needed, but for allocation | |||||
// purposes we need to now how much space everything needs, including | |||||
// any existing data already in the buffer | |||||
needed += avail(); | |||||
if (needed > bufSize) { | if (needed > bufSize) { | ||||
size_t newSize; | size_t newSize; | ||||
U8* newBuffer; | U8* newBuffer; | ||||
end -= ptr - start; | end -= ptr - start; | ||||
ptr = start; | ptr = start; | ||||
} | } | ||||
} | |||||
bool BufferedInStream::overrun(size_t needed) | |||||
{ | |||||
// Make sure fillBuffer() has room for all the requested data | |||||
assert(needed > avail()); | |||||
ensureSpace(needed - avail()); | |||||
while (avail() < needed) { | while (avail() < needed) { | ||||
if (!fillBuffer(start + bufSize - end)) | |||||
if (!fillBuffer()) | |||||
return false; | return false; | ||||
} | } | ||||
virtual size_t pos(); | virtual size_t pos(); | ||||
protected: | |||||
size_t availSpace() { return start + bufSize - end; } | |||||
void ensureSpace(size_t needed); | |||||
private: | private: | ||||
virtual bool fillBuffer(size_t maxSize) = 0; | |||||
virtual bool fillBuffer() = 0; | |||||
virtual bool overrun(size_t needed); | virtual bool overrun(size_t needed); | ||||
} | } | ||||
bool FdInStream::fillBuffer(size_t maxSize) | |||||
bool FdInStream::fillBuffer() | |||||
{ | { | ||||
size_t n = readFd((U8*)end, maxSize); | |||||
size_t n = readFd((U8*)end, availSpace()); | |||||
if (n == 0) | if (n == 0) | ||||
return false; | return false; | ||||
end += n; | end += n; |
int getFd() { return fd; } | int getFd() { return fd; } | ||||
private: | private: | ||||
virtual bool fillBuffer(size_t maxSize); | |||||
virtual bool fillBuffer(); | |||||
size_t readFd(void* buf, size_t len); | size_t readFd(void* buf, size_t len); | ||||
} | } | ||||
} | } | ||||
bool FileInStream::fillBuffer(size_t maxSize) | |||||
bool FileInStream::fillBuffer() | |||||
{ | { | ||||
size_t n = fread((U8 *)end, 1, maxSize, file); | |||||
size_t n = fread((U8 *)end, 1, availSpace(), file); | |||||
if (n == 0) { | if (n == 0) { | ||||
if (ferror(file)) | if (ferror(file)) | ||||
throw SystemException("fread", errno); | throw SystemException("fread", errno); |
~FileInStream(void); | ~FileInStream(void); | ||||
private: | private: | ||||
virtual bool fillBuffer(size_t maxSize); | |||||
virtual bool fillBuffer(); | |||||
private: | private: | ||||
FILE *file; | FILE *file; |
} | } | ||||
bool HexInStream::fillBuffer(size_t maxSize) { | |||||
bool HexInStream::fillBuffer() { | |||||
if (!in_stream.hasData(2)) | if (!in_stream.hasData(2)) | ||||
return false; | return false; | ||||
size_t length = min(in_stream.avail()/2, maxSize); | |||||
size_t length = min(in_stream.avail()/2, availSpace()); | |||||
const U8* iptr = in_stream.getptr(length*2); | const U8* iptr = in_stream.getptr(length*2); | ||||
U8* optr = (U8*) end; | U8* optr = (U8*) end; |
static bool hexStrToBin(const char* s, char** data, size_t* length); | static bool hexStrToBin(const char* s, char** data, size_t* length); | ||||
private: | private: | ||||
virtual bool fillBuffer(size_t maxSize); | |||||
virtual bool fillBuffer(); | |||||
private: | private: | ||||
InStream& in_stream; | InStream& in_stream; |
#endif | #endif | ||||
} | } | ||||
bool RandomStream::fillBuffer(size_t maxSize) { | |||||
bool RandomStream::fillBuffer() { | |||||
#ifdef RFB_HAVE_WINCRYPT | #ifdef RFB_HAVE_WINCRYPT | ||||
if (provider) { | if (provider) { | ||||
if (!CryptGenRandom(provider, maxSize, (U8*)end)) | |||||
if (!CryptGenRandom(provider, availSpace(), (U8*)end)) | |||||
throw rdr::SystemException("unable to CryptGenRandom", GetLastError()); | throw rdr::SystemException("unable to CryptGenRandom", GetLastError()); | ||||
end += maxSize; | |||||
end += availSpace(); | |||||
} else { | } else { | ||||
#else | #else | ||||
#ifndef WIN32 | #ifndef WIN32 | ||||
if (fp) { | if (fp) { | ||||
size_t n = fread((U8*)end, 1, maxSize, fp); | |||||
size_t n = fread((U8*)end, 1, availSpace(), fp); | |||||
if (n <= 0) | if (n <= 0) | ||||
throw rdr::SystemException("reading /dev/urandom or /dev/random failed", | throw rdr::SystemException("reading /dev/urandom or /dev/random failed", | ||||
errno); | errno); | ||||
{ | { | ||||
#endif | #endif | ||||
#endif | #endif | ||||
for (size_t i=0; i<maxSize; i++) | |||||
for (size_t i=availSpace(); i>0; i--) | |||||
*(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0)); | *(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0)); | ||||
} | } | ||||
virtual ~RandomStream(); | virtual ~RandomStream(); | ||||
private: | private: | ||||
virtual bool fillBuffer(size_t maxSize); | |||||
virtual bool fillBuffer(); | |||||
private: | private: | ||||
static unsigned int seed; | static unsigned int seed; |
delete saved_exception; | delete saved_exception; | ||||
} | } | ||||
bool TLSInStream::fillBuffer(size_t maxSize) | |||||
bool TLSInStream::fillBuffer() | |||||
{ | { | ||||
size_t n = readTLS((U8*) end, maxSize); | |||||
size_t n = readTLS((U8*) end, availSpace()); | |||||
if (n == 0) | if (n == 0) | ||||
return false; | return false; | ||||
end += n; | end += n; |
virtual ~TLSInStream(); | virtual ~TLSInStream(); | ||||
private: | private: | ||||
virtual bool fillBuffer(size_t maxSize); | |||||
virtual bool fillBuffer(); | |||||
size_t readTLS(U8* buf, size_t len); | size_t readTLS(U8* buf, size_t len); | ||||
static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size); | static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size); | ||||
zs = NULL; | zs = NULL; | ||||
} | } | ||||
bool ZlibInStream::fillBuffer(size_t maxSize) | |||||
bool ZlibInStream::fillBuffer() | |||||
{ | { | ||||
if (!underlying) | if (!underlying) | ||||
throw Exception("ZlibInStream overrun: no underlying stream"); | throw Exception("ZlibInStream overrun: no underlying stream"); | ||||
zs->next_out = (U8*)end; | zs->next_out = (U8*)end; | ||||
zs->avail_out = maxSize; | |||||
zs->avail_out = availSpace(); | |||||
if (!underlying->hasData(1)) | if (!underlying->hasData(1)) | ||||
return false; | return false; |
void init(); | void init(); | ||||
void deinit(); | void deinit(); | ||||
virtual bool fillBuffer(size_t maxSize); | |||||
virtual bool fillBuffer(); | |||||
private: | private: | ||||
InStream* underlying; | InStream* underlying; |