Don't try to push out another update if the socket is already full. This
avoids stalling the entire server because of one slow client.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4737 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index 4ca58ac..34be0ef 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -37,8 +37,8 @@
   : SConnection(reverse), sock(s), server(server_),
     updates(false), image_getter(server->useEconomicTranslate),
     drawRenderedCursor(false), removeRenderedCursor(false),
-    pointerEventTime(0), accessRights(AccessDefault),
-    startTime(time(0))
+    updateTimer(this), pointerEventTime(0),
+    accessRights(AccessDefault), startTime(time(0))
 {
   setStreams(&sock->inStream(), &sock->outStream());
   peerEndpoint.buf = sock->getPeerEndpoint();
@@ -625,11 +625,40 @@
 }
 
 
+bool VNCSConnectionST::handleTimeout(Timer* t)
+{
+  if (t == &updateTimer)
+    writeFramebufferUpdateOrClose();
+
+  return false;
+}
+
+
+bool VNCSConnectionST::isCongested()
+{
+  int offset, space;
+
+  if (sock->outStream().bufferUsage() > 0)
+    return true;
+
+  return false;
+}
+
+
 void VNCSConnectionST::writeFramebufferUpdate()
 {
+  updateTimer.stop();
+
   if (state() != RFBSTATE_NORMAL || requested.is_empty())
     return;
 
+  // Check that we actually have some space on the link and retry in a
+  // bit if things are congested.
+  if (isCongested()) {
+    updateTimer.start(50);
+    return;
+  }
+
   // First take care of any updates that cannot contain framebuffer data
   // changes.
   if (writer()->needNoDataUpdate()) {
diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h
index c9e4ac8..abf4383 100644
--- a/common/rfb/VNCSConnectionST.h
+++ b/common/rfb/VNCSConnectionST.h
@@ -32,10 +32,12 @@
 #include <rfb/SMsgWriter.h>
 #include <rfb/TransImageGetter.h>
 #include <rfb/VNCServerST.h>
+#include <rfb/Timer.h>
 
 namespace rfb {
   class VNCSConnectionST : public SConnection,
-                           public WriteSetCursorCallback {
+                           public WriteSetCursorCallback,
+                           public Timer::Callback {
   public:
     VNCSConnectionST(VNCServerST* server_, network::Socket* s, bool reverse);
     virtual ~VNCSConnectionST();
@@ -140,8 +142,13 @@
     // WriteSetCursorCallback
     virtual void writeSetCursorCallback();
 
+    // Timer callbacks
+    virtual bool handleTimeout(Timer* t);
+
     // Internal methods
 
+    bool isCongested();
+
     // writeFramebufferUpdate() attempts to write a framebuffer update to the
     // client.
 
@@ -161,6 +168,8 @@
     bool drawRenderedCursor, removeRenderedCursor;
     Rect renderedCursorRect;
 
+    Timer updateTimer;
+
     std::set<rdr::U32> pressedKeys;
 
     time_t lastEventTime;