From 11fc700c5db6afc6978211f5735707848b94ae8e Mon Sep 17 00:00:00 2001
From: dscho <dscho>
Date: Thu, 6 Oct 2005 19:23:26 +0000
Subject: add BackChannel extension example

---
 examples/Makefile.am   |   2 +-
 examples/backchannel.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+), 1 deletion(-)
 create mode 100644 examples/backchannel.c

diff --git a/examples/Makefile.am b/examples/Makefile.am
index 2a14db9..b936e77 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -14,6 +14,6 @@ noinst_HEADERS=radon.h
 
 noinst_PROGRAMS=example pnmshow regiontest pnmshow24 fontsel \
 	vncev storepasswd colourmaptest simple simple15 $(MAC) \
-	$(FILETRANSFER)
+	$(FILETRANSFER) backchannel
 
 
diff --git a/examples/backchannel.c b/examples/backchannel.c
new file mode 100644
index 0000000..4db01a8
--- /dev/null
+++ b/examples/backchannel.c
@@ -0,0 +1,113 @@
+#include <rfb/rfb.h>
+
+/*
+ * This is a simple example demonstrating a protocol extension.
+ *
+ * The "back channel" permits sending commands between client and server.
+ * It works by sending plain text messages.
+ *
+ * As suggested in the RFB protocol, the back channel is enabled by asking
+ * for a "pseudo encoding", and enabling the back channel on the client side
+ * as soon as it gets a back channel message from the server.
+ *
+ * This implements the server part.
+ *
+ * Note: If you design your own extension and want it to be useful for others,
+ * too, you should make sure that
+ *
+ * - your server as well as your client can speak to other clients and
+ *   servers respectively (i.e. they are nice if they are talking to a
+ *   program which does not know about your extension).
+ *
+ * - if the machine is little endian, all 16-bit and 32-bit integers are
+ *   swapped before they are sent and after they are received.
+ *
+ */
+
+#define rfbBackChannel 155
+
+typedef struct backChannelMsg {
+	uint8_t type;
+	uint8_t pad1;
+	uint16_t pad2;
+	uint32_t size;
+} backChannelMsg;
+
+rfbBool enableBackChannel(rfbClientPtr cl, void* data, int encoding)
+{
+	if(encoding == rfbBackChannel) {
+		backChannelMsg msg;
+		const char* text="Server acknowledges back channel encoding\n";
+		uint32_t length = strlen(text)+1;
+		int n;
+
+		rfbLog("Enabling the back channel\n");
+
+		msg.type = rfbBackChannel;
+		msg.size = Swap32IfLE(length);
+		if((n = rfbWriteExact(cl, (char*)&msg, sizeof(msg))) <= 0 ||
+				(n = rfbWriteExact(cl, text, length)) <= 0) {
+			rfbLogPerror("enableBackChannel: write");
+		}
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static rfbBool handleBackChannelMessage(rfbClientPtr cl, void* data,
+		const rfbClientToServerMsg* message)
+{
+	if(message->type == rfbBackChannel) {
+		backChannelMsg msg;
+		char* text;
+		int n;
+		if((n = rfbReadExact(cl, ((char*)&msg)+1, sizeof(backChannelMsg)-1)) <= 0) {
+			if(n != 0)
+				rfbLogPerror("handleBackChannelMessage: read");
+			rfbCloseClient(cl);
+			return TRUE;
+		}
+		msg.size = Swap32IfLE(msg.size);
+		if((text = malloc(msg.size)) == NULL) {
+			rfbErr("Could not allocate %d bytes\n", msg.size);
+			return TRUE;
+		}
+		if((n = rfbReadExact(cl, text, msg.size)) <= 0) {
+			if(n != 0)
+				rfbLogPerror("handleBackChannelMessage: read");
+			rfbCloseClient(cl);
+			return TRUE;
+		}
+		rfbLog("got message:\n%s\n", text);
+		free(text);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static int backChannelEncodings[] = {rfbBackChannel, 0};
+
+static rfbProtocolExtension backChannelExtension = {
+	NULL,				/* newClient */
+	NULL,				/* init */
+	backChannelEncodings,		/* pseudoEncodings */
+	enableBackChannel,		/* enablePseudoEncoding */
+	handleBackChannelMessage,	/* handleMessage */
+	NULL,				/* close */
+	NULL,				/* usage */
+	NULL,				/* processArgument */
+	NULL				/* next extension */
+};
+
+int main(int argc,char** argv)
+{                                                                
+	rfbScreenInfoPtr server;
+
+	rfbRegisterProtocolExtension(&backChannelExtension);
+
+	server=rfbGetScreen(&argc,argv,400,300,8,3,4);
+	server->frameBuffer=(char*)malloc(400*300*4);
+	rfbInitServer(server);           
+	rfbRunEventLoop(server,-1,FALSE);
+	return(0);
+}
-- 
cgit v1.2.3

