diff --git a/configs/samv71-xult/vnc/defconfig b/configs/samv71-xult/vnc/defconfig index 5e5f76362a..d22ec9f2ce 100644 --- a/configs/samv71-xult/vnc/defconfig +++ b/configs/samv71-xult/vnc/defconfig @@ -991,8 +991,8 @@ CONFIG_NXFONT_SANS28X37=y # # CONFIG_NX_MULTIUSER is not set CONFIG_VNCSERVER=y -CONFIG_VNCSERVER_PROTO3p3=y -# CONFIG_VNCSERVER_PROTO3p8 is not set +# CONFIG_VNCSERVER_PROTO3p3 is not set +CONFIG_VNCSERVER_PROTO3p8=y CONFIG_VNCSERVER_NDISPLAYS=1 CONFIG_VNCSERVER_PRIO=100 CONFIG_VNCSERVER_STACKSIZE=2048 diff --git a/graphics/vnc/server/Kconfig b/graphics/vnc/server/Kconfig index 1a5ad3ad71..ef4e1dfe28 100644 --- a/graphics/vnc/server/Kconfig +++ b/graphics/vnc/server/Kconfig @@ -16,14 +16,14 @@ if VNCSERVER choice prompt "VNC server protocol" - default VNCSERVER_PROTO3p3 + default VNCSERVER_PROTO3p8 config VNCSERVER_PROTO3p3 bool "Version 3.3" + depends on EXPERIMENTAL config VNCSERVER_PROTO3p8 bool "Version 3.8" - depends on EXPERIMENTAL endchoice # VNC server protocol @@ -66,10 +66,24 @@ endchoice # VNC color format config VNCSERVER_SCREENWIDTH int "Framebuffer width (pixels)" default 320 + ---help--- + This setting defines the width in pixels of the local framebuffer. + + Memory usage: PixelWidth * ScreenWidth * ScreenHeight + + So, for example, a 320x240 screen with RGB16 pixels would require + 2x320x240 = 150 KB of RAM. config VNCSERVER_SCREENHEIGHT int "Framebuffer height (rows)" default 240 + ---help--- + This setting defines the height in rows of the local framebuffer. + + Memory usage: PixelWidth * ScreenWidth * ScreenHeight + + So, for example, a 320x240 screen with RGB16 pixels would require + 2x320x240 = 150 KB of RAM. config VNCSERVER_NUPDATES int "Number of pre-allocate update structures" diff --git a/graphics/vnc/server/vnc_negotiate.c b/graphics/vnc/server/vnc_negotiate.c index fd294f451a..36d731c022 100644 --- a/graphics/vnc/server/vnc_negotiate.c +++ b/graphics/vnc/server/vnc_negotiate.c @@ -62,6 +62,7 @@ static const char g_vncproto[] = RFB_PROTOCOL_VERSION_3p3; #elif defined(CONFIG_VNCSERVER_PROTO3p8) static const char g_vncproto[] = RFB_PROTOCOL_VERSION_3p8; +static const char g_nosecurity[] = "No security types are supported"; #endif /**************************************************************************** @@ -84,10 +85,16 @@ static const char g_vncproto[] = RFB_PROTOCOL_VERSION_3p8; * ****************************************************************************/ -#ifdef CONFIG_VNCSERVER_PROTO3p3 int vnc_negotiate(FAR struct vnc_session_s *session) { +#ifdef CONFIG_VNCSERVER_PROTO3p3 FAR struct rfb_sectype_s *sectype; +#else /* ifdef CONFIG_VNCSERVER_PROTO3p8 */ + FAR struct rfb_supported_sectypes_s *sectypes; + FAR struct rfb_selected_sectype_s *sectype; + FAR struct rfb_sectype_result_s *secresult; + FAR struct rfb_sectype_fail_s *secfail; +#endif FAR struct rfb_serverinit_s *serverinit; FAR struct rfb_pixelfmt_s *pixelfmt; FAR struct rfb_setpixelformat_s *setformat; @@ -148,13 +155,13 @@ int vnc_negotiate(FAR struct vnc_session_s *session) DEBUGASSERT(nrecvd == len); - /* Tell the client that we won't use any stinkin' security. - * - * "Version 3.3 The server decides the security type and sends a single - * word:" +#ifdef CONFIG_VNCSERVER_PROTO3p3 + /* Version 3.3: The server decides the security type and sends a single + * word containing the security type: Tell the client that we won't use + * any stinkin' security. */ - gvdbg("Send security type (None)\n"); + gvdbg("Send SecurityType\n"); sectype = (FAR struct rfb_sectype_s *)session->outbuf; rfb_putbe32(sectype->type, RFB_SECTYPE_NONE); @@ -171,6 +178,110 @@ int vnc_negotiate(FAR struct vnc_session_s *session) DEBUGASSERT(nsent == sizeof(struct rfb_sectype_s)); +#else /* ifdef CONFIG_VNCSERVER_PROTO3p8 */ + /* Version 3.8: Offer the client a choice of security -- where None is the + * only option offered. + */ + + gvdbg("Send SupportedSecurityTypes\n"); + + sectypes = (FAR struct rfb_supported_sectypes_s *)session->outbuf; + sectypes->ntypes = 1; + sectypes->type[0] = RFB_SECTYPE_NONE; + + nsent = psock_send(&session->connect, sectypes, + SIZEOF_RFB_SUPPORTED_SECTYPES_S(1), 0); + if (nsent < 0) + { + errcode = get_errno(); + gdbg("ERROR: Send SupportedSecurityTypes failed: %d\n", errcode); + DEBUGASSERT(errcode > 0); + return -errcode; + } + + DEBUGASSERT(nsent == SIZEOF_RFB_SUPPORTED_SECTYPES_S(1)); + + /* If the server listed at least one valid security type supported by the + * client, the client sends back a single byte indicating which security + * type is to be used on the connection. + */ + + gvdbg("Receive SecurityType\n"); + + sectype = (FAR struct rfb_selected_sectype_s *)session->inbuf; + + nrecvd = psock_recv(&session->connect, sectype, + sizeof(struct rfb_selected_sectype_s), 0); + if (nrecvd < 0) + { + errcode = get_errno(); + gdbg("ERROR: Receive SecurityType failed: %d\n", errcode); + DEBUGASSERT(errcode > 0); + return -errcode; + } + + DEBUGASSERT(nrecvd == sizeof(struct rfb_selected_sectype_s)); + + gvdbg("Send SecurityResult\n"); + + secresult = (FAR struct rfb_sectype_result_s *)session->outbuf; + + if (sectype->type != RFB_SECTYPE_NONE) + { + gdbg("ERROR: Received unsupported SecurityType: %d\n", sectype->type); + + /* REVISIT: Should send the reason string here */ + + rfb_putbe32(secresult->result, RFB_SECTYPE_FAIL); + + nsent = psock_send(&session->connect, secresult, + sizeof(struct rfb_sectype_result_s), 0); + if (nsent < 0) + { + errcode = get_errno(); + gdbg("ERROR: Send SecurityResult failed: %d\n", errcode); + DEBUGASSERT(errcode > 0); + return -errcode; + } + + DEBUGASSERT(nsent == sizeof(struct rfb_sectype_result_s)); + + gvdbg("Send failure reason\n"); + + secfail = (FAR struct rfb_sectype_fail_s *)session->outbuf; + len = strlen(g_nosecurity); + rfb_putbe32(secfail->len, len); + memcpy(secfail->str, g_nosecurity, len); + + nsent = psock_send(&session->connect, secfail, + SIZEOF_RFB_SECTYPE_FAIL_S(len), 0); + if (nsent < 0) + { + errcode = get_errno(); + gdbg("ERROR: Send failure reason failed: %d\n", errcode); + DEBUGASSERT(errcode > 0); + return -errcode; + } + + DEBUGASSERT(nsent == SIZEOF_RFB_SECTYPE_FAIL_S(len)); + return -EPROTONOSUPPORT; + } + + rfb_putbe32(secresult->result, RFB_SECTYPE_SUCCESS); + + nsent = psock_send(&session->connect, secresult, + sizeof(struct rfb_sectype_result_s), 0); + if (nsent < 0) + { + errcode = get_errno(); + gdbg("ERROR: Send SecurityResult failed: %d\n", errcode); + DEBUGASSERT(errcode > 0); + return -errcode; + } + + DEBUGASSERT(nsent == sizeof(struct rfb_sectype_result_s)); +#endif + /* Receive the ClientInit message * * "Once the client and server are sure that they’re happy to talk to one @@ -198,11 +309,11 @@ int vnc_negotiate(FAR struct vnc_session_s *session) /* Send the ServerInit message * * "After receiving the ClientInit message, the server sends a ServerInit - * message. This tells the client the width and height of the server’s + * message. This tells the client the width and height of the server’s * framebuffer, its pixel format and the name associated with the desktop: */ - gvdbg("Receive ServerInit\n"); + gvdbg("Send ServerInit\n"); serverinit = (FAR struct rfb_serverinit_s *)session->outbuf; @@ -248,7 +359,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session) if (nrecvd < 0) { errcode = get_errno(); - gdbg("ERROR: Receive SetFormat failed: %d\n", errcode); + gdbg("ERROR: Receive SetPixelFormat failed: %d\n", errcode); DEBUGASSERT(errcode > 0); return -errcode; } @@ -261,7 +372,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session) } else if (setformat->msgtype != RFB_SETPIXELFMT_MSG) { - gdbg("ERROR: Not a SetFormat message: %d\n", (int)setformat->msgtype); + gdbg("ERROR: Not a SetPixelFormat message: %d\n", (int)setformat->msgtype); return -EPROTO; } @@ -318,66 +429,3 @@ int vnc_negotiate(FAR struct vnc_session_s *session) session->state = VNCSERVER_CONFIGURED; return OK; } -#endif - -#ifdef CONFIG_VNCSERVER_PROTO3p8 -int vnc_negotiate(FAR struct vnc_session_s *session) -{ - ssize_t nsent; - ssize_t nrecvd; - size_t len; - -#ifdef CONFIG_NET_SOCKOPTS - struct timeval tv; - int ret; - - /* Set a receive timeout so that we don't hang if the client does not - * respond according to RFB 3.3 protocol. - */ - - tv.tv_sec = 5; - tv.tv_usec = 0; - ret = psock_setsockopt(&session->connect, SOL_SOCKET, SO_RCVTIMEO, - &tv, sizeof(struct timeval)); - if (ret < 0) - { - errcode = get_errno(); - gdbg("ERROR: Failed to set receive timeout: %d\n", errcode); - DEBUGASSERT(errcode > 0); - return -errcode; - } -#endif - - /* Inform the client of the VNC protocol version */ - - len = strlen(g_vncproto); - nsent = psock_send(&session->connect, g_vncproto, len, 0); - if (nsent < 0) - { - errcode = get_errno(); - gdbg("ERROR: Send ProtocolVersion failed: %d\n", errcode); - DEBUGASSERT(errcode > 0); - return -errcode; - } - - DEBUGASSERT(nsent == len); - - /* Receive the echo of the protocol string */ - - nrecvd = psock_recv(&session->connect, session->inbuf, len, 0); - if (nrecvd <= 0) - { - errcode = get_errno(); - gdbg("ERROR: Receive protocol confirmation failed: %d\n", errcode); - DEBUGASSERT(errcode > 0); - return -errcode; - } - - DEBUGASSERT(nrecvd == len); - - /* Offer the client a choice of security -- where None is the only option. */ -#warning Missing logic - - return OK; -} -#endif