diff --git a/graphics/vnc/server/Kconfig b/graphics/vnc/server/Kconfig index f4dc219c37d..f688da3ab15 100644 --- a/graphics/vnc/server/Kconfig +++ b/graphics/vnc/server/Kconfig @@ -34,13 +34,21 @@ config VNCSERVER_NDISPLAYS Normally this should be one. config VNCSERVER_PRIO - int "VNC server thread priority" + int "VNC server task priority" default 100 config VNCSERVER_STACKSIZE int "VNC server stack size" default 2048 +config VNCSERVER_UPDATER_PRIO + int "VNC updater thread priority" + default 100 + +config VNCSERVER_UPDATER_STACKSIZE + int "VNC updater thread stack size" + default 2048 + choice prompt "VNC color format" default VNCSERVER_COLORFMT_RGB16 diff --git a/graphics/vnc/server/Make.defs b/graphics/vnc/server/Make.defs index 4e86bfeda19..263be54df6e 100644 --- a/graphics/vnc/server/Make.defs +++ b/graphics/vnc/server/Make.defs @@ -35,7 +35,7 @@ ifeq ($(CONFIG_VNCSERVER),y) -CSRCS += vnc_server.c vnc_session.c vnc_negotiate.c vnc_fbdev.c +CSRCS += vnc_server.c vnc_negotiate.c vnc_updater.c vnc_receiver.c vnc_fbdev.c ifeq ($(CONFIG_NX_KBD),y) CSRCS += vnc_keymap.c diff --git a/graphics/vnc/server/vnc_fbdev.c b/graphics/vnc/server/vnc_fbdev.c index cb05686cda6..7433f4b3bc5 100644 --- a/graphics/vnc/server/vnc_fbdev.c +++ b/graphics/vnc/server/vnc_fbdev.c @@ -153,7 +153,7 @@ static int up_getvideoinfo(FAR struct fb_vtable_s *vtable, if (fbinfo != NULL && vinfo != NULL) { session = vnc_find_session(fbinfo->display); - if (session == NULL || session->state != VNCSERVER_SCANNING) + if (session == NULL || session->state != VNCSERVER_RUNNING) { gdbg("ERROR: session is not connected\n"); return -ENOTCONN; @@ -165,8 +165,8 @@ static int up_getvideoinfo(FAR struct fb_vtable_s *vtable, */ vinfo->fmt = RFB_COLORFMT; - vinfo->xres = session->screen.w; - vinfo->yres = session->screen.h; + vinfo->xres = CONFIG_VNCSERVER_SCREENWIDTH; + vinfo->yres = CONFIG_VNCSERVER_SCREENHEIGHT; vinfo->nplanes = 1; return OK; @@ -192,7 +192,7 @@ static int up_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno, if (fbinfo != NULL && pinfo != NULL && planeno == 0) { session = vnc_find_session(fbinfo->display); - if (session == NULL || session->state != VNCSERVER_SCANNING) + if (session == NULL || session->state != VNCSERVER_RUNNING) { gdbg("ERROR: session is not connected\n"); return -ENOTCONN; @@ -206,8 +206,8 @@ static int up_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno, */ pinfo->fbmem = (FAR void *)session->fb; - pinfo->fblen = (uint32_t)session->stride * CONFIG_VNCSERVER_SCREENWIDTH; - pinfo->stride = (fb_coord_t)session->stride; + pinfo->fblen = RFB_SIZE; + pinfo->stride = RFB_STRIDE; pinfo->bpp = RFB_BITSPERPIXEL; return OK; @@ -236,7 +236,7 @@ static int up_getcmap(FAR struct fb_vtable_s *vtable, if (fbinfo != NULL && cmap != NULL) { session = vnc_find_session(fbinfo->display); - if (session == NULL || session->state != VNCSERVER_SCANNING) + if (session == NULL || session->state != VNCSERVER_RUNNING) { gdbg("ERROR: session is not connected\n"); return -ENOTCONN; @@ -271,7 +271,7 @@ static int up_putcmap(FAR struct fb_vtable_s *vtable, FAR const struct fb_cmap_s if (fbinfo != NULL && cmap != NULL) { session = vnc_find_session(fbinfo->display); - if (session == NULL || session->state != VNCSERVER_SCANNING) + if (session == NULL || session->state != VNCSERVER_RUNNING) { gdbg("ERROR: session is not connected\n"); return -ENOTCONN; @@ -307,7 +307,7 @@ static int up_getcursor(FAR struct fb_vtable_s *vtable, if (fbinfo != NULL && attrib != NULL) { session = vnc_find_session(fbinfo->display); - if (session == NULL || session->state != VNCSERVER_SCANNING) + if (session == NULL || session->state != VNCSERVER_RUNNING) { gdbg("ERROR: session is not connected\n"); return -ENOTCONN; @@ -341,7 +341,7 @@ static int up_setcursor(FAR struct fb_vtable_s *vtable, if (fbinfo != NULL && settings != NULL) { session = vnc_find_session(fbinfo->display); - if (session == NULL || session->state != VNCSERVER_SCANNING) + if (session == NULL || session->state != VNCSERVER_RUNNING) { gdbg("ERROR: session is not connected\n"); return -ENOTCONN; @@ -451,7 +451,7 @@ FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane) /* Verify that the session is still valid */ - if (session->state != VNCSERVER_SCANNING) + if (session->state != VNCSERVER_RUNNING) { return NULL; } diff --git a/graphics/vnc/server/vnc_negotiate.c b/graphics/vnc/server/vnc_negotiate.c index f5f487873bb..44f1d8c312d 100644 --- a/graphics/vnc/server/vnc_negotiate.c +++ b/graphics/vnc/server/vnc_negotiate.c @@ -45,7 +45,6 @@ #include #include -#include #include #include @@ -74,8 +73,7 @@ static const char g_vncproto[] = RFB_PROTOCOL_VERSION_3p8; * properties. * * Input Parameters: - * session - An instance of the session structure allocated by - * vnc_create_session(). + * session - An instance of the session structure. * * Returned Value: * Returns zero (OK) on success; a negated errno value on failure. @@ -91,7 +89,6 @@ int vnc_negotiate(FAR struct vnc_session_s *session) FAR struct rfb_setpixelformat_s *setformat; ssize_t nsent; ssize_t nrecvd; - size_t alloc; size_t len; int errcode; @@ -111,7 +108,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session) /* Receive the echo of the protocol string */ - nrecvd = psock_recv(&session->connect, session->iobuf, len, 0); + nrecvd = psock_recv(&session->connect, session->inbuf, len, 0); if (nrecvd <= 0) { errcode = get_errno(); @@ -128,7 +125,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session) * word:" */ - sectype = (FAR struct rfb_sectype_s *)session->iobuf; + sectype = (FAR struct rfb_sectype_s *)session->outbuf; rfb_putbe32(sectype->type, RFB_SECTYPE_NONE); nsent = psock_send(&session->connect, sectype, @@ -153,7 +150,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session) * In this implementation, the sharing flag is ignored. */ - nrecvd = psock_recv(&session->connect, session->iobuf, + nrecvd = psock_recv(&session->connect, session->inbuf, sizeof(struct rfb_clientinit_s), 0); if (nrecvd < 0) { @@ -172,7 +169,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session) * framebuffer, its pixel format and the name associated with the desktop: */ - serverinit = (FAR struct rfb_serverinit_s *)session->iobuf; + serverinit = (FAR struct rfb_serverinit_s *)session->outbuf; rfb_putbe16(serverinit->width, CONFIG_VNCSERVER_SCREENWIDTH); rfb_putbe16(serverinit->height, CONFIG_VNCSERVER_SCREENHEIGHT); @@ -207,7 +204,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session) * This may override some of our framebuffer settings. */ - setformat = (FAR struct rfb_setpixelformat_s *)session->iobuf; + setformat = (FAR struct rfb_setpixelformat_s *)session->inbuf; nrecvd = psock_recv(&session->connect, setformat, sizeof(struct rfb_setpixelformat_s), 0); @@ -272,30 +269,11 @@ int vnc_negotiate(FAR struct vnc_session_s *session) return -ENOSYS; } - session->screen.w = CONFIG_VNCSERVER_SCREENWIDTH; - session->screen.h = CONFIG_VNCSERVER_SCREENHEIGHT; - - /* Now allocate the framebuffer memory. We rely on the fact that - * the KMM allocator will align memory to 32-bits or better. - */ - - len = (session->bpp + 7) >> 3; - session->stride = len * CONFIG_VNCSERVER_SCREENWIDTH; - alloc = (size_t)session->stride * CONFIG_VNCSERVER_SCREENHEIGHT; - - session->fb = (FAR uint8_t *)kmm_zalloc(alloc); - if (session->fb == NULL) - { - gdbg("ERROR: Failed to allocate framebuffer memory: %lu\n", - (unsigned long)alloc); - return -ENOMEM; - } - /* Receive supported encoding types from client, but ignore them. * we will do only raw format. */ - (void)psock_recv(&session->connect, session->iobuf, + (void)psock_recv(&session->connect, session->inbuf, CONFIG_VNCSERVER_IOBUFFER_SIZE, 0); session->state = VNCSERVER_CONFIGURED; @@ -326,7 +304,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session) /* Receive the echo of the protocol string */ - nrecvd = psock_recv(&session->connect, session->iobuf, len, 0); + nrecvd = psock_recv(&session->connect, session->inbuf, len, 0); if (nrecvd <= 0) { errcode = get_errno(); diff --git a/graphics/vnc/server/vnc_receiver.c b/graphics/vnc/server/vnc_receiver.c new file mode 100644 index 00000000000..f8c9e47e1ea --- /dev/null +++ b/graphics/vnc/server/vnc_receiver.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * graphics/vnc/vnc_receiver.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "vnc_server.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vnc_receiver + * + * Description: + * This function handles all Client-to-Server messages. + * + * Input Parameters: + * session - An instance of the session structure. + * + * Returned Value: + * At present, always returns OK + * + ****************************************************************************/ + +int vnc_receiver(FAR struct vnc_session_s *session) +{ +#warning Missing logic + return -ENOSYS; +} diff --git a/graphics/vnc/server/vnc_server.c b/graphics/vnc/server/vnc_server.c index ac1c4e6d5dc..77ed0f6410d 100644 --- a/graphics/vnc/server/vnc_server.c +++ b/graphics/vnc/server/vnc_server.c @@ -39,12 +39,25 @@ #include "nuttx/config.h" +#include #include +#include #include +#include #include +#include +#include + +#include +#include + #include "vnc_server.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + /**************************************************************************** * Private Data ****************************************************************************/ @@ -55,6 +68,116 @@ static FAR struct vnc_session_s *g_vnc_sessions[RFB_MAX_DISPLAYS]; +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vnc_reset_session + * + * Description: + * Conclude the current VNC session. This function re-initializes the + * session structure; it does not free either the session structure nor + * the framebuffer so that they may be re-used. + * + * Input Parameters: + * session - An instance of the session structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void vnc_reset_session(FAR struct vnc_session_s *session, + FAR uint8_t *fb) +{ + /* Close any open sockets */ + + if (session->state >= VNCSERVER_CONNECTED) + { + psock_close(&session->connect); + psock_close(&session->listen); + } + + /* [Re-]nitialize the session. Set all values to 0 == NULL == false. */ + + memset(session, 0, sizeof(struct vnc_session_s)); + + /* Then initialize only non-zero values */ + + session->fb = fb; + session->state = VNCSERVER_INITIALIZED; +} + +/**************************************************************************** + * Name: vnc_connect + * + * Description: + * Wait for a connection from the VNC client + * + * Input Parameters: + * session - An instance of the session structure. + * port - The listen port to use + * + * Returned Value: + * Returns zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int vnc_connect(FAR struct vnc_session_s *session, int port) +{ + struct sockaddr_in addr; + int ret; + + /* Create a listening socket */ + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + + ret = psock_socket(AF_INET, SOCK_STREAM, 0, &session->listen); + if (ret < 0) + { + ret = -get_errno(); + return ret; + } + + /* Bind the listening socket to a local address */ + + ret = psock_bind(&session->listen, (struct sockaddr *)&addr, + sizeof(struct sockaddr_in)); + if (ret < 0) + { + ret = -get_errno(); + goto errout_with_listener; + } + + /* Listen for a connection */ + + ret = psock_listen(&session->listen, 5); + if (ret < 0) + { + ret = -get_errno(); + goto errout_with_listener; + } + + /* Connect to the client */ + + ret = psock_accept(&session->listen, NULL, NULL, &session->connect); + if (ret < 0) + { + ret = -get_errno(); + goto errout_with_listener; + } + + session->state = VNCSERVER_CONNECTED; + return OK; + +errout_with_listener: + psock_close(&session->listen); + return ret; +} + /**************************************************************************** * Pubic Functions ****************************************************************************/ @@ -76,6 +199,7 @@ static FAR struct vnc_session_s *g_vnc_sessions[RFB_MAX_DISPLAYS]; int vnc_server(int argc, FAR char *argv[]) { FAR struct vnc_session_s *session; + FAR uint8_t *fb; int display; int ret; @@ -96,13 +220,25 @@ int vnc_server(int argc, FAR char *argv[]) return EXIT_FAILURE; } + /* Allocate the framebuffer memory. We rely on the fact that + * the KMM allocator will align memory to 32-bits or better. + */ + + fb = (FAR uint8_t *)kmm_zalloc(RFB_SIZE); + if (fb == NULL) + { + gdbg("ERROR: Failed to allocate framebuffer memory: %lu\n", + (unsigned long)alloc); + return -ENOMEM; + } + /* Allocate a session structure for this display */ - session = vnc_create_session(); + session = kmm_zalloc(sizeof(struct vnc_session_s)); if (session == NULL) { gdbg("ERROR: Failed to allocate session\n"); - return EXIT_FAILURE; + goto errout_with_fb; } g_vnc_sessions[display] = session; @@ -113,6 +249,12 @@ int vnc_server(int argc, FAR char *argv[]) for (; ; ) { + /* Release the last sesstion and [Re-]initialize the session structure + * for the next connection. + */ + + vnc_reset_session(session, fb); + /* Establish a connection with the VNC client */ ret = vnc_connect(session, RFB_DISPLAY_PORT(display)); @@ -130,24 +272,42 @@ int vnc_server(int argc, FAR char *argv[]) { gdbg("ERROR: Failed to negotiate security/framebuffer: %d\n", ret); + continue; } - else - { - /* Start the VNC session. This function does not return until - * the session has been terminated (or an error occurs). - */ - ret = vnc_session(session); - gvdbg("Session terminated with %d\n", ret); + /* Start the VNC updater thread that sends all Server-to-Client + * messages. + */ + + ret = vnc_start_updater(session); + if (ret < 0) + { + gdbg("ERROR: Failed to start updater thread: %d\n", ret); + continue; + } + + /* Start the VNC receiver on this this. The VNC receiver handles + * all Client-to-Server messages. The VNC receiver function does + * not return until the session has been terminated (or an error + * occurs). + */ + + ret = vnc_receiver(session); + gvdbg("Session terminated with %d\n", ret); + + /* Stop the VNC updater thread. */ + + ret = vnc_stop_updater(session); + if (ret < 0) + { + gdbg("ERROR: Failed to stop updater thread: %d\n", ret); } } - - /* Re-initialize the session structure for re-use */ - - vnc_release_session(session); } - return EXIT_FAILURE; /* We won't get here */ +errout_with_fb: + kmm_free(fb); + return EXIT_FAILURE; } /**************************************************************************** @@ -160,10 +320,9 @@ int vnc_server(int argc, FAR char *argv[]) * display - The display number of interest. * * Returned Value: - * Returns the instance of the session structure allocated by - * vnc_create_session() for this display. NULL will be returned if the - * server has not yet been started or if the display number is out of - * range. + * Returns the instance of the session structure for this display. NULL + * will be returned if the server has not yet been started or if the + * display number is out of range. * ****************************************************************************/ diff --git a/graphics/vnc/server/vnc_server.h b/graphics/vnc/server/vnc_server.h index fda657b1abb..4e0a2cf3eef 100644 --- a/graphics/vnc/server/vnc_server.h +++ b/graphics/vnc/server/vnc_server.h @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -109,10 +110,24 @@ # define CONFIG_VNCSERVER_STACKSIZE 2048 #endif +#ifndef CONFIG_VNCSERVER_UPDATER_PRIO +# define CONFIG_VNCSERVER_UPDATER_PRIO 100 +#endif + +#ifndef CONFIG_VNCSERVER_UPDATER_STACKSIZE +# define CONFIG_VNCSERVER_UPDATER_STACKSIZE 2048 +#endif + #ifndef CONFIG_VNCSERVER_IOBUFFER_SIZE # define CONFIG_VNCSERVER_IOBUFFER_SIZE 80 #endif +/* Local framebuffer characteristics in bytes */ + +#define RFB_BYTESPERPIXEL ((RFB_BITSPERPIXEL + 7) >> 8) +#define RFB_STRIDE (RFB_BYTESPERPIXEL * CONFIG_VNCSERVER_SCREENWIDTH) +#define RFB_SIZE (RFB_STRIDE * CONFIG_VNCSERVER_SCREENHEIGHT) + /* RFB Port Number */ #define RFB_PORT_BASE 5900 @@ -141,7 +156,7 @@ enum vnc_server_e VNCSERVER_INITIALIZED, /* State structured initialized, but not connected */ VNCSERVER_CONNECTED, /* Connect to a client, but not yet configured */ VNCSERVER_CONFIGURED, /* Configured and ready to transfer graphics */ - VNCSERVER_SCANNING, /* Running and activly transferring graphics */ + VNCSERVER_RUNNING, /* Running and activly transferring graphics */ VNCSERVER_STOPPING /* The server has been asked to stop */ }; @@ -159,15 +174,18 @@ struct vnc_session_s /* Display geometry and color characteristics */ - uint8_t colorfmt; /* See include/nuttx/fb.h */ - uint8_t bpp; /* Bits per pixel */ - size_t stride; /* Width of a row in bytes */ - struct nxgl_size_s screen; /* Size of the screen in pixels x rows */ + uint8_t colorfmt; /* Remote color format (See include/nuttx/fb.h) */ + uint8_t bpp; /* Remote bits per pixel */ FAR uint8_t *fb; /* Allocated local frame buffer */ - /* I/O buffer for misc network send/receive */ + /* Updater information */ - uint8_t iobuf[CONFIG_VNCSERVER_IOBUFFER_SIZE]; + pthread_t updater; /* Updater thread ID */ + + /* I/O buffers for misc network send/receive */ + + uint8_t inbuf[CONFIG_VNCSERVER_IOBUFFER_SIZE]; + uint8_t outbuf[CONFIG_VNCSERVER_IOBUFFER_SIZE]; }; /**************************************************************************** @@ -198,60 +216,6 @@ extern "C" int vnc_server(int argc, FAR char *argv[]); -/**************************************************************************** - * Name: vnc_connect - * - * Description: - * Wait for a connection from the VNC client - * - * Input Parameters: - * session - An instance of the session structure allocated by - * vnc_create_session(). - * port - The listen port to use - * - * Returned Value: - * Returns zero (OK) on success; a negated errno value on failure. - * - ****************************************************************************/ - -int vnc_connect(FAR struct vnc_session_s *session, int port); - -/**************************************************************************** - * Name: vnc_create_session - * - * Description: - * Create a new, unconnected session - * - * Input Parameters: - * None - * - * Returned Value: - * On success, this function returns the allocated and initialize session - * structure. NULL is returned on failure. - * - ****************************************************************************/ - -FAR struct vnc_session_s *vnc_create_session(void); - -/**************************************************************************** - * Name: vnc_release_session - * - * Description: - * Conclude the current VNC session and free most resources. This function - * re-initializes the session structure; it does not free it so that it - * can be re-used. - * - * Input Parameters: - * session - An instance of the session structure allocated by - * vnc_create_session(). - * - * Returned Value: - * None - * - ****************************************************************************/ - -void vnc_release_session(FAR struct vnc_session_s *session); - /**************************************************************************** * Name: vnc_negotiate * @@ -261,8 +225,7 @@ void vnc_release_session(FAR struct vnc_session_s *session); * properties. * * Input Parameters: - * session - An instance of the session structure allocated by - * vnc_create_session(). + * session - An instance of the session structure. * * Returned Value: * Returns zero (OK) on success; a negated errno value on failure. @@ -272,40 +235,54 @@ void vnc_release_session(FAR struct vnc_session_s *session); int vnc_negotiate(FAR struct vnc_session_s *session); /**************************************************************************** - * Name: vnc_session + * Name: vnc_start_updater * * Description: - * This function encapsulates the entire VNC session. + * Start the updater thread * * Input Parameters: - * session - An instance of the session structure allocated by - * vnc_create_session(). + * session - An instance of the session structure. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +int vnc_start_updater(FAR struct vnc_session_s *session); + +/**************************************************************************** + * Name: vnc_stop_updater + * + * Description: + * Stop the updater thread + * + * Input Parameters: + * session - An instance of the session structure. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +int vnc_stop_updater(FAR struct vnc_session_s *session); + +/**************************************************************************** + * Name: vnc_receiver + * + * Description: + * This function handles all Client-to-Server messages. + * + * Input Parameters: + * session - An instance of the session structure. * * Returned Value: * At present, always returns OK * ****************************************************************************/ -int vnc_session(FAR struct vnc_session_s *session); - -/**************************************************************************** - * Name: vnc_find_session - * - * Description: - * Return the session structure associated with this display. - * - * Input Parameters: - * display - The display number of interest. - * - * Returned Value: - * Returns the instance of the session structure allocated by - * vnc_create_session() for this display. NULL will be returned if the - * server has not yet been started or if the display number is out of - * range. - * - ****************************************************************************/ - -FAR struct vnc_session_s *vnc_find_session(int display); +int vnc_receiver(FAR struct vnc_session_s *session); /**************************************************************************** * Name: vnc_key_map @@ -315,8 +292,7 @@ FAR struct vnc_session_s *vnc_find_session(int display); * that through NX to the appropriate window. * * Input Parameters: - * session - An instance of the session structure allocated by - * vnc_create_session(). + * session - An instance of the session structure. * keysym - The X11 keysym value (see include/nuttx/inputx11_keysymdef) * keydown - True: Key pressed; False: Key released * @@ -330,6 +306,24 @@ void vnc_key_map(FAR struct vnc_session_s *session, uint32_t keysym, bool keydown); #endif +/**************************************************************************** + * Name: vnc_find_session + * + * Description: + * Return the session structure associated with this display. + * + * Input Parameters: + * display - The display number of interest. + * + * Returned Value: + * Returns the instance of the session structure for this display. NULL + * will be returned if the server has not yet been started or if the + * display number is out of range. + * + ****************************************************************************/ + +FAR struct vnc_session_s *vnc_find_session(int display); + #undef EXTERN #ifdef __cplusplus } diff --git a/graphics/vnc/server/vnc_session.c b/graphics/vnc/server/vnc_session.c deleted file mode 100644 index 35589938008..00000000000 --- a/graphics/vnc/server/vnc_session.c +++ /dev/null @@ -1,227 +0,0 @@ -/**************************************************************************** - * graphics/vnc/vnc_session.c - * - * Copyright (C) 2016 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include "vnc_server.h" - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: vnc_initialize_session - * - * Description: - * [Re-]initialize a VNC session - * - * Input Parameters: - * session - the VNC session to be initialized - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void vnc_initialize_session(FAR struct vnc_session_s *session) -{ - /* Initialize the session. Set all values to 0 == NULL == false. */ - - memset(session, 0, sizeof(struct vnc_session_s)); - - /* Then initialize only non-zero values */ - /* Initialized, not connected */ - - session->state = VNCSERVER_INITIALIZED; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: vnc_connect - * - * Description: - * Wait for a connection from the VNC client - * - * Input Parameters: - * session - An instance of the session structure allocated by - * vnc_create_session(). - * port - The listen port to use - * - * Returned Value: - * Returns zero (OK) on success; a negated errno value on failure. - * - ****************************************************************************/ - -int vnc_connect(FAR struct vnc_session_s *session, int port) -{ - struct sockaddr_in addr; - int ret; - - /* Create a listening socket */ - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = INADDR_ANY; - - ret = psock_socket(AF_INET, SOCK_STREAM, 0, &session->listen); - if (ret < 0) - { - ret = -get_errno(); - return ret; - } - - /* Bind the listening socket to a local address */ - - ret = psock_bind(&session->listen, (struct sockaddr *)&addr, - sizeof(struct sockaddr_in)); - if (ret < 0) - { - ret = -get_errno(); - goto errout_with_listener; - } - - /* Listen for a connection */ - - ret = psock_listen(&session->listen, 5); - if (ret < 0) - { - ret = -get_errno(); - goto errout_with_listener; - } - - /* Connect to the client */ - - ret = psock_accept(&session->listen, NULL, NULL, &session->connect); - if (ret < 0) - { - ret = -get_errno(); - goto errout_with_listener; - } - - session->state = VNCSERVER_CONNECTED; - return OK; - -errout_with_listener: - psock_close(&session->listen); - return ret; -} - -/**************************************************************************** - * Name: vnc_create_session - * - * Description: - * Create a new, unconnected session - * - * Input Parameters: - * None - * - * Returned Value: - * On success, this function returns the allocated and initialize session - * structure. NULL is returned on failure. - * - ****************************************************************************/ - -FAR struct vnc_session_s *vnc_create_session(void) -{ - FAR struct vnc_session_s *session; - - /* Allocate the session */ - - session = (FAR struct vnc_session_s *) - kmm_zalloc(sizeof(struct vnc_session_s)); - - /* Initialize the session */ - - if (session != NULL) - { - vnc_initialize_session(session); - } - - return session; -} - -/**************************************************************************** - * Name: vnc_release_session - * - * Description: - * Conclude the current VNC session and free most resources. This function - * re-initializes the session structure; it does not free it so that it - * can be re-used. - * - * Input Parameters: - * session - An instance of the session structure allocated by - * vnc_create_session(). - * - * Returned Value: - * None - * - ****************************************************************************/ - -void vnc_release_session(FAR struct vnc_session_s *session) -{ - /* Close any open sockets */ - - if (session->state >= VNCSERVER_CONNECTED) - { - psock_close(&session->connect); - psock_close(&session->listen); - } - - /* Free the allocated framebuffer */ - - if (session->fb) - { - kmm_free(session->fb); - } - - vnc_initialize_session(session); -} diff --git a/graphics/vnc/server/vnc_updater.c b/graphics/vnc/server/vnc_updater.c new file mode 100644 index 00000000000..f8a44a9341d --- /dev/null +++ b/graphics/vnc/server/vnc_updater.c @@ -0,0 +1,171 @@ +/**************************************************************************** + * graphics/vnc/vnc_updater.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "vnc_server.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vnc_updater + * + * Description: + * This is the "updater" thread. It is the sender of all Server-to-Client + * messages + * + * Input Parameters: + * Standard pthread arguments. + * + * Returned Value: + * NULL is always returned. + * + ****************************************************************************/ + +static FAR void *vnc_updater(FAR void *arg) +{ + FAR struct vnc_session_s *session = (FAR struct vnc_session_s *)arg; + + DEBUGASSERT(session != NULL); + + while (session->state == VNCSERVER_RUNNING) + { +#warning Missing logic + } + + return NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vnc_start_updater + * + * Description: + * Start the updater thread + * + * Input Parameters: + * session - An instance of the session structure. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +int vnc_start_updater(FAR struct vnc_session_s *session) +{ + pthread_attr_t attr; + struct sched_param param; + int status; + + /* Create thread that is gonna send rectangles to the client */ + + session->state = VNCSERVER_RUNNING; + + DEBUGVERIFY(pthread_attr_init(&attr)); + DEBUGVERIFY(pthread_attr_setstacksize(&attr, CONFIG_VNCSERVER_UPDATER_STACKSIZE)); + + param.sched_priority = CONFIG_VNCSERVER_UPDATER_PRIO; + DEBUGVERIFY(pthread_attr_setschedparam(&attr, ¶m)); + + status = pthread_create(&session->updater, &attr, vnc_updater, + (pthread_addr_t)session); + if (status != 0) + { + return -status; + } + + return OK; +} + +/**************************************************************************** + * Name: vnc_stop_updater + * + * Description: + * Stop the updater thread + * + * Input Parameters: + * session - An instance of the session structure. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +int vnc_stop_updater(FAR struct vnc_session_s *session) +{ + pthread_addr_t result; + int status; + + /* Is the update thread running? */ + + if (session->state == VNCSERVER_RUNNING) + { + /* Yes.. ask it to please stop */ + + session->state = VNCSERVER_STOPPING; + + /* Wait for the thread to comply with our request */ + + status = pthread_join(session->updater, &result); + if (status != 0) + { + return -status; + } + + /* Return what the thread returned */ + + return (int)((intptr_t)result); + } + + /* Not running? Just say we stopped the thread successfully. */ + + return OK; +} +