Implement server-side downgrade from udp

This commit is contained in:
Lauri Kasanen 2022-10-03 14:54:40 +03:00
parent 6c0eff0828
commit 582740b3d8
12 changed files with 47 additions and 12 deletions

View File

@ -125,7 +125,7 @@ static uint8_t udpsend(WuClient *client, const uint8_t *data, unsigned len, uint
return 0; return 0;
} }
UdpStream::UdpStream(): OutStream(), client(NULL), total_len(0), id(0) { UdpStream::UdpStream(): OutStream(), client(NULL), total_len(0), id(0), failed(false) {
ptr = data; ptr = data;
end = data + UDPSTREAM_BUFSIZE; end = data + UDPSTREAM_BUFSIZE;
@ -137,8 +137,10 @@ void UdpStream::flush() {
total_len += len; total_len += len;
if (client) { if (client) {
if (udpsend(client, data, len, &id)) if (udpsend(client, data, len, &id)) {
vlog.error("Error sending udp, client gone?"); vlog.error("Error sending udp, client gone?");
failed = true;
}
} else { } else {
vlog.error("Tried to send udp without a client"); vlog.error("Tried to send udp without a client");
} }
@ -151,6 +153,14 @@ void UdpStream::overrun(size_t needed) {
abort(); abort();
} }
bool UdpStream::isFailed() const {
return failed;
}
void UdpStream::clearFailed() {
failed = false;
}
void wuGotHttp(const char msg[], const uint32_t msglen, char resp[]) { void wuGotHttp(const char msg[], const uint32_t msglen, char resp[]) {
WuGotHttp(host, msg, msglen, resp); WuGotHttp(host, msg, msglen, resp);
} }

View File

@ -39,11 +39,15 @@ namespace network {
void setClient(WuClient *cli) { void setClient(WuClient *cli) {
client = cli; client = cli;
} }
bool isFailed() const;
void clearFailed();
private: private:
uint8_t data[UDPSTREAM_BUFSIZE]; uint8_t data[UDPSTREAM_BUFSIZE];
WuClient *client; WuClient *client;
size_t total_len; size_t total_len;
uint32_t id; uint32_t id;
bool failed;
}; };
} }

View File

@ -1716,3 +1716,7 @@ unsigned EncodeManager::scaledQuality(const Rect& rect) const {
return dynamic; return dynamic;
} }
void EncodeManager::resetZlib() {
((TightEncoder *) encoders[encoderTight])->resetZlib();
}

View File

@ -79,6 +79,8 @@ namespace rfb {
return scalingTime; return scalingTime;
}; };
void resetZlib();
struct codecstats_t { struct codecstats_t {
uint32_t ms; uint32_t ms;
uint32_t area; uint32_t area;

View File

@ -96,7 +96,7 @@ namespace rfb {
virtual void supportsQEMUKeyEvent(); virtual void supportsQEMUKeyEvent();
virtual void udpUpgrade(const char *resp) = 0; virtual void udpUpgrade(const char *resp) = 0;
virtual void udpDowngrade() = 0; virtual void udpDowngrade(const bool) = 0;
ConnParams cp; ConnParams cp;
}; };

View File

@ -346,7 +346,7 @@ void SMsgReader::readUpgradeToUdp()
} }
if (!len) { if (!len) {
handler->udpDowngrade(); handler->udpDowngrade(false);
return; return;
} }

View File

@ -57,7 +57,7 @@ static const TightConf conf[10] = {
}; };
TightEncoder::TightEncoder(SConnection* conn) : TightEncoder::TightEncoder(SConnection* conn) :
Encoder(conn, encodingTight, EncoderPlain, 256) Encoder(conn, encodingTight, EncoderPlain, 256), zlibNeedsReset(false)
{ {
setCompressLevel(-1); setCompressLevel(-1);
} }
@ -166,7 +166,7 @@ void TightEncoder::writeFullColourRect(const PixelBuffer* pb, const Palette& pal
int stride, h; int stride, h;
os = conn->getOutStream(conn->cp.supportsUdp); os = conn->getOutStream(conn->cp.supportsUdp);
if (conn->cp.supportsUdp) if (conn->cp.supportsUdp || zlibNeedsReset)
os->writeU8((streamId << 4) | (1 << streamId)); os->writeU8((streamId << 4) | (1 << streamId));
else else
os->writeU8(streamId << 4); os->writeU8(streamId << 4);
@ -247,7 +247,7 @@ rdr::OutStream* TightEncoder::getZlibOutStream(int streamId, int level, size_t l
zlibStreams[streamId].setUnderlying(&memStream); zlibStreams[streamId].setUnderlying(&memStream);
zlibStreams[streamId].setCompressionLevel(level); zlibStreams[streamId].setCompressionLevel(level);
if (conn->cp.supportsUdp) if (conn->cp.supportsUdp || zlibNeedsReset)
zlibStreams[streamId].resetDeflate(); zlibStreams[streamId].resetDeflate();
return &zlibStreams[streamId]; return &zlibStreams[streamId];
@ -272,6 +272,11 @@ void TightEncoder::flushZlibOutStream(rdr::OutStream* os_)
memStream.clear(); memStream.clear();
} }
void TightEncoder::resetZlib()
{
zlibNeedsReset = true;
}
// //
// Including BPP-dependent implementation of the encoder. // Including BPP-dependent implementation of the encoder.
// //

View File

@ -39,6 +39,7 @@ namespace rfb {
virtual void writeSolidRect(int width, int height, virtual void writeSolidRect(int width, int height,
const PixelFormat& pf, const PixelFormat& pf,
const rdr::U8* colour); const rdr::U8* colour);
void resetZlib();
protected: protected:
void writeMonoRect(const PixelBuffer* pb, const Palette& palette); void writeMonoRect(const PixelBuffer* pb, const Palette& palette);
@ -76,6 +77,7 @@ namespace rfb {
rdr::MemOutStream memStream; rdr::MemOutStream memStream;
int idxZlibLevel, monoZlibLevel, rawZlibLevel; int idxZlibLevel, monoZlibLevel, rawZlibLevel;
bool zlibNeedsReset;
}; };
} }

View File

@ -40,7 +40,7 @@ void TightEncoder::writeMonoRect(int width, int height,
os = conn->getOutStream(conn->cp.supportsUdp); os = conn->getOutStream(conn->cp.supportsUdp);
if (conn->cp.supportsUdp) if (conn->cp.supportsUdp || zlibNeedsReset)
os->writeU8(((streamId | tightExplicitFilter) << 4) | (1 << streamId)); os->writeU8(((streamId | tightExplicitFilter) << 4) | (1 << streamId));
else else
os->writeU8((streamId | tightExplicitFilter) << 4); os->writeU8((streamId | tightExplicitFilter) << 4);
@ -130,7 +130,7 @@ void TightEncoder::writeIndexedRect(int width, int height,
os = conn->getOutStream(conn->cp.supportsUdp); os = conn->getOutStream(conn->cp.supportsUdp);
if (conn->cp.supportsUdp) if (conn->cp.supportsUdp || zlibNeedsReset)
os->writeU8(((streamId | tightExplicitFilter) << 4) | (1 << streamId)); os->writeU8(((streamId | tightExplicitFilter) << 4) | (1 << streamId));
else else
os->writeU8((streamId | tightExplicitFilter) << 4); os->writeU8((streamId | tightExplicitFilter) << 4);

View File

@ -1769,10 +1769,12 @@ void VNCSConnectionST::udpUpgrade(const char *resp)
writer()->writeUdpUpgrade(resp); writer()->writeUdpUpgrade(resp);
} }
void VNCSConnectionST::udpDowngrade() void VNCSConnectionST::udpDowngrade(const bool byServer)
{ {
cp.supportsUdp = false; cp.supportsUdp = false;
cp.useCopyRect = true; cp.useCopyRect = true;
encodeManager.resetZlib();
vlog.info("Client %s downgrading from udp", sock->getPeerAddress()); vlog.info("Client %s downgrading from udp by %s", sock->getPeerAddress(),
byServer ? "the server" : "its own request");
} }

View File

@ -196,6 +196,8 @@ namespace rfb {
return encodeManager.getScalingTime(); return encodeManager.getScalingTime();
} }
virtual void udpDowngrade(const bool byServer);
bool upgradingToUdp; bool upgradingToUdp;
private: private:
@ -220,7 +222,6 @@ namespace rfb {
virtual void handleClipboardAnnounce(bool available); virtual void handleClipboardAnnounce(bool available);
virtual void handleClipboardAnnounceBinary(const unsigned num, const char mimes[][32]); virtual void handleClipboardAnnounceBinary(const unsigned num, const char mimes[][32]);
virtual void udpUpgrade(const char *resp); virtual void udpUpgrade(const char *resp);
virtual void udpDowngrade();
virtual void supportsLocalCursor(); virtual void supportsLocalCursor();
virtual void supportsFence(); virtual void supportsFence();
virtual void supportsContinuousUpdates(); virtual void supportsContinuousUpdates();

View File

@ -1064,6 +1064,11 @@ void VNCServerST::writeUpdate()
(*ci)->add_changed(ui.changed); (*ci)->add_changed(ui.changed);
(*ci)->writeFramebufferUpdateOrClose(); (*ci)->writeFramebufferUpdateOrClose();
if (((network::UdpStream *)(*ci)->getOutStream(true))->isFailed()) {
((network::UdpStream *)(*ci)->getOutStream(true))->clearFailed();
(*ci)->udpDowngrade(true);
}
if (apimessager) { if (apimessager) {
(*ci)->sendStats(false); (*ci)->sendStats(false);
const EncodeManager::codecstats_t subjpeg = (*ci)->getJpegStats(); const EncodeManager::codecstats_t subjpeg = (*ci)->getJpegStats();