Blame SOURCES/0001-libvncserver-Add-API-to-add-custom-I-O-entry-points.patch

4743e5
From fb4b12407e869c3da33df65ed3a43ef87aeae1c4 Mon Sep 17 00:00:00 2001
9b8edd
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
9b8edd
Date: Mon, 11 Jun 2018 23:47:02 +0200
9b8edd
Subject: [PATCH 1/2] libvncserver: Add API to add custom I/O entry points
9b8edd
9b8edd
Add API to make it possible to channel RFB input and output through
9b8edd
another layer, for example TLS. This is done by making it possible to
9b8edd
override the default read/write/peek functions.
9b8edd
---
4743e5
 libvncserver/rfbserver.c |  4 ++
4743e5
 libvncserver/sockets.c   | 79 ++++++++++++++++++++++++++++++++++++----
4743e5
 rfb/rfb.h                | 17 +++++++++
4743e5
 3 files changed, 93 insertions(+), 7 deletions(-)
9b8edd
9b8edd
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
4743e5
index bc9cc117..0c8ee735 100644
9b8edd
--- a/libvncserver/rfbserver.c
9b8edd
+++ b/libvncserver/rfbserver.c
4743e5
@@ -319,6 +319,10 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
9b8edd
 
9b8edd
     cl->screen = rfbScreen;
9b8edd
     cl->sock = sock;
9b8edd
+    cl->readFromSocket = rfbDefaultReadFromSocket;
9b8edd
+    cl->peekAtSocket = rfbDefaultPeekAtSocket;
9b8edd
+    cl->hasPendingOnSocket = rfbDefaultHasPendingOnSocket;
9b8edd
+    cl->writeToSocket = rfbDefaultWriteToSocket;
9b8edd
     cl->viewOnly = FALSE;
9b8edd
     /* setup pseudo scaling */
9b8edd
     cl->scaledScreen = rfbScreen;
9b8edd
diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c
4743e5
index bbc3d90d..4874d4b6 100644
9b8edd
--- a/libvncserver/sockets.c
9b8edd
+++ b/libvncserver/sockets.c
4743e5
@@ -126,6 +126,9 @@ int deny_severity=LOG_WARNING;
4743e5
 int rfbMaxClientWait = 20000;   /* time (ms) after which we decide client has
4743e5
                                    gone away - needed to stop us hanging */
4743e5
 
4743e5
+static rfbBool
4743e5
+rfbHasPendingOnSocket(rfbClientPtr cl);
4743e5
+
4743e5
 static rfbBool
4743e5
 rfbNewConnectionFromSock(rfbScreenInfoPtr rfbScreen, int sock)
4743e5
 {
4743e5
@@ -370,16 +373,20 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
4743e5
 	tv.tv_usec = usec;
4743e5
 	nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv;;
4743e5
 	if (nfds == 0) {
4743e5
+            rfbBool hasPendingData = FALSE;
4743e5
+
4743e5
 	    /* timed out, check for async events */
4743e5
             i = rfbGetClientIterator(rfbScreen);
4743e5
             while((cl = rfbClientIteratorNext(i))) {
4743e5
                 if (cl->onHold)
4743e5
                     continue;
4743e5
+                hasPendingData |= rfbHasPendingOnSocket(cl);
4743e5
                 if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
4743e5
                     rfbSendFileTransferChunk(cl);
4743e5
             }
4743e5
             rfbReleaseClientIterator(i);
4743e5
-	    return result;
4743e5
+            if (!hasPendingData)
4743e5
+                return result;
4743e5
 	}
4743e5
 
4743e5
 	if (nfds < 0) {
4743e5
@@ -455,9 +462,11 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
4743e5
 	    if (cl->onHold)
4743e5
 		continue;
4743e5
 
4743e5
-            if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
4743e5
+            if (rfbHasPendingOnSocket (cl) ||
4743e5
+                FD_ISSET(cl->sock, &(rfbScreen->allFds)))
4743e5
             {
4743e5
-                if (FD_ISSET(cl->sock, &fds))
4743e5
+                if (rfbHasPendingOnSocket (cl) ||
4743e5
+                    FD_ISSET(cl->sock, &fds))
4743e5
                 {
4743e5
 #ifdef LIBVNCSERVER_WITH_WEBSOCKETS
4743e5
                     do {
4743e5
@@ -589,6 +598,30 @@ rfbConnect(rfbScreenInfoPtr rfbScreen,
9b8edd
     return sock;
9b8edd
 }
9b8edd
 
9b8edd
+int
9b8edd
+rfbDefaultReadFromSocket(rfbClientPtr cl, char *buf, int len)
9b8edd
+{
9b8edd
+    return read(cl->sock, buf, len);
9b8edd
+}
9b8edd
+
9b8edd
+static int
9b8edd
+rfbReadFromSocket(rfbClientPtr cl, char *buf, int len)
9b8edd
+{
9b8edd
+    return cl->readFromSocket(cl, buf, len);
9b8edd
+}
9b8edd
+
9b8edd
+rfbBool
9b8edd
+rfbDefaultHasPendingOnSocket(rfbClientPtr cl)
9b8edd
+{
9b8edd
+    return FALSE;
9b8edd
+}
9b8edd
+
9b8edd
+static rfbBool
9b8edd
+rfbHasPendingOnSocket(rfbClientPtr cl)
9b8edd
+{
4743e5
+    return cl->hasPendingOnSocket(cl);
9b8edd
+}
9b8edd
+
9b8edd
 /*
9b8edd
  * ReadExact reads an exact number of bytes from a client.  Returns 1 if
9b8edd
  * those bytes have been read, 0 if the other end has closed, or -1 if an error
4743e5
@@ -610,10 +643,10 @@ rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
9b8edd
         } else if (cl->sslctx) {
9b8edd
 	    n = rfbssl_read(cl, buf, len);
9b8edd
 	} else {
9b8edd
-            n = read(sock, buf, len);
9b8edd
+            n = rfbReadFromSocket(cl, buf, len);
9b8edd
         }
9b8edd
 #else
9b8edd
-        n = read(sock, buf, len);
9b8edd
+        n = rfbReadFromSocket(cl, buf, len);
9b8edd
 #endif
9b8edd
 
9b8edd
         if (n > 0) {
4743e5
@@ -645,6 +678,10 @@ rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
9b8edd
 		    continue;
9b8edd
 	    }
9b8edd
 #endif
9b8edd
+
9b8edd
+            if (rfbHasPendingOnSocket(cl))
9b8edd
+                continue;
9b8edd
+
9b8edd
             FD_ZERO(&fds);
9b8edd
             FD_SET(sock, &fds);
9b8edd
             tv.tv_sec = timeout / 1000;
4743e5
@@ -681,6 +718,18 @@ int rfbReadExact(rfbClientPtr cl,char* buf,int len)
9b8edd
     return(rfbReadExactTimeout(cl,buf,len,rfbMaxClientWait));
9b8edd
 }
9b8edd
 
9b8edd
+int
9b8edd
+rfbDefaultPeekAtSocket(rfbClientPtr cl, char *buf, int len)
9b8edd
+{
9b8edd
+    return recv(cl->sock, buf, len, MSG_PEEK);
9b8edd
+}
9b8edd
+
9b8edd
+int
9b8edd
+rfbPeekAtSocket(rfbClientPtr cl, char *buf, int len)
9b8edd
+{
9b8edd
+    cl->peekAtSocket(cl, buf, len);
9b8edd
+}
9b8edd
+
9b8edd
 /*
9b8edd
  * PeekExact peeks at an exact number of bytes from a client.  Returns 1 if
9b8edd
  * those bytes have been read, 0 if the other end has closed, or -1 if an
4743e5
@@ -701,7 +750,7 @@ rfbPeekExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
9b8edd
 	    n = rfbssl_peek(cl, buf, len);
9b8edd
 	else
9b8edd
 #endif
9b8edd
-	    n = recv(sock, buf, len, MSG_PEEK);
9b8edd
+            n = rfbPeekAtSocket(cl, buf, len);
9b8edd
 
9b8edd
         if (n == len) {
9b8edd
 
4743e5
@@ -757,6 +806,22 @@ rfbPeekExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
9b8edd
     return 1;
9b8edd
 }
9b8edd
 
9b8edd
+int
9b8edd
+rfbDefaultWriteToSocket(rfbClientPtr cl,
9b8edd
+			const char *buf,
9b8edd
+			int len)
9b8edd
+{
9b8edd
+    return write(cl->sock, buf, len);
9b8edd
+}
9b8edd
+
9b8edd
+static int
9b8edd
+rfbWriteToSocket(rfbClientPtr cl,
9b8edd
+		 const char *buf,
9b8edd
+		 int len)
9b8edd
+{
9b8edd
+    return cl->writeToSocket(cl, buf, len);
9b8edd
+}
9b8edd
+
9b8edd
 /*
9b8edd
  * WriteExact writes an exact number of bytes to a client.  Returns 1 if
9b8edd
  * those bytes have been written, or -1 if an error occurred (errno is set to
4743e5
@@ -801,7 +866,7 @@ rfbWriteExact(rfbClientPtr cl,
9b8edd
 	    n = rfbssl_write(cl, buf, len);
9b8edd
 	else
9b8edd
 #endif
9b8edd
-	    n = write(sock, buf, len);
9b8edd
+	    n = rfbWriteToSocket(cl, buf, len);
9b8edd
 
9b8edd
         if (n > 0) {
9b8edd
 
9b8edd
diff --git a/rfb/rfb.h b/rfb/rfb.h
4743e5
index c6edc119..2e5597a9 100644
9b8edd
--- a/rfb/rfb.h
9b8edd
+++ b/rfb/rfb.h
4743e5
@@ -414,6 +414,14 @@ typedef struct sraRegion* sraRegionPtr;
9b8edd
 
9b8edd
 typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl);
9b8edd
 
9b8edd
+typedef int (*ClientReadFromSocket)(struct _rfbClientRec* cl,
9b8edd
+                                    char *buf, int len);
9b8edd
+typedef int (*ClientPeekAtSocket)(struct _rfbClientRec* cl,
9b8edd
+                                  char *buf, int len);
9b8edd
+typedef rfbBool (*ClientHasPendingOnSocket)(struct _rfbClientRec* cl);
9b8edd
+typedef int (*ClientWriteToSocket)(struct _rfbClientRec* cl,
9b8edd
+                                   const char *buf, int len);
9b8edd
+
9b8edd
 typedef struct _rfbFileTransferData {
9b8edd
   int fd;
9b8edd
   int compressionEnabled;
4743e5
@@ -695,6 +703,11 @@ typedef struct _rfbClientRec {
9b8edd
     wsCtx     *wsctx;
9b8edd
     char *wspath;                          /* Requests path component */
9b8edd
 #endif
9b8edd
+
9b8edd
+    ClientReadFromSocket readFromSocket;         /* Read data from socket */
9b8edd
+    ClientPeekAtSocket peekAtSocket;             /* Peek at data from socket */
9b8edd
+    ClientHasPendingOnSocket hasPendingOnSocket; /* Peek at data from socket */
9b8edd
+    ClientWriteToSocket writeToSocket;           /* Write data to socket */
9b8edd
 } rfbClientRec, *rfbClientPtr;
9b8edd
 
9b8edd
 /**
4743e5
@@ -747,8 +760,12 @@ extern void rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen);
9b8edd
 extern void rfbCloseClient(rfbClientPtr cl);
9b8edd
 extern int rfbReadExact(rfbClientPtr cl, char *buf, int len);
9b8edd
 extern int rfbReadExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout);
9b8edd
+extern int rfbDefaultReadFromSocket(rfbClientPtr cl, char *buf, int len);
9b8edd
 extern int rfbPeekExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout);
9b8edd
+extern int rfbDefaultPeekAtSocket(rfbClientPtr cl, char *buf, int len);
9b8edd
+extern rfbBool rfbDefaultHasPendingOnSocket(rfbClientPtr cl);
9b8edd
 extern int rfbWriteExact(rfbClientPtr cl, const char *buf, int len);
9b8edd
+extern int rfbDefaultWriteToSocket(rfbClientPtr cl, const char *buf, int len);
9b8edd
 extern int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec);
9b8edd
 extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port);
9b8edd
 extern int rfbConnectToTcpAddr(char* host, int port);
9b8edd
-- 
4743e5
2.23.0
9b8edd