diff --git a/graphics/vnc/server/Make.defs b/graphics/vnc/server/Make.defs index 6baa8b463b..5c168b969a 100644 --- a/graphics/vnc/server/Make.defs +++ b/graphics/vnc/server/Make.defs @@ -35,6 +35,8 @@ ifeq ($(CONFIG_VNCSERVER),y) +CSRCS += vnc_server.c vnc_session.c + DEPPATH += --dep-path vnc/server CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)/graphics/vnc/server} VPATH += :vnc/server diff --git a/graphics/vnc/server/vnc_server.c b/graphics/vnc/server/vnc_server.c new file mode 100644 index 0000000000..2afc14e97f --- /dev/null +++ b/graphics/vnc/server/vnc_server.c @@ -0,0 +1,122 @@ +/**************************************************************************** + * graphics/vnc/vnc_server.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 "nuttx/config.h" + +#include +#include +#include + +#include "vnc_server.h" + +/**************************************************************************** + * Pubic Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vnc_server + * + * Description: + * The VNC server daemon. This daemon is implemented as a kernel thread. + * + * Input Parameters: + * Standard kernel thread arguments (all ignored) + * + * Returned Value: + * This function does not return. + * + ****************************************************************************/ + +int vnc_server(int argc, FAR char *argv[]) +{ + FAR struct vnc_session_s *session; + int display; + int ret; + + DEBUGASSERT(session != NULL); + + /* A single argument is expected: A diplay port number in ASCII form */ + + if (argc != 2) + { + gdbg("ERROR: Unexpected number of arguments: %d\n", argc); + return EXIT_FAILURE; + } + + display = atoi(argv[1]); + if (display < 0 || display >= RFB_MAX_DISPLAYS) + { + gdbg("ERROR: Invalid display number: %d\n", display); + return EXIT_FAILURE; + } + + /* Allocate a session structure for this display */ + + session = vnc_create_session(); + if (session == NULL) + { + gdbg("ERROR: Failed to allocate session\n"); + return EXIT_FAILURE; + } + + /* Loop... handling each each VNC client connection to this display. Only + * a single client is allowed for each display. + */ + + for (; ; ) + { + /* Establish a connection with the VNC client */ + + ret = vnc_connect(session, RFB_DISPLAY_PORT(display)); + if (ret >= 0) + { + gvdbg("New VNC connection\n"); + + /* Start the VNC session */ + + (void)vnc_session(session); + + /* Re-initialize the session structure for re-use */ + + vnc_release_session(session); + } + } + + return EXIT_FAILURE; /* We won't get here */ +} diff --git a/graphics/vnc/server/vnc_server.h b/graphics/vnc/server/vnc_server.h index 980a7680df..ef24920515 100644 --- a/graphics/vnc/server/vnc_server.h +++ b/graphics/vnc/server/vnc_server.h @@ -46,12 +46,19 @@ #include #include +#include #include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* RFB Port Number */ + +#define RFB_PORT_BASE 5900 +#define RFB_MAX_DISPLAYS 100 +#define RFB_DISPLAY_PORT(d) (RFB_PORT_BASE + (d)) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -66,7 +73,7 @@ enum vnc_server_e VNCSERVER_CONFIGURED, /* Configured and ready to transfer graphics */ VNCSERVER_SCANNING, /* Running and activly transferring graphics */ VNCSERVER_STOPPING /* The server has been asked to stop */ -} +}; struct vnc_session_s { @@ -82,7 +89,7 @@ struct vnc_session_s /* Display geometry and color characteristics */ - uint8_t colorfmt /* See include/nuttx/fb.h */ + uint8_t colorfmt; /* See include/nuttx/fb.h */ struct nxgl_size_s screen; /* Size of the screen in pixels x rows */ }; @@ -90,4 +97,75 @@ struct vnc_session_s * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * 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_session + * + * Description: + * This function encapsulates the entire VNC session. + * + * Input Parameters: + * session - An instance of the session structure allocated by + * vnc_create_session(). + * + * Returned Value: + * At present, always returns OK + * + ****************************************************************************/ + +int vnc_session(FAR struct vnc_session_s *session); + #endif /* __GRAPHICS_VNC_SERVER_VNC_SERVER_H */ diff --git a/graphics/vnc/server/vnc_session.c b/graphics/vnc/server/vnc_session.c new file mode 100644 index 0000000000..16ec9ff846 --- /dev/null +++ b/graphics/vnc/server/vnc_session.c @@ -0,0 +1,220 @@ +/**************************************************************************** + * 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); + } + + vnc_initialize_session(session); +}