-
-
Notifications
You must be signed in to change notification settings - Fork 502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MCU support #632
Comments
You can build without threading support, the rest is probably reseaching cmake and FreeRTOS. If your efforts are successful, let me know; would be happy to merge in some documentation w.r.t. embedded systems! |
That would really make the library truly cross platform. question tho. are there functions that are public that can encode and decode the VNC packets without having to use any of the built in connection code. The network related API for the ESP32 doesn't follow POSIX standards, not 100% anyway. so I would only use the library to encode and decode the packets. the library would handle reading the data that I would feed into it via a function call and it would work like it would normally would when doing that. for sending messages I would only need the library to build the packets when transmitting. |
I guess your best bet is to write/get-from-a-third-party shims for BSD socket functions; there might be other issues as well. But at least documenting those here in public would be nice. |
I am still crossing the bridge to get it to compile. It appears the only way to set the config options is I have to add the project as a sub directory. That is the only way the environment will carry over to it. There is no way to just use the packet encoding/decoding portions of the library? I could write wrapper code for the network functions to make it work. |
I am actually pretty damned close to getting it to compile. There are a few issues however. You have some macro definitions that are redefinition's. you don't have any guards in place to see if they are already defined. I am thinking you may want to do this... you have I am going to manually add the guard for that macro and see if there is anything else that causes problems. at the moment that is all there appears to be. |
If you got a simple PR with additional header guards, I'll happily merge this. |
I got sidetracked on something else and I have not put a guard in for the one error I am getting. Once I have it compiling I will submit a PR for any changes to the code I have made, |
OK so I am making headway. so far a simple include solves the issue. In #ifndef INADDR_NONE
#define INADDR_NONE ((in_addr_t) 0xffffffff)
#endif and it's awesome that there is a guard in place to check to see if it is already defined. Issue is this macro gets set before There are a couple of ways to handle this.
Personally I believe that option 1 is the best way to go about it because it is pretty much a gurantee never have anyone open an issue should they not read the docs or they missed the line where it informs them of option 2 above. It's not going to cause any kind of an issue to include I changed the lines seen below which are located in #if defined(WIN32)
typedef int8_t rfbBool;
#include <sys/timeb.h>
#include <winsock2.h>
#endif to read
and that solved that issue. Next issue is a bit more complex and it is one that is going to take me a bit to figure out how to solve. Perhaps you might be able to help me out with the best solution. This is the issue. In a multitude of places Includes are handled so when an include is wrapped in double quotes the way the compiler does the search is local path from where the include is taking place and then it searches the paths that are provided using the Se here is the issue.... lwip provides an It would take me days to figure out how to do that with cmake so it would do a proper recursive search so the paths and filename match properly and create the same path and filename. |
My 2 cents here: For the time being, don't bother to automate this with cmake, let humans do it. I think a section in the README describing the very special steps for the errno.h situation on esp32 would be enough. |
OK so I am getting down to the wire with this... couple of errors I am not sure how to fix.,...
|
This is probably all stuff not in FreeRTOS. I recommend commenting out vigorously and getting stuff to build, take notes, then clean up later. PS: Also, you probably don't need libvncclient, so errors there can be ignored. |
There is a use case for having the client which is providing a client to the user. LVGL is a light weight graphics library so providing a client would be easy to do because all of the graphics bits exist. There also seems to be no way to compile only the server without it compiling the client too. Can I omit the client source files from being compiled? There doesn't appear to be a macro available to turn off the client being compiled. |
I don't know what |
can the http server be turned off? does it need to compile when it is not being used?... We only plan on using sockets to send and receive data so there really is no need to have the http code compiled. I don't know if there is a dependence on it being compiled. |
No, both always built as of now. |
No idea, this code is very likely from a time before I entered the project. |
Not as of now, in principle of course yes. It's not essential at all. |
How do I go about turning it off? There is no macro that controls this. would I need to remove the source files from the list to be compiled? I am thinking there should be some config macros added to the source files and header files that control what does and doesn't get compiled. This is easier than having to modify the build script to control turning on and off parts of the library that could be considered as optional. |
IDK if the server code has any dependency on the code in the client if it doesn't then the client would be an optional thing. The same with the client being dependent on any of the code in the server side of things. I see there is a common folder and I would imagine anything that both the client and server both use would be located in there. That kind of indicates that the server code should be able to compile without the client code and vice versa. |
ok so here is some information in
https://man7.org/linux/man-pages/man2/wait4.2.html so a code update to use |
fixing the issue with 'getrlimit` should be pretty easy to do as well. need to add a check to the build system to see if that function is available. Right now a check is done to see if the resource.h file exists instead of check to see if the specific function that is needed exists. pretty simple thing to correct. |
Thank you for your contribution, your work has realized what I have always wanted to do but have not been able to do! What encodings do you currently want to support? All or just some encodings (due to the performance of the MCU)? |
what do you mean by encodings? are you referring to the color format? if that is the case then RGB565, RGB888, xRGB888 and ARGB888. we will use no encryption due to the additional overhead because of using software encryption. Possibly in the future add encryption but one what is supported at the hardware level on the MCU. I already wrote the code that converts the keysyms that are not control/function keys to UTF-8 and also single byte ASCII is those codes are received. being able to do file transfers will be a handy thing to have working. IDK if your library handles writing a pointer to the frame buffer data or not, if it does that could be used but I think that the GUI frameworks handling of rendering a cursor might be better. Functionally how it is going to work is the RAW RGB framebuffer data is going to get handed off to the VCN server if there is a client connection. The user will be able to choose whether or not to blank the display when a client is connected to VNC or to leave it displaying what is seen on the VNC connection. Could even use it to go one step further and set up a kind of VM design where more than one user is able to access the thing and have 2 completely different UI's showing over the connection. MicroControllers these days are pretty robust, some of them being 4 cores @ 1.4ghz and they have hardware graphics accelerators built in. The GUI framework is able to render to a 1280 x 1024 display having a framerate of 60fps on some MCU's. That's pretty quick. That's a very large amount of data to send to a display to able to maintain 60fps refresh rate on the display. it comes out to 176947200 bits a second. or 176mbit transfer speed to the display. The limitation is not going to be the MCU as far as processing ability so much as it is going to be a limit of the network connection like WiFI which is only going to be able to send data at 30mbit a second. I will hammer out some code that will decide what color format to use based on how fast the data is transferring. |
I do have a question about how exactly the data is handled on the client. I know that there are 2 ways that frame buffer data can be transmitted. It can be transmitted when the client requests it or the server can send it when it is told to send it. Now my question is does the entire frame buffer get sent when a request is made or when the server needs to send an update? or does only the updated parts get sent? I am hoping that only the parts that have been updated are what gets sent. I mam thinking the client should be writing data to a frame buffer that it has made for the entire display and when an update is received that new data gets written to the frame buffer and then the frame buffer gets rendered on the client side. The protocol specification doesn't go into much detail about the handling of this and if partial frame buffer data is able to be sent. |
Also, I am going to submit another PR and this PR is for enabling/disabling the server and client code. It stops the code from being compiled. program storage is rather skinny on an MCU so the smaller we can make the compiled binary the better. don't need to have the client code on the MCU if it is not going to be used. I know that the changes I made are not going to work because the test suite is not divided by client and server. It would be easier if someone more familiar with the test suite could separate the client and server tests so we could have the CI build only the client, then only the server and then both... this way it would ensure that everything is working correctly. |
Sorry for the confusion, I am referring to https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#76encodings |
Ahhhh, compression. I would have to run tests to see if the time it takes to do the compression would give better performance than transferring the raw data. It all depends on how small the data that gets sent is. we also have to deal with compatibility of the external compression libraries and the MCU. That will be something that I can mess with after getting uncompressed (raw) to work. |
It compiles!!! WOOOOO... Both the server and the client compile. dunno if they actually work just yet but to cross compilation using the xtensa GCC compiler was a success. |
As of now, yes. A CMake switch could be added, but is not there (yet).
Yes, am open for it. |
You're correct. server does only depend on common, client depends on common. no client<->server dependency. The configure logic is simply not (yet) in CMake :-) |
That's basically the same ;-) The RFB protocol is pull-based, so you described it correctly.
Depends on the request. A client can request a full update or tell the server "gimme just the changed parts". See https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#743framebufferupdaterequest |
Congrats! Looking forward to your PRs. |
I added the logic tho I have not yet tested it. You are more then welcome to give it a go if you want or you can look at the code to see what you think before I submit a PR for it. Here are the branches I have for the things I have changed, some I have submitted a PR for and others I have not. https://github.com/kdschlosser/libvncserver/tree/adds-build-options https://github.com/kdschlosser/libvncserver/tree/fixes-invalid-pointer-cast https://github.com/kdschlosser/libvncserver/tree/fixes-string-formatting https://github.com/kdschlosser/libvncserver/tree/fixes-string-formatting https://github.com/kdschlosser/libvncserver/tree/replaces-wait4 That addresses all of the issues in libvncserver that I was having when compiling. I managed to get all other issues sorted out externally by overriding the libc/glibc header files. There were issues with how things were implimented in the xtensa compiler and in the ESP-IDF for posix compatability that needed to be corrected. For example in
this way the Now... That being said this could be handled a little bit differently to make sure this doesn't happen if wanting to compile using other MCU's the code I wrote to handle this in the cmake file is specific to the ESP32 series of MCU's using the ESP-IDF version 5.2.x. If wanting to make it universal so the problem would not come up using any compiler that provides posix compat headers you would need to create a #ifndef WIN32
#include <sys/errno.h>
#endif
#include <errno.h> Then you would change all of the includes for errno.h in the library to point to that header file using a relative path #include "../common/errno.h" That is a more graceful approach that covers pretty much all the bases for most of the C compilers that use the libc or glibc libraries or some form of a posix compat set of libraries. |
This is an example cmake file that can be used to compile the library as an ESP32 component Click me for codecmake_minimum_required(VERSION 3.4)
set(PROJECT_LANGUAGES C)
if(DEFINED CMAKE_CXX_COMPILER)
set(CMAKE_CXX_STANDARD 17)
list(APPEND PROJECT_LANGUAGES CXX)
endif(DEFINED CMAKE_CXX_COMPILER)
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckIncludeFile)
include(CheckTypeSize)
include(TestBigEndian)
include(CheckCSourceCompiles)
include(CheckCSourceRuns)
include(GNUInstallDirs)
enable_testing()
set(LIBVNCSERVER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/libvncserver)
set(COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/common)
set(LIBVNCCLIENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/libvncclient)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules/")
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckIncludeFile)
include(CheckTypeSize)
include(TestBigEndian)
include(CheckCSourceCompiles)
include(CheckCSourceRuns)
include(GNUInstallDirs)
check_include_file("dirent.h" LIBVNCSERVER_HAVE_DIRENT_H)
check_include_file("endian.h" LIBVNCSERVER_HAVE_ENDIAN_H)
check_include_file("fcntl.h" LIBVNCSERVER_HAVE_FCNTL_H)
check_include_file("netinet/in.h" LIBVNCSERVER_HAVE_NETINET_IN_H)
check_include_file("sys/endian.h" LIBVNCSERVER_HAVE_SYS_ENDIAN_H)
check_include_file("sys/socket.h" LIBVNCSERVER_HAVE_SYS_SOCKET_H)
check_include_file("sys/stat.h" LIBVNCSERVER_HAVE_SYS_STAT_H)
check_include_file("sys/time.h" LIBVNCSERVER_HAVE_SYS_TIME_H)
check_include_file("sys/types.h" LIBVNCSERVER_HAVE_SYS_TYPES_H)
check_include_file("sys/wait.h" LIBVNCSERVER_HAVE_SYS_WAIT_H)
check_include_file("unistd.h" LIBVNCSERVER_HAVE_UNISTD_H)
check_include_file("sys/resource.h" LIBVNCSERVER_HAVE_SYS_RESOURCE_H)
# headers needed for check_type_size()
check_include_file("vfork.h" LIBVNCSERVER_HAVE_VFORK_H)
check_include_file("ws2tcpip.h" LIBVNCSERVER_HAVE_WS2TCPIP_H)
check_include_file("arpa/inet.h" HAVE_ARPA_INET_H)
check_include_file("stdint.h" HAVE_STDINT_H)
check_include_file("stddef.h" HAVE_STDDEF_H)
check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
# error out if required headers not found
if(NOT HAVE_STDINT_H)
message(FATAL_ERROR "Could NOT find required header stdint.h")
endif()
check_function_exists(getrlimit LIBVNCSERVER_HAVE_GETRLIMIT)
check_function_exists(gettimeofday LIBVNCSERVER_HAVE_GETTIMEOFDAY)
check_function_exists(vfork LIBVNCSERVER_HAVE_VFORK)
check_function_exists(vprintf LIBVNCSERVER_HAVE_VPRINTF)
check_function_exists(mmap LIBVNCSERVER_HAVE_MMAP)
check_function_exists(fork LIBVNCSERVER_HAVE_FORK)
check_function_exists(ftime LIBVNCSERVER_HAVE_FTIME)
check_function_exists(gethostbyname LIBVNCSERVER_HAVE_GETHOSTBYNAME)
check_function_exists(gethostname LIBVNCSERVER_HAVE_GETHOSTNAME)
check_function_exists(inet_ntoa LIBVNCSERVER_HAVE_INET_NTOA)
check_function_exists(memmove LIBVNCSERVER_HAVE_MEMMOVE)
check_function_exists(memset LIBVNCSERVER_HAVE_MEMSET)
check_function_exists(mkfifo LIBVNCSERVER_HAVE_MKFIFO)
check_function_exists(select LIBVNCSERVER_HAVE_SELECT)
check_function_exists(socket LIBVNCSERVER_HAVE_SOCKET)
check_function_exists(strchr LIBVNCSERVER_HAVE_STRCHR)
check_function_exists(strcspn LIBVNCSERVER_HAVE_STRCSPN)
check_function_exists(strdup LIBVNCSERVER_HAVE_STRDUP)
check_function_exists(strerror LIBVNCSERVER_HAVE_STRERROR)
check_function_exists(strstr LIBVNCSERVER_HAVE_STRSTR)
check_symbol_exists(htobe64 "endian.h" LIBVNCSERVER_HAVE_HTOBE64)
check_symbol_exists(htobe64 "sys/endian.h" LIBVNCSERVER_HAVE_HTOBE64)
check_symbol_exists(OSSwapHostToBigInt64 "libkern/OSByteOrder.h" LIBVNCSERVER_HAVE_OSSWAPHOSTTOBIGINT64)
set(LIBVNCSERVER_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}/include
${LIBVNCSERVER_DIR}
${LIBVNCCLIENT_DIR}
${COMMON_DIR}
)
set(LIBVNCSERVER_SOURCES
${LIBVNCSERVER_DIR}/main.c
${LIBVNCSERVER_DIR}/rfbserver.c
${LIBVNCSERVER_DIR}/rfbregion.c
${LIBVNCSERVER_DIR}/auth.c
${LIBVNCSERVER_DIR}/sockets.c
${LIBVNCSERVER_DIR}/stats.c
${LIBVNCSERVER_DIR}/corre.c
${LIBVNCSERVER_DIR}/hextile.c
${LIBVNCSERVER_DIR}/rre.c
${LIBVNCSERVER_DIR}/translate.c
${LIBVNCSERVER_DIR}/cutpaste.c
${LIBVNCSERVER_DIR}/httpd.c
${LIBVNCSERVER_DIR}/cursor.c
${LIBVNCSERVER_DIR}/font.c
${LIBVNCSERVER_DIR}/draw.c
${LIBVNCSERVER_DIR}/selbox.c
${COMMON_DIR}/vncauth.c
${COMMON_DIR}/sockets.c
${LIBVNCSERVER_DIR}/cargs.c
${LIBVNCSERVER_DIR}/ultra.c
${LIBVNCSERVER_DIR}/scale.c
${COMMON_DIR}/ghpringbuf.c
)
set(LIBVNCCLIENT_SOURCES
${LIBVNCCLIENT_DIR}/cursor.c
${LIBVNCCLIENT_DIR}/listen.c
${LIBVNCCLIENT_DIR}/rfbclient.c
${LIBVNCCLIENT_DIR}/sockets.c
${LIBVNCCLIENT_DIR}/vncviewer.c
)
if(ESP_PLATFORM) # check to see if we are compiling for ESP32 using the ESP-IDF
check_symbol_exists(htobe64 "machine/endian.h" LIBVNCSERVER_HAVE_HTOBE64)
# getting esp-idf component paths
idf_component_get_property(NEWLIB_DIR newlib COMPONENT_DIR)
idf_component_get_property(LWIP_DIR lwip COMPONENT_DIR)
file(WRITE ${CMAKE_BINARY_DIR}/gen_includes/errno.h
"#include \"${LWIP_DIR}/lwip/src/include/lwip/errno.h\"\n"
"#include \"${NEWLIB_DIR}/platform_include/errno.h\"\n"
"#include <sys/errno.h>\n"
)
set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES
${CMAKE_BINARY_DIR}/gen_includes
${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}
)
set(LIBVNCSERVER_INCLUDES
${CMAKE_BINARY_DIR}/gen_includes
${LIBVNCSERVER_INCLUDES}
)
set(LIBVNCSERVER_HAVE_SYS_SOCKET_H 1)
set(LIBVNCSERVER_HAVE_NETINET_IN_H 1)
set(LIBVNCSERVER_HAVE_DIRENT_H, 1)
set(HAVE_ARPA_INET_H 1)
set(LIBVNCSERVER_HAVE_GETHOSTBYNAME 1)
set(LIBVNCSERVER_HAVE_GETHOSTNAME 1)
set(LIBVNCSERVER_HAVE_INET_NTOA 1)
set(LIBVNCSERVER_HAVE_SELECT 1)
set(LIBVNCSERVER_HAVE_SOCKET 1)
set(LIBVNCSERVER_HAVE_STRCHR 1)
set(LIBVNCSERVER_HAVE_STRDUP 1)
set(LIBVNCSERVER_HAVE_STRSTR 1)
set(HAVE_LIBVNCSERVER_PID_T 1)
set(HAVE_LIBVNCSERVER_SIZE_T 1)
set(HAVE_LIBVNCSERVER_SOCKLEN_T 1)
set(HAVE_LIBVNCSERVER_IN_ADDR_T 1)
set(LIBVNCSERVER_HAVE_LIBPTHREAD 1)
set(LIBVNCSERVER_ALLOW24BPP 1)
set(LibVNCServer_VERSION "0.9.15")
set(LibVNCServer_VERSION_MAJOR "0")
set(LibVNCServer_VERSION_MINOR "9")
set(LibVNCServer_VERSION_PATCH "15")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/rfb/rfbconfig.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/include/rfb/rfbconfig.h)
idf_component_register(
SRCS ${LIBVNCSERVER_SOURCES} ${LIBVNCCLIENT_SOURCES}
INCLUDE_DIRS ${LIBVNCSERVER_INCLUDES}
REQUIRES lwip newlib
)
else()
project(LibVNCServer VERSION 0.9.15 LANGUAGES ${PROJECT_LANGUAGES})
set(PACKAGE_NAME "LibVNCServer")
set(FULL_PACKAGE_NAME "LibVNCServer")
set(VERSION_SO "1")
set(PROJECT_BUGREPORT_PATH "https://github.com/LibVNC/libvncserver/issues")
set(LIBVNCSRVEXAMPLE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples/server)
set(LIBVNCCLIEXAMPLE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples/client)
set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(CMAKE_GENERATOR MATCHES "Unix Makefiles|Ninja")
# some LSP servers expect compile_commands.json in the project root
add_custom_target(
copy-compile-commands ALL
${CMAKE_COMMAND} -E copy_if_different
${CMAKE_BINARY_DIR}/compile_commands.json
${CMAKE_CURRENT_SOURCE_DIR}
)
endif(CMAKE_GENERATOR MATCHES "Unix Makefiles|Ninja")
include_directories(${LIBVNCSERVER_INCLUDES})
# all the build configuration switches
option(LIBVNCSERVER_INSTALL "Generate installation target" ON)
option(BUILD_SHARED_LIBS "Build shared libraries" ${UNIX})
option(WITH_ZLIB "Search for the zlib compression library to support additional encodings" ON)
option(WITH_LZO "Search for the LZO compression library to omit internal miniLZO implementation" ON)
option(WITH_JPEG "Search for the libjpeg compression library to support additional encodings" ON)
option(WITH_PNG "Search for the PNG compression library to support additional encodings" ON)
option(WITH_SDL "Search for the Simple Direct Media Layer library to build an example SDL vnc client" ON)
option(WITH_GTK "Search for the GTK library to build an example GTK vnc client" ON)
option(WITH_LIBSSHTUNNEL "Search for libsshtunnel to build an example ssh-tunneled client" ON)
option(WITH_THREADS "Search for a threading library to build with multithreading support" ON)
option(PREFER_WIN32THREADS "When searching for a threading library, prefer win32 threads if they are found" OFF)
option(WITH_GNUTLS "Search for the GnuTLS secure communications library to support TLS" ON)
option(WITH_OPENSSL "Search for the OpenSSL cryptography library to support TLS and use as crypto backend" ON)
option(WITH_SYSTEMD "Search for libsystemd to build with systemd socket activation support" ON)
option(WITH_GCRYPT "Search for Libgcrypt to use as crypto backend" ON)
option(WITH_FFMPEG "Search for FFMPEG to build an example VNC to MPEG encoder" ON)
option(WITH_TIGHTVNC_FILETRANSFER "Enable filetransfer if there is pthreads support" ON)
option(WITH_24BPP "Allow 24 bpp" ON)
option(WITH_IPv6 "Enable IPv6 Support" ON)
option(WITH_WEBSOCKETS "Build with websockets support" ON)
option(WITH_SASL "Build with SASL support" ON)
option(WITH_XCB "Build with XCB support" ON)
option(WITH_EXAMPLES "Build examples" ON)
option(WITH_TESTS "Build tests" ON)
option(WITH_QT "Build the Qt client example" ON)
if(WITH_ZLIB)
find_package(ZLIB)
endif(WITH_ZLIB)
if(WITH_LZO)
find_package(LZO)
endif()
if(WITH_XCB)
find_package(X11) # Need CMake 3.24.0 to find XCB libraries. see https://cmake.org/cmake/help/v3.24/module/FindX11.html
endif()
if(WITH_JPEG)
find_package(JPEG)
if(JPEG_FOUND)
# Check whether the version of libjpeg we found was libjpeg-turbo and print a
# warning if not.
set(CMAKE_REQUIRED_LIBRARIES ${JPEG_LIBRARIES})
if(JPEG_INCLUDE_DIRS) # this was not present in 3.4
set(CMAKE_REQUIRED_INCLUDES ${JPEG_INCLUDE_DIRS})
else()
set(CMAKE_REQUIRED_INCLUDES ${JPEG_INCLUDE_DIR})
endif()
set(JPEG_TEST_SOURCE "\n
#include <stdio.h>\n
#include <jpeglib.h>\n
int main(void) {\n
struct jpeg_compress_struct cinfo;\n
struct jpeg_error_mgr jerr;\n
cinfo.err=jpeg_std_error(&jerr);\n
jpeg_create_compress(&cinfo);\n
cinfo.input_components = 3;\n
jpeg_set_defaults(&cinfo);\n
cinfo.in_color_space = JCS_EXT_RGB;\n
jpeg_default_colorspace(&cinfo);\n
return 0;\n
}"
)
if(CMAKE_CROSSCOMPILING)
check_c_source_compiles("${JPEG_TEST_SOURCE}" FOUND_LIBJPEG_TURBO)
else()
check_c_source_runs("${JPEG_TEST_SOURCE}" FOUND_LIBJPEG_TURBO)
endif()
set(CMAKE_REQUIRED_LIBRARIES)
set(CMAKE_REQUIRED_INCLUDES)
set(CMAKE_REQUIRED_DEFINITIONS)
if(NOT FOUND_LIBJPEG_TURBO)
# last-resort grep check (when using LibVNCServer as a CMake subdir together with turbojpeg CMake subdir, the build check above fails since turbojpeg is not yet built when LibVNCServer is configured)
get_filename_component(JPEGLIB_H_PATH "${JPEG_INCLUDE_DIR}/jpeglib.h" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
message(STATUS "Runtime check for libjpeg-turbo failed, inspecting ${JPEGLIB_H_PATH}")
file(STRINGS ${JPEGLIB_H_PATH} FOUND_LIBJPEG_TURBO REGEX "JCS_EXT_RGB")
if(NOT FOUND_LIBJPEG_TURBO)
message(WARNING "*** The libjpeg library you are building against is not libjpeg-turbo. Performance will be reduced. You can obtain libjpeg-turbo from: https://sourceforge.net/projects/libjpeg-turbo/files/ ***")
else()
message(STATUS "Detected libjpeg-turbo via ${JPEGLIB_H_PATH}")
endif()
endif()
endif(JPEG_FOUND)
endif(WITH_JPEG)
if(WITH_PNG)
find_package(PNG)
endif(WITH_PNG)
if(WITH_SDL)
find_package(SDL2)
endif(WITH_SDL)
if(WITH_GTK)
find_package(GTK2)
endif(WITH_GTK)
if(WITH_QT)
find_package(Qt5 COMPONENTS Core Widgets QUIET)
endif(WITH_QT)
if(WITH_LIBSSHTUNNEL)
find_path(LIBSSHTUNNEL_INCLUDE_DIR libsshtunnel.h)
find_library(LIBSSHTUNNEL_LIBRARY sshtunnel)
if("${LIBSSHTUNNEL_LIBRARY}" MATCHES ".*NOTFOUND.*")
# would otherwise contain -NOTFOUND, confusing target_link_libraries()
set(LIBSSHTUNNEL_LIBRARY "")
endif()
endif(WITH_LIBSSHTUNNEL)
if(WITH_THREADS)
find_package(Threads)
endif(WITH_THREADS)
if(WITH_GNUTLS)
find_package(GnuTLS 3.4.0)
endif(WITH_GNUTLS)
if(WITH_OPENSSL)
find_package(OpenSSL)
endif(WITH_OPENSSL)
if(WITH_SYSTEMD AND NOT ANDROID AND NOT WIN32)
find_package(PkgConfig)
pkg_check_modules(SYSTEMD "libsystemd")
endif(WITH_SYSTEMD AND NOT ANDROID AND NOT WIN32)
if(WITH_GCRYPT)
find_library(LIBGCRYPT_LIBRARIES gcrypt)
endif(WITH_GCRYPT)
if(WITH_FFMPEG)
find_package(
FFMPEG 3.1.0
COMPONENTS avformat avcodec avutil swscale
)
endif(WITH_FFMPEG)
if(WITH_THREADS AND Threads_FOUND)
set(ADDITIONAL_LIBS
${ADDITIONAL_LIBS}
${CMAKE_THREAD_LIBS_INIT}
)
endif(WITH_THREADS AND Threads_FOUND)
if(ZLIB_FOUND)
set(LIBVNCSERVER_HAVE_LIBZ 1)
else()
unset(ZLIB_LIBRARIES) # would otherwise contain -NOTFOUND, confusing target_link_libraries()
endif(ZLIB_FOUND)
if(LZO_FOUND)
set(LIBVNCSERVER_HAVE_LZO 1)
else()
unset(LZO_LIBRARIES CACHE) # would otherwise contain -NOTFOUND, confusing target_link_libraries()
endif()
if(JPEG_FOUND)
set(LIBVNCSERVER_HAVE_LIBJPEG 1)
else()
unset(JPEG_LIBRARIES) # would otherwise confuse target_link_libraries()
endif(JPEG_FOUND)
if(PNG_FOUND)
set(LIBVNCSERVER_HAVE_LIBPNG 1)
else()
unset(PNG_LIBRARIES) # would otherwise contain -NOTFOUND, confusing target_link_libraries()
endif(PNG_FOUND)
if(NOT OPENSSL_FOUND)
unset(OPENSSL_LIBRARIES) # would otherwise contain -NOTFOUND, confusing target_link_libraries()
endif()
if(SYSTEMD_FOUND)
add_definitions(-DLIBVNCSERVER_WITH_SYSTEMD)
include_directories(${SYSTEMD_INCLUDE_DIRS})
set(ADDITIONAL_LIBS
${ADDITIONAL_LIBS}
${SYSTEMD_LIBRARIES}
)
endif(SYSTEMD_FOUND)
# common crypto used by both libvncserver and libvncclient
if(WITH_GCRYPT AND LIBGCRYPT_LIBRARIES)
message(STATUS "Building crypto with Libgcrypt")
set(CRYPTO_LIBRARIES ${LIBGCRYPT_LIBRARIES})
set(CRYPTO_SOURCES ${COMMON_DIR}/crypto_libgcrypt.c)
elseif(OPENSSL_FOUND)
message(STATUS "Building crypto with OpenSSL")
set(CRYPTO_LIBRARIES ${OPENSSL_LIBRARIES})
set(CRYPTO_SOURCES ${COMMON_DIR}/crypto_openssl.c)
else()
message(STATUS "Building crypto with builtin functions, only including SHA1 and D3DES")
set(CRYPTO_SOURCES
${COMMON_DIR}/crypto_included.c
${COMMON_DIR}/sha1.c
${COMMON_DIR}/d3des.c
)
endif()
if(WITH_WEBSOCKETS AND (LIBVNCSERVER_HAVE_HTOBE64 OR LIBVNCSERVER_HAVE_OSSWAPHOSTTOBIGINT64))
set(LIBVNCSERVER_WITH_WEBSOCKETS 1)
endif()
if(WITH_GCRYPT AND LIBGCRYPT_LIBRARIES)
set(LIBVNCSERVER_HAVE_LIBGCRYPT 1)
endif(WITH_GCRYPT AND LIBGCRYPT_LIBRARIES)
if(GNUTLS_FOUND)
set(LIBVNCSERVER_HAVE_GNUTLS 1)
endif(GNUTLS_FOUND)
if(OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
set(LIBVNCSERVER_HAVE_LIBSSL 1)
endif(OPENSSL_FOUND)
if(WITH_IPv6)
if(WIN32 AND LIBVNCSERVER_HAVE_WS2TCPIP_H AND LIBVNCSERVER_HAVE_VPRINTF)
set(LIBVNCSERVER_IPv6 1)
endif()
if(NOT WIN32)
set(LIBVNCSERVER_IPv6 1)
endif()
endif(WITH_IPv6)
if(WITH_24BPP)
set(LIBVNCSERVER_ALLOW24BPP 1)
endif()
# Make sure that only one threading system is used. This happens on MinGW.
if(WITH_THREADS)
if(CMAKE_USE_PTHREADS_INIT AND CMAKE_USE_WIN32_THREADS_INIT)
if(PREFER_WIN32THREADS)
unset(CMAKE_USE_PTHREADS_INIT)
else()
unset(CMAKE_USE_WIN32_THREADS_INIT)
endif(PREFER_WIN32THREADS)
endif(CMAKE_USE_PTHREADS_INIT AND CMAKE_USE_WIN32_THREADS_INIT)
if(CMAKE_USE_PTHREADS_INIT)
message(STATUS "Threads support is using pthreads")
set(LIBVNCSERVER_HAVE_LIBPTHREAD 1)
endif(CMAKE_USE_PTHREADS_INIT)
if(CMAKE_USE_WIN32_THREADS_INIT)
message(STATUS "Threads support is using win32 threads")
set(LIBVNCSERVER_HAVE_WIN32THREADS 1)
endif(CMAKE_USE_WIN32_THREADS_INIT)
endif(WITH_THREADS)
if(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
# socklen_t
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
endif(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
if(HAVE_ARPA_INET_H)
# in_addr_t
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "arpa/inet.h")
endif(HAVE_ARPA_INET_H)
if(NOT HAVE_LIBVNCSERVER_IN_ADDR_T)
set(LIBVNCSERVER_NEED_INADDR_T 1)
endif(NOT HAVE_LIBVNCSERVER_IN_ADDR_T)
TEST_BIG_ENDIAN(LIBVNCSERVER_WORDS_BIGENDIAN)
if(WITH_SASL)
find_path(SASL2_INCLUDE_DIR sasl/sasl.h)
find_library(LIBSASL2_LIBRARIES sasl2 libsasl.lib)
endif(WITH_SASL)
if(WITH_SASL AND LIBSASL2_LIBRARIES AND SASL2_INCLUDE_DIR)
message(STATUS "Building with SASL: ${LIBSASL2_LIBRARIES} and ${SASL2_INCLUDE_DIR}")
set(LIBVNCSERVER_HAVE_SASL 1)
set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${LIBSASL2_LIBRARIES})
include_directories(${SASL2_INCLUDE_DIR})
endif(WITH_SASL AND LIBSASL2_LIBRARIES AND SASL2_INCLUDE_DIR)
list(APPEND LIBVNCSERVER_SOURCES ${CRYPTO_SOURCES})
list(APPEND LIBVNCCLIENT_SOURCES
${COMMON_DIR}/ghpringbuf.c
${COMMON_DIR}/sockets.c
${CRYPTO_SOURCES}
)
if(JPEG_FOUND)
list(APPEND LIBVNCCLIENT_SOURCES ${COMMON_DIR}/turbojpeg.c)
endif()
TEST_BIG_ENDIAN(LIBVNCSERVER_WORDS_BIGENDIAN)
if(GNUTLS_FOUND)
message(STATUS "Building TLS with GnuTLS")
list(APPEND LIBVNCCLIENT_SOURCES ${LIBVNCCLIENT_DIR}/tls_gnutls.c)
list(APPEND LIBVNCSERVER_SOURCES ${LIBVNCSERVER_DIR}/rfbssl_gnutls.c)
include_directories(${GNUTLS_INCLUDE_DIR})
elseif(OPENSSL_FOUND)
message(STATUS "Building TLS with OpenSSL")
list(APPEND LIBVNCCLIENT_SOURCES ${LIBVNCCLIENT_DIR}/tls_openssl.c)
list(APPEND LIBVNCSERVER_SOURCES ${LIBVNCSERVER_DIR}/rfbssl_openssl.c)
include_directories(${OPENSSL_INCLUDE_DIR})
else()
message(STATUS "Building without TLS")
list(APPEND LIBVNCCLIENT_SOURCES ${LIBVNCCLIENT_DIR}/tls_none.c)
list(APPEND LIBVNCSERVER_SOURCES ${LIBVNCSERVER_DIR}/rfbssl_none.c)
endif()
if(LIBVNCSERVER_HAVE_SASL)
list(APPEND LIBVNCCLIENT_SOURCES ${LIBVNCCLIENT_DIR}/sasl.c)
endif()
if(ZLIB_FOUND)
add_definitions(-DLIBVNCSERVER_HAVE_LIBZ)
include_directories(${ZLIB_INCLUDE_DIR})
list(APPEND LIBVNCSERVER_SOURCES
${LIBVNCSERVER_DIR}/zlib.c
${LIBVNCSERVER_DIR}/zrle.c
${LIBVNCSERVER_DIR}/zrleoutstream.c
${LIBVNCSERVER_DIR}/zrlepalettehelper.c
)
endif(ZLIB_FOUND)
if(LZO_FOUND)
add_definitions(-DLIBVNCSERVER_HAVE_LZO)
include_directories(${LZO_INCLUDE_DIR})
else()
list(APPEND LIBVNCSERVER_SOURCES ${COMMON_DIR}/minilzo.c)
list(APPEND LIBVNCCLIENT_SOURCES ${COMMON_DIR}/minilzo.c)
endif()
if(JPEG_FOUND)
add_definitions(-DLIBVNCSERVER_HAVE_LIBJPEG)
include_directories(${JPEG_INCLUDE_DIR})
if(PNG_FOUND OR ZLIB_FOUND)
set(TIGHT_C ${LIBVNCSERVER_DIR}/tight.c ${COMMON_DIR}/turbojpeg.c)
endif(PNG_FOUND OR ZLIB_FOUND)
endif(JPEG_FOUND)
if(PNG_FOUND)
add_definitions(-DLIBVNCSERVER_HAVE_LIBPNG)
include_directories(${PNG_INCLUDE_DIR})
endif(PNG_FOUND)
list(APPEND LIBVNCSERVER_SOURCES ${TIGHT_C})
if(WITH_THREADS AND WITH_TIGHTVNC_FILETRANSFER AND CMAKE_USE_PTHREADS_INIT)
list(APPEND LIBVNCSERVER_SOURCES
${LIBVNCSERVER_DIR}/tightvnc-filetransfer/rfbtightserver.c
${LIBVNCSERVER_DIR}/tightvnc-filetransfer/handlefiletransferrequest.c
${LIBVNCSERVER_DIR}/tightvnc-filetransfer/filetransfermsg.c
${LIBVNCSERVER_DIR}/tightvnc-filetransfer/filelistinfo.c
)
endif(WITH_THREADS AND WITH_TIGHTVNC_FILETRANSFER AND CMAKE_USE_PTHREADS_INIT)
if(LIBVNCSERVER_WITH_WEBSOCKETS)
add_definitions(-DLIBVNCSERVER_WITH_WEBSOCKETS)
list(APPEND LIBVNCSERVER_SOURCES
${LIBVNCSERVER_DIR}/websockets.c
${LIBVNCSERVER_DIR}/ws_decode.c
${COMMON_DIR}/base64.c
)
endif(LIBVNCSERVER_WITH_WEBSOCKETS)
add_library(vncclient ${LIBVNCCLIENT_SOURCES})
add_library(vncserver ${LIBVNCSERVER_SOURCES})
if(WIN32)
set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ws2_32)
if(WITH_TIGHTVNC_FILETRANSFER)
add_definitions(-D_WIN32_WINNT=0x0600)
endif(WITH_TIGHTVNC_FILETRANSFER)
endif(WIN32)
target_link_libraries(vncclient
${ADDITIONAL_LIBS}
${ZLIB_LIBRARIES}
${LZO_LIBRARIES}
${JPEG_LIBRARIES}
${CRYPTO_LIBRARIES}
${GNUTLS_LIBRARIES}
${OPENSSL_LIBRARIES}
)
target_link_libraries(vncserver
${ADDITIONAL_LIBS}
${ZLIB_LIBRARIES}
${LZO_LIBRARIES}
${JPEG_LIBRARIES}
${PNG_LIBRARIES}
${CRYPTO_LIBRARIES}
${GNUTLS_LIBRARIES}
${OPENSSL_LIBRARIES}
)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/rfb/rfbconfig.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/include/rfb/rfbconfig.h)
SET_TARGET_PROPERTIES(vncclient vncserver
PROPERTIES SOVERSION "${VERSION_SO}" VERSION "${LibVNCServer_VERSION}" C_STANDARD 90
)
# EXAMPLES
set(LIBVNCSERVER_EXAMPLES
backchannel
camera
cursors
colourmaptest
example
fontsel
pnmshow
pnmshow24
regiontest
repeater
rotate
simple
simple15
storepasswd
vncev
multicast
)
if(WITH_THREADS AND (CMAKE_USE_PTHREADS_INIT OR CMAKE_USE_WIN32_THREADS_INIT))
list(APPEND LIBVNCSERVER_EXAMPLES blooptest)
endif(WITH_THREADS AND (CMAKE_USE_PTHREADS_INIT OR CMAKE_USE_WIN32_THREADS_INIT))
if(WITH_THREADS AND WITH_TIGHTVNC_FILETRANSFER AND CMAKE_USE_PTHREADS_INIT)
list(APPEND LIBVNCSERVER_EXAMPLES filetransfer)
endif(WITH_THREADS AND WITH_TIGHTVNC_FILETRANSFER AND CMAKE_USE_PTHREADS_INIT)
if(ANDROID)
list(APPEND LIBVNCSERVER_EXAMPLES androidvncserver)
endif(ANDROID)
if(X11_xcb_FOUND AND X11_xcb_xtest_FOUND AND X11_xcb_keysyms_FOUND)
list(APPEND LIBVNCSERVER_EXAMPLES x11)
else()
# clear NOTFOUND
unset(X11_xcb_LIB CACHE)
unset(X11_xcb_xtest_LIB CACHE)
unset(X11_xcb_keysyms_LIB CACHE)
endif(X11_xcb_FOUND AND X11_xcb_xtest_FOUND AND X11_xcb_keysyms_FOUND)
set(LIBVNCCLIENT_EXAMPLES
backchannel
ppmtest
)
if(SDL2_FOUND)
include_directories(${SDL2_INCLUDE_DIR})
list(APPEND LIBVNCCLIENT_EXAMPLES SDLvncviewer)
endif(SDL2_FOUND)
if(GTK2_FOUND)
include_directories(${GTK2_INCLUDE_DIRS})
list(APPEND LIBVNCCLIENT_EXAMPLES gtkvncviewer)
endif(GTK2_FOUND)
if(WITH_LIBSSHTUNNEL AND LIBSSHTUNNEL_LIBRARY AND LIBSSHTUNNEL_INCLUDE_DIR)
message(STATUS "Building with libsshtunnel: ${LIBSSHTUNNEL_LIBRARY} and ${LIBSSHTUNNEL_INCLUDE_DIR}")
include_directories(${LIBSSHTUNNEL_INCLUDE_DIR})
list(APPEND LIBVNCCLIENT_EXAMPLES sshtunnel)
endif()
if(FFMPEG_FOUND)
include_directories(${FFMPEG_INCLUDE_DIRS})
list(APPEND LIBVNCCLIENT_EXAMPLES vnc2mpg)
endif(FFMPEG_FOUND)
if(WITH_EXAMPLES)
foreach(e ${LIBVNCSERVER_EXAMPLES})
add_executable(examples_${e} ${LIBVNCSRVEXAMPLE_DIR}/${e}.c)
set_target_properties(examples_${e} PROPERTIES OUTPUT_NAME ${e})
set_target_properties(examples_${e} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/server)
target_link_libraries(examples_${e} vncserver ${CMAKE_THREAD_LIBS_INIT} ${X11_xcb_LIB} ${X11_xcb_xtest_LIB} ${X11_xcb_keysyms_LIB})
endforeach(e ${LIBVNCSERVER_EXAMPLES})
foreach(e ${LIBVNCCLIENT_EXAMPLES})
add_executable(client_examples_${e} ${LIBVNCCLIEXAMPLE_DIR}/${e}.c ${LIBVNCCLIEXAMPLE_DIR}/${${e}_EXTRA_SOURCES} )
set_target_properties(client_examples_${e} PROPERTIES OUTPUT_NAME ${e})
set_target_properties(client_examples_${e} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/client)
target_link_libraries(client_examples_${e} vncclient ${CMAKE_THREAD_LIBS_INIT} ${SDL2_LIBRARY} ${GTK2_LIBRARIES} ${FFMPEG_LIBRARIES} ${LIBSSHTUNNEL_LIBRARY})
endforeach(e ${LIBVNCCLIENT_EXAMPLES})
#This example must have its own building instructions,
#apart from the other examples because it is written in
#C++, so it has a distinct file extension and depends on
#a C++ compiler
if(Qt5Widgets_FOUND AND WITH_QT AND DEFINED CMAKE_CXX_COMPILER)
add_executable(client_examples_qt5client ${LIBVNCCLIEXAMPLE_DIR}/qt5client.cpp ${LIBVNCCLIEXAMPLE_DIR}/${qt5client_EXTRA_SOURCES})
set_target_properties(client_examples_qt5client PROPERTIES OUTPUT_NAME qt5client)
set_target_properties(client_examples_qt5client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/client)
target_link_libraries(client_examples_qt5client vncclient ${CMAKE_THREAD_LIBS_INIT} ${Qt5Widgets_LIBRARIES})
endif(Qt5Widgets_FOUND AND WITH_QT AND DEFINED CMAKE_CXX_COMPILER)
endif(WITH_EXAMPLES)
#
# them tests
#
if(WITH_TESTS)
# First fuzzing
if(DEFINED ENV{LIB_FUZZING_ENGINE})
add_executable(fuzz_server ${TESTS_DIR}/fuzz_server.c)
target_link_libraries(fuzz_server vncserver ${CMAKE_THREAD_LIBS_INIT} $ENV{LIB_FUZZING_ENGINE})
endif()
if(UNIX)
set(ADDITIONAL_TEST_LIBS m)
endif(UNIX)
set(SIMPLETESTS
cargstest
copyrecttest
)
if(WITH_THREADS AND (CMAKE_USE_PTHREADS_INIT OR CMAKE_USE_WIN32_THREADS_INIT))
set(SIMPLETESTS
${SIMPLETESTS}
encodingstest
)
endif(WITH_THREADS AND (CMAKE_USE_PTHREADS_INIT OR CMAKE_USE_WIN32_THREADS_INIT))
foreach(t ${SIMPLETESTS})
add_executable(test_${t} ${TESTS_DIR}/${t}.c)
set_target_properties(test_${t} PROPERTIES OUTPUT_NAME ${t})
set_target_properties(test_${t} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test)
target_link_libraries(test_${t} vncserver vncclient ${ADDITIONAL_TEST_LIBS})
endforeach(t ${SIMPLETESTS})
if(WITH_JPEG AND FOUND_LIBJPEG_TURBO)
add_executable(test_tjunittest
${TESTS_DIR}/tjunittest.c
${TESTS_DIR}/tjutil.c
${TESTS_DIR}/tjutil.h
${COMMON_DIR}/turbojpeg.c
${COMMON_DIR}/turbojpeg.h
)
set_target_properties(test_tjunittest PROPERTIES OUTPUT_NAME tjunittest)
set_target_properties(test_tjunittest PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test)
target_link_libraries(test_tjunittest vncserver vncclient ${ADDITIONAL_TEST_LIBS})
add_executable(test_tjbench
${TESTS_DIR}/tjbench.c
${TESTS_DIR}/tjutil.c
${TESTS_DIR}/tjutil.h
${TESTS_DIR}/bmp.c
${TESTS_DIR}/bmp.h
${COMMON_DIR}/turbojpeg.c
${COMMON_DIR}/turbojpeg.h
)
set_target_properties(test_tjbench PROPERTIES OUTPUT_NAME tjbench)
set_target_properties(test_tjbench PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test)
target_link_libraries(test_tjbench vncserver vncclient ${ADDITIONAL_TEST_LIBS})
endif(WITH_JPEG AND FOUND_LIBJPEG_TURBO)
if(LIBVNCSERVER_WITH_WEBSOCKETS)
add_executable(test_wstest
${TESTS_DIR}/wstest.c
${TESTS_DIR}/wstestdata.inc
)
set_target_properties(test_wstest PROPERTIES OUTPUT_NAME wstest)
set_target_properties(test_wstest PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test)
target_link_libraries(test_wstest vncserver vncclient ${ADDITIONAL_TEST_LIBS})
endif(LIBVNCSERVER_WITH_WEBSOCKETS)
add_test(NAME cargs COMMAND test_cargstest)
if(UNIX)
add_test(NAME includetest COMMAND ${TESTS_DIR}/includetest.sh ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR} ${CMAKE_MAKE_PROGRAM})
endif(UNIX)
if(WITH_JPEG AND FOUND_LIBJPEG_TURBO)
add_test(NAME turbojpeg COMMAND test_tjunittest)
endif(WITH_JPEG AND FOUND_LIBJPEG_TURBO)
if(LIBVNCSERVER_WITH_WEBSOCKETS)
add_test(NAME wstest COMMAND test_wstest)
endif(LIBVNCSERVER_WITH_WEBSOCKETS)
endif(WITH_TESTS)
#
# this gets the libraries needed by TARGET in "-libx -liby ..." form
#
function(get_link_libraries OUT TARGET)
set(RESULT "")
get_target_property(LIBRARIES ${TARGET} INTERFACE_LINK_LIBRARIES)
foreach(LIB ${LIBRARIES})
if("${LIB}" MATCHES ".*NOTFOUND.*")
continue()
endif()
string(REGEX REPLACE "^.*/lib" "" LIB ${LIB}) # remove leading path and "lib" name prefix
string(REGEX REPLACE "-l" "" LIB ${LIB}) # remove leading -l
string(REGEX REPLACE "\\.so$" "" LIB ${LIB}) # remove trailing .so
list(APPEND RESULT "-l${LIB}")
endforeach()
list(REMOVE_DUPLICATES RESULT)
string(CONCAT RESULT ${RESULT}) # back to string
if(RESULT)
string(REPLACE "-l" " -l" RESULT ${RESULT}) # re-add separators
endif(RESULT)
set(${OUT} ${RESULT} PARENT_SCOPE)
endfunction()
get_link_libraries(PRIVATE_LIBS vncserver)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/libvncserver/libvncserver.pc.cmakein ${CMAKE_CURRENT_BINARY_DIR}/libvncserver.pc @ONLY)
get_link_libraries(PRIVATE_LIBS vncclient)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/libvncclient/libvncclient.pc.cmakein ${CMAKE_CURRENT_BINARY_DIR}/libvncclient.pc @ONLY)
if(LIBVNCSERVER_INSTALL)
set(INSTALL_HEADER_FILES
include/rfb/keysym.h
include/rfb/threading.h
include/rfb/rfb.h
include/rfb/rfbclient.h
${CMAKE_CURRENT_BINARY_DIR}/include/rfb/rfbconfig.h
include/rfb/rfbproto.h
include/rfb/rfbregion.h
)
set_property(TARGET vncclient PROPERTY PUBLIC_HEADER ${INSTALL_HEADER_FILES})
set_property(TARGET vncserver PROPERTY PUBLIC_HEADER ${INSTALL_HEADER_FILES})
if(WIN32)
INSTALL(TARGETS vncclient vncserver
EXPORT LibVNCServerTargets
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_BINDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rfb
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
else()
INSTALL(TARGETS vncclient vncserver
EXPORT LibVNCServerTargets
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rfb
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
endif()
# Install cmake configure files
install(EXPORT LibVNCServerTargets
NAMESPACE "LibVNCServer::"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/LibVNCServer"
)
include(CMakePackageConfigHelpers)
configure_package_config_file(
${PROJECT_SOURCE_DIR}/cmake/Modules/LibVNCServerConfig.cmake.in
${CMAKE_BINARY_DIR}/LibVNCServerConfig.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/LibVNCServer"
)
# Install cmake version configure file
write_basic_package_version_file(
"${CMAKE_BINARY_DIR}/LibVNCServerConfigVersion.cmake"
VERSION ${PARA_VERSION}
COMPATIBILITY AnyNewerVersion
)
install(FILES
"${CMAKE_BINARY_DIR}/LibVNCServerConfigVersion.cmake"
"${CMAKE_BINARY_DIR}/LibVNCServerConfig.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/LibVNCServer"
)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/libvncserver.pc
${CMAKE_CURRENT_BINARY_DIR}/libvncclient.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
endif() That would allow it to compile as it did originally and also hanmdle the ESP32 ends of things. |
This is not correct. In later version of the RFB protocol it can be set so it's push based. the client would not send any requests for a frame buffer update. The server would push the changes when the changes occur. This is an optional feature to use. When working with a GUI framework like I am it is optimal to keep the amount of data that is being sent to as minimal as possible so having the server only push data when changes have occurred is the most ideal thing to do.
Because we are dealing with memory constrained devices the need to create a full sized display buffer on the MCU in a lot of cases is not possible. This is where the server pushing the sections that have updated comes into play. There is no actual display sized frame buffer in these cases. There is only a partial and that partial is typically 1/10th the size of a display sized frame buffer. the graphics framework is able to track where objects would reside on a full sized frame buffer so it known the bounding rect for areas that need updating and to stay within the memory constraimnts of the MCU only the areas that need updating are what actually get rendered to the partial frame buffer. If there are multiple areas that need to be rendered then it renders one area and calls a flush callback so that area is able to be sent to the display or in this case it would be passed to the RFB server to be transferred over the network connection to the client. When the flush function returns the buffer gets filled with the next area to be sent. This process gets a wee bit more complex because of some MCU's having direct memory access for it's peripherals. What that means is a buffer can be sent without blocking.. It gets sent without used the processor at all. To make use of this feature you would have 2 partial sized frame buffers so while one is sending the other can be rendered to. Now there are mechanics in place that keep things in sync and this involves a callback function that gets passed to the DMA controller so a notification can be passed when the DMA transfer has finished. in that callback is where the GUI framework is told that it can pass the just rendered buffer to the flush function. if it is not told it can do that the whole program stalls. This is where things get a bit hard to deal with because on order to attach that callback for the buffer transfer being finished it has to be done at the same time the buffer gets passed to be written. This is something that is handled internally in libvncserver. The encoding of the packet gets done and then it makes the call to send the data. If the encoding portions of the code were publicly exposed then we could simply encode the packet and then I could take care of calling the function to send the data and passing the callback at the same time. Right now the encoding portions of the server are not publicly exposed and that is something that would improve the performance by a very large amount if it was. For the time being I just want to see if I can get it up and running even if it's done at a lower speed. If I can then we can discuss making the packet encoding public. It also appears that by default the library wants to create it's own frame buffer that is the size of the display. |
Question for ya. Would you entertain the idea of separating the socket code from the server code? I ask this because I have some people that are interested in running RFB over a serial blueteeth connection. The RFB protocol specification doesn't lock the use of the protocol to any one kind of connection type. so long as data is able to be sent and received then the protocol should work over that connection. Right now the library is locked to using a socket connection and I believe that separating the socket code from both the client and server code would align more with the specification. I am not saying to remove the socket code, just to move it so it is not a requirement to use it. function pointers to callback functions for sending and receiving can be used by the server and client code this way all that has to be done is assigning functions to those pointers so the server and client code would be able to call them. Probably would need some kind of an initialization function pointer as well. |
Hey I wanted to also let you know that if you want I can write a CPython binding to your library. It would automatically generate the Python code form the header files and it would also compile the library for Linux, macOS and Windows. Then people could use it with their favorite Python GUI framework. This would allow them to provide a way to remotely connect to a specific application that they have written... by using the HTTPd code in your library it could be used as a way for the user to make their application available on the web without the need to port their application code. That could be a really useful thing to be able to do. I know that porting an application for the sole purpose of it being accessible on the web is a royal pain in the ass to do. |
Please do a PR for each change you want to bring in - that makes collaboration and review way easier :-) |
Would be open for it. This was raised before #432 and handled partially #477 #234. I have to be honest in that I lack the time-for-review and testing capacity for big changes touching the fundamentals - a focused PR that only changes one thing is way easier to review and more likely to get in. |
That sounds like a good fit for an external project that I'd happily link from the main README. |
This is why you see a branch made for each fix that is being made. They will all be made as separate PR's |
Is your feature request related to a problem? Please describe.
No
Describe the solution you'd like
I have been working with micro controllers that have attached touch screen displays and writing a binding for a GUI framework to MicroPython. One of the things I am striving to provide to the users is fast prototyping. Currently a user is able to write Python code and it will run on a micro controller for creating a GUI to be shown on an attached display. The binding is also able to be compiled to run on macOS and also Linux and this allows a user to be able to develop without needing to use an MCU with an attached display. While the ability to test a GUI on a PC does make things easier it has a downside, no hardware related bits are available. So NO GPIO access and things like that. This would make sense seeing as how the binding is running on a PC and not on the actual MCU.
What I am wanting to do is allow the user to be able to develop without the need to have a display attached to the MCU. Using the RFB protocol would be the best solution because just about every OS available has some form of VNC client software available. Ideally I would like to make thing easier by using an already existing library. The only hangup I am having is all the libraries I have come across handle to actual receiving and transmitting of the data. This is something that I would not use because the MCU I am using doesn't have the same API for networking as Linux et al. has. The library would be used to handle the reading of the incoming data and formatting the outgoing data but the actual sending and receiving would be done using code that I would write. This could be done easily if there are functions that would handle the reading of the data and creating the packets needed for sending.
The MCU I am working with uses an Xtensa 32-bit LX7 processor with 2 cores @ 240mhz. Depending on how it's configured it can have 2mb-8mb of RAM and 4mb-32mb of flash based program storage.
The first thing to hurdle is getting the library to compile using a gcc like compiler that is made for these specific MCU's. I don't know enough about CMAKE to know if adding it to my projects CMAKE build will carry over using a specific compiler and also how to set option flags that would normally be done by passing them in the build command.
The processor that I am using is dual core and I have the ability to set specific code to run on specific cores. I see that this library supports pthread but unfortunately this is not available. FreeRTOS is what is used to handle "threads". while the functionality of how the threading works is pretty close to pthread the API is completely different. I did come across a library that is a wrapper around FreeRTOS to provide a pthread API. I have not tested this to see if it will work. I am pretty sure there is going to be things that I will need to modify to get it to run on the MCU I am using. If there were macros that could be changed by the user to point to a different function for thing like creating a mutex and creating a thread this would make you library very flexible.
Describe alternatives you've considered
I have looked at quite a few different VNC server libraries as a possible solution. Your library is the most complete in terms of much of the RFB protocol API is supported and the way it is written also would make it easier to make alterations that would allow it to be run on a micro controller.
Additional context
Now that I am thinking about it providing macros to handle using encryption libraries other than the ones directly supported by the library would be of added benefit as a lot of MCUs have hardware accelerators for doing the encrypting and decrypting.
The text was updated successfully, but these errors were encountered: