mirror of
https://github.com/kasmtech/KasmVNC.git
synced 2025-02-23 05:40:48 +01:00
Implement server-side downgrade from udp
This commit is contained in:
parent
6c0eff0828
commit
582740b3d8
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1716,3 +1716,7 @@ unsigned EncodeManager::scaledQuality(const Rect& rect) const {
|
|||||||
|
|
||||||
return dynamic;
|
return dynamic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EncodeManager::resetZlib() {
|
||||||
|
((TightEncoder *) encoders[encoderTight])->resetZlib();
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -346,7 +346,7 @@ void SMsgReader::readUpgradeToUdp()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!len) {
|
if (!len) {
|
||||||
handler->udpDowngrade();
|
handler->udpDowngrade(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
//
|
//
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user