1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <rfb/rfb.h> 2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/** 4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * @example backchannel.c 5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * This is a simple example demonstrating a protocol extension. 6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * The "back channel" permits sending commands between client and server. 8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * It works by sending plain text messages. 9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * As suggested in the RFB protocol, the back channel is enabled by asking 11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * for a "pseudo encoding", and enabling the back channel on the client side 12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * as soon as it gets a back channel message from the server. 13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * This implements the server part. 15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Note: If you design your own extension and want it to be useful for others, 17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * too, you should make sure that 18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * - your server as well as your client can speak to other clients and 20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * servers respectively (i.e. they are nice if they are talking to a 21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * program which does not know about your extension). 22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * - if the machine is little endian, all 16-bit and 32-bit integers are 24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * swapped before they are sent and after they are received. 25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 26a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 27a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 28a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define rfbBackChannel 155 29a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 30a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehattypedef struct backChannelMsg { 31a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat uint8_t type; 32a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat uint8_t pad1; 33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat uint16_t pad2; 34a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat uint32_t size; 35a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} backChannelMsg; 36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool enableBackChannel(rfbClientPtr cl, void** data, int encoding) 38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(encoding == rfbBackChannel) { 40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat backChannelMsg msg; 41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat const char* text="Server acknowledges back channel encoding\n"; 42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat uint32_t length = strlen(text)+1; 43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat int n; 44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("Enabling the back channel\n"); 46a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 47a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat msg.type = rfbBackChannel; 48a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat msg.size = Swap32IfLE(length); 49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if((n = rfbWriteExact(cl, (char*)&msg, sizeof(msg))) <= 0 || 50a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat (n = rfbWriteExact(cl, text, length)) <= 0) { 51a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("enableBackChannel: write"); 52a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 53a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return TRUE; 54a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool handleBackChannelMessage(rfbClientPtr cl, void* data, 59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat const rfbClientToServerMsg* message) 60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(message->type == rfbBackChannel) { 62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat backChannelMsg msg; 63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char* text; 64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat int n; 65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if((n = rfbReadExact(cl, ((char*)&msg)+1, sizeof(backChannelMsg)-1)) <= 0) { 66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(n != 0) 67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("handleBackChannelMessage: read"); 68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbCloseClient(cl); 69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return TRUE; 70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat msg.size = Swap32IfLE(msg.size); 72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if((text = malloc(msg.size)) == NULL) { 73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbErr("Could not allocate %d bytes\n", msg.size); 74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return TRUE; 75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if((n = rfbReadExact(cl, text, msg.size)) <= 0) { 77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(n != 0) 78a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("handleBackChannelMessage: read"); 79a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbCloseClient(cl); 80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return TRUE; 81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 82a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("got message:\n%s\n", text); 83a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat free(text); 84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return TRUE; 85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic int backChannelEncodings[] = {rfbBackChannel, 0}; 90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbProtocolExtension backChannelExtension = { 92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat NULL, /* newClient */ 93a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat NULL, /* init */ 94a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat backChannelEncodings, /* pseudoEncodings */ 95a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat enableBackChannel, /* enablePseudoEncoding */ 96a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat handleBackChannelMessage, /* handleMessage */ 97a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat NULL, /* close */ 98a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat NULL, /* usage */ 99a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat NULL, /* processArgument */ 100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat NULL /* next extension */ 101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}; 102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint main(int argc,char** argv) 104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreenInfoPtr server; 106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbRegisterProtocolExtension(&backChannelExtension); 108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat server=rfbGetScreen(&argc,argv,400,300,8,3,4); 110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(!server) 111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return 0; 112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat server->frameBuffer=(char*)malloc(400*300*4); 113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbInitServer(server); 114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbRunEventLoop(server,-1,FALSE); 115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return(0); 116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 117