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