These will always be byte streams at heart, so let's try to keep them with a proper type. Should make it clearer how they will be used.pull/1640/head
// returning EINTR. | // returning EINTR. | ||||
// | // | ||||
size_t FdInStream::readFd(void* buf, size_t len) | |||||
size_t FdInStream::readFd(uint8_t* buf, size_t len) | |||||
{ | { | ||||
int n; | int n; | ||||
do { | do { |
private: | private: | ||||
virtual bool fillBuffer(); | virtual bool fillBuffer(); | ||||
size_t readFd(void* buf, size_t len); | |||||
size_t readFd(uint8_t* buf, size_t len); | |||||
int fd; | int fd; | ||||
bool closeWhenDone; | bool closeWhenDone; |
bool FdOutStream::flushBuffer() | bool FdOutStream::flushBuffer() | ||||
{ | { | ||||
size_t n = writeFd((const void*) sentUpTo, ptr - sentUpTo); | |||||
size_t n = writeFd(sentUpTo, ptr - sentUpTo); | |||||
if (n == 0) | if (n == 0) | ||||
return false; | return false; | ||||
// returning EINTR. | // returning EINTR. | ||||
// | // | ||||
size_t FdOutStream::writeFd(const void* data, size_t length) | |||||
size_t FdOutStream::writeFd(const uint8_t* data, size_t length) | |||||
{ | { | ||||
int n; | int n; | ||||
private: | private: | ||||
virtual bool flushBuffer(); | virtual bool flushBuffer(); | ||||
size_t writeFd(const void* data, size_t length); | |||||
size_t writeFd(const uint8_t* data, size_t length); | |||||
int fd; | int fd; | ||||
struct timeval lastWrite; | struct timeval lastWrite; | ||||
}; | }; |
// readBytes() reads an exact number of bytes. | // readBytes() reads an exact number of bytes. | ||||
void readBytes(void* data, size_t length) { | |||||
void readBytes(uint8_t* data, size_t length) { | |||||
check(length); | check(length); | ||||
memcpy(data, ptr, length); | memcpy(data, ptr, length); | ||||
ptr += length; | ptr += length; |
public: | public: | ||||
MemInStream(const void* data, size_t len, bool deleteWhenDone_=false) | |||||
: start((const uint8_t*)data), deleteWhenDone(deleteWhenDone_) | |||||
MemInStream(const uint8_t* data, size_t len, bool deleteWhenDone_=false) | |||||
: start(data), deleteWhenDone(deleteWhenDone_) | |||||
{ | { | ||||
ptr = start; | ptr = start; | ||||
end = start + len; | end = start + len; |
// data() returns a pointer to the buffer. | // data() returns a pointer to the buffer. | ||||
const void* data() { return (const void*)start; } | |||||
const uint8_t* data() { return start; } | |||||
protected: | protected: | ||||
// writeBytes() writes an exact number of bytes. | // writeBytes() writes an exact number of bytes. | ||||
void writeBytes(const void* data, size_t length) { | |||||
void writeBytes(const uint8_t* data, size_t length) { | |||||
while (length > 0) { | while (length > 0) { | ||||
check(1); | check(1); | ||||
size_t n = length; | size_t n = length; |
if (in->avail() < size) | if (in->avail() < size) | ||||
size = in->avail(); | size = in->avail(); | ||||
in->readBytes(data, size); | |||||
in->readBytes((uint8_t*)data, size); | |||||
} catch (EndOfStream&) { | } catch (EndOfStream&) { | ||||
return 0; | return 0; | ||||
} catch (SystemException &e) { | } catch (SystemException &e) { |
self->saved_exception = NULL; | self->saved_exception = NULL; | ||||
try { | try { | ||||
out->writeBytes(data, size); | |||||
out->writeBytes((const uint8_t*)data, size); | |||||
out->flush(); | out->flush(); | ||||
} catch (SystemException &e) { | } catch (SystemException &e) { | ||||
vlog.error("Failure sending TLS data: %s", e.str()); | vlog.error("Failure sending TLS data: %s", e.str()); |
if (!is->hasData(12)) | if (!is->hasData(12)) | ||||
return false; | return false; | ||||
is->readBytes(verStr, 12); | |||||
is->readBytes((uint8_t*)verStr, 12); | |||||
verStr[12] = '\0'; | verStr[12] = '\0'; | ||||
if (sscanf(verStr, "RFB %03d.%03d\n", | if (sscanf(verStr, "RFB %03d.%03d\n", | ||||
sprintf(verStr, "RFB %03d.%03d\n", | sprintf(verStr, "RFB %03d.%03d\n", | ||||
server.majorVersion, server.minorVersion); | server.majorVersion, server.minorVersion); | ||||
os->writeBytes(verStr, 12); | |||||
os->writeBytes((const uint8_t*)verStr, 12); | |||||
os->flush(); | os->flush(); | ||||
state_ = RFBSTATE_SECURITY_TYPES; | state_ = RFBSTATE_SECURITY_TYPES; | ||||
is->clearRestorePoint(); | is->clearRestorePoint(); | ||||
std::vector<char> reason(len + 1); | std::vector<char> reason(len + 1); | ||||
is->readBytes(reason.data(), len); | |||||
is->readBytes((uint8_t*)reason.data(), len); | |||||
reason[len] = '\0'; | reason[len] = '\0'; | ||||
state_ = RFBSTATE_INVALID; | state_ = RFBSTATE_INVALID; | ||||
formatChange = true; | formatChange = true; | ||||
} | } | ||||
void CConnection::fence(uint32_t flags, unsigned len, const char data[]) | |||||
void CConnection::fence(uint32_t flags, unsigned len, const uint8_t data[]) | |||||
{ | { | ||||
CMsgHandler::fence(flags, len, data); | CMsgHandler::fence(flags, len, data); | ||||
// responds to requests, stating no support for synchronisation. | // responds to requests, stating no support for synchronisation. | ||||
// When overriding, call CMsgHandler::fence() directly in order to | // When overriding, call CMsgHandler::fence() directly in order to | ||||
// state correct support for fence flags. | // state correct support for fence flags. | ||||
virtual void fence(uint32_t flags, unsigned len, const char data[]); | |||||
virtual void fence(uint32_t flags, unsigned len, const uint8_t data[]); | |||||
private: | private: | ||||
bool processVersionMsg(); | bool processVersionMsg(); |
} | } | ||||
void CMsgHandler::fence(uint32_t /*flags*/, unsigned /*len*/, | void CMsgHandler::fence(uint32_t /*flags*/, unsigned /*len*/, | ||||
const char /*data*/ []) | |||||
const uint8_t /*data*/ []) | |||||
{ | { | ||||
server.supportsFence = true; | server.supportsFence = true; | ||||
} | } |
virtual void setCursorPos(const Point& pos) = 0; | virtual void setCursorPos(const Point& pos) = 0; | ||||
virtual void setPixelFormat(const PixelFormat& pf); | virtual void setPixelFormat(const PixelFormat& pf); | ||||
virtual void setName(const char* name); | virtual void setName(const char* name); | ||||
virtual void fence(uint32_t flags, unsigned len, const char data[]); | |||||
virtual void fence(uint32_t flags, unsigned len, const uint8_t data[]); | |||||
virtual void endOfContinuousUpdates(); | virtual void endOfContinuousUpdates(); | ||||
virtual void supportsQEMUKeyEvent(); | virtual void supportsQEMUKeyEvent(); | ||||
virtual void serverInit(int width, int height, | virtual void serverInit(int width, int height, |
return false; | return false; | ||||
is->clearRestorePoint(); | is->clearRestorePoint(); | ||||
std::vector<char> name(len + 1); | std::vector<char> name(len + 1); | ||||
is->readBytes(name.data(), len); | |||||
is->readBytes((uint8_t*)name.data(), len); | |||||
name[len] = '\0'; | name[len] = '\0'; | ||||
handler->serverInit(width, height, pf, name.data()); | handler->serverInit(width, height, pf, name.data()); | ||||
return true; | return true; | ||||
} | } | ||||
std::vector<char> ca(len); | std::vector<char> ca(len); | ||||
is->readBytes(ca.data(), len); | |||||
is->readBytes((uint8_t*)ca.data(), len); | |||||
std::string filtered(convertLF(ca.data(), len)); | std::string filtered(convertLF(ca.data(), len)); | ||||
handler->serverCutText(filtered.c_str()); | handler->serverCutText(filtered.c_str()); | ||||
{ | { | ||||
uint32_t flags; | uint32_t flags; | ||||
uint8_t len; | uint8_t len; | ||||
char data[64]; | |||||
uint8_t data[64]; | |||||
if (!is->hasData(3 + 4 + 1)) | if (!is->hasData(3 + 4 + 1)) | ||||
return false; | return false; | ||||
is->clearRestorePoint(); | is->clearRestorePoint(); | ||||
std::vector<char> name(len + 1); | std::vector<char> name(len + 1); | ||||
is->readBytes(name.data(), len); | |||||
is->readBytes((uint8_t*)name.data(), len); | |||||
name[len] = '\0'; | name[len] = '\0'; | ||||
if (x || y || w || h) { | if (x || y || w || h) { |
endMsg(); | endMsg(); | ||||
} | } | ||||
void CMsgWriter::writeFence(uint32_t flags, unsigned len, const char data[]) | |||||
void CMsgWriter::writeFence(uint32_t flags, unsigned len, const uint8_t data[]) | |||||
{ | { | ||||
if (!server->supportsFence) | if (!server->supportsFence) | ||||
throw Exception("Server does not support fences"); | throw Exception("Server does not support fences"); | ||||
startMsg(msgTypeClientCutText); | startMsg(msgTypeClientCutText); | ||||
os->pad(3); | os->pad(3); | ||||
os->writeU32(len); | os->writeU32(len); | ||||
os->writeBytes(str, len); | |||||
os->writeBytes((const uint8_t*)str, len); | |||||
endMsg(); | endMsg(); | ||||
} | } | ||||
void writeFramebufferUpdateRequest(const Rect& r,bool incremental); | void writeFramebufferUpdateRequest(const Rect& r,bool incremental); | ||||
void writeEnableContinuousUpdates(bool enable, int x, int y, int w, int h); | void writeEnableContinuousUpdates(bool enable, int x, int y, int w, int h); | ||||
void writeFence(uint32_t flags, unsigned len, const char data[]); | |||||
void writeFence(uint32_t flags, unsigned len, const uint8_t data[]); | |||||
void writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down); | void writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down); | ||||
void writePointerEvent(const Point& pos, int buttonMask); | void writePointerEvent(const Point& pos, int buttonMask); |
struct aes128_ctx aesCtx; | struct aes128_ctx aesCtx; | ||||
aes128_set_encrypt_key(&aesCtx, key); | aes128_set_encrypt_key(&aesCtx, key); | ||||
char buf[128]; | |||||
uint8_t buf[128]; | |||||
if (!rs.hasData(128)) | if (!rs.hasData(128)) | ||||
throw ConnFailedException("failed to generate random padding"); | throw ConnFailedException("failed to generate random padding"); | ||||
rs.readBytes(buf, 128); | rs.readBytes(buf, 128); | ||||
if (password.size() >= 64) | if (password.size() >= 64) | ||||
throw AuthFailureException("password is too long"); | throw AuthFailureException("password is too long"); | ||||
memcpy(buf + 64, password.c_str(), password.size() + 1); | memcpy(buf + 64, password.c_str(), password.size() + 1); | ||||
aes128_encrypt(&aesCtx, 128, (uint8_t *)buf, (uint8_t *)buf); | |||||
aes128_encrypt(&aesCtx, 128, buf, buf); | |||||
rdr::OutStream* os = cc->getOutStream(); | rdr::OutStream* os = cc->getOutStream(); | ||||
os->writeBytes(buf, 128); | os->writeBytes(buf, 128); |
// Return the response to the server | // Return the response to the server | ||||
os->writeU32(username.size()); | os->writeU32(username.size()); | ||||
os->writeU32(password.size()); | os->writeU32(password.size()); | ||||
os->writeBytes(username.data(), username.size()); | |||||
os->writeBytes(password.data(), password.size()); | |||||
os->writeBytes((const uint8_t*)username.data(), username.size()); | |||||
os->writeBytes((const uint8_t*)password.data(), password.size()); | |||||
os->flush(); | os->flush(); | ||||
return true; | return true; | ||||
} | } |
if (username.size() > 255) | if (username.size() > 255) | ||||
throw AuthFailureException("username is too long"); | throw AuthFailureException("username is too long"); | ||||
raos->writeU8(username.size()); | raos->writeU8(username.size()); | ||||
raos->writeBytes(username.data(), username.size()); | |||||
raos->writeBytes((const uint8_t*)username.data(), username.size()); | |||||
} else { | } else { | ||||
raos->writeU8(0); | raos->writeU8(0); | ||||
} | } | ||||
if (password.size() > 255) | if (password.size() > 255) | ||||
throw AuthFailureException("password is too long"); | throw AuthFailureException("password is too long"); | ||||
raos->writeU8(password.size()); | raos->writeU8(password.size()); | ||||
raos->writeBytes(password.data(), password.size()); | |||||
raos->writeBytes((const uint8_t*)password.data(), password.size()); | |||||
raos->flush(); | raos->flush(); | ||||
} | } |
void CopyRectDecoder::getAffectedRegion(const Rect& rect, | void CopyRectDecoder::getAffectedRegion(const Rect& rect, | ||||
const void* buffer, | |||||
const uint8_t* buffer, | |||||
size_t buflen, | size_t buflen, | ||||
const ServerParams& server, | const ServerParams& server, | ||||
Region* region) | Region* region) | ||||
srcY-rect.tl.y)))); | srcY-rect.tl.y)))); | ||||
} | } | ||||
void CopyRectDecoder::decodeRect(const Rect& r, const void* buffer, | |||||
void CopyRectDecoder::decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, | size_t buflen, | ||||
const ServerParams& /*server*/, | const ServerParams& /*server*/, | ||||
ModifiablePixelBuffer* pb) | ModifiablePixelBuffer* pb) |
virtual ~CopyRectDecoder(); | virtual ~CopyRectDecoder(); | ||||
virtual bool readRect(const Rect& r, rdr::InStream* is, | virtual bool readRect(const Rect& r, rdr::InStream* is, | ||||
const ServerParams& server, rdr::OutStream* os); | const ServerParams& server, rdr::OutStream* os); | ||||
virtual void getAffectedRegion(const Rect& rect, const void* buffer, | |||||
virtual void getAffectedRegion(const Rect& rect, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
Region* region); | Region* region); | ||||
virtual void decodeRect(const Rect& r, const void* buffer, | |||||
virtual void decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb); | ModifiablePixelBuffer* pb); | ||||
}; | }; |
} | } | ||||
void Decoder::getAffectedRegion(const Rect& rect, | void Decoder::getAffectedRegion(const Rect& rect, | ||||
const void* /*buffer*/, | |||||
const uint8_t* /*buffer*/, | |||||
size_t /*buflen*/, | size_t /*buflen*/, | ||||
const ServerParams& /*server*/, | const ServerParams& /*server*/, | ||||
Region* region) | Region* region) | ||||
} | } | ||||
bool Decoder::doRectsConflict(const Rect& /*rectA*/, | bool Decoder::doRectsConflict(const Rect& /*rectA*/, | ||||
const void* /*bufferA*/, | |||||
const uint8_t* /*bufferA*/, | |||||
size_t /*buflenA*/, | size_t /*buflenA*/, | ||||
const Rect& /*rectB*/, | const Rect& /*rectB*/, | ||||
const void* /*bufferB*/, | |||||
const uint8_t* /*bufferB*/, | |||||
size_t /*buflenB*/, | size_t /*buflenB*/, | ||||
const ServerParams& /*server*/) | const ServerParams& /*server*/) | ||||
{ | { |
#ifndef __RFB_DECODER_H__ | #ifndef __RFB_DECODER_H__ | ||||
#define __RFB_DECODER_H__ | #define __RFB_DECODER_H__ | ||||
#include <stdint.h> | |||||
namespace rdr { | namespace rdr { | ||||
class InStream; | class InStream; | ||||
class OutStream; | class OutStream; | ||||
// getAffectedRegion() returns the parts of the frame buffer will | // getAffectedRegion() returns the parts of the frame buffer will | ||||
// be either read from or written do when decoding this rect. The | // be either read from or written do when decoding this rect. The | ||||
// default implementation simply returns the given rectangle. | // default implementation simply returns the given rectangle. | ||||
virtual void getAffectedRegion(const Rect& rect, const void* buffer, | |||||
virtual void getAffectedRegion(const Rect& rect, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
Region* region); | Region* region); | ||||
// in the order they were received. This will only be called if the | // in the order they were received. This will only be called if the | ||||
// DecoderPartiallyOrdered flag has been set. | // DecoderPartiallyOrdered flag has been set. | ||||
virtual bool doRectsConflict(const Rect& rectA, | virtual bool doRectsConflict(const Rect& rectA, | ||||
const void* bufferA, | |||||
const uint8_t* bufferA, | |||||
size_t buflenA, | size_t buflenA, | ||||
const Rect& rectB, | const Rect& rectB, | ||||
const void* bufferB, | |||||
const uint8_t* bufferB, | |||||
size_t buflenB, | size_t buflenB, | ||||
const ServerParams& server); | const ServerParams& server); | ||||
// given buffer, onto the ModifiablePixelBuffer. The PixelFormat of | // given buffer, onto the ModifiablePixelBuffer. The PixelFormat of | ||||
// the PixelBuffer might not match the ConnParams and it is up to | // the PixelBuffer might not match the ConnParams and it is up to | ||||
// the decoder to do any necessary conversion. | // the decoder to do any necessary conversion. | ||||
virtual void decodeRect(const Rect& r, const void* buffer, | |||||
virtual void decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb)=0; | ModifiablePixelBuffer* pb)=0; | ||||
return true; | return true; | ||||
} | } | ||||
void H264Decoder::decodeRect(const Rect& r, const void* buffer, | |||||
void H264Decoder::decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, | size_t buflen, | ||||
const ServerParams& /*server*/, | const ServerParams& /*server*/, | ||||
ModifiablePixelBuffer* pb) | ModifiablePixelBuffer* pb) |
virtual ~H264Decoder(); | virtual ~H264Decoder(); | ||||
virtual bool readRect(const Rect& r, rdr::InStream* is, | virtual bool readRect(const Rect& r, rdr::InStream* is, | ||||
const ServerParams& server, rdr::OutStream* os); | const ServerParams& server, rdr::OutStream* os); | ||||
virtual void decodeRect(const Rect& r, const void* buffer, | |||||
virtual void decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb); | ModifiablePixelBuffer* pb); | ||||
return true; | return true; | ||||
} | } | ||||
void HextileDecoder::decodeRect(const Rect& r, const void* buffer, | |||||
void HextileDecoder::decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb) | ModifiablePixelBuffer* pb) | ||||
{ | { | ||||
int tileType = is->readU8(); | int tileType = is->readU8(); | ||||
if (tileType & hextileRaw) { | if (tileType & hextileRaw) { | ||||
is->readBytes(buf, t.area() * sizeof(T)); | |||||
is->readBytes((uint8_t*)buf, t.area() * sizeof(T)); | |||||
pb->imageRect(pf, t, buf); | pb->imageRect(pf, t, buf); | ||||
continue; | continue; | ||||
} | } |
virtual ~HextileDecoder(); | virtual ~HextileDecoder(); | ||||
virtual bool readRect(const Rect& r, rdr::InStream* is, | virtual bool readRect(const Rect& r, rdr::InStream* is, | ||||
const ServerParams& server, rdr::OutStream* os); | const ServerParams& server, rdr::OutStream* os); | ||||
virtual void decodeRect(const Rect& r, const void* buffer, | |||||
virtual void decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb); | ModifiablePixelBuffer* pb); | ||||
private: | private: |
if (encodedLen < 0) { | if (encodedLen < 0) { | ||||
pb->getImage(buf, t); | pb->getImage(buf, t); | ||||
os->writeU8(hextileRaw); | os->writeU8(hextileRaw); | ||||
os->writeBytes(buf, t.width() * t.height() * sizeof(T)); | |||||
os->writeBytes((const uint8_t*)buf, | |||||
t.width() * t.height() * sizeof(T)); | |||||
oldBgValid = oldFgValid = false; | oldBgValid = oldFgValid = false; | ||||
continue; | continue; | ||||
} | } | ||||
if ( (tileType & hextileRaw) != 0 || | if ( (tileType & hextileRaw) != 0 || | ||||
encodedLen >= t.width() * t.height() * sizeof(T)) { | encodedLen >= t.width() * t.height() * sizeof(T)) { | ||||
os->writeU8(hextileRaw); | os->writeU8(hextileRaw); | ||||
os->writeBytes(buf, t.width() * t.height() * sizeof(T)); | |||||
os->writeBytes((const uint8_t*)buf, | |||||
t.width() * t.height() * sizeof(T)); | |||||
oldBgValid = oldFgValid = false; | oldBgValid = oldFgValid = false; | ||||
continue; | continue; | ||||
} | } |
delete[] rowPointer; | delete[] rowPointer; | ||||
} | } | ||||
void JpegCompressor::writeBytes(const void* /*data*/, int /*length*/) | |||||
void JpegCompressor::writeBytes(const uint8_t* /*data*/, int /*length*/) | |||||
{ | { | ||||
throw rdr::Exception("writeBytes() is not valid with a JpegCompressor instance. Use compress() instead."); | throw rdr::Exception("writeBytes() is not valid with a JpegCompressor instance. Use compress() instead."); | ||||
} | } |
void compress(const uint8_t *, int, const Rect&, const PixelFormat&, int, int); | void compress(const uint8_t *, int, const Rect&, const PixelFormat&, int, int); | ||||
void writeBytes(const void*, int); | |||||
void writeBytes(const uint8_t*, int); | |||||
private: | private: | ||||
return true; | return true; | ||||
} | } | ||||
void RREDecoder::decodeRect(const Rect& r, const void* buffer, | |||||
void RREDecoder::decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb) | ModifiablePixelBuffer* pb) | ||||
{ | { |
virtual ~RREDecoder(); | virtual ~RREDecoder(); | ||||
virtual bool readRect(const Rect& r, rdr::InStream* is, | virtual bool readRect(const Rect& r, rdr::InStream* is, | ||||
const ServerParams& server, rdr::OutStream* os); | const ServerParams& server, rdr::OutStream* os); | ||||
virtual void decodeRect(const Rect& r, const void* buffer, | |||||
virtual void decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb); | ModifiablePixelBuffer* pb); | ||||
private: | private: |
return true; | return true; | ||||
} | } | ||||
void RawDecoder::decodeRect(const Rect& r, const void* buffer, | |||||
void RawDecoder::decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb) | ModifiablePixelBuffer* pb) | ||||
{ | { |
virtual ~RawDecoder(); | virtual ~RawDecoder(); | ||||
virtual bool readRect(const Rect& r, rdr::InStream* is, | virtual bool readRect(const Rect& r, rdr::InStream* is, | ||||
const ServerParams& server, rdr::OutStream* os); | const ServerParams& server, rdr::OutStream* os); | ||||
virtual void decodeRect(const Rect& r, const void* buffer, | |||||
virtual void decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb); | ModifiablePixelBuffer* pb); | ||||
}; | }; |
char str[13]; | char str[13]; | ||||
sprintf(str, "RFB %03d.%03d\n", defaultMajorVersion, defaultMinorVersion); | sprintf(str, "RFB %03d.%03d\n", defaultMajorVersion, defaultMinorVersion); | ||||
os->writeBytes(str, 12); | |||||
os->writeBytes((const uint8_t*)str, 12); | |||||
os->flush(); | os->flush(); | ||||
state_ = RFBSTATE_PROTOCOL_VERSION; | state_ = RFBSTATE_PROTOCOL_VERSION; | ||||
if (!is->hasData(12)) | if (!is->hasData(12)) | ||||
return false; | return false; | ||||
is->readBytes(verStr, 12); | |||||
is->readBytes((uint8_t*)verStr, 12); | |||||
verStr[12] = '\0'; | verStr[12] = '\0'; | ||||
if (sscanf(verStr, "RFB %03d.%03d\n", | if (sscanf(verStr, "RFB %03d.%03d\n", | ||||
os->writeU32(secResultFailed); | os->writeU32(secResultFailed); | ||||
if (!client.beforeVersion(3,8)) { // 3.8 onwards have failure message | if (!client.beforeVersion(3,8)) { // 3.8 onwards have failure message | ||||
os->writeU32(authFailureMsg.size()); | os->writeU32(authFailureMsg.size()); | ||||
os->writeBytes(authFailureMsg.data(), authFailureMsg.size()); | |||||
os->writeBytes((const uint8_t*)authFailureMsg.data(), | |||||
authFailureMsg.size()); | |||||
} | } | ||||
os->flush(); | os->flush(); | ||||
} catch (rdr::Exception& e) { | } catch (rdr::Exception& e) { | ||||
if (client.majorVersion == 3 && client.minorVersion == 3) { | if (client.majorVersion == 3 && client.minorVersion == 3) { | ||||
os->writeU32(0); | os->writeU32(0); | ||||
os->writeU32(strlen(str)); | os->writeU32(strlen(str)); | ||||
os->writeBytes(str, strlen(str)); | |||||
os->writeBytes((const uint8_t*)str, strlen(str)); | |||||
os->flush(); | os->flush(); | ||||
} else { | } else { | ||||
os->writeU8(0); | os->writeU8(0); | ||||
os->writeU32(strlen(str)); | os->writeU32(strlen(str)); | ||||
os->writeBytes(str, strlen(str)); | |||||
os->writeBytes((const uint8_t*)str, strlen(str)); | |||||
os->flush(); | os->flush(); | ||||
} | } | ||||
} | } | ||||
if (!reason) | if (!reason) | ||||
reason = "Authentication failure"; | reason = "Authentication failure"; | ||||
os->writeU32(strlen(reason)); | os->writeU32(strlen(reason)); | ||||
os->writeBytes(reason, strlen(reason)); | |||||
os->writeBytes((const uint8_t*)reason, strlen(reason)); | |||||
} | } | ||||
} | } | ||||
os->flush(); | os->flush(); | ||||
} | } | ||||
} | } | ||||
void SConnection::fence(uint32_t flags, unsigned len, const char data[]) | |||||
void SConnection::fence(uint32_t flags, unsigned len, | |||||
const uint8_t data[]) | |||||
{ | { | ||||
if (!(flags & fenceFlagRequest)) | if (!(flags & fenceFlagRequest)) | ||||
return; | return; |
// it responds directly to requests (stating it doesn't support any | // it responds directly to requests (stating it doesn't support any | ||||
// synchronisation) and drops responses. Override to implement more proper | // synchronisation) and drops responses. Override to implement more proper | ||||
// support. | // support. | ||||
virtual void fence(uint32_t flags, unsigned len, const char data[]); | |||||
virtual void fence(uint32_t flags, unsigned len, const uint8_t data[]); | |||||
// enableContinuousUpdates() is called when the client wants to enable | // enableContinuousUpdates() is called when the client wants to enable | ||||
// or disable continuous updates, or change the active area. | // or disable continuous updates, or change the active area. |
virtual void framebufferUpdateRequest(const Rect& r, bool incremental) = 0; | virtual void framebufferUpdateRequest(const Rect& r, bool incremental) = 0; | ||||
virtual void setDesktopSize(int fb_width, int fb_height, | virtual void setDesktopSize(int fb_width, int fb_height, | ||||
const ScreenSet& layout) = 0; | const ScreenSet& layout) = 0; | ||||
virtual void fence(uint32_t flags, unsigned len, const char data[]) = 0; | |||||
virtual void fence(uint32_t flags, unsigned len, const uint8_t data[]) = 0; | |||||
virtual void enableContinuousUpdates(bool enable, | virtual void enableContinuousUpdates(bool enable, | ||||
int x, int y, int w, int h) = 0; | int x, int y, int w, int h) = 0; | ||||
{ | { | ||||
uint32_t flags; | uint32_t flags; | ||||
uint8_t len; | uint8_t len; | ||||
char data[64]; | |||||
uint8_t data[64]; | |||||
if (!is->hasData(3 + 4 + 1)) | if (!is->hasData(3 + 4 + 1)) | ||||
return false; | return false; | ||||
} | } | ||||
std::vector<char> ca(len); | std::vector<char> ca(len); | ||||
is->readBytes(ca.data(), len); | |||||
is->readBytes((uint8_t*)ca.data(), len); | |||||
std::string filtered(convertLF(ca.data(), len)); | std::string filtered(convertLF(ca.data(), len)); | ||||
handler->clientCutText(filtered.c_str()); | handler->clientCutText(filtered.c_str()); | ||||
os->writeU16(height); | os->writeU16(height); | ||||
pf.write(os); | pf.write(os); | ||||
os->writeU32(strlen(name)); | os->writeU32(strlen(name)); | ||||
os->writeBytes(name, strlen(name)); | |||||
os->writeBytes((const uint8_t*)name, strlen(name)); | |||||
endMsg(); | endMsg(); | ||||
} | } | ||||
startMsg(msgTypeServerCutText); | startMsg(msgTypeServerCutText); | ||||
os->pad(3); | os->pad(3); | ||||
os->writeU32(len); | os->writeU32(len); | ||||
os->writeBytes(str, len); | |||||
os->writeBytes((const uint8_t*)str, len); | |||||
endMsg(); | endMsg(); | ||||
} | } | ||||
endMsg(); | endMsg(); | ||||
} | } | ||||
void SMsgWriter::writeFence(uint32_t flags, unsigned len, const char data[]) | |||||
void SMsgWriter::writeFence(uint32_t flags, unsigned len, | |||||
const uint8_t data[]) | |||||
{ | { | ||||
if (!client->supportsEncoding(pseudoEncodingFence)) | if (!client->supportsEncoding(pseudoEncodingFence)) | ||||
throw Exception("Client does not support fences"); | throw Exception("Client does not support fences"); | ||||
os->writeU16(0); | os->writeU16(0); | ||||
os->writeU32(pseudoEncodingDesktopName); | os->writeU32(pseudoEncodingDesktopName); | ||||
os->writeU32(strlen(name)); | os->writeU32(strlen(name)); | ||||
os->writeBytes(name, strlen(name)); | |||||
os->writeBytes((const uint8_t*)name, strlen(name)); | |||||
} | } | ||||
void SMsgWriter::writeSetCursorRect(int width, int height, | void SMsgWriter::writeSetCursorRect(int width, int height, | ||||
int hotspotX, int hotspotY, | int hotspotX, int hotspotY, | ||||
const void* data, const void* mask) | |||||
const uint8_t* data, | |||||
const uint8_t* mask) | |||||
{ | { | ||||
if (!client->supportsEncoding(pseudoEncodingCursor)) | if (!client->supportsEncoding(pseudoEncodingCursor)) | ||||
throw Exception("Client does not support local cursors"); | throw Exception("Client does not support local cursors"); | ||||
void SMsgWriter::writeSetXCursorRect(int width, int height, | void SMsgWriter::writeSetXCursorRect(int width, int height, | ||||
int hotspotX, int hotspotY, | int hotspotX, int hotspotY, | ||||
const void* data, const void* mask) | |||||
const uint8_t* data, | |||||
const uint8_t* mask) | |||||
{ | { | ||||
if (!client->supportsEncoding(pseudoEncodingXCursor)) | if (!client->supportsEncoding(pseudoEncodingXCursor)) | ||||
throw Exception("Client does not support local cursors"); | throw Exception("Client does not support local cursors"); |
const uint8_t* const* data); | const uint8_t* const* data); | ||||
// writeFence() sends a new fence request or response to the client. | // writeFence() sends a new fence request or response to the client. | ||||
void writeFence(uint32_t flags, unsigned len, const char data[]); | |||||
void writeFence(uint32_t flags, unsigned len, const uint8_t data[]); | |||||
// writeEndOfContinuousUpdates() indicates that we have left continuous | // writeEndOfContinuousUpdates() indicates that we have left continuous | ||||
// updates mode. | // updates mode. | ||||
void writeSetDesktopNameRect(const char *name); | void writeSetDesktopNameRect(const char *name); | ||||
void writeSetCursorRect(int width, int height, | void writeSetCursorRect(int width, int height, | ||||
int hotspotX, int hotspotY, | int hotspotX, int hotspotY, | ||||
const void* data, const void* mask); | |||||
const uint8_t* data, const uint8_t* mask); | |||||
void writeSetXCursorRect(int width, int height, | void writeSetXCursorRect(int width, int height, | ||||
int hotspotX, int hotspotY, | int hotspotX, int hotspotY, | ||||
const void* data, const void* mask); | |||||
const uint8_t* data, const uint8_t* mask); | |||||
void writeSetCursorWithAlphaRect(int width, int height, | void writeSetCursorWithAlphaRect(int width, int height, | ||||
int hotspotX, int hotspotY, | int hotspotX, int hotspotY, | ||||
const uint8_t* data); | const uint8_t* data); |
if (!is->hasData(ulen + plen)) | if (!is->hasData(ulen + plen)) | ||||
return false; | return false; | ||||
state = 2; | state = 2; | ||||
is->readBytes(username, ulen); | |||||
is->readBytes(password, plen); | |||||
is->readBytes((uint8_t*)username, ulen); | |||||
is->readBytes((uint8_t*)password, plen); | |||||
password[plen] = 0; | password[plen] = 0; | ||||
username[ulen] = 0; | username[ulen] = 0; | ||||
plen = 0; | plen = 0; |
uint8_t lenUsername = rais->readU8(); | uint8_t lenUsername = rais->readU8(); | ||||
if (!rais->hasDataOrRestore(lenUsername + 1)) | if (!rais->hasDataOrRestore(lenUsername + 1)) | ||||
return false; | return false; | ||||
rais->readBytes(username, lenUsername); | |||||
rais->readBytes((uint8_t*)username, lenUsername); | |||||
username[lenUsername] = 0; | username[lenUsername] = 0; | ||||
uint8_t lenPassword = rais->readU8(); | uint8_t lenPassword = rais->readU8(); | ||||
if (!rais->hasDataOrRestore(lenPassword)) | if (!rais->hasDataOrRestore(lenPassword)) | ||||
return false; | return false; | ||||
rais->readBytes(password, lenPassword); | |||||
rais->readBytes((uint8_t*)password, lenPassword); | |||||
password[lenPassword] = 0; | password[lenPassword] = 0; | ||||
rais->clearRestorePoint(); | rais->clearRestorePoint(); | ||||
return true; | return true; |
} | } | ||||
bool TightDecoder::doRectsConflict(const Rect& /*rectA*/, | bool TightDecoder::doRectsConflict(const Rect& /*rectA*/, | ||||
const void* bufferA, | |||||
const uint8_t* bufferA, | |||||
size_t buflenA, | size_t buflenA, | ||||
const Rect& /*rectB*/, | const Rect& /*rectB*/, | ||||
const void* bufferB, | |||||
const uint8_t* bufferB, | |||||
size_t buflenB, | size_t buflenB, | ||||
const ServerParams& /*server*/) | const ServerParams& /*server*/) | ||||
{ | { | ||||
return false; | return false; | ||||
} | } | ||||
void TightDecoder::decodeRect(const Rect& r, const void* buffer, | |||||
void TightDecoder::decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb) | ModifiablePixelBuffer* pb) | ||||
{ | { |
virtual bool readRect(const Rect& r, rdr::InStream* is, | virtual bool readRect(const Rect& r, rdr::InStream* is, | ||||
const ServerParams& server, rdr::OutStream* os); | const ServerParams& server, rdr::OutStream* os); | ||||
virtual bool doRectsConflict(const Rect& rectA, | virtual bool doRectsConflict(const Rect& rectA, | ||||
const void* bufferA, | |||||
const uint8_t* bufferA, | |||||
size_t buflenA, | size_t buflenA, | ||||
const Rect& rectB, | const Rect& rectB, | ||||
const void* bufferB, | |||||
const uint8_t* bufferB, | |||||
size_t buflenB, | size_t buflenB, | ||||
const ServerParams& server); | const ServerParams& server); | ||||
virtual void decodeRect(const Rect& r, const void* buffer, | |||||
virtual void decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb); | ModifiablePixelBuffer* pb); | ||||
writer()->writeDesktopSize(reasonClient, result); | writer()->writeDesktopSize(reasonClient, result); | ||||
} | } | ||||
void VNCSConnectionST::fence(uint32_t flags, unsigned len, const char data[]) | |||||
void VNCSConnectionST::fence(uint32_t flags, unsigned len, const uint8_t data[]) | |||||
{ | { | ||||
uint8_t type; | uint8_t type; | ||||
delete [] fenceData; | delete [] fenceData; | ||||
fenceData = NULL; | fenceData = NULL; | ||||
if (len > 0) { | if (len > 0) { | ||||
fenceData = new char[len]; | |||||
fenceData = new uint8_t[len]; | |||||
memcpy(fenceData, data, len); | memcpy(fenceData, data, len); | ||||
} | } | ||||
void VNCSConnectionST::supportsFence() | void VNCSConnectionST::supportsFence() | ||||
{ | { | ||||
char type = 0; | |||||
uint8_t type = 0; | |||||
writer()->writeFence(fenceFlagRequest, sizeof(type), &type); | writer()->writeFence(fenceFlagRequest, sizeof(type), &type); | ||||
} | } | ||||
void VNCSConnectionST::writeRTTPing() | void VNCSConnectionST::writeRTTPing() | ||||
{ | { | ||||
char type; | |||||
uint8_t type; | |||||
if (!client.supportsFence()) | if (!client.supportsFence()) | ||||
return; | return; |
virtual void framebufferUpdateRequest(const Rect& r, bool incremental); | virtual void framebufferUpdateRequest(const Rect& r, bool incremental); | ||||
virtual void setDesktopSize(int fb_width, int fb_height, | virtual void setDesktopSize(int fb_width, int fb_height, | ||||
const ScreenSet& layout); | const ScreenSet& layout); | ||||
virtual void fence(uint32_t flags, unsigned len, const char data[]); | |||||
virtual void fence(uint32_t flags, unsigned len, const uint8_t data[]); | |||||
virtual void enableContinuousUpdates(bool enable, | virtual void enableContinuousUpdates(bool enable, | ||||
int x, int y, int w, int h); | int x, int y, int w, int h); | ||||
virtual void handleClipboardRequest(); | virtual void handleClipboardRequest(); | ||||
bool pendingSyncFence, syncFence; | bool pendingSyncFence, syncFence; | ||||
uint32_t fenceFlags; | uint32_t fenceFlags; | ||||
unsigned fenceDataLen; | unsigned fenceDataLen; | ||||
char *fenceData; | |||||
uint8_t *fenceData; | |||||
Congestion congestion; | Congestion congestion; | ||||
Timer congestionTimer; | Timer congestionTimer; |
rdr::OutStream& os = sock->outStream(); | rdr::OutStream& os = sock->outStream(); | ||||
// Shortest possible way to tell a client it is not welcome | // Shortest possible way to tell a client it is not welcome | ||||
os.writeBytes("RFB 003.003\n", 12); | |||||
os.writeBytes((const uint8_t*)"RFB 003.003\n", 12); | |||||
os.writeU32(0); | os.writeU32(0); | ||||
const char* reason = "Too many security failures"; | const char* reason = "Too many security failures"; | ||||
os.writeU32(strlen(reason)); | os.writeU32(strlen(reason)); | ||||
os.writeBytes(reason, strlen(reason)); | |||||
os.writeBytes((const uint8_t*)reason, strlen(reason)); | |||||
os.flush(); | os.flush(); | ||||
} catch (rdr::Exception&) { | } catch (rdr::Exception&) { | ||||
} | } |
return true; | return true; | ||||
} | } | ||||
void ZRLEDecoder::decodeRect(const Rect& r, const void* buffer, | |||||
void ZRLEDecoder::decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb) | ModifiablePixelBuffer* pb) | ||||
{ | { | ||||
*ptr = readOpaque24B(zis); | *ptr = readOpaque24B(zis); | ||||
} | } | ||||
} else { | } else { | ||||
zis->readBytes(buf, t.area() * sizeof(T)); | |||||
zis->readBytes((uint8_t*)buf, t.area() * sizeof(T)); | |||||
} | } | ||||
} else { | } else { |
virtual ~ZRLEDecoder(); | virtual ~ZRLEDecoder(); | ||||
virtual bool readRect(const Rect& r, rdr::InStream* is, | virtual bool readRect(const Rect& r, rdr::InStream* is, | ||||
const ServerParams& server, rdr::OutStream* os); | const ServerParams& server, rdr::OutStream* os); | ||||
virtual void decodeRect(const Rect& r, const void* buffer, | |||||
virtual void decodeRect(const Rect& r, const uint8_t* buffer, | |||||
size_t buflen, const ServerParams& server, | size_t buflen, const ServerParams& server, | ||||
ModifiablePixelBuffer* pb); | ModifiablePixelBuffer* pb); | ||||
desktop->setCursorPos(pos); | desktop->setCursorPos(pos); | ||||
} | } | ||||
void CConn::fence(uint32_t flags, unsigned len, const char data[]) | |||||
void CConn::fence(uint32_t flags, unsigned len, const uint8_t data[]) | |||||
{ | { | ||||
CMsgHandler::fence(flags, len, data); | CMsgHandler::fence(flags, len, data); | ||||
const uint8_t* data); | const uint8_t* data); | ||||
void setCursorPos(const rfb::Point& pos); | void setCursorPos(const rfb::Point& pos); | ||||
void fence(uint32_t flags, unsigned len, const char data[]); | |||||
void fence(uint32_t flags, unsigned len, const uint8_t data[]); | |||||
void setLEDState(unsigned int state); | void setLEDState(unsigned int state); | ||||