|
|
@ -53,7 +53,8 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
|
|
|
|
fenceDataLen(0), fenceData(NULL), congestionTimer(this),
|
|
|
|
fenceDataLen(0), fenceData(NULL), congestionTimer(this),
|
|
|
|
losslessTimer(this), kbdLogTimer(this), server(server_), updates(false),
|
|
|
|
losslessTimer(this), kbdLogTimer(this), server(server_), updates(false),
|
|
|
|
updateRenderedCursor(false), removeRenderedCursor(false),
|
|
|
|
updateRenderedCursor(false), removeRenderedCursor(false),
|
|
|
|
continuousUpdates(false), encodeManager(this, &server_->encCache), pointerEventTime(0),
|
|
|
|
continuousUpdates(false), encodeManager(this, &server_->encCache),
|
|
|
|
|
|
|
|
pointerEventTime(0),
|
|
|
|
clientHasCursor(false),
|
|
|
|
clientHasCursor(false),
|
|
|
|
accessRights(AccessDefault), startTime(time(0))
|
|
|
|
accessRights(AccessDefault), startTime(time(0))
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -61,6 +62,9 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
|
|
|
|
peerEndpoint.buf = sock->getPeerEndpoint();
|
|
|
|
peerEndpoint.buf = sock->getPeerEndpoint();
|
|
|
|
VNCServerST::connectionsLog.write(1,"accepted: %s", peerEndpoint.buf);
|
|
|
|
VNCServerST::connectionsLog.write(1,"accepted: %s", peerEndpoint.buf);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset(bstats_total, 0, sizeof(bstats_total));
|
|
|
|
|
|
|
|
gettimeofday(&connStart, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
// Configure the socket
|
|
|
|
// Configure the socket
|
|
|
|
setSocketTimeouts();
|
|
|
|
setSocketTimeouts();
|
|
|
|
lastEventTime = time(0);
|
|
|
|
lastEventTime = time(0);
|
|
|
@ -1037,6 +1041,14 @@ bool VNCSConnectionST::isCongested()
|
|
|
|
if (eta >= 0)
|
|
|
|
if (eta >= 0)
|
|
|
|
congestionTimer.start(eta);
|
|
|
|
congestionTimer.start(eta);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (eta > 1000 / rfb::Server::frameRate) {
|
|
|
|
|
|
|
|
struct timeval now;
|
|
|
|
|
|
|
|
gettimeofday(&now, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bstats[BS_NET_SLOW].push_back(now);
|
|
|
|
|
|
|
|
bstats_total[BS_NET_SLOW]++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1083,6 +1095,11 @@ void VNCSConnectionST::writeFramebufferUpdate()
|
|
|
|
sock->cork(false);
|
|
|
|
sock->cork(false);
|
|
|
|
|
|
|
|
|
|
|
|
congestion.updatePosition(sock->outStream().length());
|
|
|
|
congestion.updatePosition(sock->outStream().length());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct timeval now;
|
|
|
|
|
|
|
|
gettimeofday(&now, NULL);
|
|
|
|
|
|
|
|
bstats[BS_FRAME].push_back(now);
|
|
|
|
|
|
|
|
bstats_total[BS_FRAME]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VNCSConnectionST::writeNoDataUpdate()
|
|
|
|
void VNCSConnectionST::writeNoDataUpdate()
|
|
|
@ -1236,6 +1253,16 @@ void VNCSConnectionST::writeDataUpdate()
|
|
|
|
copypassed.clear();
|
|
|
|
copypassed.clear();
|
|
|
|
gettimeofday(&lastRealUpdate, NULL);
|
|
|
|
gettimeofday(&lastRealUpdate, NULL);
|
|
|
|
losslessTimer.start(losslessThreshold);
|
|
|
|
losslessTimer.start(losslessThreshold);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const unsigned ms = encodeManager.getEncodingTime();
|
|
|
|
|
|
|
|
const unsigned limit = 1000 / rfb::Server::frameRate;
|
|
|
|
|
|
|
|
if (ms >= limit) {
|
|
|
|
|
|
|
|
bstats[BS_CPU_SLOW].push_back(lastRealUpdate);
|
|
|
|
|
|
|
|
bstats_total[BS_CPU_SLOW]++;
|
|
|
|
|
|
|
|
} else if (ms >= limit * 0.8f) {
|
|
|
|
|
|
|
|
bstats[BS_CPU_CLOSE].push_back(lastRealUpdate);
|
|
|
|
|
|
|
|
bstats_total[BS_CPU_CLOSE]++;
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
encodeManager.writeLosslessRefresh(req, server->getPixelBuffer(),
|
|
|
|
encodeManager.writeLosslessRefresh(req, server->getPixelBuffer(),
|
|
|
|
cursor, maxUpdateSize);
|
|
|
|
cursor, maxUpdateSize);
|
|
|
@ -1265,6 +1292,59 @@ void VNCSConnectionST::screenLayoutChange(rdr::U16 reason)
|
|
|
|
cp.screenLayout);
|
|
|
|
cp.screenLayout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void pruneStatList(std::list<struct timeval> &list, const struct timeval &now) {
|
|
|
|
|
|
|
|
std::list<struct timeval>::iterator it;
|
|
|
|
|
|
|
|
for (it = list.begin(); it != list.end(); ) {
|
|
|
|
|
|
|
|
if ((*it).tv_sec + 60 < now.tv_sec)
|
|
|
|
|
|
|
|
it = list.erase(it);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
it++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void VNCSConnectionST::sendStats() {
|
|
|
|
|
|
|
|
char buf[1024];
|
|
|
|
|
|
|
|
struct timeval now;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Prune too old stats from the recent lists
|
|
|
|
|
|
|
|
gettimeofday(&now, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pruneStatList(bstats[BS_CPU_CLOSE], now);
|
|
|
|
|
|
|
|
pruneStatList(bstats[BS_CPU_SLOW], now);
|
|
|
|
|
|
|
|
pruneStatList(bstats[BS_NET_SLOW], now);
|
|
|
|
|
|
|
|
pruneStatList(bstats[BS_FRAME], now);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const unsigned minuteframes = bstats[BS_FRAME].size();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate stats
|
|
|
|
|
|
|
|
float cpu_recent = bstats[BS_CPU_SLOW].size() + bstats[BS_CPU_CLOSE].size() * 0.2f;
|
|
|
|
|
|
|
|
cpu_recent /= minuteframes;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float cpu_total = bstats_total[BS_CPU_SLOW] + bstats_total[BS_CPU_CLOSE] * 0.2f;
|
|
|
|
|
|
|
|
cpu_total /= bstats_total[BS_FRAME];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float net_recent = bstats[BS_NET_SLOW].size();
|
|
|
|
|
|
|
|
net_recent /= minuteframes;
|
|
|
|
|
|
|
|
if (net_recent > 1)
|
|
|
|
|
|
|
|
net_recent = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float net_total = bstats_total[BS_NET_SLOW];
|
|
|
|
|
|
|
|
net_total /= bstats_total[BS_FRAME];
|
|
|
|
|
|
|
|
if (net_total > 1)
|
|
|
|
|
|
|
|
net_total = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define ten(x) (10 - x * 10.0f)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "CPU: %.1f/10 recent, %.1f/10 total\n"
|
|
|
|
|
|
|
|
"Net: %.1f/10 recent, %.1f/10 total",
|
|
|
|
|
|
|
|
ten(cpu_recent), ten(cpu_total),
|
|
|
|
|
|
|
|
ten(net_recent), ten(net_total));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef ten
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vlog.info("Sending client stats:\n%s\n", buf);
|
|
|
|
|
|
|
|
writer()->writeStats(buf, strlen(buf));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// setCursor() is called whenever the cursor has changed shape or pixel format.
|
|
|
|
// setCursor() is called whenever the cursor has changed shape or pixel format.
|
|
|
|
// If the client supports local cursor then it will arrange for the cursor to
|
|
|
|
// If the client supports local cursor then it will arrange for the cursor to
|
|
|
|