]> source.dussan.org Git - tigervnc.git/commitdiff
Move socket write event handling in to the RFB core
authorPierre Ossman <ossman@cendio.se>
Fri, 29 Apr 2016 12:26:05 +0000 (14:26 +0200)
committerPierre Ossman <ossman@cendio.se>
Fri, 29 Apr 2016 12:26:05 +0000 (14:26 +0200)
What to do when a socket is writeable should be handled in the
RFB core code as there may be other events we want to fire off
when this happens.

common/network/Socket.h
common/rfb/HTTPServer.cxx
common/rfb/HTTPServer.h
common/rfb/VNCSConnectionST.cxx
common/rfb/VNCSConnectionST.h
common/rfb/VNCServerST.cxx
common/rfb/VNCServerST.h
unix/x0vncserver/x0vncserver.cxx
unix/xserver/hw/vnc/XserverDesktop.cc
win/rfb_win32/SocketManager.cxx

index 378a9006dad95a75940a36f0d083d0f2a28e3497..13b12d1d03ade162b4227fb5e7d8a3a8ce46f2a8 100644 (file)
@@ -125,12 +125,17 @@ namespace network {
     //   resources to be freed.
     virtual void removeSocket(network::Socket* sock) = 0;
 
-    // processSocketEvent() tells the server there is a Socket read event.
+    // processSocketReadEvent() tells the server there is a Socket read event.
     //   The implementation can indicate that the Socket is no longer active
     //   by calling shutdown() on it.  The caller will then call removeSocket()
     //   soon after processSocketEvent returns, to allow any pre-Socket
     //   resources to be tidied up.
-    virtual void processSocketEvent(network::Socket* sock) = 0;
+    virtual void processSocketReadEvent(network::Socket* sock) = 0;
+
+    // processSocketReadEvent() tells the server there is a Socket write event.
+    //   This is only necessary if the Socket has been put in non-blocking
+    //   mode and needs this callback to flush the buffer.
+    virtual void processSocketWriteEvent(network::Socket* sock) = 0;
 
     // checkTimeouts() allows the server to check socket timeouts, etc.  The
     //   return value is the number of milliseconds to wait before
index f50722ab743ce45e012de5b4ba850343f4f4d4f6..54becbb221609a05dc2246f7fedb66405a56de87 100644 (file)
@@ -337,7 +337,7 @@ HTTPServer::removeSocket(network::Socket* sock) {
 }
 
 void
-HTTPServer::processSocketEvent(network::Socket* sock) {
+HTTPServer::processSocketReadEvent(network::Socket* sock) {
   std::list<Session*>::iterator i;
   for (i=sessions.begin(); i!=sessions.end(); i++) {
     if ((*i)->getSock() == sock) {
@@ -356,6 +356,23 @@ HTTPServer::processSocketEvent(network::Socket* sock) {
   throw rdr::Exception("invalid Socket in HTTPServer");
 }
 
+void
+HTTPServer::processSocketWriteEvent(network::Socket* sock) {
+  std::list<Session*>::iterator i;
+  for (i=sessions.begin(); i!=sessions.end(); i++) {
+    if ((*i)->getSock() == sock) {
+      try {
+        sock->outStream().flush();
+      } catch (rdr::Exception& e) {
+        vlog.error("untrapped: %s", e.str());
+        sock->shutdown();
+      }
+      return;
+    }
+  }
+  throw rdr::Exception("invalid Socket in HTTPServer");
+}
+
 void HTTPServer::getSockets(std::list<network::Socket*>* sockets)
 {
   sockets->clear();
index 6412946a494dc11c983b4468e082bcd276a6740d..d7ca69ade47b66c7fde8b6d21ed8feaa8406b6d9 100644 (file)
@@ -58,11 +58,16 @@ namespace rfb {
     //   Could clean up socket-specific resources here.
     virtual void removeSocket(network::Socket* sock);
 
-    // processSocketEvent()
+    // processSocketReadEvent()
     //   The platform-specific side of the server implementation calls
     //   this method whenever data arrives on one of the active
     //   network sockets.
-    virtual void processSocketEvent(network::Socket* sock);
+    virtual void processSocketReadEvent(network::Socket* sock);
+
+    // processSocketWriteEvent()
+    //   Similar to processSocketReadEvent(), but called when it is
+    //   possible to write more data to a socket.
+    virtual void processSocketWriteEvent(network::Socket* sock);
 
     // Check for socket timeouts
     virtual int checkTimeouts();
index 932f579666cc2f1694c2fb5d81e34460d5f14d48..0f4ca94204b6e3602d9d5da3484ce5e5fe9e08fe 100644 (file)
@@ -190,6 +190,17 @@ void VNCSConnectionST::processMessages()
   }
 }
 
+void VNCSConnectionST::flushSocket()
+{
+  if (state() == RFBSTATE_CLOSING) return;
+  try {
+    setSocketTimeouts();
+    sock->outStream().flush();
+  } catch (rdr::Exception &e) {
+    close(e.str());
+  }
+}
+
 void VNCSConnectionST::pixelBufferChange()
 {
   try {
index 72ffc1dfd07f42466a383b744ab871498aa52a2a..55b7ca3eedb881af922879aacc5362413b37d137 100644 (file)
@@ -65,6 +65,9 @@ namespace rfb {
     // Socket if an error occurs, via the close() call.
     void processMessages();
 
+    // flushSocket() pushes any unwritten data on to the network.
+    void flushSocket();
+
     // Called when the underlying pixelbuffer is resized or replaced.
     void pixelBufferChange();
 
index 199524ec4c929877246bb762e37e8b7f07d27cb4..d5010854f35d0b9263d27eb82cb54ba679630959 100644 (file)
@@ -163,7 +163,7 @@ void VNCServerST::removeSocket(network::Socket* sock) {
   closingSockets.remove(sock);
 }
 
-void VNCServerST::processSocketEvent(network::Socket* sock)
+void VNCServerST::processSocketReadEvent(network::Socket* sock)
 {
   // - Find the appropriate VNCSConnectionST and process the event
   std::list<VNCSConnectionST*>::iterator ci;
@@ -176,6 +176,19 @@ void VNCServerST::processSocketEvent(network::Socket* sock)
   throw rdr::Exception("invalid Socket in VNCServerST");
 }
 
+void VNCServerST::processSocketWriteEvent(network::Socket* sock)
+{
+  // - Find the appropriate VNCSConnectionST and process the event
+  std::list<VNCSConnectionST*>::iterator ci;
+  for (ci = clients.begin(); ci != clients.end(); ci++) {
+    if ((*ci)->getSock() == sock) {
+      (*ci)->flushSocket();
+      return;
+    }
+  }
+  throw rdr::Exception("invalid Socket in VNCServerST");
+}
+
 int VNCServerST::checkTimeouts()
 {
   int timeout = 0;
index 1e055dd9d548e91855348c3f33534ccd15f03056..bd84c452e78456f1fe31a93498db5b0eaa89fc09 100644 (file)
@@ -67,11 +67,15 @@ namespace rfb {
     //   Clean up any resources associated with the Socket
     virtual void removeSocket(network::Socket* sock);
 
-    // processSocketEvent
+    // processSocketReadEvent
     //   Read more RFB data from the Socket.  If an error occurs during
     //   processing then shutdown() is called on the Socket, causing
     //   removeSocket() to be called by the caller at a later time.
-    virtual void processSocketEvent(network::Socket* sock);
+    virtual void processSocketReadEvent(network::Socket* sock);
+
+    // processSocketWriteEvent
+    //   Flush pending data from the Socket on to the network.
+    virtual void processSocketWriteEvent(network::Socket* sock);
 
     // checkTimeouts
     //   Returns the number of milliseconds left until the next idle timeout
index 6b5d479d864399637881ef42b7ea3d5e33ee81d2..791714e978a7f609dc2bc667c84f097781edb5a9 100644 (file)
@@ -593,7 +593,7 @@ int main(int argc, char** argv)
       // Process events on existing VNC connections
       for (i = sockets.begin(); i != sockets.end(); i++) {
         if (FD_ISSET((*i)->getFd(), &rfds))
-          server.processSocketEvent(*i);
+          server.processSocketReadEvent(*i);
       }
 
       if (desktop.isRunning() && sched.goodTimeToPoll()) {
index 9b91d9a440ed1eeac773d90dc099893975a326c5..f1c9b7477587f60b82fc15f4ce6f80fbd2adc00e 100644 (file)
@@ -495,7 +495,7 @@ void XserverDesktop::readWakeupHandler(fd_set* fds, int nfds)
         int fd = (*i)->getFd();
         if (FD_ISSET(fd, fds)) {
           FD_CLR(fd, fds);
-          server->processSocketEvent(*i);
+          server->processSocketReadEvent(*i);
         }
       }
 
@@ -505,7 +505,7 @@ void XserverDesktop::readWakeupHandler(fd_set* fds, int nfds)
           int fd = (*i)->getFd();
           if (FD_ISSET(fd, fds)) {
             FD_CLR(fd, fds);
-            httpServer->processSocketEvent(*i);
+            httpServer->processSocketReadEvent(*i);
           }
         }
       }
@@ -581,7 +581,7 @@ void XserverDesktop::writeWakeupHandler(fd_set* fds, int nfds)
       int fd = (*i)->getFd();
       if (FD_ISSET(fd, fds)) {
         FD_CLR(fd, fds);
-        (*i)->outStream().flush();
+        server->processSocketWriteEvent(*i);
       }
     }
 
@@ -591,7 +591,7 @@ void XserverDesktop::writeWakeupHandler(fd_set* fds, int nfds)
         int fd = (*i)->getFd();
         if (FD_ISSET(fd, fds)) {
           FD_CLR(fd, fds);
-          (*i)->outStream().flush();
+          httpServer->processSocketWriteEvent(*i);
         }
       }
     }
index b073b8fba154572af8a77bd65bd35f585cdb1530..5b211a0dbc4e8bdf9134f44c35d3ae51efcf78a6 100644 (file)
@@ -193,7 +193,7 @@ void SocketManager::processEvent(HANDLE event) {
       WSAResetEvent(event);
 
       // Call the socket server to process the event
-      ci.server->processSocketEvent(ci.sock);
+      ci.server->processSocketReadEvent(ci.sock);
       if (ci.sock->isShutdown()) {
         remSocket(ci.sock);
         return;