Udp
This commit is contained in:
committed by
Matthew McClaskey
parent
ba902f8194
commit
3b40a92548
@@ -45,6 +45,7 @@ ConnParams::ConnParams()
|
||||
supportsWEBP(false),
|
||||
supportsSetDesktopSize(false), supportsFence(false),
|
||||
supportsContinuousUpdates(false), supportsExtendedClipboard(false),
|
||||
supportsUdp(false),
|
||||
compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),
|
||||
subsampling(subsampleUndefined), name_(0), cursorPos_(0, 0), verStrPos(0),
|
||||
ledState_(ledUnknown), shandler(NULL)
|
||||
|
||||
@@ -117,6 +117,8 @@ namespace rfb {
|
||||
bool supportsContinuousUpdates;
|
||||
bool supportsExtendedClipboard;
|
||||
|
||||
bool supportsUdp;
|
||||
|
||||
int compressLevel;
|
||||
int qualityLevel;
|
||||
int fineQualityLevel;
|
||||
|
||||
@@ -622,7 +622,7 @@ Encoder *EncodeManager::startRect(const Rect& rect, int type, const bool trackQu
|
||||
if (isWebp)
|
||||
klass = encoderTightWEBP;
|
||||
|
||||
beforeLength = conn->getOutStream()->length();
|
||||
beforeLength = conn->getOutStream(conn->cp.supportsUdp)->length();
|
||||
|
||||
stats[klass][activeType].rects++;
|
||||
stats[klass][activeType].pixels += rect.area();
|
||||
@@ -655,7 +655,7 @@ void EncodeManager::endRect(const uint8_t isWebp)
|
||||
|
||||
conn->writer()->endRect();
|
||||
|
||||
length = conn->getOutStream()->length() - beforeLength;
|
||||
length = conn->getOutStream(conn->cp.supportsUdp)->length() - beforeLength;
|
||||
|
||||
klass = activeEncoders[activeType];
|
||||
if (isWebp)
|
||||
@@ -669,7 +669,7 @@ void EncodeManager::writeCopyPassRects(const std::vector<CopyPassRect>& copypass
|
||||
|
||||
Region lossyCopy;
|
||||
|
||||
beforeLength = conn->getOutStream()->length();
|
||||
beforeLength = conn->getOutStream(conn->cp.supportsUdp)->length();
|
||||
|
||||
for (rect = copypassed.begin(); rect != copypassed.end(); ++rect) {
|
||||
int equiv;
|
||||
@@ -689,7 +689,7 @@ void EncodeManager::writeCopyPassRects(const std::vector<CopyPassRect>& copypass
|
||||
lossyRegion.assign_union(lossyCopy);
|
||||
}
|
||||
|
||||
copyStats.bytes += conn->getOutStream()->length() - beforeLength;
|
||||
copyStats.bytes += conn->getOutStream(conn->cp.supportsUdp)->length() - beforeLength;
|
||||
}
|
||||
|
||||
void EncodeManager::writeCopyRects(const Region& copied, const Point& delta)
|
||||
@@ -699,7 +699,7 @@ void EncodeManager::writeCopyRects(const Region& copied, const Point& delta)
|
||||
|
||||
Region lossyCopy;
|
||||
|
||||
beforeLength = conn->getOutStream()->length();
|
||||
beforeLength = conn->getOutStream(conn->cp.supportsUdp)->length();
|
||||
|
||||
copied.get_rects(&rects, delta.x <= 0, delta.y <= 0);
|
||||
for (rect = rects.begin(); rect != rects.end(); ++rect) {
|
||||
@@ -714,7 +714,7 @@ void EncodeManager::writeCopyRects(const Region& copied, const Point& delta)
|
||||
rect->tl.y - delta.y);
|
||||
}
|
||||
|
||||
copyStats.bytes += conn->getOutStream()->length() - beforeLength;
|
||||
copyStats.bytes += conn->getOutStream(conn->cp.supportsUdp)->length() - beforeLength;
|
||||
|
||||
lossyCopy = lossyRegion;
|
||||
lossyCopy.translate(delta);
|
||||
|
||||
@@ -62,6 +62,8 @@ SConnection::SConnection()
|
||||
defaultMinorVersion = 3;
|
||||
|
||||
cp.setVersion(defaultMajorVersion, defaultMinorVersion);
|
||||
|
||||
udps = new network::UdpStream;
|
||||
}
|
||||
|
||||
SConnection::~SConnection()
|
||||
@@ -72,6 +74,7 @@ SConnection::~SConnection()
|
||||
delete writer_;
|
||||
writer_ = 0;
|
||||
strFree(clientClipboard);
|
||||
delete udps;
|
||||
}
|
||||
|
||||
void SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
|
||||
@@ -348,7 +351,7 @@ void SConnection::approveConnection(bool accept, const char* reason)
|
||||
if (accept) {
|
||||
state_ = RFBSTATE_INITIALISATION;
|
||||
reader_ = new SMsgReader(this, is);
|
||||
writer_ = new SMsgWriter(&cp, os);
|
||||
writer_ = new SMsgWriter(&cp, os, udps);
|
||||
authSuccess();
|
||||
} else {
|
||||
state_ = RFBSTATE_INVALID;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#ifndef __RFB_SCONNECTION_H__
|
||||
#define __RFB_SCONNECTION_H__
|
||||
|
||||
#include <network/Udp.h>
|
||||
#include <rdr/InStream.h>
|
||||
#include <rdr/OutStream.h>
|
||||
#include <rfb/SMsgHandler.h>
|
||||
@@ -173,7 +174,7 @@ namespace rfb {
|
||||
SMsgWriter* writer() { return writer_; }
|
||||
|
||||
rdr::InStream* getInStream() { return is; }
|
||||
rdr::OutStream* getOutStream() { return os; }
|
||||
rdr::OutStream* getOutStream(const bool udp = false) { return udp ? udps : os; }
|
||||
|
||||
enum stateEnum {
|
||||
RFBSTATE_UNINITIALISED,
|
||||
@@ -219,6 +220,7 @@ namespace rfb {
|
||||
int defaultMajorVersion, defaultMinorVersion;
|
||||
rdr::InStream* is;
|
||||
rdr::OutStream* os;
|
||||
network::UdpStream *udps;
|
||||
SMsgReader* reader_;
|
||||
SMsgWriter* writer_;
|
||||
SecurityServer security;
|
||||
|
||||
@@ -104,4 +104,3 @@ void SMsgHandler::setDesktopSize(int fb_width, int fb_height,
|
||||
cp.height = fb_height;
|
||||
cp.screenLayout = layout;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,9 @@ namespace rfb {
|
||||
// handler will send a pseudo-rect back, signalling server support.
|
||||
virtual void supportsQEMUKeyEvent();
|
||||
|
||||
virtual void udpUpgrade(const char *resp) = 0;
|
||||
virtual void udpDowngrade() = 0;
|
||||
|
||||
ConnParams cp;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* USA.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <network/Udp.h>
|
||||
#include <rdr/InStream.h>
|
||||
#include <rdr/ZlibInStream.h>
|
||||
|
||||
@@ -96,6 +97,9 @@ void SMsgReader::readMsg()
|
||||
case msgTypeQEMUClientMessage:
|
||||
readQEMUMessage();
|
||||
break;
|
||||
case msgTypeUpgradeToUdp:
|
||||
readUpgradeToUdp();
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown message type %d\n", msgType);
|
||||
throw Exception("unknown message type");
|
||||
@@ -329,3 +333,27 @@ void SMsgReader::readQEMUKeyEvent()
|
||||
}
|
||||
handler->keyEvent(keysym, keycode, down);
|
||||
}
|
||||
|
||||
void SMsgReader::readUpgradeToUdp()
|
||||
{
|
||||
char buf[4096], resp[4096];
|
||||
rdr::U16 len = is->readU16();
|
||||
|
||||
if (len >= sizeof(buf)) {
|
||||
vlog.error("Ignoring udp upgrade with too large payload");
|
||||
is->skip(len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
handler->udpDowngrade();
|
||||
return;
|
||||
}
|
||||
|
||||
is->readBytes(buf, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
wuGotHttp(buf, len, resp);
|
||||
|
||||
handler->udpUpgrade(resp);
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ namespace rfb {
|
||||
void readQEMUMessage();
|
||||
void readQEMUKeyEvent();
|
||||
|
||||
void readUpgradeToUdp();
|
||||
|
||||
SMsgHandler* handler;
|
||||
rdr::InStream* is;
|
||||
};
|
||||
|
||||
@@ -37,8 +37,8 @@ using namespace rfb;
|
||||
|
||||
static LogWriter vlog("SMsgWriter");
|
||||
|
||||
SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
|
||||
: cp(cp_), os(os_),
|
||||
SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_, rdr::OutStream* udps_)
|
||||
: cp(cp_), os(os_), udps(udps_),
|
||||
nRectsInUpdate(0), nRectsInHeader(0),
|
||||
needSetDesktopSize(false), needExtendedDesktopSize(false),
|
||||
needSetDesktopName(false), needSetCursor(false),
|
||||
@@ -362,6 +362,16 @@ void SMsgWriter::writeFramebufferUpdateEnd()
|
||||
os->writeU16(0);
|
||||
os->writeU16(0);
|
||||
os->writeU32(pseudoEncodingLastRect);
|
||||
|
||||
// Send an UDP flip marker, if needed
|
||||
if (cp->supportsUdp) {
|
||||
udps->writeS16(0);
|
||||
udps->writeS16(0);
|
||||
udps->writeU16(0);
|
||||
udps->writeU16(0);
|
||||
udps->writeU32(pseudoEncodingLastRect);
|
||||
udps->flush();
|
||||
}
|
||||
}
|
||||
|
||||
endMsg();
|
||||
@@ -370,8 +380,13 @@ void SMsgWriter::writeFramebufferUpdateEnd()
|
||||
void SMsgWriter::writeCopyRect(const Rect& r, int srcX, int srcY)
|
||||
{
|
||||
startRect(r,encodingCopyRect);
|
||||
os->writeU16(srcX);
|
||||
os->writeU16(srcY);
|
||||
if (cp->supportsUdp) {
|
||||
udps->writeU16(srcX);
|
||||
udps->writeU16(srcY);
|
||||
} else {
|
||||
os->writeU16(srcX);
|
||||
os->writeU16(srcY);
|
||||
}
|
||||
endRect();
|
||||
}
|
||||
|
||||
@@ -380,16 +395,27 @@ void SMsgWriter::startRect(const Rect& r, int encoding)
|
||||
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
|
||||
throw Exception("SMsgWriter::startRect: nRects out of sync");
|
||||
|
||||
os->writeS16(r.tl.x);
|
||||
os->writeS16(r.tl.y);
|
||||
os->writeU16(r.width());
|
||||
os->writeU16(r.height());
|
||||
os->writeU32(encoding);
|
||||
if (cp->supportsUdp) {
|
||||
udps->writeS16(r.tl.x);
|
||||
udps->writeS16(r.tl.y);
|
||||
udps->writeU16(r.width());
|
||||
udps->writeU16(r.height());
|
||||
udps->writeU32(encoding);
|
||||
} else {
|
||||
os->writeS16(r.tl.x);
|
||||
os->writeS16(r.tl.y);
|
||||
os->writeU16(r.width());
|
||||
os->writeU16(r.height());
|
||||
os->writeU32(encoding);
|
||||
}
|
||||
}
|
||||
|
||||
void SMsgWriter::endRect()
|
||||
{
|
||||
os->flush();
|
||||
if (cp->supportsUdp)
|
||||
udps->flush();
|
||||
else
|
||||
os->flush();
|
||||
}
|
||||
|
||||
void SMsgWriter::startMsg(int type)
|
||||
@@ -712,3 +738,14 @@ void SMsgWriter::writeQEMUKeyEventRect()
|
||||
os->writeU16(0);
|
||||
os->writeU32(pseudoEncodingQEMUKeyEvent);
|
||||
}
|
||||
|
||||
void SMsgWriter::writeUdpUpgrade(const char *resp)
|
||||
{
|
||||
startMsg(msgTypeUpgradeToUdp);
|
||||
|
||||
rdr::U16 len = strlen(resp);
|
||||
os->writeU16(len);
|
||||
os->writeBytes(resp, len);
|
||||
|
||||
endMsg();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace rfb {
|
||||
|
||||
class SMsgWriter {
|
||||
public:
|
||||
SMsgWriter(ConnParams* cp, rdr::OutStream* os);
|
||||
SMsgWriter(ConnParams* cp, rdr::OutStream* os, rdr::OutStream *udps);
|
||||
virtual ~SMsgWriter();
|
||||
|
||||
// writeServerInit() must only be called at the appropriate time in the
|
||||
@@ -127,6 +127,8 @@ namespace rfb {
|
||||
void startRect(const Rect& r, int enc);
|
||||
void endRect();
|
||||
|
||||
void writeUdpUpgrade(const char *resp);
|
||||
|
||||
protected:
|
||||
void startMsg(int type);
|
||||
void endMsg();
|
||||
@@ -157,6 +159,7 @@ namespace rfb {
|
||||
|
||||
ConnParams* cp;
|
||||
rdr::OutStream* os;
|
||||
rdr::OutStream* udps;
|
||||
|
||||
int nRectsInUpdate;
|
||||
int nRectsInHeader;
|
||||
|
||||
@@ -217,6 +217,16 @@ rfb::StringParameter rfb::Server::kasmPasswordFile
|
||||
"Password file for BasicAuth, created with the kasmvncpasswd utility.",
|
||||
"~/.kasmpasswd");
|
||||
|
||||
rfb::StringParameter rfb::Server::publicIP
|
||||
("publicIP",
|
||||
"The server's public IP, for UDP negotiation. If not set, will be queried via the internet.",
|
||||
"");
|
||||
|
||||
rfb::IntParameter rfb::Server::udpFullFrameFrequency
|
||||
("udpFullFrameFrequency",
|
||||
"Send a full frame every N frames for clients using UDP. 0 to disable",
|
||||
0, 0, 1000);
|
||||
|
||||
static void bandwidthPreset() {
|
||||
rfb::Server::dynamicQualityMin.setParam(2);
|
||||
rfb::Server::dynamicQualityMax.setParam(9);
|
||||
|
||||
@@ -60,7 +60,9 @@ namespace rfb {
|
||||
static IntParameter videoOutTime;
|
||||
static IntParameter videoArea;
|
||||
static IntParameter videoScaling;
|
||||
static IntParameter udpFullFrameFrequency;
|
||||
static StringParameter kasmPasswordFile;
|
||||
static StringParameter publicIP;
|
||||
static BoolParameter printVideoArea;
|
||||
static BoolParameter protocol3_3;
|
||||
static BoolParameter alwaysShared;
|
||||
|
||||
@@ -104,7 +104,7 @@ void TightEncoder::writeSolidRect(int width, int height,
|
||||
{
|
||||
rdr::OutStream* os;
|
||||
|
||||
os = conn->getOutStream();
|
||||
os = conn->getOutStream(conn->cp.supportsUdp);
|
||||
|
||||
os->writeU8(tightFill << 4);
|
||||
writePixels(colour, pf, 1, os);
|
||||
@@ -165,9 +165,11 @@ void TightEncoder::writeFullColourRect(const PixelBuffer* pb, const Palette& pal
|
||||
const rdr::U8* buffer;
|
||||
int stride, h;
|
||||
|
||||
os = conn->getOutStream();
|
||||
|
||||
os->writeU8(streamId << 4);
|
||||
os = conn->getOutStream(conn->cp.supportsUdp);
|
||||
if (conn->cp.supportsUdp)
|
||||
os->writeU8((streamId << 4) | (1 << streamId));
|
||||
else
|
||||
os->writeU8(streamId << 4);
|
||||
|
||||
// Set up compression
|
||||
if ((pb->getPF().bpp != 32) || !pb->getPF().is888())
|
||||
@@ -238,13 +240,15 @@ rdr::OutStream* TightEncoder::getZlibOutStream(int streamId, int level, size_t l
|
||||
// Minimum amount of data to be compressed. This value should not be
|
||||
// changed, doing so will break compatibility with existing clients.
|
||||
if (length < 12)
|
||||
return conn->getOutStream();
|
||||
return conn->getOutStream(conn->cp.supportsUdp);
|
||||
|
||||
assert(streamId >= 0);
|
||||
assert(streamId < 4);
|
||||
|
||||
zlibStreams[streamId].setUnderlying(&memStream);
|
||||
zlibStreams[streamId].setCompressionLevel(level);
|
||||
if (conn->cp.supportsUdp)
|
||||
zlibStreams[streamId].resetDeflate();
|
||||
|
||||
return &zlibStreams[streamId];
|
||||
}
|
||||
@@ -261,7 +265,7 @@ void TightEncoder::flushZlibOutStream(rdr::OutStream* os_)
|
||||
zos->flush();
|
||||
zos->setUnderlying(NULL);
|
||||
|
||||
os = conn->getOutStream();
|
||||
os = conn->getOutStream(conn->cp.supportsUdp);
|
||||
|
||||
writeCompact(os, memStream.length());
|
||||
os->writeBytes(memStream.data(), memStream.length());
|
||||
|
||||
@@ -38,9 +38,12 @@ void TightEncoder::writeMonoRect(int width, int height,
|
||||
|
||||
assert(palette.size() == 2);
|
||||
|
||||
os = conn->getOutStream();
|
||||
os = conn->getOutStream(conn->cp.supportsUdp);
|
||||
|
||||
os->writeU8((streamId | tightExplicitFilter) << 4);
|
||||
if (conn->cp.supportsUdp)
|
||||
os->writeU8(((streamId | tightExplicitFilter) << 4) | (1 << streamId));
|
||||
else
|
||||
os->writeU8((streamId | tightExplicitFilter) << 4);
|
||||
os->writeU8(tightFilterPalette);
|
||||
|
||||
// Write the palette
|
||||
@@ -125,9 +128,12 @@ void TightEncoder::writeIndexedRect(int width, int height,
|
||||
assert(palette.size() > 0);
|
||||
assert(palette.size() <= 256);
|
||||
|
||||
os = conn->getOutStream();
|
||||
os = conn->getOutStream(conn->cp.supportsUdp);
|
||||
|
||||
os->writeU8((streamId | tightExplicitFilter) << 4);
|
||||
if (conn->cp.supportsUdp)
|
||||
os->writeU8(((streamId | tightExplicitFilter) << 4) | (1 << streamId));
|
||||
else
|
||||
os->writeU8((streamId | tightExplicitFilter) << 4);
|
||||
os->writeU8(tightFilterPalette);
|
||||
|
||||
// Write the palette
|
||||
|
||||
@@ -147,7 +147,7 @@ void TightJPEGEncoder::writeOnly(const std::vector<uint8_t> &out) const
|
||||
{
|
||||
rdr::OutStream* os;
|
||||
|
||||
os = conn->getOutStream();
|
||||
os = conn->getOutStream(conn->cp.supportsUdp);
|
||||
|
||||
os->writeU8(tightJpeg << 4);
|
||||
|
||||
@@ -184,7 +184,7 @@ void TightJPEGEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
|
||||
jc.compress(buffer, stride, pb->getRect(),
|
||||
pb->getPF(), quality, subsampling);
|
||||
|
||||
os = conn->getOutStream();
|
||||
os = conn->getOutStream(conn->cp.supportsUdp);
|
||||
|
||||
os->writeU8(tightJpeg << 4);
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ void TightWEBPEncoder::writeOnly(const std::vector<uint8_t> &out) const
|
||||
{
|
||||
rdr::OutStream* os;
|
||||
|
||||
os = conn->getOutStream();
|
||||
os = conn->getOutStream(conn->cp.supportsUdp);
|
||||
|
||||
os->writeU8(tightWebp << 4);
|
||||
|
||||
@@ -248,7 +248,7 @@ void TightWEBPEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
|
||||
vlog.error("WEBP error %u", pic.error_code);
|
||||
}
|
||||
|
||||
os = conn->getOutStream();
|
||||
os = conn->getOutStream(conn->cp.supportsUdp);
|
||||
|
||||
os->writeU8(tightWebp << 4);
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ extern rfb::BoolParameter disablebasicauth;
|
||||
|
||||
VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
|
||||
bool reverse)
|
||||
: sock(s), reverseConnection(reverse),
|
||||
: upgradingToUdp(false), sock(s), reverseConnection(reverse),
|
||||
inProcessMessages(false),
|
||||
pendingSyncFence(false), syncFence(false), fenceFlags(0),
|
||||
fenceDataLen(0), fenceData(NULL), congestionTimer(this),
|
||||
@@ -63,7 +63,8 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
|
||||
continuousUpdates(false), encodeManager(this, &server_->encCache),
|
||||
needsPermCheck(false), pointerEventTime(0),
|
||||
clientHasCursor(false),
|
||||
accessRights(AccessDefault), startTime(time(0)), frameTracking(false)
|
||||
accessRights(AccessDefault), startTime(time(0)), frameTracking(false),
|
||||
udpFramesSinceFull(0)
|
||||
{
|
||||
setStreams(&sock->inStream(), &sock->outStream());
|
||||
peerEndpoint.buf = sock->getPeerEndpoint();
|
||||
@@ -1231,7 +1232,7 @@ bool VNCSConnectionST::isCongested()
|
||||
if (sock->outStream().bufferUsage() > 0)
|
||||
return true;
|
||||
|
||||
if (!cp.supportsFence)
|
||||
if (!cp.supportsFence || cp.supportsUdp)
|
||||
return false;
|
||||
|
||||
congestion.updatePosition(sock->outStream().length());
|
||||
@@ -1462,6 +1463,14 @@ void VNCSConnectionST::writeDataUpdate()
|
||||
if (!pending.is_empty())
|
||||
ui.copypassed.clear();
|
||||
|
||||
// Do we need to send a full frame?
|
||||
if (Server::udpFullFrameFrequency && cp.supportsUdp) {
|
||||
if (udpFramesSinceFull >= (unsigned) Server::udpFullFrameFrequency) {
|
||||
udpFramesSinceFull = 0;
|
||||
ui.changed.assign_union(Region(Rect(0, 0, cp.width, cp.height)));
|
||||
}
|
||||
}
|
||||
|
||||
// Return if there is nothing to send the client.
|
||||
const unsigned losslessThreshold = 80 + 2 * 1000 / Server::frameRate;
|
||||
|
||||
@@ -1518,6 +1527,9 @@ void VNCSConnectionST::writeDataUpdate()
|
||||
updates.subtract(req);
|
||||
|
||||
requested.clear();
|
||||
|
||||
if (Server::udpFullFrameFrequency && cp.supportsUdp)
|
||||
udpFramesSinceFull++;
|
||||
}
|
||||
|
||||
void VNCSConnectionST::writeBinaryClipboard()
|
||||
@@ -1745,3 +1757,22 @@ bool VNCSConnectionST::checkOwnerConn() const
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void VNCSConnectionST::udpUpgrade(const char *resp)
|
||||
{
|
||||
if (resp[0] == 'H') {
|
||||
vlog.info("Client %s requested upgrade to udp, but WebUdp refused", sock->getPeerAddress());
|
||||
} else {
|
||||
vlog.info("Client %s requesting upgrade to udp", sock->getPeerAddress());
|
||||
upgradingToUdp = true;
|
||||
}
|
||||
writer()->writeUdpUpgrade(resp);
|
||||
}
|
||||
|
||||
void VNCSConnectionST::udpDowngrade()
|
||||
{
|
||||
cp.supportsUdp = false;
|
||||
cp.useCopyRect = true;
|
||||
|
||||
vlog.info("Client %s downgrading from udp", sock->getPeerAddress());
|
||||
}
|
||||
|
||||
@@ -196,6 +196,8 @@ namespace rfb {
|
||||
return encodeManager.getScalingTime();
|
||||
}
|
||||
|
||||
bool upgradingToUdp;
|
||||
|
||||
private:
|
||||
// SConnection callbacks
|
||||
|
||||
@@ -217,6 +219,8 @@ namespace rfb {
|
||||
int x, int y, int w, int h);
|
||||
virtual void handleClipboardAnnounce(bool available);
|
||||
virtual void handleClipboardAnnounceBinary(const unsigned num, const char mimes[][32]);
|
||||
virtual void udpUpgrade(const char *resp);
|
||||
virtual void udpDowngrade();
|
||||
virtual void supportsLocalCursor();
|
||||
virtual void supportsFence();
|
||||
virtual void supportsContinuousUpdates();
|
||||
@@ -318,6 +322,7 @@ namespace rfb {
|
||||
std::vector<CopyPassRect> copypassed;
|
||||
|
||||
bool frameTracking;
|
||||
uint32_t udpFramesSinceFull;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <network/GetAPI.h>
|
||||
#include <network/Udp.h>
|
||||
|
||||
#include <rfb/cpuid.h>
|
||||
#include <rfb/ComparingUpdateTracker.h>
|
||||
@@ -66,6 +67,7 @@
|
||||
|
||||
#include <rdr/types.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
@@ -796,8 +798,43 @@ int VNCServerST::msToNextUpdate()
|
||||
return frameTimer.getRemainingMs();
|
||||
}
|
||||
|
||||
static void upgradeClientToUdp(const network::GetAPIMessager::action_data &act,
|
||||
std::list<VNCSConnectionST*> &clients)
|
||||
{
|
||||
std::list<VNCSConnectionST*>::iterator ci, ci_next;
|
||||
|
||||
for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
|
||||
ci_next = ci; ci_next++;
|
||||
|
||||
if (!(*ci)->upgradingToUdp)
|
||||
continue;
|
||||
|
||||
char buf[32];
|
||||
inet_ntop(AF_INET, &act.udp.ip, buf, 32);
|
||||
|
||||
const char * const who = (*ci)->getPeerEndpoint();
|
||||
const char *start = strchr(who, '@');
|
||||
if (!start)
|
||||
continue;
|
||||
start++;
|
||||
|
||||
// Slightly inaccurate, if several clients on the same IP try to upgrade at the same time
|
||||
if (strncmp(start, buf, strlen(buf)))
|
||||
continue;
|
||||
|
||||
(*ci)->upgradingToUdp = false;
|
||||
(*ci)->cp.useCopyRect = false;
|
||||
((network::UdpStream *)(*ci)->getOutStream(true))->setClient((WuClient *) act.udp.client);
|
||||
(*ci)->cp.supportsUdp = true;
|
||||
|
||||
slog.info("%s upgraded to UDP", who);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void checkAPIMessages(network::GetAPIMessager *apimessager,
|
||||
rdr::U8 &trackingFrameStats, char trackingClient[])
|
||||
rdr::U8 &trackingFrameStats, char trackingClient[],
|
||||
std::list<VNCSConnectionST*> &clients)
|
||||
{
|
||||
if (pthread_mutex_lock(&apimessager->userMutex))
|
||||
return;
|
||||
@@ -826,6 +863,9 @@ static void checkAPIMessages(network::GetAPIMessager *apimessager,
|
||||
trackingFrameStats = act.action;
|
||||
memcpy(trackingClient, act.data.password, 128);
|
||||
break;
|
||||
case network::GetAPIMessager::UDP_UPGRADE:
|
||||
upgradeClientToUdp(act, clients);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -991,7 +1031,7 @@ void VNCServerST::writeUpdate()
|
||||
shottime = msSince(&shotstart);
|
||||
|
||||
trackingFrameStats = 0;
|
||||
checkAPIMessages(apimessager, trackingFrameStats, trackingClient);
|
||||
checkAPIMessages(apimessager, trackingFrameStats, trackingClient, clients);
|
||||
}
|
||||
const rdr::U8 origtrackingFrameStats = trackingFrameStats;
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ namespace rfb {
|
||||
class ListConnInfo;
|
||||
class PixelBuffer;
|
||||
class KeyRemapper;
|
||||
class network::GetAPIMessager;
|
||||
|
||||
class VNCServerST : public VNCServer,
|
||||
public Timer::Callback,
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace rfb {
|
||||
const int encodingCoRRE = 4;
|
||||
const int encodingHextile = 5;
|
||||
const int encodingTight = 7;
|
||||
const int encodingUdp = 8;
|
||||
const int encodingZRLE = 16;
|
||||
|
||||
const int encodingMax = 255;
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace rfb {
|
||||
const int msgTypeStats = 178;
|
||||
const int msgTypeRequestFrameStats = 179;
|
||||
const int msgTypeBinaryClipboard = 180;
|
||||
const int msgTypeUpgradeToUdp = 181;
|
||||
|
||||
const int msgTypeServerFence = 248;
|
||||
|
||||
@@ -50,7 +51,9 @@ namespace rfb {
|
||||
// kasm
|
||||
const int msgTypeRequestStats = 178;
|
||||
const int msgTypeFrameStats = 179;
|
||||
// same as the other direction
|
||||
//const int msgTypeBinaryClipboard = 180;
|
||||
//const int msgTypeUpgradeToUdp = 181;
|
||||
|
||||
const int msgTypeClientFence = 248;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user