// cork() requests that the stream coalesces flushes in an efficient way | // cork() requests that the stream coalesces flushes in an efficient way | ||||
virtual void cork(bool enable) { corked = enable; flush(); } | |||||
virtual void cork(bool enable) { corked = enable; if (!enable) flush(); } | |||||
// getptr() and setptr() are "dirty" methods which allow you direct access | // getptr() and setptr() are "dirty" methods which allow you direct access | ||||
// to the buffer. This is useful for a stream which is a wrapper around an | // to the buffer. This is useful for a stream which is a wrapper around an |
void TLSOutStream::overrun(size_t needed) | void TLSOutStream::overrun(size_t needed) | ||||
{ | { | ||||
bool oldCorked; | |||||
if (needed > bufSize) | if (needed > bufSize) | ||||
throw Exception("TLSOutStream overrun: buffer size exceeded"); | throw Exception("TLSOutStream overrun: buffer size exceeded"); | ||||
// A cork might prevent the flush, so disable it temporarily | // A cork might prevent the flush, so disable it temporarily | ||||
oldCorked = corked; | |||||
corked = false; | corked = false; | ||||
flush(); | flush(); | ||||
corked = true; | |||||
corked = oldCorked; | |||||
} | } | ||||
size_t TLSOutStream::writeTLS(const U8* data, size_t length) | size_t TLSOutStream::writeTLS(const U8* data, size_t length) |
checkCompressionLevel(); | checkCompressionLevel(); | ||||
while (avail() < needed) { | while (avail() < needed) { | ||||
bool oldCorked; | |||||
// use corked to make zlib a bit more efficient since we're not trying | // use corked to make zlib a bit more efficient since we're not trying | ||||
// to end the stream here, just make some room | // to end the stream here, just make some room | ||||
oldCorked = corked; | |||||
corked = true; | corked = true; | ||||
flush(); | flush(); | ||||
corked = false; | |||||
corked = oldCorked; | |||||
} | } | ||||
} | } | ||||
lengths[num] = zis.readU32(); | lengths[num] = zis.readU32(); | ||||
if (!zis.hasData(lengths[num])) | |||||
throw Exception("Extended clipboard decode error"); | |||||
if (lengths[num] > (size_t)maxCutText) { | if (lengths[num] > (size_t)maxCutText) { | ||||
vlog.error("Extended clipboard data too long (%d bytes) - ignoring", | vlog.error("Extended clipboard data too long (%d bytes) - ignoring", | ||||
(unsigned)lengths[num]); | (unsigned)lengths[num]); | ||||
zis.skip(lengths[num]); | |||||
// Slowly (safely) drain away the data | |||||
while (lengths[num] > 0) { | |||||
size_t chunk; | |||||
if (!zis.hasData(1)) | |||||
throw Exception("Extended clipboard decode error"); | |||||
chunk = zis.avail(); | |||||
if (chunk > lengths[num]) | |||||
chunk = lengths[num]; | |||||
zis.skip(chunk); | |||||
lengths[num] -= chunk; | |||||
} | |||||
flags &= ~(1 << i); | flags &= ~(1 << i); | ||||
continue; | continue; | ||||
} | } | ||||
if (!zis.hasData(lengths[num])) | |||||
throw Exception("Extended clipboard decode error"); | |||||
buffers[num] = new rdr::U8[lengths[num]]; | buffers[num] = new rdr::U8[lengths[num]]; | ||||
zis.readBytes(buffers[num], lengths[num]); | zis.readBytes(buffers[num], lengths[num]); | ||||
num++; | num++; |
lengths[num] = zis.readU32(); | lengths[num] = zis.readU32(); | ||||
if (!zis.hasData(lengths[num])) | |||||
throw Exception("Extended clipboard decode error"); | |||||
if (lengths[num] > (size_t)maxCutText) { | if (lengths[num] > (size_t)maxCutText) { | ||||
vlog.error("Extended clipboard data too long (%d bytes) - ignoring", | vlog.error("Extended clipboard data too long (%d bytes) - ignoring", | ||||
(unsigned)lengths[num]); | (unsigned)lengths[num]); | ||||
zis.skip(lengths[num]); | |||||
// Slowly (safely) drain away the data | |||||
while (lengths[num] > 0) { | |||||
size_t chunk; | |||||
if (!zis.hasData(1)) | |||||
throw Exception("Extended clipboard decode error"); | |||||
chunk = zis.avail(); | |||||
if (chunk > lengths[num]) | |||||
chunk = lengths[num]; | |||||
zis.skip(chunk); | |||||
lengths[num] -= chunk; | |||||
} | |||||
flags &= ~(1 << i); | flags &= ~(1 << i); | ||||
continue; | continue; | ||||
} | } | ||||
if (!zis.hasData(lengths[num])) | |||||
throw Exception("Extended clipboard decode error"); | |||||
buffers[num] = new rdr::U8[lengths[num]]; | buffers[num] = new rdr::U8[lengths[num]]; | ||||
zis.readBytes(buffers[num], lengths[num]); | zis.readBytes(buffers[num], lengths[num]); | ||||
num++; | num++; |
// We might have been called to flush unwritten socket data | // We might have been called to flush unwritten socket data | ||||
cc->sock->outStream().flush(); | cc->sock->outStream().flush(); | ||||
cc->sock->outStream().cork(true); | |||||
cc->getOutStream()->cork(true); | |||||
// processMsg() only processes one message, so we need to loop | // processMsg() only processes one message, so we need to loop | ||||
// until the buffers are empty or things will stall. | // until the buffers are empty or things will stall. | ||||
break; | break; | ||||
} | } | ||||
cc->sock->outStream().cork(false); | |||||
cc->sock->outStream().flush(); | |||||
cc->getOutStream()->cork(false); | |||||
} catch (rdr::EndOfStream& e) { | } catch (rdr::EndOfStream& e) { | ||||
vlog.info("%s", e.str()); | vlog.info("%s", e.str()); | ||||
if (!cc->desktop) { | if (!cc->desktop) { |