├── .github └── workflows │ ├── sonarcloud-build.yml │ └── test-build.yml ├── AUTHORS ├── CMakeLists.txt ├── LICENSE ├── README.md ├── README_ru.md ├── doc ├── astylerc └── ltsm_channels.txt ├── etc ├── dbus-1 │ ├── ltsm.manager.service.conf │ ├── ltsm.session.audio.conf │ ├── ltsm.session.audio.service │ ├── ltsm.session.fuse.conf │ ├── ltsm.session.fuse.service │ ├── ltsm.session.pcsc.conf │ ├── ltsm.session.pcsc.service │ ├── org.freedesktop.Notifications.conf │ └── org.freedesktop.Notifications.service ├── logrotate.d │ └── ltsm ├── ltsm │ ├── config.json │ ├── keymap_rdp.json │ ├── keymap_vnc.json │ └── xclients ├── pam │ ├── ltsm │ └── xserver ├── rsyslog │ └── ltsm.conf ├── systemd │ ├── ltsm_connector_rdp.socket │ ├── ltsm_connector_rdp@.service │ ├── ltsm_connector_vnc.socket │ ├── ltsm_connector_vnc@.service │ └── ltsm_service.service ├── xinet │ ├── jetdirect │ └── ltsm_connector └── xorg │ └── ltsm.conf ├── sonar-project.properties └── src ├── channels ├── channel_system.cpp ├── channel_system.h └── ltsm_channels.h ├── common ├── CMakeLists.txt ├── flat_hash_map │ ├── flat_hash_map.hpp │ └── unordered_map.hpp ├── jsmn │ └── jsmn.h ├── libxcb-errors │ ├── errors.h │ ├── extensions.c │ ├── xcb_errors.c │ └── xcb_errors.h ├── ltsm_application.cpp ├── ltsm_application.h ├── ltsm_font_psf.h ├── ltsm_framebuffer.cpp ├── ltsm_framebuffer.h ├── ltsm_global.h ├── ltsm_gsslayer.cpp ├── ltsm_gsslayer.h ├── ltsm_json_wrapper.cpp ├── ltsm_json_wrapper.h ├── ltsm_sockets.cpp ├── ltsm_sockets.h ├── ltsm_streambuf.cpp ├── ltsm_streambuf.h ├── ltsm_tools.cpp ├── ltsm_tools.h ├── ltsm_xcb_types.cpp ├── ltsm_xcb_types.h ├── ltsm_xcb_wrapper.cpp ├── ltsm_xcb_wrapper.h └── mingw │ └── gnutls │ └── gnutlsxx.h ├── connector ├── COPYING.AGPLv3 ├── ltsm_connector.cpp ├── ltsm_connector.h ├── ltsm_connector_rdp.cpp ├── ltsm_connector_rdp.h ├── ltsm_connector_vnc.cpp └── ltsm_connector_vnc.h ├── cups_backend └── main.cpp ├── dbus ├── ltsm_audio.xml ├── ltsm_fuse.xml ├── ltsm_pcsc.xml └── ltsm_service.xml ├── librfb ├── COPYING.AGPLv3 ├── ffmpeg_tools.cpp ├── ffmpeg_tools.h ├── librfb_client.cpp ├── librfb_client.h ├── librfb_decodings.cpp ├── librfb_decodings.h ├── librfb_encodings.cpp ├── librfb_encodings.h ├── librfb_extclip.cpp ├── librfb_extclip.h ├── librfb_ffmpeg.cpp ├── librfb_ffmpeg.h ├── librfb_server.cpp ├── librfb_server.h ├── librfb_winclient.cpp ├── librfb_winclient.h ├── librfb_x11client.cpp ├── librfb_x11client.h ├── librfb_x11server.cpp ├── librfb_x11server.h ├── ltsm_librfb.cpp └── ltsm_librfb.h ├── qt_helper ├── ltsm_helper.qrc ├── ltsm_helper_ru.qm ├── ltsm_helper_ru.ts ├── ltsm_helperwindow.cpp ├── ltsm_helperwindow.h ├── ltsm_helperwindow.ui ├── ltsm_ldap_wrapper.cpp ├── ltsm_ldap_wrapper.h ├── ltsm_logo.png └── main.cpp ├── qt_sessions ├── ltsm_offline.png ├── ltsm_online.png ├── ltsm_sessions.cpp ├── ltsm_sessions.h ├── ltsm_sessions.qrc ├── ltsm_sessions.ui ├── ltsm_sessions_ru.qm ├── ltsm_sessions_ru.ts └── main.cpp ├── sane_backend ├── unix.c ├── unix.conf.in └── unix.h ├── sdl2x11 ├── ltsm_sdl2x11.cpp ├── ltsm_sdl_wrapper.cpp └── ltsm_sdl_wrapper.h ├── service ├── ltsm_service.cpp └── ltsm_service.h ├── session_audio ├── ltsm_audio.h ├── ltsm_audio_client.cpp ├── ltsm_audio_decoder.cpp ├── ltsm_audio_decoder.h ├── ltsm_audio_encoder.cpp ├── ltsm_audio_encoder.h ├── ltsm_audio_openal.cpp ├── ltsm_audio_openal.h ├── ltsm_audio_pulse.cpp ├── ltsm_audio_pulse.h ├── ltsm_audio_session.cpp └── ltsm_audio_session.h ├── session_fuse ├── ltsm_fuse.h ├── ltsm_fuse_client.cpp ├── ltsm_fuse_session.cpp └── ltsm_fuse_session.h ├── session_pcsc ├── ltsm_pcsc.h ├── ltsm_pcsc_client.cpp ├── ltsm_pcsc_session.cpp └── ltsm_pcsc_session.h ├── session_pkcs11 ├── ltsm_pkcs11.h ├── ltsm_pkcs11_client.cpp ├── ltsm_pkcs11_session.cpp ├── ltsm_pkcs11_session.h ├── ltsm_pkcs11_wrapper.cpp └── ltsm_pkcs11_wrapper.h ├── tests ├── CMakeLists.txt ├── encodings │ ├── images │ │ ├── 001.png │ │ ├── 002.png │ │ ├── 003.png │ │ └── 004.png │ ├── librfb_server2.cpp │ ├── librfb_server2.h │ └── main.cpp ├── framebuf │ └── main.cpp ├── json │ ├── main.cpp │ └── test.json ├── streambuf │ └── main.cpp ├── unixsocket │ └── main.cpp ├── x11clip │ └── main.cpp ├── x11enc │ └── main.cpp ├── xcb │ └── main.cpp └── xrandr │ └── main.cpp ├── vnc2image ├── ltsm_vnc2image.cpp └── ltsm_vnc2image.h ├── vnc2sdl ├── ltsm_vnc2sdl.cpp └── ltsm_vnc2sdl.h └── x11vnc ├── ltsm_connector_x11vnc.cpp ├── ltsm_connector_x11vnc.h ├── ltsm_x11vnc.cpp └── ltsm_x11vnc.h /.github/workflows/test-build.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 11 | BUILD_TYPE: Release 12 | 13 | jobs: 14 | build: 15 | # The CMake configure and build commands are platform agnostic and should work equally 16 | # well on Windows or Mac. You can convert this to a matrix build if you need 17 | # cross-platform coverage. 18 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | 24 | - name: Update packages 25 | run: | 26 | sudo apt update 27 | sudo apt -y upgrade 28 | 29 | - name: Install dependencies 30 | run: | 31 | sudo apt install -y cmake wget g++ git libexpat1 libpam0g-dev \ 32 | libsdbus-c++-dev gnutls-dev freerdp2-dev libxcb1-dev libxcb-xtest0-dev libxcb-xfixes0-dev \ 33 | libxcb-shm0-dev libxcb-randr0-dev libxcb-damage0-dev libxcb-keysyms1-dev libsdl2-image-dev qtbase5-dev \ 34 | libxcb-xkb-dev libxkbcommon-x11-dev \ 35 | libsdl2-image-dev qtbase5-dev libsdbus-c++-bin libsdbus-c++-dev \ 36 | libldap-dev libcups2-dev libfuse3-dev libsystemd-dev libopus-dev libpcsclite-dev libp11-kit-dev \ 37 | liblz4-dev libturbojpeg-dev libxkbfile-dev libopenal-dev \ 38 | libavdevice-dev libavformat-dev libavcodec-dev libswscale-dev libswresample-dev libavutil-dev 39 | 40 | - name: Configure CMake 41 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. 42 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type 43 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ 44 | -DLTSM_BUILD_SERVER=on \ 45 | -DLTSM_BUILD_CLIENT=on \ 46 | -DLTSM_FFMPEG=on \ 47 | -DLTSM_WITH_RDP=on \ 48 | -DLTSM_FUSE2SESSION=on \ 49 | -DLTSM_AUDIO2SESSION=on \ 50 | -DLTSM_PCSC2SESSION=on \ 51 | -DLTSM_PKCS11_AUTH=on \ 52 | -DLTSM_BUILD_X11VNC=on -DLTSM_BUILD_VNC2IMAGE=on \ 53 | -DLTSM_CUPS_BACKEND=on 54 | 55 | - name: Build 56 | # Build your program with the given configuration 57 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} 58 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | LTSM owner and contributor 2 | Andrey Afletdinov (https://github.com/AndreyBarmaley) 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # linux-terminal-service-manager 2 | Linux Terminal Service Manager (LTSM) is a set of service programs that allows remote computers to connect to a Linux operating system computer using a remote terminal session (over VNC or RDP) 3 | 4 | # Linux Only! 5 | main dependencies: 6 | - systemd, sd-bus 7 | - [sdbus-cpp](https://github.com/Kistler-Group/sdbus-cpp) 8 | - [json parser](https://github.com/zserge/jsmn) 9 | - [freerdp](https://github.com/FreeRDP/FreeRDP) 10 | - system libs: gnutls, xcb, zlib 11 | 12 | ## Developer indicators 13 | [![Build Status](https://github.com/AndreyBarmaley/linux-terminal-service-manager/actions/workflows/cmake.yml/badge.svg)](https://github.com/AndreyBarmaley/linux-terminal-service-manager/actions) 14 | [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=AndreyBarmaley_linux-terminal-service-manager&metric=bugs)](https://sonarcloud.io/summary/new_code?id=AndreyBarmaley_linux-terminal-service-manager) 15 | [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=AndreyBarmaley_linux-terminal-service-manager&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=AndreyBarmaley_linux-terminal-service-manager) 16 | [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=AndreyBarmaley_linux-terminal-service-manager&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=AndreyBarmaley_linux-terminal-service-manager) 17 | [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=AndreyBarmaley_linux-terminal-service-manager&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=AndreyBarmaley_linux-terminal-service-manager) 18 | [![OpenHub Rating](https://openhub.net/p/linux-terminal-service-manager/widgets/project_thin_badge?format=gif)](https://openhub.net/p/linux-terminal-service-manager) 19 | 20 | # Demo access 21 | ``` 22 | --- vnc 23 | vncviewer 62.109.12.152 24 | --- rdp 25 | xfreerdp /v:62.109.12.152 26 | 27 | logins: demo1, demo2, demo3, demo4 28 | pass: demo 29 | ``` 30 | 31 | # Docker demonstration 32 | ``` 33 | docker pull docker.io/ltsm/devel 34 | docker run -i -t docker.io/ltsm/devel 35 | ``` 36 | 37 | # The scheme of interaction of components 38 | ![ltsm_diagram](https://user-images.githubusercontent.com/8620726/118247282-884e7480-b492-11eb-92a8-d8db95656eee.png) 39 | The following components are implemented: 40 | 41 | # LTSM_service 42 | The main service, dbus owner *ltsm.service.manager*, receives commands from LTSM_connector, and starts login and users sessions based on Xvfb (GPLv3 license) 43 | see also: [wiki: LTSM service](https://github.com/AndreyBarmaley/linux-terminal-service-manager/wiki/LTSM-service) 44 | 45 | # LTSM_connector 46 | It is just a graphics protocol handler, and the main network part is handled by the service xinetd/(systemd sockets), and it is also a dbus client *ltsm.manager.service*, it connects to Xvfb via the shared memory mechanism (Affero GPLv3 license) 47 | see also: [wiki: LTSM connector](https://github.com/AndreyBarmaley/linux-terminal-service-manager/wiki/LTSM-connector) 48 | 49 | # LTSM_helper 50 | ![ltsm_helper](https://user-images.githubusercontent.com/8620726/123924335-66914a00-d979-11eb-9025-9d6bcf3fa250.png) 51 | ![ltsm_helper_token](https://user-images.githubusercontent.com/8620726/202207854-c9c01fa6-4654-416e-a11e-c8b8772a3905.png) 52 | GUI login utility, and it is a dbus client *ltsm.manager.service* (GPLv3 license) 53 | see also: [wiki: LTSM config](https://github.com/AndreyBarmaley/linux-terminal-service-manager/wiki/LTSM-config-(full-description)) 54 | 55 | # LTSM_sessions 56 | ![ltsm_session](https://user-images.githubusercontent.com/8620726/119793454-23e5d900-bec6-11eb-9978-ee31f44360ae.png) 57 | GUI users sessions management utility, and it is a dbus client *ltsm.manager.service* (GPLv3 license) 58 | ![ltsm_show_session](https://user-images.githubusercontent.com/8620726/123924343-67c27700-d979-11eb-9802-723d043f9f6f.png) 59 | see also: [wiki: LTSM administrator](https://github.com/AndreyBarmaley/linux-terminal-service-manager/wiki/LTSM-administrator) 60 | 61 | # LTSM_vnc2sdl 62 | This is an experimental graphical client that implements the mechanism of multiple data channels, up to a maximum of 253. 63 | 64 | **Main improvements implemented:** 65 | * Works utf8 clipboard in both directions (problem for most VNC clients) 66 | * Automatic keyboard layout, client-side layout always takes precedence (nothing needs to be configured on the server-side) 67 | * File transfer via drag & drop (client side to remote virtual session) 68 | * Implemented file printing (using an additional [backend for CUPS](https://github.com/AndreyBarmaley/linux-terminal-service-manager/tree/main/src/cups_backend)) 69 | * Implemented audio redirect via **PulseAudio** 70 | * Implemented smartcard redirect via **PCSC** 71 | * Implemented scanning redirect (using an additional [backend for SANE](https://github.com/AndreyBarmaley/linux-terminal-service-manager/tree/main/src/sane_backend)) 72 | * Directory redirection via **FUSE** has been implemented (so far only in read only mode) 73 | * Implemented authentication to a virtual session via **PKCS11** with certificate storage in **LDAP** 74 | * Implemented SSO authentication via **GSSAPI** (kerberos5) 75 | * Implemented **x264** encoding/decoding via **ffmpeg** 76 | 77 | The mechanism of pipes is implemented through the abstract schemes ```unix://, file://, socket://```, and the access mode ```ReadOnly, WriteOnly, ReadWrite```. 78 | For example, for a normal file transfer, a typical channel is created (client-server): ```file:///src_file1 (ReadOnly)``` and ```file:///dst_file2 (WriteOnly)```, then in the user session, informational GUI dialogs are launched about the transfer and selection of the destination folder, after which the file automatically saved in the remote session. 79 | Also, using this mechanism, it is possible to transfer any data stream in both directions, but the initiator of creating a channel is always the server. 80 | 81 | So printing from the server side (in a remote user session) is implemented in this way - on the server, cups adds its own backend to configure the printer, which knows which unix socket to print in the user session, from the client side, the stream can be sent to the ```socket://``` network printer ```127.0.0.1:9100```, also to local cups or ```file:///dev/usb/lp0```. In this scheme, the system administrator configures the printer only once per server. The audio redirect, scanning and pcscd redirect works according to a similar scheme. 82 | 83 | You can test all implemented features in the **docker** version. 84 | 85 | **ROADMAP** 86 | * add video recordings of all working sessions (video recording) 87 | * add [**VirtualGL**](https://virtualgl.org) support 88 | * add a video redirect via **PipeWire** 89 | * work with graphics accelerated via **Cuda GPU** (there are no technical capabilities yet) 90 | * build client for MacOs/Windows 91 | -------------------------------------------------------------------------------- /README_ru.md: -------------------------------------------------------------------------------- 1 | # linux-terminal-service-manager 2 | Linux Terminal Service Manager (LTSM) это набор программ для организации доступа к рабочему столу (сервер Linux) на основе терминальных сессий (с использованием протокола VNC или RDP) 3 | 4 | # Основные зависимости: 5 | - systemd, sd-bus 6 | - [sdbus-cpp](https://github.com/Kistler-Group/sdbus-cpp) 7 | - [json parser](https://github.com/zserge/jsmn) 8 | - [freerdp](https://github.com/FreeRDP/FreeRDP) 9 | - system libs: gnutls, xcb, zlib 10 | 11 | # Демо доступ 12 | ``` 13 | vncviewer 62.109.12.152 14 | logins: demo1, demo2, demo3, demo4 15 | pass: demo 16 | ``` 17 | 18 | # Docker демонстрация 19 | ``` 20 | docker pull docker.io/ltsm/devel 21 | docker run -i -t docker.io/ltsm/devel 22 | ``` 23 | 24 | # Схема взаимодействия компонентов 25 | ![ltsm_diagram](https://user-images.githubusercontent.com/8620726/118247282-884e7480-b492-11eb-92a8-d8db95656eee.png) 26 | реализованы следующие компоненты: 27 | 28 | # LTSM_service 29 | основная служба, менеджер dbus ltsm.service.manager, получает команды от LTSM_connector, запускает login и users сессии на базе Xvfb (Лицензия GPLv3) 30 | см дополнительно: [wiki: LTSM service](https://github.com/AndreyBarmaley/linux-terminal-service-manager/wiki/LTSM-service) 31 | 32 | # LTSM_connector 33 | является только обработчиком сетевого протокола VNC и RDP, а основной сетевой частью занимается служебный xinetd/(systemd sockets), также он является клиентом dbus ltsm.manager.service, подключается к Xvfb через механизм shared memory (Лицензия на коннектор Affero GPLv3) 34 | см дополнительно: [wiki: LTSM connector](https://github.com/AndreyBarmaley/linux-terminal-service-manager/wiki/LTSM-connector) 35 | 36 | # LTSM_helper 37 | ![ltsm_helper](https://user-images.githubusercontent.com/8620726/123924335-66914a00-d979-11eb-9025-9d6bcf3fa250.png) 38 | ![ltsm_helper_token](https://user-images.githubusercontent.com/8620726/202207854-c9c01fa6-4654-416e-a11e-c8b8772a3905.png) 39 | графическая утилита входа в систему, является клиентом dbus ltsm.manager.service (Лицензия GPLv3) 40 | см дополнительно: [wiki: LTSM config](https://github.com/AndreyBarmaley/linux-terminal-service-manager/wiki/LTSM-config-(full-description)) 41 | 42 | # LTSM_sessions 43 | ![ltsm_session](https://user-images.githubusercontent.com/8620726/119793454-23e5d900-bec6-11eb-9978-ee31f44360ae.png) 44 | графическая утилита управления сессиями пользователей, является клиентом dbus ltsm.manager.service (Лицензия GPLv3) 45 | см дополнительно: [wiki: LTSM administrator](https://github.com/AndreyBarmaley/linux-terminal-service-manager/wiki/LTSM-administrator) 46 | 47 | # LTSM_vnc2sdl 48 | Это экспериментальный графический клиент, в котором реализован механизм множественных каналов данных, максимально до 253. 49 | 50 | **Основные реализованные улучшения:** 51 | * Работает буфер обмена **utf8** в обе стороны (проблема для большинства клиентов VNC) 52 | * шифрование трафика через gnutls 53 | * Автоматическая раскладка клавиатуры, в приоритете всегда раскладка со стороны клиента (на стороне сервера ничего не нужно настраивать) 54 | * Передача файлов через **drag & drop** (со стороны клиента на удаленную виртуальную сессию) 55 | * Реализована печать файлов (с помощью дополнительного [backend для CUPS](https://github.com/AndreyBarmaley/linux-terminal-service-manager/tree/main/src/cups_backend)) 56 | * Реализован редирект звука через **PulseAudio** 57 | * Реализован редирект смарткарт через **PCSC** 58 | * Реализовано сканирование документов (с помощью дополнительного [backend для SANE](https://github.com/AndreyBarmaley/linux-terminal-service-manager/tree/main/src/sane_backend)) 59 | * Реализован редирект директорий через **FUSE** (пока только в режиме read only) 60 | * Реализована аутентификация в виртуальную сессию через **PKCS11** (модуль **rutoken** или другой) с хранилищем сертификатов в **LDAP** 61 | * Реализована SSO аутентификация через **GSSAPI** (kerberos5) 62 | * Реализовано кодирование **x264** через **ffmpeg** 63 | 64 | Механизм каналов реализован через абстрактные схемы ```unix://, file://, socket://```, и режим доступа ```ReadOnly, WriteOnly, ReadWrite```. 65 | Например для обычной передачи файла создается типовой канал (клиент сервер): ```file:///src_file1 (ReadOnly)``` и ```file:///dst_file2 (WriteOnly)```, далее в сессии пользователя запускаются информационные GUI диалоги о передаче и выборе папки назначения, после которых файл автоматически сохранится в удаленной сессии (дополнительно реализованы уведомления через dbus desktop notify). 66 | C помощью данной схемы каналов возможна передача любого потока данных в обе стороны, но инициатором создания канала всегда является сервер. 67 | 68 | Печать со стороны сервера (в удаленной сессии пользователя) реализуется таким образом - на сервере в **cups** добавляется собственный **backend** для печати, который знает в какой **unix сокет** печатать в сессии пользователя, со стороны клиента поток можно отправлять в сетевой принтер ```socket://127.0.0.1:9100```, также в локальный **cups** или в ```file:///dev/usb/lp0```. В этой схеме системный администратор настраивает принтер только один раз для сервера, например командой ```lpadmin -p ltsm -D "LTSM virtual printer" -E -v ltsm:///var/run/ltsm/cups/username -m raw```. Модуль для **cups** автоматически получает сокет из этой схемы, меняет **username** на реального и отправляет в него задание печати. Этот же формат сокета на стороне LTSM сервиса назначается в конфигурационном файле. Сокеты на стороне сервера работают в **listen** режиме поэтому допускаются множественные подключения от клиента. Каждое подключение занимает один канал (253 макс). Как только с одной из сторон освободится дескриптор считается что передача данных завершена и канал можно использовать повторно. Редирект звука, сканирования и pcscd работает по **аналогичной схеме**. 69 | 70 | Все эти реализованные возможности вы можете протестировать в версии **docker**. 71 | 72 | Программное обеспечение зарегистрировано в реестре российского ПО, Номер заявления: 246869, Дата регистрации: 01.11.2021. 73 | 74 | **Roadmap** 75 | * добавить записи видео всех рабочих сессий (видеофикация) 76 | * добавить поддержку [**VirtualGL**](https://virtualgl.org/) 77 | * добавить редирект video через **PipeWire** 78 | * поработать с графикой через **Cuda GPU** (пока нет технических возможностей) 79 | * добавить клиента для MacOs/Windows 80 | -------------------------------------------------------------------------------- /doc/astylerc: -------------------------------------------------------------------------------- 1 | -A1 2 | -S 3 | -N 4 | -Y 5 | -f 6 | --pad-negation 7 | --unpad-brackets 8 | --align-pointer=type 9 | --align-reference=middle 10 | --add-braces 11 | --keep-one-line-blocks 12 | --convert-tabs 13 | --squeeze-ws 14 | -------------------------------------------------------------------------------- /etc/dbus-1/ltsm.manager.service.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /etc/dbus-1/ltsm.session.audio.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /etc/dbus-1/ltsm.session.audio.service: -------------------------------------------------------------------------------- 1 | [D-BUS Service] 2 | Name=ltsm.session.audio 3 | Exec=/usr/libexec/ltsm/LTSM_audio2session 4 | -------------------------------------------------------------------------------- /etc/dbus-1/ltsm.session.fuse.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /etc/dbus-1/ltsm.session.fuse.service: -------------------------------------------------------------------------------- 1 | [D-BUS Service] 2 | Name=ltsm.session.fuse 3 | Exec=/usr/libexec/ltsm/LTSM_fuse2session 4 | -------------------------------------------------------------------------------- /etc/dbus-1/ltsm.session.pcsc.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /etc/dbus-1/ltsm.session.pcsc.service: -------------------------------------------------------------------------------- 1 | [D-BUS Service] 2 | Name=ltsm.session.pcsc 3 | Exec=/usr/libexec/ltsm/LTSM_pcsc2session 4 | -------------------------------------------------------------------------------- /etc/dbus-1/org.freedesktop.Notifications.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /etc/dbus-1/org.freedesktop.Notifications.service: -------------------------------------------------------------------------------- 1 | [D-BUS Service] 2 | Name=org.freedesktop.Notifications 3 | Exec=/usr/libexec/notification-daemon 4 | -------------------------------------------------------------------------------- /etc/logrotate.d/ltsm: -------------------------------------------------------------------------------- 1 | /var/log/ltsm.log 2 | /var/log/ltsm_connector.log { 3 | missingok 4 | notifempty 5 | rotate 14 6 | daily 7 | compress 8 | nocreate 9 | } 10 | -------------------------------------------------------------------------------- /etc/ltsm/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "service:debug:level": "debug", 3 | "#service:debug:types": [ "all" ], 4 | 5 | "connector:debug:level": "info", 6 | "#connector:debug:types": [ "all" ], 7 | 8 | "logging:facility": "local6", 9 | 10 | "vnc:encoding:debug": 0, 11 | "vnc:encoding:threads": 4, 12 | "vnc:encoding:blacklist": [ "zlib" ], 13 | "vnc:gnutls:disable": false, 14 | "vnc:gnutls:debug": 3, 15 | "vnc:gnutls:anonmode": true, 16 | "vnc:gnutls:priority": "NORMAL:+ANON-ECDH:+ANON-DH", 17 | "vnc:gnutls:cafile": "/etc/ltsm/cacerts.pem", 18 | "vnc:gnutls:crlfile": "/etc/ltsm/server.crl", 19 | "vnc:gnutls:certfile": "/etc/ltsm/server.crt", 20 | "vnc:gnutls:keyfile": "/etc/ltsm/server.key", 21 | "#vnc:keymap:file": "/etc/ltsm/keymap_vnc.json", 22 | "#vnc:xcb:nodamage": false, 23 | "vnc:clipboard": true, 24 | 25 | "vnc:kerberos:disable": false, 26 | "vnc:kerberos:service": "TERMSRV", 27 | "vnc:kerberos:keytab": "/etc/ltsm/termsrv.keytab", 28 | "#vnc:kerberos:trace": "/var/tmp/ltsm_krb5.trace", 29 | 30 | "rdp:wlog:level": "error", 31 | "rdp:security:rdp": true, 32 | "rdp:security:tls": true, 33 | "rdp:security:nla": false, 34 | "rdp:tls:level": 1, 35 | "rdp:encryption:level": "compatible", 36 | "rdp:server:certfile": "/etc/ltsm/server.crt", 37 | "rdp:server:keyfile": "/etc/ltsm/server.key", 38 | "#rdp:keymap:file": "/etc/ltsm/keymap_rdp.json", 39 | 40 | "transfer:file:disabled": false, 41 | "transfer:file:max": 100000000, 42 | "#transfer:group:only": "transfer-allow", 43 | 44 | "channel:printer:disabled": false, 45 | "channel:printer:format": "/var/run/ltsm/cups/printer_%{user}", 46 | "channel:audio:disabled": false, 47 | "channel:audio:format": "/var/run/ltsm/audio/%{user}", 48 | "channel:pcsc:disabled": false, 49 | "channel:pcsc:format": "/var/run/ltsm/pcsc/%{user}", 50 | "channel:fuse:disabled": false, 51 | "channel:fuse:format": "/var/run/ltsm/fuse/%{user}", 52 | "channel:sane:disabled": false, 53 | 54 | "#idle:timeout:xvfb": 10, 55 | "#idle:timeout:login": 70, 56 | "#idle:timeout:logout": 0, 57 | 58 | "#idle:action:timeout": 0, 59 | "#idle:action:path": "/usr/bin/xlock", 60 | "#idle:action:args": [], 61 | 62 | "group:shm": "ltsm-shm", 63 | "group:auth": "ltsm-auth", 64 | "user:xvfb": "ltsm-xvfb", 65 | "pam:service": "ltsm", 66 | 67 | "#access:groups": [ "ts-users", "ts-admins" ], 68 | "access:uid:min": 100, 69 | "access:uid:max": 9999, 70 | "#access:users": [ "demo1", "demo2", "demo3", "demoadm" ], 71 | 72 | "helper:autocomplete": true, 73 | "helper:path": "/usr/libexec/ltsm/LTSM_helper", 74 | "helper:args": "", 75 | "helper:dateformat": "dddd dd MMMM, hh:mm:ss", 76 | "helper:title": "X11 Remote Desktop Service (%{version})", 77 | 78 | "login:failures_count": 3, 79 | "session:kill:stop": false, 80 | "session:policy": "authlock", 81 | "session:path": "/etc/ltsm/xclients", 82 | 83 | "zenity:path": "/usr/bin/zenity", 84 | 85 | "default:width": 1024, 86 | "default:height": 768, 87 | 88 | "display:min": 55, 89 | "display:max": 99, 90 | "display:solid": "0x4e7db7", 91 | "display:cursor": "left_ptr", 92 | 93 | "xauth:file": "/var/run/ltsm/auth_%{display}", 94 | 95 | "xvfb:path": "/usr/bin/Xvfb", 96 | "xvfb:args": ":%{display} -nolisten tcp -screen 0 %{width}x%{height}x24 -auth %{authfile} +extension DAMAGE +extension MIT-SHM +extension RANDR +extension XFIXES +extension XTEST", 97 | "xvfb:socket": "/tmp/.X11-unix/X%{display}", 98 | 99 | "#session:connect": "/path/script", 100 | "#session:disconnect": "/path/script", 101 | 102 | "#system:connect": "", 103 | "#system:disconnect": "", 104 | 105 | "#system:logon": "/usr/bin/sessreg -a -l :%{display} %{user}", 106 | "#system:logoff": "/usr/bin/sessreg -d -l :%{display} %{user}" 107 | } 108 | -------------------------------------------------------------------------------- /etc/ltsm/keymap_rdp.json: -------------------------------------------------------------------------------- 1 | { 2 | "keyname_hex8": "value integer or [array]", 3 | 4 | "keysym:left": 0, 5 | "0x4100004b": 100, 6 | "0x8100004b": 100, 7 | "key:right": 0, 8 | "0x4100004d": 102, 9 | "0x8100004d": 102, 10 | "key:up": 0, 11 | "0x41000048": 98, 12 | "0x81000048": 98, 13 | "key:down": 0, 14 | "0x41000050": 104, 15 | "0x81000050": 104, 16 | "key:rctrl": 0, 17 | "0x4100001d": 109, 18 | "0x8100001d": 109, 19 | "key:lalt": 0, 20 | "0x41000040": 125, 21 | "0x81000040": 125, 22 | "key:ralt": 0, 23 | "0x41000038": 113, 24 | "0x81000038": 113, 25 | "key:context":0, 26 | "0x4100005d": 117, 27 | "0x8100005d": 117, 28 | "key:insert": 0, 29 | "0x41000052": 106, 30 | "0x81000052": 106, 31 | "key:delete": 0, 32 | "0x41000053": 107, 33 | "0x81000053": 107, 34 | "key:pageup": 0, 35 | "0x41000049": 99, 36 | "0x81000049": 99, 37 | "key:pagedw": 0, 38 | "0x41000051": 105, 39 | "0x81000051": 105, 40 | "key:home": 0, 41 | "0x41000047": 97, 42 | "0x81000047": 97, 43 | "key:end": 0, 44 | "0x4100004f": 103, 45 | "0x8100004f": 103 46 | } 47 | -------------------------------------------------------------------------------- /etc/ltsm/keymap_vnc.json: -------------------------------------------------------------------------------- 1 | { 2 | "keyname_hex8": "value integer or [array]" 3 | } 4 | -------------------------------------------------------------------------------- /etc/ltsm/xclients: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Xclients 4 | # 5 | 6 | errfile="${HOME}/.xsession-errors" 7 | if ( umask 077 && cp /dev/null "${errfile}" 2> /dev/null ); then 8 | chmod 600 "${errfile}" 9 | exec > "${errfile}" 2>&1 10 | fi 11 | 12 | UID=`id --user` 13 | export XDG_CONFIG_DIRS="/etc/xdg" 14 | export XDG_DATA_DIRS="/usr/share" 15 | export XDG_RUNTIME_DIR=/run/user/$UID 16 | export XDG_SESSION_TYPE="x11" 17 | 18 | mkdir $XDG_RUNTIME_DIR 19 | chmod 700 $XDG_RUNTIME_DIR 20 | 21 | if [ -d /etc/X11/xinit/xinitrc.d ]; then 22 | for SCRIPT in /etc/X11/xinit/xinitrc.d/*.sh; do 23 | if [ -f ${SCRIPT} ]; then 24 | . ${SCRIPT} > /dev/null 2>&1 25 | fi 26 | done 27 | fi 28 | 29 | if [ -f /etc/X11/Xresources ]; then 30 | xrdb -load /etc/X11/Xresources 31 | fi 32 | 33 | if [ -f ${HOME}/.Xresources ]; then 34 | xrdb -merge ${HOME}/.Xresources 35 | fi 36 | 37 | # model: 38 | # setxkbmap -model pc105 -layout us -option '' 39 | # 40 | # change layout: 41 | # setxkbmap -option "" 42 | # setxkbmap -layout "us,ru" -variant ",winkeys" -option "grp:ctrl_shift_toggle" 43 | # 44 | # change symbol: 45 | # setxkbmap -symbols "+kpdl(dotoss)+kpdl(dotoss):2" 46 | 47 | if [ -f /etc/X11/Xmodmap ]; then 48 | xmodmap /etc/X11/Xmodmap 49 | fi 50 | 51 | if [ -f ${HOME}/.Xmodmap ]; then 52 | xmodmap ${HOME}/.Xmodmap 53 | fi 54 | 55 | if [ -z "$XSESSION" ]; then 56 | if [ -x /usr/bin/icewm-session ]; then 57 | XSESSION=/usr/bin/icewm-session 58 | else 59 | XSESSION=/usr/bin/xterm 60 | fi 61 | fi 62 | 63 | exec ${XSESSION} 64 | -------------------------------------------------------------------------------- /etc/pam/ltsm: -------------------------------------------------------------------------------- 1 | #%PAM-1.0 2 | auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so 3 | auth substack system-auth 4 | auth include postlogin 5 | account required pam_nologin.so 6 | account include system-auth 7 | password include system-auth 8 | 9 | # pam_selinux.so close should be the first session rule 10 | session required pam_selinux.so close 11 | session required pam_loginuid.so 12 | session optional pam_console.so 13 | 14 | # pam_selinux.so open should only be followed by sessions to be executed in the user context 15 | session required pam_selinux.so open 16 | session required pam_namespace.so 17 | session include system-auth 18 | session include postlogin 19 | -------------------------------------------------------------------------------- /etc/pam/xserver: -------------------------------------------------------------------------------- 1 | #%PAM-1.0 2 | auth sufficient pam_rootok.so 3 | auth required pam_permit.so 4 | account required pam_permit.so 5 | session optional pam_keyinit.so force revoke 6 | -------------------------------------------------------------------------------- /etc/rsyslog/ltsm.conf: -------------------------------------------------------------------------------- 1 | template(name="ltsm_format" type="string" 2 | string="%$DAY%.%$MONTH%.%$YEAR% %TIMESTAMP:12:19:date-rfc3339% %syslogtag% %msg:::drop-last-lf%\n") 3 | 4 | template(name="connector_format" type="string" 5 | string="%$DAY%.%$MONTH%.%$YEAR% %TIMESTAMP:12:19:date-rfc3339% [%$!_PID%]: %msg:::drop-last-lf%\n") 6 | 7 | if $programname == "ltsm_connector" then { 8 | 9 | action(type="omfile" template="connector_format" 10 | flushOnTXEnd="off" asyncWriting="on" flushInterval="1" ioBufferSize="1k" file="/var/log/ltsm_connector.log") 11 | 12 | stop 13 | } 14 | 15 | if $programname contains "ltsm_" then { 16 | 17 | action(type="omfile" template="ltsm_format" 18 | flushOnTXEnd="off" asyncWriting="on" flushInterval="1" ioBufferSize="1k" file="/var/log/ltsm_service.log") 19 | 20 | stop 21 | } 22 | -------------------------------------------------------------------------------- /etc/systemd/ltsm_connector_rdp.socket: -------------------------------------------------------------------------------- 1 | [Socket] 2 | ListenStream=3389 3 | Accept=yes 4 | 5 | [Install] 6 | WantedBy=sockets.target 7 | -------------------------------------------------------------------------------- /etc/systemd/ltsm_connector_rdp@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=LTSM connector 3 | After=network.target 4 | #ltsm_service.service 5 | 6 | [Service] 7 | Type=simple 8 | ExecStart=-/usr/local/sbin/LTSM_connector --type rdp 9 | User=ltsm-xvfb 10 | Group=ltsm-shm 11 | StandardInput=socket 12 | StandardOutput=socket 13 | LimitCORE=infinity 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /etc/systemd/ltsm_connector_vnc.socket: -------------------------------------------------------------------------------- 1 | [Socket] 2 | ListenStream=5900 3 | Accept=yes 4 | 5 | [Install] 6 | WantedBy=sockets.target 7 | -------------------------------------------------------------------------------- /etc/systemd/ltsm_connector_vnc@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=LTSM connector 3 | After=network.target ltsm_service.service 4 | 5 | [Service] 6 | Type=simple 7 | ExecStart=-/usr/local/sbin/LTSM_connector --type vnc 8 | User=ltsm-xvfb 9 | Group=ltsm-shm 10 | StandardInput=socket 11 | StandardOutput=socket 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /etc/systemd/ltsm_service.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=LTSM service 3 | 4 | [Service] 5 | ExecStart=/usr/local/sbin/LTSM_service 6 | 7 | [Install] 8 | WantedBy=multi-user.target 9 | -------------------------------------------------------------------------------- /etc/xinet/jetdirect: -------------------------------------------------------------------------------- 1 | service jetdirect 2 | { 3 | disable = no 4 | flags = IPv4 5 | type = UNLISTED 6 | socket_type = stream 7 | protocol = tcp 8 | bind = 127.0.0.1 9 | port = 9100 10 | wait = no 11 | user = lp 12 | server = /usr/lib/cups/daemon/cups-lpd 13 | server_args = -o document-format=application/octet-stream -o job-sheets=none 14 | } 15 | -------------------------------------------------------------------------------- /etc/xinet/ltsm_connector: -------------------------------------------------------------------------------- 1 | service rfb 2 | { 3 | port = 5900 4 | disable = no 5 | flags = REUSE 6 | socket_type = stream 7 | wait = no 8 | user = ltsm-xvfb 9 | server = /usr/local/sbin/LTSM_connector 10 | server_args = --type vnc 11 | } 12 | 13 | service ms-wbt-server 14 | { 15 | port = 3389 16 | disable = no 17 | flags = REUSE 18 | socket_type = stream 19 | wait = no 20 | user = ltsm-xvfb 21 | server = /usr/local/sbin/LTSM_connector 22 | server_args = --type rdp 23 | } 24 | -------------------------------------------------------------------------------- /etc/xorg/ltsm.conf: -------------------------------------------------------------------------------- 1 | # This xorg configuration file is meant to be used by xpra 2 | # to start a dummy X11 server. 3 | # For details, please see: 4 | # https://xpra.org/Xdummy.html 5 | 6 | Section "ServerFlags" 7 | Option "DontVTSwitch" "true" 8 | Option "AllowMouseOpenFail" "true" 9 | Option "PciForceNone" "true" 10 | Option "AutoEnableDevices" "false" 11 | Option "AutoAddDevices" "false" 12 | EndSection 13 | 14 | Section "InputDevice" 15 | Identifier "dummy_mouse" 16 | Option "CorePointer" "true" 17 | Driver "void" 18 | EndSection 19 | 20 | Section "InputDevice" 21 | Identifier "dummy_keyboard" 22 | Option "CoreKeyboard" "true" 23 | Driver "void" 24 | EndSection 25 | 26 | Section "Device" 27 | Identifier "dummy_videocard" 28 | Driver "dummy" 29 | Option "ConstantDPI" "true" 30 | VideoRam 64000 31 | EndSection 32 | 33 | Section "Monitor" 34 | Identifier "dummy_monitor" 35 | HorizSync 5.0 - 300.0 36 | VertRefresh 5.0 - 200.0 37 | #NOTE: the highest modes will not work without increasing the VideoRam 38 | # for the dummy video card. 39 | Modeline "1920x1440" 69.47 1920 1960 2152 2384 1440 1441 1444 1457 40 | Modeline "1920x1200" 26.28 1920 1952 2048 2080 1200 1229 1231 1261 41 | Modeline "1920x1080" 23.53 1920 1952 2040 2072 1080 1106 1108 1135 42 | Modeline "1680x1050" 20.08 1680 1712 1784 1816 1050 1075 1077 1103 43 | Modeline "1600x1200" 22.04 1600 1632 1712 1744 1200 1229 1231 1261 44 | Modeline "1600x900" 33.92 1600 1632 1760 1792 900 921 924 946 45 | Modeline "1440x900" 30.66 1440 1472 1584 1616 900 921 924 946 46 | ModeLine "1366x768" 72.00 1366 1414 1446 1494 768 771 777 803 47 | Modeline "1280x1024" 31.50 1280 1312 1424 1456 1024 1048 1052 1076 48 | Modeline "1280x800" 24.15 1280 1312 1400 1432 800 819 822 841 49 | Modeline "1280x768" 23.11 1280 1312 1392 1424 768 786 789 807 50 | Modeline "1360x768" 24.49 1360 1392 1480 1512 768 786 789 807 51 | Modeline "1024x768" 18.71 1024 1056 1120 1152 768 786 789 807 52 | EndSection 53 | 54 | Section "Screen" 55 | Identifier "dummy_screen" 56 | Device "dummy_videocard" 57 | Monitor "dummy_monitor" 58 | DefaultDepth 24 59 | SubSection "Display" 60 | Viewport 0 0 61 | Depth 24 62 | Modes "1920x1440" "1920x1200" "1920x1080" "1600x1200" "1680x1050" "1600x900" "1400x1050" "1440x900" "1280x1024" "1366x768" "1280x800" "1024x768" 63 | Virtual 1920 1440 64 | EndSubSection 65 | EndSection 66 | 67 | Section "ServerLayout" 68 | Identifier "dummy_layout" 69 | Screen "dummy_screen" 70 | InputDevice "dummy_mouse" 71 | InputDevice "dummy_keyboard" 72 | EndSection 73 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.projectName=linux-terminal-service-manager 2 | sonar.projectVersion=20250522 3 | sonar.projectKey=AndreyBarmaley_linux-terminal-service-manager 4 | sonar.organization=andreybarmaley 5 | 6 | sonar.sources=src 7 | sonar.exclusions=src/common/flat_hash_map/**,src/common/jsmn/**,src/common/libxcb-errors/**,src/service/alexab_safe_ptr.h,src/tests/** 8 | sonar.cfamily.cache.enabled=false 9 | 10 | # Encoding of the source code. Default is default system encoding 11 | sonar.sourceEncoding=UTF-8 12 | -------------------------------------------------------------------------------- /src/channels/ltsm_channels.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2022 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_CHANNELS_ 25 | #define _LTSM_CHANNELS_ 26 | 27 | #include "channel_system.h" 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | target_sources(LTSM_common PUBLIC ltsm_application.cpp) 4 | target_sources(LTSM_common PUBLIC ltsm_json_wrapper.cpp) 5 | target_sources(LTSM_common PUBLIC ltsm_tools.cpp) 6 | target_sources(LTSM_common PUBLIC ltsm_streambuf.cpp) 7 | target_sources(LTSM_common PUBLIC ltsm_sockets.cpp) 8 | target_sources(LTSM_common PUBLIC ltsm_framebuffer.cpp) 9 | target_sources(LTSM_common PUBLIC ltsm_xcb_types.cpp) 10 | 11 | if(UNIX) 12 | target_sources(LTSM_common PUBLIC ltsm_xcb_wrapper.cpp) 13 | 14 | if(LTSM_BUILD_XCB_ERRORS) 15 | target_sources(LTSM_common PUBLIC libxcb-errors/xcb_errors.c libxcb-errors/extensions.c) 16 | endif() 17 | endif() 18 | -------------------------------------------------------------------------------- /src/common/libxcb-errors/errors.h: -------------------------------------------------------------------------------- 1 | #ifndef __ERRORS_H__ 2 | #define __ERRORS_H__ 3 | 4 | /* Copyright © 2015 Uli Schlachter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | * Except as contained in this notice, the names of the authors or their 24 | * institutions shall not be used in advertising or otherwise to promote the 25 | * sale, use or other dealings in this Software without prior written 26 | * authorization from the authors. 27 | */ 28 | 29 | #include "xcb_errors.h" 30 | 31 | struct static_extension_info_t { 32 | uint16_t num_minor; 33 | uint16_t num_xge_events; 34 | uint8_t num_events; 35 | uint8_t num_errors; 36 | const char *strings_minor; 37 | const char *strings_xge_events; 38 | const char *strings_events; 39 | const char *strings_errors; 40 | const char *name; 41 | }; 42 | 43 | extern const struct static_extension_info_t xproto_info; 44 | 45 | int register_extensions(xcb_errors_context_t *ctx, xcb_connection_t *conn); 46 | int register_extension(xcb_errors_context_t *ctx, xcb_connection_t *conn, 47 | xcb_query_extension_cookie_t cookie, 48 | const struct static_extension_info_t *static_info); 49 | 50 | #endif /* __ERRORS_H__ */ 51 | -------------------------------------------------------------------------------- /src/common/ltsm_application.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | ***************************************************************************/ 22 | 23 | #ifndef _LTSM_APPLICATION_ 24 | #define _LTSM_APPLICATION_ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #ifdef WITH_JSON 33 | #include "ltsm_json_wrapper.h" 34 | #endif 35 | 36 | namespace LTSM 37 | { 38 | enum class DebugTarget { Quiet, Console, Syslog }; 39 | enum class DebugLevel { None, Info, Debug, Trace }; 40 | 41 | enum DebugType 42 | { 43 | All = 0xFFFFFFFF, 44 | Xcb = 1 << 31, 45 | Rfb = 1 << 30, 46 | Clip = 1 << 29, 47 | Socket = 1 << 28, 48 | Tls = 1 << 27, 49 | Channels = 1 << 26, 50 | Conn = 1 << 25, 51 | Enc = 1 << 24, 52 | X11Srv = 1 << 23, 53 | X11Cli = 1 << 22, 54 | WinCli = X11Cli, 55 | Audio = 1 << 21, 56 | Fuse = 1 << 20, 57 | Pcsc = 1 << 19, 58 | Pkcs11 = 1 << 18, 59 | Sdl = 1 << 17, 60 | App = 1 << 16, 61 | Mgr = 1 << 15, 62 | Ldap = 1 << 14, 63 | Gss = 1 << 13 64 | }; 65 | 66 | class Application 67 | { 68 | public: 69 | explicit Application(std::string_view ident); 70 | virtual ~Application(); 71 | 72 | Application(Application &) = delete; 73 | Application & operator= (const Application &) = delete; 74 | 75 | static void info(const char* format, ...); 76 | static void notice(const char* format, ...); 77 | static void warning(const char* format, ...); 78 | static void error(const char* format, ...); 79 | static void vdebug(uint32_t subsys, const char* format, va_list args); 80 | static void debug(uint32_t subsys, const char* format, ...); 81 | static void vtrace(uint32_t subsys, const char* format, va_list args); 82 | static void trace(uint32_t subsys, const char* format, ...); 83 | 84 | static void redirectSyslogFile(const char* file = nullptr); 85 | static void setDebug(const DebugTarget &, const DebugLevel &); 86 | 87 | static void setDebugTarget(const DebugTarget &); 88 | static void setDebugTarget(std::string_view target); 89 | static void setDebugTargetFile(const std::filesystem::path & file); 90 | static bool isDebugTarget(const DebugTarget &); 91 | 92 | static void setDebugLevel(const DebugLevel &); 93 | static void setDebugLevel(std::string_view level); 94 | static bool isDebugLevel(const DebugLevel &); 95 | 96 | static void setDebugTypes(uint32_t); 97 | static bool isDebugTypes(uint32_t vals); 98 | 99 | virtual int start(void) = 0; 100 | }; 101 | 102 | #ifdef WITH_JSON 103 | class ApplicationJsonConfig : public Application 104 | { 105 | JsonObject json; 106 | 107 | protected: 108 | void configSet(JsonObject &&) noexcept; 109 | 110 | public: 111 | ApplicationJsonConfig(std::string_view ident, const char* fconf = nullptr); 112 | 113 | void readConfig(const std::filesystem::path &); 114 | 115 | void configSetInteger(const std::string &, int); 116 | void configSetBoolean(const std::string &, bool); 117 | void configSetString(const std::string &, std::string_view); 118 | void configSetDouble(const std::string &, double); 119 | 120 | int configGetInteger(std::string_view, int = 0) const; 121 | bool configGetBoolean(std::string_view, bool = false) const; 122 | std::string configGetString(std::string_view, std::string_view = "") const; 123 | double configGetDouble(std::string_view, double = 0) const; 124 | 125 | const JsonObject & config(void) const; 126 | }; 127 | 128 | #endif 129 | } 130 | 131 | #endif // _LTSM_APPLICATION_ 132 | -------------------------------------------------------------------------------- /src/common/ltsm_global.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | ***************************************************************************/ 22 | 23 | #ifndef _LTSM_GLOBALS_ 24 | #define _LTSM_GLOBALS_ 25 | 26 | namespace LTSM 27 | { 28 | inline static const char* dbus_manager_service_name = "ltsm.manager.service"; 29 | inline static const char* dbus_manager_service_path = "/ltsm/manager/service"; 30 | 31 | inline static const char* dbus_session_fuse_name = "ltsm.session.fuse"; 32 | inline static const char* dbus_session_fuse_path = "/ltsm/session/fuse"; 33 | 34 | inline static const char* dbus_session_audio_name = "ltsm.session.audio"; 35 | inline static const char* dbus_session_audio_path = "/ltsm/session/audio"; 36 | 37 | inline static const char* dbus_session_pcsc_name = "ltsm.session.pcsc"; 38 | inline static const char* dbus_session_pcsc_path = "/ltsm/session/pcsc"; 39 | 40 | inline static const int service_version = 20250601; 41 | 42 | inline bool platformBigEndian(void) 43 | { 44 | #if (__BYTE_ORDER__==__ORDER_BIG_ENDIAN__) 45 | return true; 46 | #else 47 | return false; 48 | #endif 49 | } 50 | 51 | namespace NotifyParams 52 | { 53 | enum IconType { Information, Warning, Error, Question }; 54 | enum UrgencyLevel { Low = 0, Normal = 1, Critical = 2 }; 55 | }; 56 | } 57 | 58 | #if defined(LTSM_BUILD_STD_MAP) || defined(__MINGW32__) 59 | #include 60 | #include 61 | #define INTMAP std::unordered_map 62 | #define INTSET std::unordered_set 63 | #else 64 | #include "flat_hash_map/unordered_map.hpp" 65 | #define INTMAP ska::unordered_map 66 | #define INTSET ska::unordered_set 67 | #endif 68 | 69 | #endif // _LTSM_GLOBALS_ 70 | -------------------------------------------------------------------------------- /src/common/ltsm_xcb_types.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2025 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | ***************************************************************************/ 22 | 23 | #ifndef _LTSM_XCB_TYPES_ 24 | #define _LTSM_XCB_TYPES_ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace LTSM 32 | { 33 | struct xcb_error : public std::runtime_error 34 | { 35 | explicit xcb_error(std::string_view what) : std::runtime_error(what.data()) {} 36 | }; 37 | 38 | namespace XCB 39 | { 40 | struct Point 41 | { 42 | int16_t x, y; 43 | 44 | Point() : x(-1), y(-1) {} 45 | 46 | Point(int16_t px, int16_t py) : x(px), y(py) {} 47 | 48 | virtual ~Point() = default; 49 | 50 | virtual bool isValid(void) const { return 0 <= x && 0 <= y; } 51 | 52 | Point operator+(const Point & pt) const { return Point(x + pt.x, y + pt.y); } 53 | 54 | Point operator-(const Point & pt) const { return Point(x - pt.x, y - pt.y); } 55 | 56 | bool operator==(const Point & pt) const { return pt.x == x && pt.y == y; } 57 | 58 | bool operator!=(const Point & pt) const { return pt.x != x || pt.y != y; } 59 | }; 60 | 61 | struct Size 62 | { 63 | uint16_t width, height; 64 | 65 | Size() : width(0), height(0) {} 66 | 67 | Size(uint16_t sw, uint16_t sh) : width(sw), height(sh) {} 68 | 69 | virtual ~Size() = default; 70 | 71 | bool isEmpty(void) const { return width == 0 || height == 0; } 72 | 73 | void reset(void) { width = 0; height = 0; } 74 | 75 | bool operator==(const Size & sz) const { return sz.width == width && sz.height == height; } 76 | 77 | bool operator!=(const Size & sz) const { return sz.width != width || sz.height != height; } 78 | }; 79 | 80 | struct PointIterator : Point 81 | { 82 | const Size limit; 83 | PointIterator(int16_t px, int16_t py, const Size & sz) : Point(px, py), limit(sz) {} 84 | 85 | PointIterator & operator++(void); 86 | PointIterator & operator--(void); 87 | 88 | bool isValid(void) const override { return Point::isValid() && x < limit.width && y < limit.height; } 89 | 90 | bool isBeginLine(void) const; 91 | bool isEndLine(void) const; 92 | virtual void lineChanged(void) { /* default empty */ } 93 | }; 94 | 95 | struct Region : public Point, public Size 96 | { 97 | Region() = default; 98 | 99 | Region(const Point & pt, const Size & sz) : Point(pt), Size(sz) {} 100 | 101 | Region(int16_t rx, int16_t ry, uint16_t rw, uint16_t rh) : Point(rx, ry), Size(rw, rh) {} 102 | 103 | const Point & topLeft(void) const { return *this; } 104 | 105 | const Size & toSize(void) const { return *this; } 106 | 107 | PointIterator coordBegin(void) const { return PointIterator(0, 0, toSize()); } 108 | 109 | bool operator== (const Region & rt) const { return rt.x == x && rt.y == y && rt.width == width && rt.height == height; } 110 | 111 | bool operator!= (const Region & rt) const { return rt.x != x || rt.y != y || rt.width != width || rt.height != height; } 112 | 113 | void reset(void); 114 | 115 | void assign(int16_t rx, int16_t ry, uint16_t rw, uint16_t rh); 116 | void assign(const Region &); 117 | 118 | void join(int16_t rx, int16_t ry, uint16_t rw, uint16_t rh); 119 | void join(const Region &); 120 | 121 | bool empty(void) const; 122 | bool invalid(void) const; 123 | 124 | Region intersected(const Region &) const; 125 | Region align(size_t) const; 126 | 127 | static bool intersects(const Region &, const Region &); 128 | static bool intersection(const Region &, const Region &, Region* res); 129 | 130 | std::list divideBlocks(const Size &) const; 131 | std::list divideCounts(uint16_t cols, uint16_t rows) const; 132 | }; 133 | 134 | Region operator- (const Region &, const Point &); 135 | Region operator+ (const Region &, const Point &); 136 | 137 | struct HasherRegion 138 | { 139 | size_t operator()(const Region & reg) const 140 | { 141 | return std::hash()((static_cast(reg.x) << 48) | (static_cast(reg.y) << 32) | 142 | (static_cast(reg.width) << 16) | static_cast(reg.height)); 143 | } 144 | }; 145 | 146 | struct RegionPixel : std::pair 147 | { 148 | RegionPixel(const Region & reg, uint32_t pixel) : std::pair(reg, pixel) {} 149 | 150 | RegionPixel() = default; 151 | 152 | const uint32_t & pixel(void) const { return second; } 153 | 154 | const Region & region(void) const { return first; } 155 | }; 156 | } 157 | } 158 | 159 | #endif // _LTSM_XCB_TYPES_ 160 | -------------------------------------------------------------------------------- /src/connector/ltsm_connector_rdp.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_CONNECTOR_RDP_ 25 | #define _LTSM_CONNECTOR_RDP_ 26 | 27 | #include 28 | 29 | #include "ltsm_sockets.h" 30 | #include "ltsm_connector.h" 31 | 32 | #include "freerdp/freerdp.h" 33 | #include "freerdp/listener.h" 34 | 35 | namespace LTSM 36 | { 37 | struct FreeRdpCallback; 38 | 39 | struct rdp_error : public std::runtime_error 40 | { 41 | explicit rdp_error(std::string_view what) : std::runtime_error(what.data()) {} 42 | }; 43 | 44 | namespace Connector 45 | { 46 | /* Connector::RDP */ 47 | class RDP : public SignalProxy, public XCB::RootDisplay, protected ProxySocket 48 | { 49 | std::atomic helperStartedFlag{false}; 50 | std::atomic loopShutdownFlag{false}; 51 | std::atomic updatePartFlag{true}; 52 | std::unique_ptr freeRdp; 53 | PixelFormat serverFormat; 54 | XCB::Region damageRegion; 55 | 56 | protected: 57 | // dbus virtual signals 58 | void onLoginSuccess(const int32_t & display, const std::string & userName, 59 | const uint32_t & userUid) override; 60 | void onSendBellSignal(const int32_t & display) override; 61 | void onShutdownConnector(const int32_t & display) override; 62 | void onHelperWidgetStarted(const int32_t & display) override; 63 | 64 | // connector 65 | void serverScreenUpdateRequest(const XCB::Region &) override; 66 | 67 | // root display 68 | void xcbDamageNotifyEvent(const xcb_rectangle_t &) override; 69 | void xcbRandrScreenChangedEvent(const XCB::Size &, const xcb_randr_notify_event_t &) override; 70 | void xcbXkbGroupChangedEvent(int) override; 71 | 72 | bool updateEvent(const XCB::Region &); 73 | bool updateBitmapPlanar(const XCB::Region &, const XCB::PixmapInfoReply &); 74 | bool updateBitmapInterleaved(const XCB::Region &, const XCB::PixmapInfoReply &); 75 | void desktopResizeEvent(freerdp_peer &, uint16_t, uint16_t); 76 | void disconnectedEvent(void); 77 | 78 | bool xcbEventLoopAsync(bool nodamage); 79 | 80 | bool channelsInit(void); 81 | void channelsFree(void); 82 | 83 | public: 84 | RDP(const JsonObject &); 85 | ~RDP(); 86 | 87 | int communication(void) override; 88 | bool createX11Session(uint8_t depth); 89 | void setEncryptionInfo(const std::string &); 90 | void setAutoLogin(const std::string &, const std::string &); 91 | 92 | // freerdp callback func 93 | static BOOL cbServerPostConnect(freerdp_peer* client); 94 | static BOOL cbServerActivate(freerdp_peer* client); 95 | static BOOL cbServerAuthenticate(freerdp_peer* client, const char** user, const char** domain, 96 | const char** password); 97 | static BOOL cbServerSynchronizeEvent(rdpInput* input, UINT32 flags); 98 | static BOOL cbServerKeyboardEvent(rdpInput* input, UINT16 flags, UINT16 code); 99 | static BOOL cbServerMouseEvent(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); 100 | static BOOL cbServerRefreshRect(rdpContext* context, BYTE count, const RECTANGLE_16* areas); 101 | static BOOL cbServerSuppressOutput(rdpContext* context, BYTE allow, const RECTANGLE_16* area); 102 | static BOOL cbServerRefreshRequest(freerdp_peer* client); 103 | 104 | static BOOL cbServerClose(freerdp_peer* client); 105 | static void cbServerDisconnect(freerdp_peer* client); 106 | static BOOL cbServerCapabilities(freerdp_peer* client); 107 | static BOOL cbServerAdjustMonitorsLayout(freerdp_peer* client); 108 | static BOOL cbServerClientCapabilities(freerdp_peer* client); 109 | }; 110 | } 111 | } 112 | 113 | #endif // _LTSM_CONNECTOR_RDP_ 114 | -------------------------------------------------------------------------------- /src/connector/ltsm_connector_vnc.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_CONNECTOR_VNC_ 25 | #define _LTSM_CONNECTOR_VNC_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "librfb_x11server.h" 35 | #include "ltsm_connector.h" 36 | 37 | namespace LTSM 38 | { 39 | struct vnc_error : public std::runtime_error 40 | { 41 | explicit vnc_error(std::string_view what) : std::runtime_error(what.data()) {} 42 | }; 43 | 44 | namespace Connector 45 | { 46 | /* Connector::VNC */ 47 | class VNC : public SignalProxy, protected RFB::X11Server 48 | { 49 | PixelFormat serverPf; 50 | 51 | std::unordered_mapkeymap; 52 | 53 | std::list> transfer; 54 | std::mutex lockTransfer; 55 | 56 | std::chrono::time_point 57 | idleSession; 58 | size_t idleTimeoutSec = 0; 59 | 60 | std::atomic frameRate{16}; 61 | std::atomic loginWidgetStarted{false}; 62 | std::atomic userSession{false}; 63 | std::atomic x11NoDamage{false}; 64 | uid_t shmUid = 0; 65 | 66 | protected: 67 | // rfb server encoding 68 | const PixelFormat & serverFormat(void) const override; 69 | void serverFrameBufferModifyEvent(FrameBuffer &) const override; 70 | std::forward_list serverDisabledEncodings(void) const override; 71 | 72 | // x11server 73 | bool xcbNoDamageOption(void) const override; 74 | void xcbDisableMessages(bool) override; 75 | bool xcbAllowMessages(void) const override; 76 | size_t frameRateOption(void) const override; 77 | 78 | bool rfbClipboardEnable(void) const override; 79 | bool rfbDesktopResizeEnabled(void) const override; 80 | RFB::SecurityInfo rfbSecurityInfo(void) const override; 81 | int rfbUserKeycode(uint32_t) const override; 82 | 83 | void serverRecvKeyEvent(bool pressed, uint32_t keysym) override; 84 | void serverRecvPointerEvent(uint8_t mask, uint16_t posx, uint16_t posy) override; 85 | 86 | // dbus virtual signals 87 | void onLoginSuccess(const int32_t & display, const std::string & userName, 88 | const uint32_t & userUid) override; 89 | void onShutdownConnector(const int32_t & display) override; 90 | void onHelperWidgetStarted(const int32_t & display) override; 91 | void onSendBellSignal(const int32_t & display) override; 92 | 93 | // connector 94 | void serverScreenUpdateRequest(const XCB::Region &) override; 95 | 96 | void onLoginFailure(const int32_t & display, const std::string & msg) override; 97 | void onCreateChannel(const int32_t & display, const std::string & client, const std::string & cmode, 98 | const std::string & server, const std::string & smode, const std::string & speed) override; 99 | void onDestroyChannel(const int32_t & display, const uint8_t & channel) override; 100 | void onTransferAllow(const int32_t & display, const std::string & filepath, const std::string & tmpfile, 101 | const std::string & dstdir) override; 102 | void onCreateListener(const int32_t & display, const std::string & client, const std::string & cmode, 103 | const std::string & server, const std::string & smode, const std::string & speed, const uint8_t & limit, 104 | const uint32_t & flags) override; 105 | void onDestroyListener(const int32_t & display, const std::string & client, 106 | const std::string & server) override; 107 | void onDebugChannel(const int32_t & display, const uint8_t & channel, const bool & debug) override; 108 | 109 | void serverHandshakeVersionEvent(void) override; 110 | void serverEncodingSelectedEvent(void) override; 111 | void serverSecurityInitEvent(void) override; 112 | void serverConnectedEvent(void) override; 113 | void serverMainLoopEvent(void) override; 114 | void serverDisplayResizedEvent(const XCB::Size &) override; 115 | void serverEncodingsEvent(void) override; 116 | 117 | // rfb channel client 118 | bool isUserSession(void) const override; 119 | void systemChannelError(const JsonObject &) override; 120 | void systemTransferFiles(const JsonObject &) override; 121 | void systemClientVariables(const JsonObject &) override; 122 | void systemKeyboardChange(const JsonObject &) override; 123 | 124 | public: 125 | VNC(const JsonObject & jo) : SignalProxy(jo, "vnc") {} 126 | 127 | ~VNC(); 128 | 129 | int communication(void) override; 130 | }; 131 | } 132 | } 133 | 134 | #endif // _LTSM_CONNECTOR_VNC_ 135 | -------------------------------------------------------------------------------- /src/dbus/ltsm_audio.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/dbus/ltsm_fuse.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/dbus/ltsm_pcsc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/librfb/ffmpeg_tools.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | ***************************************************************************/ 22 | 23 | #ifndef _FFMPEG_TOOLS_ 24 | #define _FFMPEG_TOOLS_ 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #include "libavformat/avformat.h" 31 | 32 | #ifdef __cplusplus 33 | } 34 | 35 | #endif 36 | 37 | namespace LTSM 38 | { 39 | namespace Tools 40 | { 41 | bool AV_PixelFormatEnumToMasks(AVPixelFormat format, int* bpp, uint32_t* rmask, uint32_t* gmask, uint32_t* bmask, uint32_t* amask, bool debug); 42 | AVPixelFormat AV_PixelFormatEnumFromMasks(int bpp, uint32_t rmask, uint32_t gmask, uint32_t bmask, uint32_t amask, bool debug); 43 | } 44 | } 45 | 46 | #endif // _FFMPEG_TOOLS_ 47 | -------------------------------------------------------------------------------- /src/librfb/librfb_extclip.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2025 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LIBRFB_EXTCLIP_ 25 | #define _LIBRFB_EXTCLIP_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "ltsm_sockets.h" 33 | 34 | #ifdef __UNIX__ 35 | #include "ltsm_xcb_wrapper.h" 36 | #endif 37 | 38 | namespace LTSM 39 | { 40 | enum ExtClipCaps 41 | { 42 | TypeText = 1 << 0, 43 | TypeRtf = 1 << 1, 44 | TypeHtml = 1 << 2, 45 | TypeDib = 1 << 3, 46 | TypeFiles= 1 << 4, 47 | Type5 = 1 << 5, 48 | Type6 = 1 << 6, 49 | Type7 = 1 << 7, 50 | Type8 = 1 << 8, 51 | Type9 = 1 << 9, 52 | Type10 = 1 << 10, 53 | Type11 = 1 << 11, 54 | Type12 = 1 << 12, 55 | Type13 = 1 << 13, 56 | Type14 = 1 << 14, 57 | Type15 = 1 << 15, 58 | OpCaps = 1 << 24, 59 | OpRequest= 1 << 25, 60 | OpPeek = 1 << 26, 61 | OpNotify = 1 << 27, 62 | OpProvide= 1 << 28 63 | }; 64 | 65 | struct ExtClipTypes 66 | { 67 | int flags = 0; 68 | uint32_t textSize = 0; 69 | uint32_t rtfSize = 0; 70 | uint32_t htmlSize = 0; 71 | uint32_t dibSize = 0; 72 | uint32_t fileSize = 0; 73 | }; 74 | 75 | namespace RFB 76 | { 77 | class ServerEncoder; 78 | 79 | /// ExtClip 80 | class ExtClip 81 | { 82 | protected: 83 | int remoteExtClipboardFlags = 0; 84 | uint32_t remoteExtClipTypeTextSz = 0; 85 | uint32_t remoteExtClipTypeRtfSz = 0; 86 | uint32_t remoteExtClipTypeHtmlSz = 0; 87 | uint32_t remoteExtClipTypeDibSz = 0; 88 | uint32_t remoteExtClipTypeFilesSz= 0; 89 | 90 | int localExtClipboardFlags = 0; 91 | uint32_t localExtClipTypeTextSz = 0; 92 | uint32_t localExtClipTypeRtfSz = 0; 93 | uint32_t localExtClipTypeHtmlSz = 0; 94 | uint32_t localExtClipTypeDibSz = 0; 95 | uint32_t localExtClipTypeFilesSz= 0; 96 | 97 | std::mutex localProvide; 98 | uint32_t localProvideTypes = 0; 99 | 100 | protected: 101 | void recvExtClipboardCapsContinue(uint32_t flags, StreamBuf && sb); 102 | void recvExtClipboardRequest(uint32_t flags); 103 | void recvExtClipboardPeek(void); 104 | void recvExtClipboardNotify(uint32_t flags); 105 | void recvExtClipboardProvide(StreamBuf && sb); 106 | 107 | void sendExtClipboardRequest(uint16_t types); 108 | void sendExtClipboardPeek(void); 109 | void sendExtClipboardNotify(uint16_t types); 110 | void sendExtClipboardProvide(uint16_t types); 111 | 112 | virtual uint16_t extClipboardLocalTypes(void) const = 0; 113 | virtual std::vector extClipboardLocalData(uint16_t type) const = 0; 114 | virtual void extClipboardRemoteTypesEvent(uint16_t type) = 0; 115 | virtual void extClipboardRemoteDataEvent(uint16_t type, std::vector &&) = 0; 116 | virtual void extClipboardSendEvent(const std::vector & buf) = 0; 117 | 118 | public: 119 | ExtClip() = default; 120 | virtual ~ExtClip() = default; 121 | 122 | void sendExtClipboardCaps(void); 123 | void recvExtClipboardCaps(StreamBuf &&); 124 | 125 | void setExtClipboardRemoteCaps(int); 126 | int extClipboardRemoteCaps(void) const; 127 | 128 | void setExtClipboardLocalCaps(int); 129 | int extClipboardLocalCaps(void) const; 130 | 131 | #ifdef __UNIX__ 132 | static std::vector typesToX11Atoms(uint16_t types, const XCB::Connector &); 133 | static uint16_t x11AtomToType(xcb_atom_t); 134 | static void x11AtomsUpdate(const XCB::Connector &); 135 | #endif 136 | }; 137 | } 138 | } 139 | 140 | #endif // _LIBRFB_EXTCLIP_ 141 | -------------------------------------------------------------------------------- /src/librfb/librfb_ffmpeg.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2022 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LIBRFB_FFMPEG_ 25 | #define _LIBRFB_FFMPEG_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | #include "libavdevice/avdevice.h" 37 | #include "libavcodec/avcodec.h" 38 | #include "libavformat/avformat.h" 39 | #include "libavformat/avio.h" 40 | #include "libavutil/timestamp.h" 41 | #include "libswscale/swscale.h" 42 | #include "libswresample/swresample.h" 43 | #include "libavutil/imgutils.h" 44 | 45 | #ifdef __cplusplus 46 | } 47 | 48 | #endif 49 | 50 | #include "librfb_encodings.h" 51 | #include "librfb_decodings.h" 52 | 53 | namespace LTSM 54 | { 55 | struct ffmpeg_error : public std::runtime_error 56 | { 57 | explicit ffmpeg_error(std::string_view what) : std::runtime_error(what.data()) {} 58 | }; 59 | 60 | struct AVCodecContextDeleter 61 | { 62 | void operator()(AVCodecContext* ctx) 63 | { 64 | #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(61, 19, 100) 65 | avcodec_close(ctx); // deprecated 66 | #endif 67 | #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100) 68 | avcodec_free_context(& ctx); 69 | #else 70 | avcodec_free(ctx); 71 | #endif 72 | } 73 | }; 74 | 75 | struct SwsContextDeleter 76 | { 77 | void operator()(SwsContext* ctx) 78 | { 79 | sws_freeContext(ctx); 80 | } 81 | }; 82 | 83 | struct SwrContextDeleter 84 | { 85 | void operator()(SwrContext* ctx) 86 | { 87 | swr_free(& ctx); 88 | } 89 | }; 90 | 91 | struct AVFrameDeleter 92 | { 93 | void operator()(AVFrame* ptr) 94 | { 95 | av_frame_free(& ptr); 96 | } 97 | }; 98 | 99 | struct AVPacketDeleter 100 | { 101 | void operator()(AVPacket* ptr) 102 | { 103 | av_packet_free(& ptr); 104 | } 105 | }; 106 | 107 | namespace RFB 108 | { 109 | #ifdef LTSM_ENCODING_FFMPEG 110 | /// EncodingFFmpeg 111 | class EncodingFFmpeg : public EncodingBase 112 | { 113 | std::unique_ptr avcctx; 114 | std::unique_ptr swsctx; 115 | std::unique_ptr frame; 116 | std::unique_ptr packet; 117 | 118 | #if LIBAVFORMAT_VERSION_MAJOR < 59 119 | AVCodec* codec = nullptr; 120 | #else 121 | const AVCodec* codec = nullptr; 122 | #endif 123 | 124 | std::mutex lockUpdate; 125 | std::chrono::steady_clock::time_point updatePoint; 126 | 127 | //int bitrate = 1024; 128 | int fps = 25; 129 | int pts = 0; 130 | 131 | protected: 132 | void initContext(const XCB::Size &); 133 | 134 | public: 135 | void resizedEvent(const XCB::Size &) override; 136 | void sendFrameBuffer(EncoderStream*, const FrameBuffer &) override; 137 | 138 | EncodingFFmpeg(int type); 139 | ~EncodingFFmpeg() = default; 140 | 141 | const char* getTypeName(void) const override; 142 | }; 143 | 144 | #endif // ENCODING_FFMPEG 145 | 146 | #ifdef LTSM_DECODING_FFMPEG 147 | /// DecodingFFmpeg 148 | class DecodingFFmpeg : public DecodingBase 149 | { 150 | PixelFormat pf; 151 | 152 | std::unique_ptr avcctx; 153 | std::unique_ptr swsctx; 154 | std::unique_ptr frame; 155 | std::unique_ptr packet; 156 | std::unique_ptr rgb; 157 | std::unique_ptr rgbdata{nullptr, av_free}; 158 | 159 | #if LIBAVFORMAT_VERSION_MAJOR < 59 160 | AVCodec* codec = nullptr; 161 | #else 162 | const AVCodec* codec = nullptr; 163 | #endif 164 | 165 | std::mutex lockUpdate; 166 | 167 | protected: 168 | void initContext(const XCB::Size &); 169 | 170 | public: 171 | void resizedEvent(const XCB::Size &) override; 172 | void updateRegion(DecoderStream &, const XCB::Region &) override; 173 | 174 | DecodingFFmpeg(int type); 175 | ~DecodingFFmpeg() = default; 176 | }; 177 | 178 | #endif // DECODING_FFMPEG 179 | } 180 | } 181 | 182 | #endif // _LIBRFB_FFMPEG_ 183 | -------------------------------------------------------------------------------- /src/librfb/librfb_winclient.cpp: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2025 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #include 25 | #include 26 | 27 | #include "ltsm_application.h" 28 | #include "ltsm_tools.h" 29 | 30 | #include "ltsm_librfb.h" 31 | #include "librfb_winclient.h" 32 | 33 | using namespace std::chrono_literals; 34 | 35 | namespace LTSM 36 | { 37 | RFB::WinClient::WinClient() 38 | { 39 | } 40 | 41 | void RFB::WinClient::extClipboardSendEvent(const std::vector & buf) 42 | { 43 | Application::debug(DebugType::WinCli, "%s, length: %" PRIu32, __FUNCTION__, buf.size()); 44 | sendCutTextEvent(buf.data(), buf.size(), true); 45 | } 46 | 47 | uint16_t RFB::WinClient::extClipboardLocalTypes(void) const 48 | { 49 | return clipLocalTypes; 50 | } 51 | 52 | std::vector RFB::WinClient::extClipboardLocalData(uint16_t type) const 53 | { 54 | if(0 == extClipboardLocalCaps()) 55 | { 56 | Application::error("%s: unsupported encoding: %s", __FUNCTION__, encodingName(ENCODING_EXT_CLIPBOARD)); 57 | throw rfb_error(NS_FuncName); 58 | } 59 | 60 | Application::debug(DebugType::WinCli, "%s", __FUNCTION__); 61 | 62 | /* 63 | auto ptr = const_cast(this); 64 | if(auto copy = static_cast(ptr->getExtension(XCB::Module::SELECTION_COPY))) 65 | { 66 | for(const auto & atom: ExtClip::typesToX11Atoms(type, *this)) 67 | { 68 | ptr->clientClipboard.clear(); 69 | copy->convertSelection(atom, *this); 70 | 71 | // wait data from selectionReceiveData 72 | Tools::Timeout waitCb(100ms); 73 | 74 | while(true) 75 | { 76 | std::this_thread::sleep_for(3ms); 77 | 78 | if(waitCb.check()) 79 | break; 80 | 81 | const std::scoped_lock guard{ clientLock }; 82 | 83 | if(clientClipboard.size()) 84 | return clientClipboard; 85 | } 86 | } 87 | } 88 | */ 89 | return {}; 90 | } 91 | 92 | void RFB::WinClient::extClipboardRemoteTypesEvent(uint16_t types) 93 | { 94 | Application::debug(DebugType::WinCli, "%s, types: 0x%04" PRIx16, __FUNCTION__, types); 95 | if(extClipboardRemoteCaps()) 96 | { 97 | clipRemoteTypes = types; 98 | 99 | //if(auto paste = static_cast(getExtension(XCB::Module::SELECTION_PASTE))) 100 | // paste->setSelectionOwner(*this); 101 | } 102 | else 103 | { 104 | Application::error("%s: unsupported encoding: %s", __FUNCTION__, encodingName(ENCODING_EXT_CLIPBOARD)); 105 | throw rfb_error(NS_FuncName); 106 | } 107 | } 108 | 109 | void RFB::WinClient::extClipboardRemoteDataEvent(uint16_t type, std::vector && buf) 110 | { 111 | Application::debug(DebugType::WinCli, "%s, type: 0x%04" PRIx16 ", length: %" PRIu32, __FUNCTION__, type, buf.size()); 112 | if(extClipboardRemoteCaps()) 113 | { 114 | const std::scoped_lock guard{ clientLock }; 115 | clientClipboard.swap(buf); 116 | } 117 | else 118 | { 119 | Application::error("%s: unsupported encoding: %s", __FUNCTION__, encodingName(ENCODING_EXT_CLIPBOARD)); 120 | throw rfb_error(NS_FuncName); 121 | } 122 | } 123 | 124 | void RFB::WinClient::clientRecvCutTextEvent(std::vector && buf) 125 | { 126 | Application::debug(DebugType::WinCli, "%s: data length: %" PRIu32, __FUNCTION__, buf.size()); 127 | 128 | const std::scoped_lock guard{ clientLock }; 129 | clientClipboard.swap(buf); 130 | 131 | //if(auto paste = static_cast(getExtension(XCB::Module::SELECTION_PASTE))) 132 | // paste->setSelectionOwner(*this); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/librfb/librfb_winclient.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2025 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LIBRFB_WINCLI_ 25 | #define _LIBRFB_WINCLI_ 26 | 27 | #include 28 | #include 29 | 30 | #include "librfb_client.h" 31 | 32 | namespace LTSM 33 | { 34 | namespace RFB 35 | { 36 | class WinClient : public ClientDecoder 37 | { 38 | std::vector clientClipboard; 39 | 40 | mutable std::mutex clientLock; 41 | 42 | mutable uint16_t clipLocalTypes = 0; 43 | uint16_t clipRemoteTypes = 0; 44 | 45 | protected: 46 | 47 | // ext clipboard 48 | uint16_t extClipboardLocalTypes(void) const override; 49 | std::vector extClipboardLocalData(uint16_t type) const override; 50 | void extClipboardRemoteTypesEvent(uint16_t type) override; 51 | void extClipboardRemoteDataEvent(uint16_t type, std::vector &&) override; 52 | void extClipboardSendEvent(const std::vector &) override; 53 | 54 | void clientRecvCutTextEvent(std::vector &&) override; 55 | 56 | public: 57 | WinClient(); 58 | }; 59 | } 60 | } 61 | 62 | #endif // _LIBRFB_WINCLI_ 63 | -------------------------------------------------------------------------------- /src/librfb/librfb_x11client.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2025 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LIBRFB_X11CLI_ 25 | #define _LIBRFB_X11CLI_ 26 | 27 | #include 28 | #include 29 | 30 | #include "librfb_client.h" 31 | #include "ltsm_xcb_wrapper.h" 32 | 33 | namespace LTSM 34 | { 35 | namespace RFB 36 | { 37 | class X11Client : public XCB::RootDisplay, public ClientDecoder, public XCB::SelectionSource, public XCB::SelectionRecipient 38 | { 39 | std::vector clientClipboard; 40 | 41 | mutable std::mutex clientLock; 42 | 43 | mutable uint16_t clipLocalTypes = 0; 44 | uint16_t clipRemoteTypes = 0; 45 | 46 | protected: 47 | 48 | // selection source 49 | std::vector selectionSourceTargets(void) const override; 50 | bool selectionSourceReady(xcb_atom_t) const override; 51 | size_t selectionSourceSize(xcb_atom_t) const override; 52 | std::vector selectionSourceData(xcb_atom_t, size_t offset, uint32_t length) const override; 53 | 54 | // selection recipient 55 | void selectionReceiveData(xcb_atom_t, const uint8_t* ptr, uint32_t len) const override; 56 | void selectionReceiveTargets(const xcb_atom_t* beg, const xcb_atom_t* end) const override; 57 | void selectionChangedEvent(void) const override; 58 | 59 | // ext clipboard 60 | uint16_t extClipboardLocalTypes(void) const override; 61 | std::vector extClipboardLocalData(uint16_t type) const override; 62 | void extClipboardRemoteTypesEvent(uint16_t type) override; 63 | void extClipboardRemoteDataEvent(uint16_t type, std::vector &&) override; 64 | void extClipboardSendEvent(const std::vector &) override; 65 | 66 | void clientRecvCutTextEvent(std::vector &&) override; 67 | 68 | // x11 event 69 | void xcbDisplayConnectedEvent(void) override; 70 | 71 | public: 72 | X11Client(); 73 | }; 74 | } 75 | } 76 | 77 | #endif // _LIBRFB_X11CLI_ 78 | -------------------------------------------------------------------------------- /src/qt_helper/ltsm_helper.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | ltsm_logo.png 4 | 5 | 6 | ltsm_helper_ru.qm 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/qt_helper/ltsm_helper_ru.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndreyBarmaley/linux-terminal-service-manager/ce163fff8ded0cdcb6fdbc234a61082a53f33e64/src/qt_helper/ltsm_helper_ru.qm -------------------------------------------------------------------------------- /src/qt_helper/ltsm_helper_ru.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LTSM_HelperWindow 6 | 7 | 8 | LTSM_HelperWindow 9 | 10 | 11 | 12 | 13 | 14 | X11 Remote Desktop 15 | 16 | 17 | 18 | 19 | username: 20 | пользователь: 21 | 22 | 23 | 24 | password: 25 | пароль: 26 | 27 | 28 | 29 | encryption: 30 | шифрование: 31 | 32 | 33 | 34 | none 35 | отсутсвует 36 | 37 | 38 | 39 | login 40 | вход в систему 41 | 42 | 43 | 44 | default 45 | 46 | 47 | 48 | 49 | dbus init failed 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/qt_helper/ltsm_ldap_wrapper.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2022 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | ***************************************************************************/ 22 | 23 | #ifndef _LTSM_LDAP_WRAPPER_H_ 24 | #define _LTSM_LDAP_WRAPPER_H_ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | namespace LTSM 33 | { 34 | struct ldap_error : public std::runtime_error 35 | { 36 | explicit ldap_error(std::string_view what) : std::runtime_error(what.data()) {} 37 | }; 38 | 39 | class LdapWrapper 40 | { 41 | LDAP* ldap = nullptr; 42 | 43 | public: 44 | LdapWrapper(); 45 | ~LdapWrapper(); 46 | 47 | std::string findLoginFromDn(const std::string & dn); 48 | std::string findDnFromCertificate(const uint8_t*, size_t); 49 | }; 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/qt_helper/ltsm_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndreyBarmaley/linux-terminal-service-manager/ce163fff8ded0cdcb6fdbc234a61082a53f33e64/src/qt_helper/ltsm_logo.png -------------------------------------------------------------------------------- /src/qt_helper/main.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | ***************************************************************************/ 22 | 23 | #include 24 | #include 25 | 26 | #include "ltsm_application.h" 27 | #include "ltsm_helperwindow.h" 28 | 29 | class LtsmHelper : public LTSM::Application, public QApplication 30 | { 31 | 32 | public: 33 | LtsmHelper(int & argc, char** argv) : LTSM::Application("ltsm_helper"), QApplication(argc, argv) 34 | { 35 | LTSM::Application::setDebug(LTSM::DebugTarget::Syslog, LTSM::DebugLevel::Info); 36 | } 37 | 38 | int start(void) override 39 | { 40 | QTranslator tr; 41 | tr.load(QLocale(), QLatin1String("ltsm_helper"), QLatin1String("_"), QLatin1String(":/i18n")); 42 | installTranslator(& tr); 43 | LTSM_HelperSDBus win; 44 | win.show(); 45 | return exec(); 46 | } 47 | }; 48 | 49 | int main(int argc, char* argv[]) 50 | { 51 | int res = 0; 52 | 53 | try 54 | { 55 | LtsmHelper app(argc, argv); 56 | res = app.start(); 57 | } 58 | catch(const sdbus::Error & err) 59 | { 60 | LTSM::Application::error("sdbus exception: [%s] %s", err.getName().c_str(), err.getMessage().c_str()); 61 | } 62 | catch(const std::exception & err) 63 | { 64 | LTSM::Application::error("%s: exception: %s", NS_FuncName.c_str(), err.what()); 65 | } 66 | 67 | return res; 68 | } 69 | -------------------------------------------------------------------------------- /src/qt_sessions/ltsm_offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndreyBarmaley/linux-terminal-service-manager/ce163fff8ded0cdcb6fdbc234a61082a53f33e64/src/qt_sessions/ltsm_offline.png -------------------------------------------------------------------------------- /src/qt_sessions/ltsm_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndreyBarmaley/linux-terminal-service-manager/ce163fff8ded0cdcb6fdbc234a61082a53f33e64/src/qt_sessions/ltsm_online.png -------------------------------------------------------------------------------- /src/qt_sessions/ltsm_sessions.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | ***************************************************************************/ 22 | 23 | #ifndef LTSM_SESSIONS_H 24 | #define LTSM_SESSIONS_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | struct XvfbInfo 37 | { 38 | int display = -1; 39 | int pid1 = 0; 40 | int pid2 = 0; 41 | int width = 0; 42 | int height = 0; 43 | int uid = 0; 44 | int gid = 0; 45 | int durationLimit = 0; 46 | int mode = 0; 47 | int policy = 0; 48 | QString user; 49 | QString authfile; 50 | QString remoteaddr; 51 | QString conntype; 52 | QString encryption; 53 | }; 54 | 55 | Q_DECLARE_METATYPE(XvfbInfo); 56 | 57 | struct RowItem : QTableWidgetItem 58 | { 59 | RowItem(const XvfbInfo &, const QString &); 60 | RowItem(const XvfbInfo &, const QIcon &, const QString &); 61 | 62 | XvfbInfo xvfbInfo(void) const; 63 | int display(void) const; 64 | }; 65 | 66 | namespace Ui 67 | { 68 | class LTSM_Sessions; 69 | } 70 | 71 | class LTSM_Sessions : public QDialog 72 | { 73 | Q_OBJECT 74 | 75 | protected slots: 76 | void tableReload(void); 77 | void disconnectClicked(void); 78 | void logoffClicked(void); 79 | void showClicked(void); 80 | void showInformation(void); 81 | void sendmsgClicked(void); 82 | void itemSelectionChanged(void); 83 | void itemDoubleClicked(QTableWidgetItem*); 84 | void displayRemovedCallback(int); 85 | void sessionChangedCallback(int); 86 | void customContextMenu(QPoint); 87 | void changeSessionPolicy(void); 88 | void changeSessionDuration(void); 89 | 90 | public: 91 | explicit LTSM_Sessions(QWidget* parent = 0); 92 | ~LTSM_Sessions(); 93 | 94 | private: 95 | Ui::LTSM_Sessions* ui; 96 | QScopedPointer dbusInterfacePtr; 97 | const RowItem* selectedRow; 98 | QFileInfo sdl2x11; 99 | QProcess process; 100 | }; 101 | 102 | #endif // LTSM_SESSIONS_H 103 | -------------------------------------------------------------------------------- /src/qt_sessions/ltsm_sessions.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | ltsm_offline.png 4 | ltsm_online.png 5 | 6 | 7 | ltsm_sessions_ru.qm 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/qt_sessions/ltsm_sessions.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | LTSM_Sessions 4 | 5 | 6 | 7 | 0 8 | 0 9 | 515 10 | 339 11 | 12 | 13 | 14 | LTSM sessions 15 | 16 | 17 | 18 | 19 | 20 | QAbstractItemView::NoEditTriggers 21 | 22 | 23 | QAbstractItemView::SelectRows 24 | 25 | 26 | 0 27 | 28 | 29 | true 30 | 31 | 32 | 33 | 34 | 35 | 36 | Qt::Horizontal 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Qt::Horizontal 46 | 47 | 48 | 49 | 40 50 | 20 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | false 59 | 60 | 61 | show display 62 | 63 | 64 | Show 65 | 66 | 67 | 68 | 69 | 70 | 71 | false 72 | 73 | 74 | disconnect session 75 | 76 | 77 | Disconnect 78 | 79 | 80 | 81 | 82 | 83 | 84 | false 85 | 86 | 87 | logout session 88 | 89 | 90 | Logout 91 | 92 | 93 | 94 | 95 | 96 | 97 | false 98 | 99 | 100 | send message 101 | 102 | 103 | Send Message... 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | disconnectClicked() 118 | logoffClicked() 119 | sendmsgClicked() 120 | itemClicked(QTableWidgetItem*) 121 | showClicked() 122 | showMenu(QPoint) 123 | 124 | 125 | -------------------------------------------------------------------------------- /src/qt_sessions/ltsm_sessions_ru.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndreyBarmaley/linux-terminal-service-manager/ce163fff8ded0cdcb6fdbc234a61082a53f33e64/src/qt_sessions/ltsm_sessions_ru.qm -------------------------------------------------------------------------------- /src/qt_sessions/main.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | ***************************************************************************/ 22 | 23 | #include "ltsm_sessions.h" 24 | #include 25 | #include 26 | 27 | int main(int argc, char* argv[]) 28 | { 29 | int res = 0; 30 | 31 | try 32 | { 33 | QApplication a(argc, argv); 34 | QTranslator t; 35 | t.load(QLocale(), QLatin1String("ltsm_sessions"), QLatin1String("_"), QLatin1String(":/i18n")); 36 | a.installTranslator(& t); 37 | LTSM_Sessions w; 38 | w.show(); 39 | res = a.exec(); 40 | } 41 | catch(int e) 42 | { 43 | res = e; 44 | } 45 | 46 | return res; 47 | } 48 | -------------------------------------------------------------------------------- /src/sane_backend/unix.conf.in: -------------------------------------------------------------------------------- 1 | # This is the unix backend config file. 2 | 3 | ## env: SANE_UNIX_PATH 4 | 5 | ## saned socket path 6 | /var/run/ltsm/sane/path 7 | -------------------------------------------------------------------------------- /src/sane_backend/unix.h: -------------------------------------------------------------------------------- 1 | /* sane - Scanner Access Now Easy. 2 | Copyright (C) 1997 David Mosberger-Tang 3 | Copyright (C) 2003 Julien BLACHE 4 | Copyright (C) 2022 Andrey Afletdinov 5 | 6 | This file is part of the LTSM sane_backend package. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation; either version 2 of the 11 | License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see . 20 | */ 21 | #ifndef unix_h 22 | #define unix_h 23 | 24 | #include 25 | #include 26 | 27 | #include "../include/sane/sanei_wire.h" 28 | #include "../include/sane/config.h" 29 | 30 | typedef struct Unix_Device 31 | { 32 | struct Unix_Device *next; 33 | const char *name; 34 | struct sockaddr addr; 35 | int ctl; /* socket descriptor (or -1) */ 36 | Wire wire; 37 | int auth_active; 38 | } 39 | 40 | Unix_Device; 41 | 42 | typedef struct Unix_Scanner 43 | { 44 | /* all the state needed to define a scan request: */ 45 | struct Unix_Scanner *next; 46 | 47 | int options_valid; /* are the options current? */ 48 | SANE_Option_Descriptor_Array opt, local_opt; 49 | 50 | SANE_Word handle; /* remote handle (it's a word, not a ptr!) */ 51 | 52 | int data; /* data socket descriptor */ 53 | int reclen_buf_offset; 54 | u_char reclen_buf[4]; 55 | size_t bytes_remaining; /* how many bytes left in this record? */ 56 | 57 | /* device (host) info: */ 58 | Unix_Device *hw; 59 | } 60 | 61 | Unix_Scanner; 62 | 63 | #endif /* unix_h */ 64 | -------------------------------------------------------------------------------- /src/sdl2x11/ltsm_sdl_wrapper.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | ***************************************************************************/ 22 | 23 | #ifndef _SDL_WRAPPER_ 24 | #define _SDL_WRAPPER_ 25 | 26 | #include 27 | #include 28 | 29 | #include "SDL.h" 30 | 31 | namespace LTSM 32 | { 33 | #if SDL_BYTEORDER == SDL_BIG_ENDIAN 34 | inline static const int TEXTURE_FMT = SDL_PIXELFORMAT_ARGB32; 35 | #else 36 | inline static const int TEXTURE_FMT = SDL_PIXELFORMAT_BGRA32; 37 | #endif 38 | 39 | struct sdl_error : public std::runtime_error 40 | { 41 | explicit sdl_error(std::string_view what) : std::runtime_error(what.data()) {} 42 | }; 43 | 44 | namespace SDL 45 | { 46 | struct Texture : std::shared_ptr 47 | { 48 | Texture(SDL_Texture* ptr = nullptr) 49 | : std::shared_ptr(ptr, SDL_DestroyTexture) {} 50 | 51 | bool isValid(void) const; 52 | 53 | int width(void) const; 54 | int height(void) const; 55 | 56 | void updateRect(const SDL_Rect*, const void* pixels, int pitch); 57 | }; 58 | 59 | struct Surface : std::shared_ptr 60 | { 61 | Surface(SDL_Surface* ptr = nullptr) 62 | : std::shared_ptr(ptr, SDL_FreeSurface) {} 63 | 64 | bool isValid(void) const; 65 | int width(void) const; 66 | int height(void) const; 67 | }; 68 | 69 | struct GenericEvent 70 | { 71 | const SDL_Event* ptr; 72 | 73 | GenericEvent(const SDL_Event* ev) : ptr(ev) {} 74 | 75 | bool isValid(void) const 76 | { 77 | return ptr; 78 | } 79 | 80 | int type(void) const 81 | { 82 | return ptr ? ptr->type : 0; 83 | } 84 | 85 | const SDL_KeyboardEvent* key(void) const 86 | { 87 | return ptr ? & ptr->key : nullptr; 88 | } 89 | 90 | const SDL_MouseMotionEvent* motion(void) const 91 | { 92 | return ptr ? & ptr->motion : nullptr; 93 | } 94 | 95 | const SDL_MouseButtonEvent* button(void) const 96 | { 97 | return ptr ? & ptr->button : nullptr; 98 | } 99 | 100 | const SDL_MouseWheelEvent* wheel(void) const 101 | { 102 | return ptr ? & ptr->wheel : nullptr; 103 | } 104 | 105 | const SDL_WindowEvent* window(void) const 106 | { 107 | return ptr ? & ptr->window : nullptr; 108 | } 109 | 110 | const SDL_DropEvent* drop(void) const 111 | { 112 | return ptr ? & ptr->drop : nullptr; 113 | } 114 | 115 | const SDL_UserEvent* user(void) const 116 | { 117 | return ptr ? & ptr->user : nullptr; 118 | } 119 | }; 120 | 121 | class Window 122 | { 123 | std::unique_ptr _window{ nullptr, SDL_DestroyWindow }; 124 | std::unique_ptr _renderer{ nullptr, SDL_DestroyRenderer }; 125 | std::unique_ptr _display{ nullptr, SDL_DestroyTexture }; 126 | SDL_Event _event; 127 | bool _accel = false; 128 | 129 | protected: 130 | 131 | public: 132 | Window(const std::string & title, int rendsz_w, int rendsz_h, int winsz_w = 0, int winsz_h = 0, int flags = 0, 133 | bool accel = true); 134 | ~Window(); 135 | 136 | bool isValid(void) const; 137 | bool resize(int newsz_w, int newsz_h); 138 | 139 | uint32_t pixelFormat(void) const; 140 | std::pair geometry(void) const; 141 | 142 | SDL_Texture* display(void) 143 | { 144 | return _display.get(); 145 | } 146 | 147 | SDL_Renderer* render(void) 148 | { 149 | return _renderer.get(); 150 | } 151 | 152 | SDL_Window* get(void) 153 | { 154 | return _window.get(); 155 | } 156 | 157 | void renderClear(const SDL_Color*, SDL_Texture* target = nullptr); 158 | void renderColor(const SDL_Color*, const SDL_Rect*, SDL_Texture* target = nullptr); 159 | void renderTexture(SDL_Texture* source, const SDL_Rect* srcrt = nullptr, SDL_Texture* target = nullptr, 160 | const SDL_Rect* dstrt = nullptr); 161 | 162 | void renderReset(SDL_Texture* target = nullptr); 163 | void renderPresent(void); 164 | 165 | Texture createTexture(int width, int height, uint32_t format = TEXTURE_FMT) const; 166 | 167 | GenericEvent pollEvent(void); 168 | static int convertScanCodeToKeySym(SDL_Scancode); 169 | 170 | std::pair scaleCoord(int posx, int posy) const; 171 | }; 172 | } 173 | } 174 | 175 | #endif // LTSM_SDL_WRAPPER_ 176 | -------------------------------------------------------------------------------- /src/session_audio/ltsm_audio.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_AUDIO_ 25 | #define _LTSM_AUDIO_ 26 | 27 | #define LTSM_AUDIO2SESSION_VERSION 20240304 28 | 29 | #include 30 | #include 31 | 32 | namespace LTSM 33 | { 34 | namespace AudioOp 35 | { 36 | enum 37 | { 38 | Init = 0xFE01, 39 | Data = 0xFE02, 40 | Silent = 0xFE03 41 | }; 42 | } 43 | 44 | namespace AudioEncoding 45 | { 46 | enum 47 | { 48 | PCM = 0, 49 | OPUS = 1, 50 | AAC = 2 51 | }; 52 | } 53 | 54 | struct AudioFormat 55 | { 56 | uint16_t type = 0; 57 | uint16_t channels = 0; 58 | uint32_t samplePerSec = 0; 59 | uint16_t bitsPerSample = 0; 60 | }; 61 | 62 | class AudioPlayer 63 | { 64 | public: 65 | AudioPlayer() = default; 66 | virtual ~AudioPlayer() = default; 67 | 68 | virtual bool streamWrite(const uint8_t*, size_t) const = 0; 69 | }; 70 | 71 | struct audio_error : public std::runtime_error 72 | { 73 | explicit audio_error(std::string_view what) : std::runtime_error(what.data()) {} 74 | }; 75 | } 76 | 77 | #endif // _LTSM_AUDIO_ 78 | -------------------------------------------------------------------------------- /src/session_audio/ltsm_audio_decoder.cpp: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #include "ltsm_tools.h" 25 | #include "ltsm_audio.h" 26 | #include "ltsm_application.h" 27 | #include "ltsm_audio_decoder.h" 28 | 29 | namespace LTSM 30 | { 31 | #ifdef LTSM_WITH_OPUS 32 | AudioDecoder::Opus::Opus(uint32_t samplesPerSec, uint16_t audioChannels, uint16_t bitsPerSample) 33 | : sampleLength(audioChannels * (bitsPerSample >> 3)) 34 | { 35 | if(bitsPerSample != sizeof(opus_int16) * 8) 36 | { 37 | Application::error("%s: %s failed", __FUNCTION__, "bitsPerSample"); 38 | throw audio_error(NS_FuncName); 39 | } 40 | 41 | int error = OPUS_OK; 42 | ctx.reset(opus_decoder_create(samplesPerSec, audioChannels, & error)); 43 | 44 | if(! ctx || error != OPUS_OK) 45 | { 46 | Application::error("%s: %s failed, error: %d, sampleRate: %" PRIu32 ", audioChannels: %" PRIu16, __FUNCTION__, 47 | "opus_decoder_create", error, samplesPerSec, audioChannels); 48 | throw audio_error(NS_FuncName); 49 | } 50 | } 51 | 52 | bool AudioDecoder::Opus::decode(const uint8_t* ptr, size_t len) 53 | { 54 | int frames = opus_decoder_get_nb_samples(ctx.get(), ptr, len); 55 | 56 | if(0 > frames) 57 | { 58 | Application::error("%s: %s failed, error: %d, data size: %u", __FUNCTION__, "opus_decoder_get_nb_samples", frames, len); 59 | throw audio_error(NS_FuncName); 60 | } 61 | 62 | if(0 == frames) 63 | { 64 | return false; 65 | } 66 | 67 | tmp.resize(frames* sampleLength); 68 | int nSamples = opus_decode(ctx.get(), ptr, len, (opus_int16*) tmp.data(), frames, 0); 69 | 70 | if(nSamples < 0) 71 | { 72 | Application::error("%: %s failed, error: %d", __FUNCTION__, "opus_decode", nSamples); 73 | return false; 74 | } 75 | 76 | decodeSize = nSamples * sampleLength; 77 | return true; 78 | } 79 | 80 | const uint8_t* AudioDecoder::Opus::data(void) const 81 | { 82 | return tmp.data(); 83 | } 84 | 85 | size_t AudioDecoder::Opus::size(void) const 86 | { 87 | if(decodeSize > tmp.size()) 88 | { 89 | Application::error("%s: out of range, size: %u, buf: %u", __FUNCTION__, decodeSize, tmp.size()); 90 | throw audio_error(NS_FuncName); 91 | } 92 | 93 | return decodeSize; 94 | } 95 | 96 | #endif 97 | } 98 | -------------------------------------------------------------------------------- /src/session_audio/ltsm_audio_decoder.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_AUDIO_DECODER_ 25 | #define _LTSM_AUDIO_DECODER_ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #ifdef LTSM_WITH_OPUS 32 | #include "opus/opus.h" 33 | #endif 34 | 35 | namespace LTSM 36 | { 37 | namespace AudioDecoder 38 | { 39 | class BaseDecoder 40 | { 41 | public: 42 | BaseDecoder() = default; 43 | virtual ~BaseDecoder() = default; 44 | 45 | virtual bool decode(const uint8_t* ptr, size_t len) = 0; 46 | 47 | virtual const uint8_t* data(void) const = 0; 48 | virtual size_t size(void) const = 0; 49 | }; 50 | 51 | #ifdef LTSM_WITH_OPUS 52 | struct OpusDeleter 53 | { 54 | void operator()(OpusDecoder* st) 55 | { 56 | opus_decoder_destroy(st); 57 | } 58 | }; 59 | 60 | class Opus : public BaseDecoder 61 | { 62 | std::unique_ptr ctx; 63 | 64 | std::vector tmp; 65 | size_t decodeSize = 0; 66 | 67 | const size_t sampleLength; 68 | 69 | public: 70 | Opus(uint32_t samplesPerSec, uint16_t audioChannels, uint16_t bitsPerSample); 71 | 72 | bool decode(const uint8_t* ptr, size_t len) override; 73 | const uint8_t* data(void) const override; 74 | size_t size(void) const override; 75 | }; 76 | 77 | #endif 78 | } 79 | } 80 | 81 | #endif // _LTSM_AUDIO_DECODER_ 82 | -------------------------------------------------------------------------------- /src/session_audio/ltsm_audio_encoder.cpp: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #include "ltsm_tools.h" 25 | #include "ltsm_audio.h" 26 | #include "ltsm_application.h" 27 | #include "ltsm_audio_encoder.h" 28 | 29 | namespace LTSM 30 | { 31 | #ifdef LTSM_WITH_OPUS 32 | AudioEncoder::Opus::Opus(uint32_t samplesPerSec, uint16_t audioChannels, uint16_t bitsPerSample, uint16_t frames) 33 | : framesCount(frames), sampleLength(audioChannels * (bitsPerSample >> 3)) 34 | { 35 | const size_t reserveSize = 256 * 1024; 36 | last.reserve(reserveSize); 37 | int error = OPUS_OK; 38 | ctx.reset(opus_encoder_create(samplesPerSec, audioChannels, 39 | OPUS_APPLICATION_AUDIO /* OPUS_APPLICATION_RESTRICTED_LOWDELAY OPUS_APPLICATION_VOIP OPUS_APPLICATION_AUDIO */, 40 | & error)); 41 | 42 | if(! ctx || error != OPUS_OK) 43 | { 44 | Application::error("%s: %s failed, error: %d, sampleRate: %" PRIu32 ", audioChannels: %" PRIu16, __FUNCTION__, 45 | "opus_encoder_create", error, samplesPerSec, audioChannels); 46 | throw audio_error(NS_FuncName); 47 | } 48 | 49 | /* 50 | error = opus_encoder_ctl(ctx.get(), OPUS_SET_BITRATE(bitRate)); 51 | if(error != OPUS_OK) 52 | { 53 | Application::error("%s: %s failed, error: %d", __FUNCTION__, "opus_encoder_ctl", error); 54 | throw audio_error(NS_FuncName); 55 | } 56 | */ 57 | } 58 | 59 | bool AudioEncoder::Opus::encode(const uint8_t* ptr, size_t len) 60 | { 61 | if(len) 62 | { 63 | last.insert(last.end(), ptr, ptr + len); 64 | } 65 | 66 | const size_t samplesCount = last.size() / sampleLength; 67 | 68 | if(framesCount > samplesCount) 69 | { 70 | return false; 71 | } 72 | 73 | auto src = (const opus_int16*) last.data(); 74 | int nBytes = opus_encode(ctx.get(), src, framesCount, tmp.data(), tmp.size()); 75 | 76 | if(nBytes < 0) 77 | { 78 | Application::error("%s: %s failed, error: %d", __FUNCTION__, "opus_encode", nBytes); 79 | return false; 80 | } 81 | 82 | last.erase(last.begin(), Tools::nextToEnd(last.begin(), framesCount * sampleLength, last.end())); 83 | encodeSize = nBytes; 84 | return 0 < encodeSize; 85 | } 86 | 87 | const uint8_t* AudioEncoder::Opus::data(void) const 88 | { 89 | return tmp.data(); 90 | } 91 | 92 | size_t AudioEncoder::Opus::size(void) const 93 | { 94 | if(encodeSize > tmp.size()) 95 | { 96 | Application::error("%s: out of range, size: %u, buf: %u", __FUNCTION__, encodeSize, tmp.size()); 97 | throw audio_error(NS_FuncName); 98 | } 99 | 100 | return encodeSize; 101 | } 102 | 103 | #endif 104 | } 105 | -------------------------------------------------------------------------------- /src/session_audio/ltsm_audio_encoder.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_AUDIO_ENCODER_ 25 | #define _LTSM_AUDIO_ENCODER_ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #ifdef LTSM_WITH_OPUS 32 | #include "opus/opus.h" 33 | #endif 34 | 35 | namespace LTSM 36 | { 37 | namespace AudioEncoder 38 | { 39 | class BaseEncoder 40 | { 41 | public: 42 | BaseEncoder() = default; 43 | virtual ~BaseEncoder() = default; 44 | 45 | virtual bool encode(const uint8_t* ptr, size_t len) = 0; 46 | 47 | virtual const uint8_t* data(void) const = 0; 48 | virtual size_t size(void) const = 0; 49 | }; 50 | 51 | #ifdef LTSM_WITH_OPUS 52 | struct OpusDeleter 53 | { 54 | void operator()(OpusEncoder* st) 55 | { 56 | opus_encoder_destroy(st); 57 | } 58 | }; 59 | 60 | class Opus : public BaseEncoder 61 | { 62 | std::unique_ptr ctx; 63 | 64 | // ref: https://www.opus-codec.org/docs/html_api/group__opusencoder.html 65 | // max_packet is the maximum number of bytes that can be written in the packet (1276 bytes is recommended) 66 | std::array tmp; 67 | size_t encodeSize = 0; 68 | 69 | // Opus: frame size - at 48kHz the permitted values are 120, 240, 480, or 960, the remainder will be stored here. 70 | std::vector last; 71 | 72 | const size_t framesCount; 73 | const size_t sampleLength; 74 | 75 | public: 76 | Opus(uint32_t samplesPerSec, uint16_t audioChannels, uint16_t bitsPerSample, uint16_t frames = 480); 77 | 78 | bool encode(const uint8_t* ptr, size_t len) override; 79 | 80 | const uint8_t* data(void) const override; 81 | size_t size(void) const override; 82 | }; 83 | 84 | #endif 85 | } 86 | } 87 | 88 | #endif // _LTSM_AUDIO_ENCODER_ 89 | -------------------------------------------------------------------------------- /src/session_audio/ltsm_audio_openal.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2025 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_AUDIO_OPENAL_ 25 | #define _LTSM_AUDIO_OPENAL_ 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | namespace LTSM 33 | { 34 | namespace OpenAL 35 | { 36 | const char* alcErrorName(ALCenum); 37 | 38 | class Playback : public AudioPlayer 39 | { 40 | std::unique_ptr dev{ nullptr, alcCloseDevice }; 41 | std::unique_ptr ctx{ nullptr, alcDestroyContext }; 42 | 43 | ALuint sourceId = 0; 44 | mutable ALuint playAfterBytes = 0; 45 | 46 | ALenum fmtFormat = 0; 47 | ALsizei fmtFrequency = 0; 48 | 49 | protected: 50 | ALint getBuffersProcessed(void) const; 51 | ALint getBuffersQueued(void) const; 52 | ALuint findFreeBufferId(void) const; 53 | 54 | public: 55 | Playback(const AudioFormat &, ALuint autoPlayAfterSec = 0); 56 | ~Playback(); 57 | 58 | bool streamWrite(const uint8_t*, size_t) const override; 59 | 60 | bool playStart(void) const; 61 | bool playStop(void) const; 62 | bool playPause(void) const; 63 | bool stateIsPlaying(void) const; 64 | }; 65 | } 66 | } 67 | 68 | #endif // _LTSM_AUDIO_OPENAL_ 69 | -------------------------------------------------------------------------------- /src/session_audio/ltsm_audio_session.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_AUDIO_SESSION_ 25 | #define _LTSM_AUDIO_SESSION_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "ltsm_streambuf.h" 34 | #include "ltsm_application.h" 35 | #include "ltsm_audio_pulse.h" 36 | #include "ltsm_audio_encoder.h" 37 | #include "ltsm_audio_adaptor.h" 38 | 39 | namespace LTSM 40 | { 41 | struct AudioClient 42 | { 43 | std::string socketPath; 44 | 45 | std::unique_ptr pulse; 46 | std::unique_ptr encoder; 47 | std::unique_ptr sock; 48 | 49 | std::thread thread; 50 | std::atomic shutdown{false}; 51 | 52 | AudioClient(const std::string &); 53 | ~AudioClient(); 54 | }; 55 | 56 | class AudioSessionBus : public sdbus::AdaptorInterfaces, public Application 57 | { 58 | std::forward_list clients; 59 | 60 | public: 61 | AudioSessionBus(sdbus::IConnection &); 62 | virtual ~AudioSessionBus(); 63 | 64 | int start(void) override; 65 | 66 | int32_t getVersion(void) override; 67 | void serviceShutdown(void) override; 68 | void setDebug(const std::string & level) override; 69 | 70 | bool connectChannel(const std::string & clientSocket) override; 71 | void disconnectChannel(const std::string & clientSocket) override; 72 | 73 | void pulseFragmentSize(const uint32_t & fragsz) override; 74 | }; 75 | } 76 | 77 | #endif // _LTSM_AUDIO_SESSION_ 78 | -------------------------------------------------------------------------------- /src/session_fuse/ltsm_fuse.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_FUSE_ 25 | #define _LTSM_FUSE_ 26 | 27 | #define LTSM_FUSE2SESSION_VERSION 20240304 28 | 29 | #include 30 | 31 | namespace LTSM 32 | { 33 | namespace FuseOp 34 | { 35 | enum 36 | { 37 | Init = 0xFF01, 38 | Quit = 0xFF02, 39 | GetAttr = 0xFF03, 40 | ReadDir = 0xFF04, 41 | Open = 0xFF05, 42 | Read = 0xFF06, 43 | Release = 0xFF07, 44 | // 45 | Access = 0xFF08, 46 | RmDir = 0xFF09, 47 | UnLink = 0xFF10, 48 | Rename = 0xFF11, 49 | Truncate = 0xFF12, 50 | Write = 0xFF13, 51 | Create = 0xFF14, 52 | // 53 | Lookup = 0xFF15 54 | }; 55 | } 56 | 57 | struct fuse_error : public std::runtime_error 58 | { 59 | explicit fuse_error(std::string_view what) : std::runtime_error(what.data()) {} 60 | }; 61 | } 62 | 63 | #endif // _LTSM_FUSE_ 64 | -------------------------------------------------------------------------------- /src/session_fuse/ltsm_fuse_session.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_FUSE_SESSION_ 25 | #define _LTSM_FUSE_SESSION_ 26 | 27 | #include 28 | #include 29 | 30 | #include "ltsm_fuse.h" 31 | #include "ltsm_fuse_adaptor.h" 32 | 33 | namespace LTSM 34 | { 35 | struct FuseSession; 36 | 37 | class FuseSessionBus : public sdbus::AdaptorInterfaces, public Application 38 | { 39 | std::forward_list> childs; 40 | 41 | public: 42 | FuseSessionBus(sdbus::IConnection &); 43 | virtual ~FuseSessionBus(); 44 | 45 | int start(void) override; 46 | 47 | int32_t getVersion(void) override; 48 | void serviceShutdown(void) override; 49 | void setDebug(const std::string & level) override; 50 | 51 | bool mountPoint(const std::string & localPoint, const std::string & remotePoint, 52 | const std::string & fuseSocket) override; 53 | void umountPoint(const std::string & point) override; 54 | }; 55 | } 56 | 57 | #endif // _LTSM_FUSE_ 58 | -------------------------------------------------------------------------------- /src/session_pcsc/ltsm_pcsc.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_PCSC_ 25 | #define _LTSM_PCSC_ 26 | 27 | #define LTSM_PCSC2SESSION_VERSION 20240723 28 | 29 | #include 30 | #include 31 | 32 | namespace PcscLite 33 | { 34 | enum 35 | { 36 | EstablishContext = 0x01, 37 | ReleaseContext = 0x02, 38 | ListReaders = 0x03, 39 | Connect = 0x04, 40 | Reconnect = 0x05, 41 | Disconnect = 0x06, 42 | BeginTransaction = 0x07, 43 | EndTransaction = 0x08, 44 | Transmit = 0x09, 45 | Control = 0x0A, 46 | Status = 0x0B, 47 | GetStatusChange = 0x0C, 48 | Cancel = 0x0D, 49 | CancelTransaction = 0x0E, 50 | GetAttrib = 0x0F, 51 | SetAttrib = 0x10, 52 | GetVersion = 0x11, 53 | GetReaderState = 0x12, 54 | WaitReaderStateChangeStart = 0x13, 55 | WaitReaderStateChangeStop = 0x14 56 | }; 57 | } 58 | 59 | namespace LTSM 60 | { 61 | namespace PcscOp 62 | { 63 | enum 64 | { 65 | Init = 0xFD01 66 | }; 67 | } 68 | 69 | struct pcsc_error : public std::runtime_error 70 | { 71 | explicit pcsc_error(std::string_view what) : std::runtime_error(what.data()) {} 72 | }; 73 | } 74 | 75 | #endif // _LTSM_PCSC_ 76 | -------------------------------------------------------------------------------- /src/session_pcsc/ltsm_pcsc_session.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_PCSC_SESSION_ 25 | #define _LTSM_PCSC_SESSION_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "pcsclite.h" 35 | 36 | #include "ltsm_pcsc.h" 37 | #include "ltsm_streambuf.h" 38 | #include "ltsm_application.h" 39 | #include "ltsm_pcsc_adaptor.h" 40 | 41 | namespace PcscLite 42 | { 43 | // origin READER_STATE: PCSC/src/eventhandler.h 44 | struct ReaderState 45 | { 46 | char name[MAX_READERNAME];///< reader name 47 | uint32_t event = 0; ///< number of card events 48 | uint32_t state = 0; ///< SCARD_* bit field 49 | int32_t share = 0; ///< PCSCLITE_SHARING_* sharing status 50 | 51 | uint8_t atr[MAX_ATR_SIZE];///< ATR 52 | uint32_t atrLen = 0; ///< ATR length 53 | uint32_t protocol = 0; ///< SCARD_PROTOCOL_* value 54 | 55 | void reset(void); 56 | }; 57 | } 58 | 59 | namespace LTSM 60 | { 61 | class PcscSessionBus; 62 | 63 | struct WaitStatus 64 | { 65 | std::future job; 66 | std::atomic stopped{true}; 67 | std::atomic canceled{true}; 68 | 69 | void reset(void) 70 | { 71 | stopped = true; 72 | canceled = true; 73 | } 74 | 75 | void start(void) 76 | { 77 | stopped = false; 78 | canceled = false; 79 | } 80 | 81 | void stop(void) 82 | { 83 | stopped = true; 84 | 85 | if(job.valid()) 86 | { 87 | job.get(); 88 | } 89 | } 90 | 91 | void cancel(void) 92 | { 93 | canceled = true; 94 | 95 | if(job.valid()) 96 | { 97 | job.get(); 98 | } 99 | } 100 | }; 101 | 102 | struct PcscClient 103 | { 104 | SocketStream sock; 105 | PcscLite::ReaderState* reader = nullptr; 106 | 107 | std::thread thread; 108 | std::atomic shutdown{false}; 109 | 110 | WaitStatus waitStatusChanged; 111 | 112 | uint64_t remoteContext = 0; 113 | uint64_t remoteHandle = 0; 114 | 115 | uint32_t versionMajor = 0; 116 | uint32_t versionMinor = 0; 117 | 118 | uint32_t context = 0; 119 | uint32_t handle = 0; 120 | 121 | PcscClient(int fd, PcscSessionBus* sessionBus); 122 | ~PcscClient(); 123 | 124 | int id(void) const 125 | { 126 | return sock.fd(); 127 | } 128 | }; 129 | 130 | class PcscSessionBus : public sdbus::AdaptorInterfaces, public Application 131 | { 132 | std::forward_list clients; 133 | std::mutex clientsLock; 134 | 135 | std::array readers; 136 | std::mutex readersLock; 137 | 138 | std::unique_ptr ltsm; 139 | std::recursive_mutex ltsmLock; 140 | 141 | std::filesystem::path socketPath; 142 | int socketFd = -1; 143 | 144 | protected: 145 | bool pcscEstablishContext(PcscClient &, uint32_t len); 146 | bool pcscReleaseContext(PcscClient &, uint32_t len); 147 | bool pcscConnect(PcscClient &, uint32_t len); 148 | bool pcscReconnect(PcscClient &, uint32_t len); 149 | bool pcscDisconnect(PcscClient &, uint32_t len); 150 | bool pcscBeginTransaction(PcscClient &, uint32_t len); 151 | bool pcscEndTransaction(PcscClient &, uint32_t len); 152 | bool pcscTransmit(PcscClient &, uint32_t len); 153 | bool pcscStatus(PcscClient &, uint32_t len); 154 | bool pcscControl(PcscClient &, uint32_t len); 155 | bool pcscCancel(PcscClient &, uint32_t len); 156 | bool pcscGetAttrib(PcscClient &, uint32_t len); 157 | bool pcscSetAttrib(PcscClient &, uint32_t len); 158 | bool pcscGetVersion(PcscClient &, uint32_t len); 159 | bool pcscGetReaderState(PcscClient &, uint32_t len); 160 | bool pcscReaderStateChangeStart(PcscClient &, uint32_t len); 161 | bool pcscReaderStateChangeStop(PcscClient &, uint32_t len); 162 | 163 | int syncReaderStatusChange(PcscClient &, const std::string &, PcscLite::ReaderState &, bool* changed = nullptr); 164 | int64_t pcscGetStatusChange(PcscClient &, uint32_t timeout, SCARD_READERSTATE* states, uint32_t statesCount); 165 | 166 | std::list pcscListReaders(PcscClient &); 167 | PcscLite::ReaderState* findReaderState(const std::string & name); 168 | 169 | public: 170 | PcscSessionBus(sdbus::IConnection &, std::string_view pcscSockName); 171 | virtual ~PcscSessionBus(); 172 | 173 | int start(void) override; 174 | 175 | int32_t getVersion(void) override; 176 | void serviceShutdown(void) override; 177 | void setDebug(const std::string & level) override; 178 | 179 | bool connectChannel(const std::string & clientSocket) override; 180 | void disconnectChannel(const std::string & clientSocket) override; 181 | 182 | bool pcscClientAction(PcscClient &); 183 | 184 | int64_t syncReaders(PcscClient &, bool* changed = nullptr); 185 | }; 186 | } 187 | 188 | #endif // _LTSM_PCSC_SESSION_ 189 | -------------------------------------------------------------------------------- /src/session_pkcs11/ltsm_pkcs11.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_PKSC11_ 25 | #define _LTSM_PKSC11_ 26 | 27 | #define LTSM_PKCS11_VERSION 20240723 28 | 29 | namespace LTSM 30 | { 31 | namespace Pkcs11Op 32 | { 33 | enum 34 | { 35 | Init = 0xFC01, 36 | GetSlots = 0xFC02, 37 | GetSlotMechanisms = 0xFC03, 38 | GetSlotCertificates = 0xFC04, 39 | SignData = 0xFC11, 40 | DecryptData = 0xFC12 41 | }; 42 | } 43 | } 44 | 45 | #endif // _LTSM_PKCS11_ 46 | -------------------------------------------------------------------------------- /src/session_pkcs11/ltsm_pkcs11_session.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2024 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | ***************************************************************************/ 22 | 23 | #ifndef LTSM_HELPER_PKCS11_H 24 | #define LTSM_HELPER_PKCS11_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "ltsm_sockets.h" 35 | #include "ltsm_pkcs11_wrapper.h" 36 | 37 | struct Pkcs11Token 38 | { 39 | uint64_t slotId; 40 | 41 | LTSM::PKCS11::SlotInfo slotInfo; 42 | LTSM::PKCS11::TokenInfo tokenInfo; 43 | 44 | bool operator== (const Pkcs11Token & st) const 45 | { 46 | return tokenInfo.getModel() == st.tokenInfo.getModel() && 47 | tokenInfo.getSerialNumber() == st.tokenInfo.getSerialNumber(); 48 | } 49 | 50 | bool operator< (const Pkcs11Token & st) const 51 | { 52 | auto model1 = tokenInfo.getModel(); 53 | auto model2 = st.tokenInfo.getModel(); 54 | 55 | if(model1 == model2) 56 | { 57 | return tokenInfo.getSerialNumber() < st.tokenInfo.getSerialNumber(); 58 | } 59 | 60 | return model1 < model2; 61 | } 62 | }; 63 | 64 | struct Pkcs11Mech 65 | { 66 | uint64_t mechId; 67 | uint64_t minKey; 68 | uint64_t maxKey; 69 | uint64_t flags; 70 | std::string name; 71 | }; 72 | 73 | struct Pkcs11Cert 74 | { 75 | std::vector objectId; 76 | std::vector objectValue; 77 | }; 78 | 79 | class Pkcs11Client : public QThread 80 | { 81 | Q_OBJECT 82 | 83 | LTSM::SocketStream sock; 84 | QString templatePath; 85 | 86 | mutable std::mutex lock; 87 | std::atomic shutdown{false}; 88 | 89 | std::list tokens; 90 | 91 | public: 92 | Pkcs11Client(int displayNum, QObject*); 93 | ~Pkcs11Client(); 94 | 95 | const std::list & getTokens(void) const; 96 | std::list getCertificates(uint64_t slotId); 97 | std::list getMechanisms(uint64_t slotId); 98 | 99 | std::vector signData(uint64_t slotId, const std::string & pin, const std::vector & certId, 100 | const void* data, size_t len, uint64_t mechType = CKM_RSA_PKCS); 101 | std::vector decryptData(uint64_t slotId, const std::string & pin, const std::vector & certId, 102 | const void* data, size_t len, uint64_t mechType = CKM_RSA_PKCS); 103 | 104 | protected: 105 | void run(void) override; 106 | 107 | bool updateTokens(void); 108 | 109 | signals: 110 | void pkcs11Error(const QString &); 111 | void pkcs11Shutdown(void); 112 | void pkcs11TokensChanged(void); 113 | }; 114 | 115 | #endif // LTSM_HELPER_PKCS11_H 116 | -------------------------------------------------------------------------------- /src/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | foreach(DIR IN ITEMS json streambuf unixsocket framebuf xrandr x11clip) 2 | add_executable(LTSM_test_${DIR}) 3 | 4 | file(GLOB_RECURSE SOURCELIST "${DIR}/*.cpp") 5 | target_sources(LTSM_test_${DIR} PRIVATE ${SOURCELIST}) 6 | 7 | find_package(GnuTLS REQUIRED) 8 | 9 | target_link_libraries(LTSM_test_${DIR} ${SDL2_LIBRARIES}) 10 | target_link_libraries(LTSM_test_${DIR} ${SDL2_IMAGE_LIBRARIES}) 11 | target_compile_options(LTSM_test_${DIR} PRIVATE ${EXTRA_CFLAGS}) 12 | target_compile_definitions(LTSM_test_${DIR} PRIVATE -DLTSM_WITH_GNUTLS -DLTSM_SOCKET_ZLIB) 13 | 14 | target_include_directories(LTSM_test_${DIR} PRIVATE ${CMAKE_SOURCE_DIR}/src/common) 15 | 16 | target_link_libraries(LTSM_test_${DIR} LTSM_common) 17 | target_link_libraries(LTSM_test_${DIR} ${GNUTLS_LIBRARIES}) 18 | target_link_libraries(LTSM_test_${DIR} z) 19 | 20 | set_target_properties(LTSM_test_${DIR} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../..) 21 | endforeach() 22 | 23 | foreach(DIR IN ITEMS encodings x11enc) 24 | add_executable(LTSM_test_${DIR}) 25 | 26 | file(GLOB_RECURSE SOURCELIST "${DIR}/*.cpp") 27 | target_sources(LTSM_test_${DIR} PRIVATE ${SOURCELIST} 28 | ${CMAKE_SOURCE_DIR}/src/librfb/ltsm_librfb.cpp 29 | ${CMAKE_SOURCE_DIR}/src/librfb/librfb_encodings.cpp 30 | ${CMAKE_SOURCE_DIR}/src/librfb/librfb_ffmpeg.cpp 31 | ${CMAKE_SOURCE_DIR}/src/channels/channel_system.cpp) 32 | 33 | find_package(GnuTLS REQUIRED) 34 | 35 | pkg_search_module(SDL2 REQUIRED sdl2>=2.0.1) 36 | pkg_search_module(SDL2_IMAGE REQUIRED SDL2_image>=2.0.1) 37 | pkg_search_module(LZ4 REQUIRED lz4) 38 | pkg_search_module(TURBOJPEG REQUIRED turbojpeg) 39 | 40 | target_link_libraries(LTSM_test_${DIR} ${SDL2_LIBRARIES}) 41 | target_link_libraries(LTSM_test_${DIR} ${SDL2_IMAGE_LIBRARIES} ${LZ4_LIBRARIES} ${TURBOJPEG_LIBRARIES}) 42 | target_compile_options(LTSM_test_${DIR} PRIVATE ${EXTRA_CFLAGS}) 43 | target_compile_definitions(LTSM_test_${DIR} PRIVATE -DLTSM_WITH_GNUTLS -DLTSM_SOCKET_ZLIB -DLTSM_ENCODING -DLTSM_ENCODING_FFMPEG) 44 | 45 | target_include_directories(LTSM_test_${DIR} PRIVATE ${CMAKE_SOURCE_DIR}/src/librfb) 46 | target_include_directories(LTSM_test_${DIR} PRIVATE ${CMAKE_SOURCE_DIR}/src/common) 47 | target_include_directories(LTSM_test_${DIR} PRIVATE ${CMAKE_SOURCE_DIR}/src/channels) 48 | 49 | if(LTSM_FFMPEG) 50 | pkg_search_module(AVDEVICE REQUIRED libavdevice) 51 | pkg_search_module(AVFORMAT REQUIRED libavformat) 52 | pkg_search_module(AVCODEC REQUIRED libavcodec) 53 | pkg_search_module(AVSWSCALE REQUIRED libswscale) 54 | pkg_search_module(AVSWRESAMPLE REQUIRED libswresample) 55 | pkg_search_module(AVUTIL REQUIRED libavutil) 56 | 57 | target_sources(LTSM_test_${DIR} PRIVATE ${CMAKE_SOURCE_DIR}/src/librfb/ffmpeg_tools.cpp ${CMAKE_SOURCE_DIR}/src/librfb/librfb_ffmpeg.cpp) 58 | 59 | target_compile_options(LTSM_test_${DIR} PRIVATE 60 | ${AVDEVICE_CFLAGS} ${AVFORMAT_CFLAGS} ${AVCODEC_CFLAGS} 61 | ${AVSWSCALE_CFLAGS} ${AVSWRESAMPLE_CFLAGS} ${AVUTIL_CFLAGS}) 62 | 63 | target_link_options(LTSM_test_${DIR} PRIVATE 64 | ${AVDEVICE_LDFLAGS} ${AVFORMAT_LDFLAGS} ${AVCODEC_LDFLAGS} 65 | ${AVSWSCALE_LDFLAGS} ${AVSWRESAMPLE_LDFLAGS} ${AVUTIL_LDFLAGS}) 66 | 67 | target_link_libraries(LTSM_test_${DIR} 68 | ${AVDEVICE_LIBRARIES} ${AVFORMAT_LIBRARIES} ${AVCODEC_LIBRARIES} 69 | ${AVSWSCALE_LIBRARIES} ${AVSWRESAMPLE_LIBRARIES} ${AVUTIL_LIBRARIES}) 70 | endif() 71 | 72 | if(LTSM_PKCS11_AUTH) 73 | pkg_search_module(P11KIT REQUIRED p11-kit-1) 74 | target_include_directories(LTSM_test_${DIR} PRIVATE ${CMAKE_SOURCE_DIR}/src/session_pkcs11 ${P11KIT_INCLUDE_DIRS}) 75 | endif() 76 | 77 | target_link_libraries(LTSM_test_${DIR} LTSM_common) 78 | target_link_libraries(LTSM_test_${DIR} ${SDL2_LIBRARIES}) 79 | target_link_libraries(LTSM_test_${DIR} ${SDL2_IMAGE_LIBRARIES}) 80 | target_link_libraries(LTSM_test_${DIR} ${GNUTLS_LIBRARIES}) 81 | target_link_libraries(LTSM_test_${DIR} z) 82 | 83 | set_target_properties(LTSM_test_${DIR} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../..) 84 | endforeach() 85 | -------------------------------------------------------------------------------- /src/tests/encodings/images/001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndreyBarmaley/linux-terminal-service-manager/ce163fff8ded0cdcb6fdbc234a61082a53f33e64/src/tests/encodings/images/001.png -------------------------------------------------------------------------------- /src/tests/encodings/images/002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndreyBarmaley/linux-terminal-service-manager/ce163fff8ded0cdcb6fdbc234a61082a53f33e64/src/tests/encodings/images/002.png -------------------------------------------------------------------------------- /src/tests/encodings/images/003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndreyBarmaley/linux-terminal-service-manager/ce163fff8ded0cdcb6fdbc234a61082a53f33e64/src/tests/encodings/images/003.png -------------------------------------------------------------------------------- /src/tests/encodings/images/004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndreyBarmaley/linux-terminal-service-manager/ce163fff8ded0cdcb6fdbc234a61082a53f33e64/src/tests/encodings/images/004.png -------------------------------------------------------------------------------- /src/tests/encodings/librfb_server2.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2022 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LIBRFB_SERVER_ 25 | #define _LIBRFB_SERVER_ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "ltsm_librfb.h" 32 | #include "librfb_encodings.h" 33 | 34 | namespace LTSM 35 | { 36 | namespace RFB 37 | { 38 | /// ServerEncoder 39 | class ServerEncoderBuf : public EncoderStream 40 | { 41 | std::vector clientEncodings; 42 | 43 | BinaryBuf bufData; 44 | std::unique_ptr socket; 45 | std::unique_ptr encoder; 46 | 47 | XCB::Size dsz; 48 | PixelFormat clientPf, serverPf; 49 | std::mutex sendLock; 50 | 51 | mutable size_t netStatRx = 0; 52 | mutable size_t netStatTx = 0; 53 | 54 | NetworkStream* streamIn = nullptr; 55 | NetworkStream* streamOut = nullptr; 56 | 57 | bool clientTrueColor = true; 58 | bool clientBigEndian = false; 59 | 60 | protected: 61 | friend class EncodingBase; 62 | friend class EncodingRaw; 63 | friend class EncodingRRE; 64 | friend class EncodingHexTile; 65 | friend class EncodingTRLE; 66 | friend class EncodingZlib; 67 | 68 | // network stream interface 69 | void sendFlush(void) override; 70 | void sendRaw(const void* ptr, size_t len) override; 71 | void recvRaw(void* ptr, size_t len) const override; 72 | bool hasInput(void) const override; 73 | size_t hasData(void) const override; 74 | uint8_t peekInt8(void) const override; 75 | 76 | XCB::Size displaySize(void) const override; 77 | 78 | //bool isUpdateProcessed(void) const; 79 | //void waitUpdateProcess(void); 80 | 81 | void recvPixelFormat(void); 82 | void recvSetEncodings(void); 83 | void recvKeyCode(void); 84 | void recvPointer(void); 85 | void recvCutText(void); 86 | void recvFramebufferUpdate(void); 87 | void recvSetContinuousUpdates(void); 88 | void recvSetDesktopSize(void); 89 | 90 | public: 91 | ServerEncoderBuf(const FrameBuffer*); 92 | 93 | const PixelFormat & clientFormat(void) const override { return clientPf; } 94 | const PixelFormat & serverFormat(void) const override { return serverPf; } 95 | bool clientIsBigEndian(void) const override { return clientBigEndian; } 96 | 97 | void sendFrameBufferUpdate(const FrameBuffer &); 98 | 99 | void setEncodingDebug(int v); 100 | void setEncodingThreads(int v); 101 | bool serverSetClientEncoding(int type); 102 | 103 | const std::vector & getBuffer(void) const; 104 | void resetBuffer(void); 105 | }; 106 | } 107 | } 108 | 109 | #endif // _LTSM_LIBRFB_ 110 | -------------------------------------------------------------------------------- /src/tests/encodings/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "ltsm_application.h" 12 | #include "ltsm_framebuffer.h" 13 | #include "librfb_server2.h" 14 | #include "ltsm_tools.h" 15 | 16 | using namespace LTSM; 17 | 18 | struct Image 19 | { 20 | std::unique_ptr fb; 21 | 22 | Image(std::filesystem::path file) 23 | { 24 | std::unique_ptr sf{IMG_Load(file.c_str()), SDL_FreeSurface}; 25 | 26 | if(sf) 27 | { 28 | SDL_PixelFormat* pf = sf->format; 29 | auto fb24 = FrameBuffer((uint8_t*) sf->pixels, XCB::Region(0, 0, sf->w, sf->h), PixelFormat(pf->BitsPerPixel, pf->Rmask, pf->Gmask, pf->Bmask, pf->Amask), sf->pitch); 30 | fb = std::make_unique(XCB::Size(fb24.width(), fb24.height()), BGRA32); 31 | fb->blitRegion(fb24, XCB::Region(0, 0, fb->width(), fb->height()), XCB::Point(0, 0)); 32 | } 33 | 34 | Application::info("%s: loading: %s", __FUNCTION__, file.c_str()); 35 | } 36 | }; 37 | 38 | class EncodingTest : public Application 39 | { 40 | std::unique_ptr srv; 41 | std::list images; 42 | std::string imagesPath; 43 | int useThreads = 1; 44 | 45 | public: 46 | EncodingTest(const std::string & folder, int threadNum) : Application("encoding-test"), imagesPath(folder), useThreads(threadNum) 47 | { 48 | } 49 | 50 | int start(void) 51 | { 52 | std::list jobs; 53 | 54 | if(std::filesystem::is_directory(imagesPath)) 55 | { 56 | for(auto const & dirEntry : std::filesystem::directory_iterator{imagesPath}) 57 | { 58 | jobs.emplace_back(std::thread([this, file = dirEntry.path()]() 59 | { 60 | images.emplace_back(std::move(file)); 61 | })); 62 | } 63 | } 64 | 65 | for(auto & job: jobs) 66 | if(job.joinable()) job.join(); 67 | 68 | if(! images.empty()) 69 | { 70 | /* 71 | auto encodings = { RFB::ENCODING_RRE, RFB::ENCODING_CORRE, RFB::ENCODING_HEXTILE, 72 | #ifdef LTSM_ENCODING_FFMPEG 73 | RFB::ENCODING_FFMPEG_H264, 74 | #endif 75 | #ifdef LTSM_ENCODING 76 | RFB::ENCODING_LTSM_QOI, RFB::ENCODING_LTSM_LZ4, RFB::ENCODING_LTSM_TJPG, 77 | #endif 78 | RFB::ENCODING_ZLIB, RFB::ENCODING_TRLE, RFB::ENCODING_ZRLE }; 79 | */ 80 | auto encodings = { 81 | RFB::ENCODING_LTSM_QOI, RFB::ENCODING_LTSM_LZ4, RFB::ENCODING_LTSM_TJPG }; 82 | 83 | auto & pf = images.front().fb->pixelFormat(); 84 | 85 | srv = std::make_unique(images.front().fb.get()); 86 | 87 | Application::info("%s: pixel format, bpp: %d, rmask: 0x%08x, gmask: 0x%08x, bmask: 0x%08x, amask: 0x%08x", 88 | __FUNCTION__, (int) pf.bitsPerPixel(), pf.rmask(), pf.gmask(), pf.bmask(), pf.amask()); 89 | 90 | 91 | for(auto type: encodings) 92 | { 93 | srv->serverSetClientEncoding(type); 94 | srv->setEncodingDebug(0); 95 | srv->setEncodingThreads(useThreads); 96 | 97 | auto tp = std::chrono::steady_clock::now(); 98 | 99 | for(const auto & img: images) 100 | srv->sendFrameBufferUpdate(*img.fb); 101 | 102 | auto dt = std::chrono::duration_cast(std::chrono::steady_clock::now() - tp); 103 | Application::info("%s: encoding: %s, time: %dms, stream sz: %dMb", __FUNCTION__, RFB::encodingName(type), dt.count(), srv->getBuffer().size()/(1024*1024)); 104 | 105 | srv->resetBuffer(); 106 | } 107 | } 108 | 109 | return 0; 110 | } 111 | }; 112 | 113 | int main(int argc, char** argv) 114 | { 115 | auto hardwareThreads = std::thread::hardware_concurrency(); 116 | int threadNum = hardwareThreads; 117 | std::string folder = "images"; 118 | 119 | for(int it = 1; it < argc; ++it) 120 | { 121 | if(0 == std::strcmp(argv[it], "--thread") && it + 1 < argc) 122 | { 123 | try 124 | { 125 | threadNum = std::stoi(argv[it + 1]); 126 | } 127 | catch(const std::invalid_argument &) 128 | { 129 | std::cerr << "incorrect threads number" << std::endl; 130 | } 131 | it = it + 1; 132 | } 133 | else 134 | if(0 == std::strcmp(argv[it], "--images") && it + 1 < argc) 135 | { 136 | folder.assign(argv[it + 1]); 137 | it = it + 1; 138 | } 139 | else 140 | { 141 | std::cout << "usage: " << argv[0] << " --thread " << " --images " << std::endl; 142 | return 0; 143 | } 144 | } 145 | 146 | if(threadNum < 0 || hardwareThreads < threadNum) 147 | threadNum = hardwareThreads; 148 | 149 | int res = 0; 150 | SDL_Init(SDL_INIT_TIMER); 151 | 152 | try 153 | { 154 | res = EncodingTest(folder, threadNum).start(); 155 | } 156 | catch(const std::exception & err) 157 | { 158 | Application::error("exception: %s", err.what()); 159 | } 160 | 161 | SDL_Quit(); 162 | return res; 163 | } 164 | -------------------------------------------------------------------------------- /src/tests/framebuf/main.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "ltsm_framebuffer.h" 11 | #include "ltsm_xcb_wrapper.h" 12 | 13 | using namespace LTSM; 14 | 15 | int rand2(int min, int max) 16 | { 17 | if(min > max) std::swap(min, max); 18 | return min + std::rand() / (RAND_MAX + 1.0) * (max - min + 1); 19 | } 20 | 21 | XCB::RegionPixel regionPixelRandom(const XCB::Size & wsz, const PixelFormat & pixelFormat) 22 | { 23 | uint8_t cr = rand2(0, 255); 24 | uint8_t cg = rand2(0, 255); 25 | uint8_t cb = rand2(0, 255); 26 | 27 | auto col = Color(cr, cg, cb, 0xFF); 28 | auto reg = XCB::Region(rand2(0, wsz.width - 1), rand2(0, wsz.height - 1), 32, 32); 29 | 30 | return XCB::RegionPixel(reg, pixelFormat.pixel(col)); 31 | } 32 | 33 | FrameBuffer generate(const PixelFormat & pf) 34 | { 35 | FrameBuffer back(XCB::Size(640, 480), pf); 36 | back.fillColor(back.region(), Color()); 37 | 38 | std::cout << "generate 1000 regions" << std::endl; 39 | for(int it = 0; it < 1000; ++it) 40 | { 41 | auto rp = regionPixelRandom(back.region(), back.pixelFormat()); 42 | back.fillPixel(rp.region(), rp.pixel()); 43 | } 44 | 45 | back.drawRect(XCB::Region(160, 120, 320, 240), Color(0xFF, 0xFF, 0)); 46 | return back; 47 | } 48 | 49 | int main(int argc, char** argv) 50 | { 51 | std::cout << "sizeof PixelFormat " << sizeof(LTSM::PixelFormat) << std::endl; 52 | std::cout << "sizeof FrameBuffer " << sizeof(LTSM::FrameBuffer) << std::endl; 53 | std::cout << "sizeof Region " << sizeof(LTSM::XCB::Region) << std::endl; 54 | std::cout << "sizeof unique_ptr " << sizeof(std::unique_ptr) << std::endl; 55 | std::cout << "sizeof shared_ptr " << sizeof(std::shared_ptr) << std::endl; 56 | std::cout << "sizeof atomic " << sizeof(std::atomic) << std::endl; 57 | std::cout << "sizeof string " << sizeof(std::string) << std::endl; 58 | std::cout << "sizeof PixmapInfoReply " << sizeof(LTSM::XCB::PixmapInfoReply) << std::endl; 59 | 60 | auto today = std::chrono::system_clock::now(); 61 | auto dtn = today.time_since_epoch(); 62 | std::srand(dtn.count()); 63 | 64 | auto formats = { RGB565, BGR565, RGB24, BGR24, RGBA32, BGRA32, ARGB32, ABGR32 }; 65 | FrameBuffer back(XCB::Size(640, 480), RGB24); 66 | int index = 0; 67 | 68 | for(const auto & pf : formats) 69 | { 70 | std::cout << "test framebuffer: " << index++ << std::endl; 71 | auto tmp = generate(pf); 72 | back.blitRegion(tmp, tmp.region(), XCB::Point(0, 0)); 73 | } 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /src/tests/json/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ltsm_tools.h" 8 | #include "ltsm_application.h" 9 | #include "ltsm_json_wrapper.h" 10 | 11 | using namespace LTSM; 12 | 13 | class Test1App : public Application 14 | { 15 | JsonObject config; 16 | 17 | public: 18 | Test1App(const char* ident, int argc, const char** argv) : Application(ident) 19 | { 20 | const char* file = 1 < argc ? argv[1] : "test.json"; 21 | 22 | JsonContentFile jsonFile(file); 23 | 24 | if(! jsonFile.isValid() || ! jsonFile.isObject()) 25 | throw std::invalid_argument("json parse error"); 26 | 27 | config = jsonFile.toObject(); 28 | } 29 | 30 | int start(void) override 31 | { 32 | auto arr1 = config.getArray("test:array"); 33 | auto obj1 = config.getObject("test:object"); 34 | 35 | std::cout << "test Object::isArray" << std::endl; 36 | assert(config.isArray("test:array")); 37 | assert(obj1->isArray("test:arr")); 38 | 39 | std::cout << "test Object::isObject" << std::endl; 40 | assert(config.isObject("test:object")); 41 | assert(obj1->isObject("test:obj")); 42 | 43 | auto arr2 = obj1->getArray("test:arr"); 44 | auto obj2 = obj1->getObject("test:obj"); 45 | 46 | std::cout << "test Object::isString" << std::endl; 47 | assert(config.isString("test:string")); 48 | std::cout << "test Object::isInteger" << std::endl; 49 | assert(config.isInteger("test:int")); 50 | std::cout << "test Object::isDouble" << std::endl; 51 | assert(config.isDouble("test:double")); 52 | std::cout << "test Object::isBoolean" << std::endl; 53 | assert(config.isBoolean("test:true")); 54 | std::cout << "test Object::isNull" << std::endl; 55 | assert(config.isNull("test:null")); 56 | 57 | std::cout << "test Object::getArray" << std::endl; 58 | assert(arr1); 59 | 60 | std::cout << "test Object::getObject" << std::endl; 61 | assert(obj1); 62 | 63 | std::cout << "test Object::getInteger" << std::endl; 64 | assert(config.getInteger("test:int") == 1234567); 65 | assert(obj1->getInteger("test:int") == 111); 66 | 67 | std::cout << "test Object::getDouble" << std::endl; 68 | assert(config.getDouble("test:double") == 1.234567); 69 | assert(obj1->getDouble("test:double") == 555.6789); 70 | 71 | std::cout << "test Object::getBoolean true" << std::endl; 72 | assert(config.getBoolean("test:true")); 73 | assert(! obj1->getBoolean("test:false")); 74 | 75 | std::cout << "test Object::getBoolean false" << std::endl; 76 | assert(! config.getBoolean("test:false")); 77 | 78 | std::cout << "test Object::keys" << " [" << Tools::join(config.keys(), ",") << "]" << std::endl; 79 | assert(config.keys().size() == 7); 80 | 81 | std::cout << "test Object::getStdVector" << std::endl; 82 | assert(config.getStdVector("test:array").size() == 9); 83 | 84 | std::cout << "test Object::getStdList" << std::endl; 85 | assert(config.getStdList("test:array").size() == 9); 86 | 87 | std::cout << "test Array::getInteger" << std::endl; 88 | assert(arr1->getInteger(0) == 1 && arr1->getInteger(8) == 9); 89 | 90 | std::cout << "test Array::getString" << std::endl; 91 | assert(arr1->getString(0) == "1"); 92 | 93 | std::cout << "test Array::getBoolean" << std::endl; 94 | assert(arr1->getBoolean(0)); 95 | 96 | std::cout << "test Array::isValid" << std::endl; 97 | assert(! arr1->isValid(9)); 98 | 99 | JsonObject obj; 100 | obj.addInteger("val1", 111); 101 | obj.addString("val2", "112"); 102 | obj.addDouble("val3", 113.123); 103 | obj.addArray("val4", *arr2); 104 | obj.addObject("val5", *obj2); 105 | 106 | std::cout << "test JsonObject new" << std::endl; 107 | assert(obj.size() == 5); 108 | 109 | std::cout << obj.toString() << std::endl; 110 | 111 | std::string teststr("errtert"); 112 | 113 | JsonArray jarr; 114 | jarr << "test1" << "test2" << "test3" << "test4" << teststr; 115 | std::cout << jarr.toString() << std::endl; 116 | 117 | JsonObjectStream jos; 118 | std::cout << "json stream: " << jos.push("key1", "string").push("key11",teststr).push("key2", 456).push("key3", 3.147).push("key4", true).push("key5").flush() << std::endl; 119 | return 0; 120 | } 121 | }; 122 | 123 | int main(int argc, const char** argv) 124 | { 125 | Test1App test1("Test1", argc, argv); 126 | return test1.start(); 127 | } 128 | -------------------------------------------------------------------------------- /src/tests/json/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "test:array": [ 1, 2, 3 ,4 ,5 ,6 ,7 ,8 ,9 ], 3 | "test:object": { 4 | "test:int": 111, 5 | "test:string": "test test test", 6 | "test:false": false, 7 | "test:double": 555.67890, 8 | "test:arr": [ false, 1, 2, 3, 4, "5", 6, 7, "8", 9 ], 9 | "test:obj": { "posx": 11, "posy": 22 } 10 | }, 11 | "test:string": "xyz %{display}, $var1, ${var2}, '123', \\., \"long string\", the end", 12 | "test:int": 1234567, 13 | "test:double": 1.234567, 14 | "test:true": true, 15 | "test:false": false 16 | } 17 | -------------------------------------------------------------------------------- /src/tests/unixsocket/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "ltsm_tools.h" 15 | #include "ltsm_sockets.h" 16 | #include "ltsm_streambuf.h" 17 | #include "ltsm_application.h" 18 | 19 | using namespace std::chrono_literals; 20 | using namespace LTSM; 21 | 22 | int main() 23 | { 24 | auto path = "test2.sock"; 25 | 26 | auto fd0 = UnixSocket::listen(path); 27 | if(0 == fd0) 28 | { 29 | std::cerr << "listen socket failed" << std::endl; 30 | return -1; 31 | } 32 | std::cout << "listen socket: " << fd0 << std::endl; 33 | 34 | // accept 35 | std::future job = std::async(std::launch::async, [=](){ return accept(fd0, nullptr, nullptr); }); 36 | std::this_thread::sleep_for(100ms); 37 | 38 | auto fd2 = UnixSocket::connect(path); 39 | if(0 == fd2) 40 | { 41 | std::cerr << "client socket failed" << std::endl; 42 | return -1; 43 | } 44 | std::cout << "client socket: " << fd2 << std::endl; 45 | 46 | 47 | // wait server socket 48 | while(job.wait_for(std::chrono::milliseconds(1)) != std::future_status::ready); 49 | auto fd1 = job.get(); 50 | 51 | if(0 == fd1) 52 | { 53 | std::cerr << "server socket failed" << std::endl; 54 | return -1; 55 | } 56 | std::cout << "server socket: " << fd1 << std::endl; 57 | 58 | // close listen 59 | close(fd0); 60 | 61 | // server stream 62 | SocketStream sock1(fd1); 63 | // client stream 64 | SocketStream sock2(fd2); 65 | 66 | sock1.sendIntBE16(0x1234); 67 | sock1.sendIntBE32(0x12345678); 68 | sock1.sendIntBE64(0x1234567898765432); 69 | sock1.sendFlush(); 70 | 71 | std::cout << "test1 socket::sendInt16BE/recvInt16BE" << std::endl; 72 | assert(sock2.recvIntBE16() == 0x1234); 73 | std::cout << "test1 socket::sendInt32BE/recvInt32BE" << std::endl; 74 | assert(sock2.recvIntBE32() == 0x12345678); 75 | std::cout << "test1 socket::sendInt64BE/recvInt64BE" << std::endl; 76 | assert(sock2.recvIntBE64() == 0x1234567898765432); 77 | 78 | sock2.sendIntLE64(0x1234567898765432); 79 | sock2.sendIntLE32(0x12345678); 80 | sock2.sendIntLE16(0x1234); 81 | sock2.sendFlush(); 82 | 83 | std::cout << "test2 socket::sendInt64LE/recvInt64LE" << std::endl; 84 | assert(sock1.recvIntLE64() == 0x1234567898765432); 85 | std::cout << "test2 socket::sendInt32LE/recvInt32LE" << std::endl; 86 | assert(sock1.recvIntLE32() == 0x12345678); 87 | std::cout << "test2 socket::sendInt16LE/recvInt16LE" << std::endl; 88 | assert(sock1.recvIntLE16() == 0x1234); 89 | 90 | // zlib part1 91 | auto zlib1 = std::make_unique(); 92 | for(int it = 0; it < 100; it++) 93 | zlib1->sendIntLE64(0x1234567898765432); 94 | 95 | auto buf1 = zlib1->deflateFlush(); 96 | sock1.sendIntBE32(buf1.size()).sendData(buf1).sendFlush(); 97 | 98 | auto len = sock2.recvIntBE32(); 99 | auto buf2 = sock2.recvData(len); 100 | auto zlib2 = std::make_unique(); 101 | zlib2->appendData(buf2); 102 | 103 | std::cout << "test1 zlib socket::sendInt64LE/recvInt64LE" << std::endl; 104 | for(int it = 0; it < 100; it++) 105 | { 106 | auto val = zlib2->recvIntLE64(); 107 | assert(val == 0x1234567898765432); 108 | } 109 | 110 | // zlib part1 111 | for(int it = 0; it < 100; it++) 112 | zlib1->sendIntBE16(it); 113 | 114 | buf1 = zlib1->deflateFlush(); 115 | sock1.sendIntBE32(buf1.size()).sendData(buf1).sendFlush(); 116 | 117 | len = sock2.recvIntBE32(); 118 | buf2 = sock2.recvData(len); 119 | zlib2->appendData(buf2); 120 | 121 | std::cout << "test2 zlib socket::sendInt16BE/recvInt16BE" << std::endl; 122 | for(int it = 0; it < 100; it++) 123 | { 124 | auto val = zlib2->recvIntBE16(); 125 | assert(val == it); 126 | } 127 | 128 | zlib1.reset(); 129 | zlib2.reset(); 130 | 131 | // tls part 132 | auto priority = "NORMAL:+ANON-ECDH:+ANON-DH"; 133 | 134 | auto tls1 = std::make_unique(& sock1); 135 | bool srvMode = true; 136 | std::future job2 = std::async(std::launch::async, [&](){ return tls1->initAnonHandshake(priority, srvMode, 0); }); 137 | std::this_thread::sleep_for(10ms); 138 | 139 | auto tls2 = std::make_unique(& sock2); 140 | if(! tls2->initAnonHandshake(priority, ! srvMode, 0)) 141 | { 142 | std::cerr << "tls2 init failed" << std::endl; 143 | return -1; 144 | } 145 | 146 | // wait init tls1 147 | while(job2.wait_for(std::chrono::milliseconds(1)) != std::future_status::ready); 148 | if(! job2.get()) 149 | { 150 | std::cerr << "tls1 init failed" << std::endl; 151 | return -1; 152 | } 153 | 154 | 155 | for(int it = 0; it < 100; it++) 156 | tls1->sendIntLE64(0x1234567898765432); 157 | 158 | tls1->sendFlush(); 159 | 160 | std::cout << "tls socket::sendInt64LE/recvInt64LE" << std::endl; 161 | for(int it = 0; it < 100; it++) 162 | { 163 | auto val = tls2->recvIntLE64(); 164 | assert(val == 0x1234567898765432); 165 | } 166 | 167 | tls1.reset(); 168 | tls2.reset(); 169 | 170 | std::filesystem::remove(path); 171 | return 0; 172 | } 173 | -------------------------------------------------------------------------------- /src/tests/x11clip/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ltsm_tools.h" 10 | #include "ltsm_xcb_wrapper.h" 11 | #include "ltsm_application.h" 12 | 13 | using namespace LTSM; 14 | using namespace std::chrono_literals; 15 | 16 | class X11Clip : public Application, public XCB::RootDisplay 17 | { 18 | public: 19 | X11Clip(int display) : Application("x11clip"), XCB::RootDisplay(display) 20 | { 21 | Application::info("DisplayInfo: width: %u, height: %u, depth: %u, maxreq: %u", width(), height(), depth(), getMaxRequest()); 22 | XCB::RootDisplay::extensionDisable(XCB::Module::DAMAGE); 23 | } 24 | 25 | virtual int start(void) = 0; 26 | }; 27 | 28 | class X11ClipCopy : public X11Clip, public XCB::SelectionRecipient 29 | { 30 | XCB::ModuleCopySelection* copy = nullptr; 31 | xcb_atom_t target = XCB_ATOM_STRING; 32 | xcb_atom_t targets = XCB_ATOM_NONE; 33 | std::filesystem::path file; 34 | 35 | protected: 36 | void selectionReceiveData(xcb_atom_t atom, const uint8_t* ptr, uint32_t len) const override 37 | { 38 | auto name = getAtomName(atom); 39 | Application::info("%s: atom: `%s', size: %u", __FUNCTION__, name.data(), len); 40 | 41 | if(! file.empty()) 42 | { 43 | Tools::binaryToFile(ptr, len, file); 44 | } 45 | } 46 | 47 | void selectionReceiveTargets(const xcb_atom_t* beg, const xcb_atom_t* end) const override 48 | { 49 | std::for_each(beg, end, [&](auto & atom) 50 | { 51 | Application::info("%s: target: `%s'", "selectionReceiveTargets", getAtomName(atom).data()); 52 | 53 | if(atom == target) 54 | copy->convertSelection(target, *this); 55 | }); 56 | } 57 | 58 | void selectionChangedEvent(void) const override 59 | { 60 | Application::info("%s", __FUNCTION__); 61 | copy->convertSelection(targets, *this); 62 | } 63 | 64 | public: 65 | X11ClipCopy(int argc, const char** argv) : X11Clip(-1) 66 | { 67 | if(2 < argc) 68 | { 69 | target = getAtom(argv[2], true); 70 | 71 | if(3 < argc) 72 | file = argv[3]; 73 | } 74 | 75 | targets = getAtom("TARGETS", true); 76 | copy = static_cast(getExtension(XCB::Module::SELECTION_COPY)); 77 | 78 | Application::info("mode: %s, target: `%s', data save: `%s'", "copy", getAtomName(target).data(), file.c_str()); 79 | } 80 | 81 | int start(void) override 82 | { 83 | Tools::TimePoint getsel(std::chrono::seconds(3)); 84 | 85 | copy->convertSelection(targets, *this); 86 | 87 | while(! hasError()) 88 | { 89 | while(auto ev = pollEvent()) 90 | { 91 | } 92 | 93 | if(getsel.check()) 94 | { 95 | } 96 | 97 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); 98 | } 99 | 100 | return EXIT_SUCCESS; 101 | } 102 | }; 103 | 104 | class X11ClipPaste : public X11Clip, public XCB::SelectionSource 105 | { 106 | XCB::ModulePasteSelection* paste = nullptr; 107 | xcb_atom_t target = XCB_ATOM_NONE; 108 | 109 | std::vector buf; 110 | 111 | protected: 112 | std::vector selectionSourceTargets(void) const override 113 | { 114 | return { target }; 115 | } 116 | 117 | size_t selectionSourceSize(xcb_atom_t atom) const override 118 | { 119 | Application::info("%s, atom: `%s'", __FUNCTION__, getAtomName(atom).data()); 120 | 121 | if(atom == target) 122 | { 123 | return buf.size(); 124 | } 125 | 126 | return 0; 127 | } 128 | 129 | std::vector selectionSourceData(xcb_atom_t atom, size_t offset, uint32_t length) const override 130 | { 131 | Application::info("%s, atom: `%s', offset: %u, length: %u", __FUNCTION__, getAtomName(atom).data(), offset, length); 132 | 133 | if(atom == target) 134 | { 135 | if(offset + length <= buf.size()) 136 | { 137 | return std::vector(buf.begin() + offset, buf.begin() + offset + length); 138 | } 139 | else 140 | { 141 | Application::error("invalid length: %u, offset: %u", length, offset); 142 | } 143 | } 144 | 145 | return {}; 146 | } 147 | 148 | public: 149 | X11ClipPaste(int argc, const char** argv) : X11Clip(-1) 150 | { 151 | std::string_view test{"0123456789"}; 152 | 153 | if(2 < argc) 154 | { 155 | target = getAtom(argv[2], true); 156 | 157 | if(3 < argc) 158 | buf = Tools::fileToBinaryBuf(argv[3]); 159 | } 160 | 161 | if(target == XCB_ATOM_NONE) 162 | target = XCB_ATOM_STRING; 163 | 164 | if(buf.empty()) 165 | buf.assign(test.begin(), test.end()); 166 | 167 | Application::info("mode: %s, target: `%s', data size: %u", "paste", getAtomName(target).data(), buf.size()); 168 | paste = static_cast(getExtension(XCB::Module::SELECTION_PASTE)); 169 | } 170 | 171 | int start(void) override 172 | { 173 | Tools::TimePoint getsel(std::chrono::seconds(3)); 174 | 175 | auto thr = std::thread([this]() 176 | { 177 | while(! this->hasError()) 178 | { 179 | while(auto ev = this->pollEvent()) 180 | { 181 | } 182 | 183 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); 184 | } 185 | }); 186 | 187 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 188 | paste->setSelectionOwner(*this); 189 | 190 | thr.join(); 191 | return EXIT_SUCCESS; 192 | } 193 | }; 194 | 195 | int main(int argc, const char** argv) 196 | { 197 | try 198 | { 199 | Application::setDebugLevel(DebugLevel::Info); 200 | 201 | if(1 < argc) 202 | { 203 | std::unique_ptr app; 204 | 205 | if(0 == strcmp(argv[1], "copy")) 206 | app = std::make_unique(argc, argv); 207 | else 208 | if(0 == strcmp(argv[1], "paste")) 209 | app = std::make_unique(argc, argv); 210 | 211 | if(app) 212 | return app->start(); 213 | } 214 | 215 | std::cout << "usage: " << argv[0] << " " << std::endl; 216 | return EXIT_SUCCESS; 217 | } 218 | catch(const std::exception & err) 219 | { 220 | Application::error("exception: %s", err.what()); 221 | } 222 | 223 | return EXIT_FAILURE; 224 | } 225 | -------------------------------------------------------------------------------- /src/vnc2image/ltsm_vnc2image.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program; if not, write to the * 19 | * Free Software Foundation, Inc., * 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 | **************************************************************************/ 22 | 23 | #ifndef _LTSM_VNC2IMAGE_ 24 | #define _LTSM_VNC2IMAGE_ 25 | 26 | #include 27 | #include 28 | 29 | #include "ltsm_global.h" 30 | #include "ltsm_application.h" 31 | #include "ltsm_framebuffer.h" 32 | 33 | #define LTSM_VNC2IMAGE_VERSION 20220829 34 | 35 | namespace LTSM 36 | { 37 | class Vnc2Image : public Application, protected RFB::ClientDecoder 38 | { 39 | std::chrono::steady_clock::time_point tp; 40 | std::unique_ptr fbPtr; 41 | 42 | std::string host{"localhost"}; 43 | std::string password; 44 | std::string filename{"screenshot.png"}; 45 | int port = 5900; 46 | int timeout = 0; 47 | bool notls = false; 48 | 49 | protected: 50 | void setPixel(const XCB::Point &, uint32_t pixel) override; 51 | void fillPixel(const XCB::Region &, uint32_t pixel) override; 52 | void updateRawPixels(const void*, const XCB::Region &, uint32_t pitch, const PixelFormat & pf) override; 53 | void updateRawPixels2(const void*, const XCB::Region &, uint8_t depth, uint32_t pitch, uint32_t sdlFormat) override; 54 | const PixelFormat & clientFormat(void) const override; 55 | XCB::Size clientSize(void) const override; 56 | 57 | uint16_t extClipboardLocalTypes(void) const override; 58 | std::vector extClipboardLocalData(uint16_t type) const override; 59 | void extClipboardRemoteTypesEvent(uint16_t type) override; 60 | void extClipboardRemoteDataEvent(uint16_t type, std::vector &&) override; 61 | void extClipboardSendEvent(const std::vector &) override; 62 | 63 | int startSocket(std::string_view host, int port) const; 64 | 65 | public: 66 | Vnc2Image(int argc, const char** argv); 67 | 68 | void clientRecvPixelFormatEvent(const PixelFormat &, const XCB::Size &) override; 69 | void clientRecvFBUpdateEvent(void) override; 70 | 71 | int start(void) override; 72 | }; 73 | } 74 | 75 | #endif // _LTSM_VNC2IMAGE_ 76 | -------------------------------------------------------------------------------- /src/x11vnc/ltsm_connector_x11vnc.cpp: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #include 25 | 26 | #include "ltsm_application.h" 27 | #include "ltsm_connector_x11vnc.h" 28 | 29 | using namespace std::chrono_literals; 30 | 31 | namespace LTSM 32 | { 33 | Connector::X11VNC::X11VNC(int fd, const JsonObject & jo) : RFB::X11Server(fd) 34 | { 35 | _config = & jo; 36 | _remoteaddr.assign("local"); 37 | 38 | if(auto env = std::getenv("REMOTE_ADDR")) 39 | { 40 | _remoteaddr.assign(env); 41 | } 42 | 43 | loadKeymap(); 44 | } 45 | 46 | bool Connector::X11VNC::loadKeymap(void) 47 | { 48 | if(! _config->hasKey("keymapfile")) 49 | { 50 | return false; 51 | } 52 | 53 | auto jc = JsonContentFile(_config->getString("keymapfile")); 54 | 55 | if(! jc.isObject()) 56 | { 57 | Application::error("%s: invalid keymap file", __FUNCTION__); 58 | return false; 59 | } 60 | 61 | auto jo = jc.toObject(); 62 | 63 | for(const auto & skey : jo.keys()) 64 | { 65 | try 66 | { 67 | keymap.emplace(std::stoi(skey, nullptr, 0), jo.getInteger(skey)); 68 | } 69 | catch(const std::exception &) 70 | { 71 | } 72 | } 73 | 74 | return keymap.size(); 75 | } 76 | 77 | bool Connector::X11VNC::rfbClipboardEnable(void) const 78 | { 79 | return _config->getBoolean("ClipBoard"); 80 | } 81 | 82 | bool Connector::X11VNC::rfbDesktopResizeEnabled(void) const 83 | { 84 | return _config->getBoolean("DesktopResized"); 85 | } 86 | 87 | bool Connector::X11VNC::xcbNoDamageOption(void) const 88 | { 89 | return _config->getBoolean("nodamage", false); 90 | } 91 | 92 | bool Connector::X11VNC::xcbAllowMessages(void) const 93 | { 94 | return ! _xcbDisable; 95 | } 96 | 97 | void Connector::X11VNC::xcbDisableMessages(bool f) 98 | { 99 | _xcbDisable = f; 100 | } 101 | 102 | int Connector::X11VNC::rfbUserKeycode(uint32_t keysym) const 103 | { 104 | auto it = keymap.find(keysym); 105 | return it != keymap.end() ? it->second : 0; 106 | } 107 | 108 | const PixelFormat & Connector::X11VNC::serverFormat(void) const 109 | { 110 | return _pf; 111 | } 112 | 113 | std::forward_list Connector::X11VNC::serverDisabledEncodings(void) const 114 | { 115 | return {}; 116 | } 117 | 118 | RFB::SecurityInfo Connector::X11VNC::rfbSecurityInfo(void) const 119 | { 120 | RFB::SecurityInfo secInfo; 121 | secInfo.authNone = _config->getBoolean("noauth", false); 122 | secInfo.authVnc = _config->hasKey("passwdfile"); 123 | secInfo.passwdFile = _config->getString("passwdfile"); 124 | secInfo.authVenCrypt = ! _config->getBoolean("notls", false); 125 | secInfo.tlsPriority = "NORMAL:+ANON-ECDH:+ANON-DH"; 126 | secInfo.tlsAnonMode = true; 127 | secInfo.tlsDebug = 0; 128 | 129 | if(Application::isDebugLevel(DebugLevel::Debug)) 130 | { 131 | secInfo.tlsDebug = 1; 132 | } 133 | else if(Application::isDebugLevel(DebugLevel::Trace)) 134 | { 135 | secInfo.tlsDebug = 3; 136 | } 137 | 138 | return secInfo; 139 | } 140 | 141 | bool Connector::X11VNC::xcbConnect(void) 142 | { 143 | // FIXM XAUTH 144 | std::string xauthFile = _config->getString("authfile"); 145 | Application::debug(DebugType::Conn, "%s: xauthfile: `%s'", __FUNCTION__, xauthFile.c_str()); 146 | // Xvfb: wait display starting 147 | setenv("XAUTHORITY", xauthFile.c_str(), 1); 148 | size_t screen = _config->getInteger("display", 0); 149 | 150 | try 151 | { 152 | xcbDisplay()->displayReconnect(screen); 153 | } 154 | catch(const std::exception & err) 155 | { 156 | Application::error("%s: exception: %s", NS_FuncName.c_str(), err.what()); 157 | return false; 158 | } 159 | 160 | Application::info("%s: display: %d, size: [%d,%d], depth: %d", __FUNCTION__, screen, xcbDisplay()->width(), 161 | xcbDisplay()->height(), xcbDisplay()->depth()); 162 | Application::debug(DebugType::Conn, "%s: xcb max request: %d", __FUNCTION__, xcbDisplay()->getMaxRequest()); 163 | const xcb_visualtype_t* visual = xcbDisplay()->visual(); 164 | 165 | if(! visual) 166 | { 167 | Application::error("%s: xcb visual empty", __FUNCTION__); 168 | return false; 169 | } 170 | 171 | xcbShmInit(); 172 | // init server format 173 | _pf = PixelFormat(xcbDisplay()->bitsPerPixel(), visual->red_mask, visual->green_mask, visual->blue_mask, 0); 174 | return true; 175 | } 176 | 177 | void Connector::X11VNC::serverHandshakeVersionEvent(void) 178 | { 179 | if(! xcbConnect()) 180 | { 181 | Application::error("%s: %s", __FUNCTION__, "xcb connect failed"); 182 | throw rfb_error(NS_FuncName); 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/x11vnc/ltsm_connector_x11vnc.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_CONNECTOR_X11VNC_ 25 | #define _LTSM_CONNECTOR_X11VNC_ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "librfb_x11server.h" 32 | 33 | namespace LTSM 34 | { 35 | namespace Connector 36 | { 37 | /* Connector::VNC */ 38 | class X11VNC : public RFB::X11Server 39 | { 40 | std::unordered_map keymap; 41 | 42 | const JsonObject* _config = nullptr; 43 | std::string _remoteaddr; 44 | 45 | PixelFormat _pf; 46 | 47 | std::atomic _display{0}; 48 | std::atomic _xcbDisable{true}; 49 | 50 | protected: 51 | // rfb server encoding 52 | const PixelFormat & serverFormat(void) const override; 53 | std::forward_list serverDisabledEncodings(void) const override; 54 | 55 | bool xcbNoDamageOption(void) const override; 56 | bool xcbAllowMessages(void) const override; 57 | void xcbDisableMessages(bool) override; 58 | 59 | bool rfbClipboardEnable(void) const override; 60 | bool rfbDesktopResizeEnabled(void) const override; 61 | RFB::SecurityInfo rfbSecurityInfo(void) const override; 62 | int rfbUserKeycode(uint32_t) const override; 63 | 64 | void serverHandshakeVersionEvent(void) override; 65 | size_t frameRateOption(void) const override 66 | { 67 | return 16; 68 | } 69 | 70 | bool xcbConnect(void); 71 | bool loadKeymap(void); 72 | 73 | public: 74 | X11VNC(int fd, const JsonObject & jo); 75 | }; 76 | } 77 | } 78 | 79 | #endif // _LTSM_CONNECTOR_X11VNC_ 80 | -------------------------------------------------------------------------------- /src/x11vnc/ltsm_x11vnc.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright © 2021 by Andrey Afletdinov * 3 | * * 4 | * Part of the LTSM: Linux Terminal Service Manager: * 5 | * https://github.com/AndreyBarmaley/linux-terminal-service-manager * 6 | * * 7 | * This program is free software; * 8 | * you can redistribute it and/or modify it under the terms of the * 9 | * GNU Affero General Public License as published by the * 10 | * Free Software Foundation; either version 3 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, * 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 16 | * See the GNU Affero General Public License for more details. * 17 | * * 18 | * You should have received a copy of the * 19 | * GNU Affero General Public License along with this program; * 20 | * if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 22 | **********************************************************************/ 23 | 24 | #ifndef _LTSM_X11VNC_ 25 | #define _LTSM_X11VNC_ 26 | 27 | #include "ltsm_application.h" 28 | #define LTSM_X11VNC_VERSION 20220920 29 | 30 | namespace LTSM 31 | { 32 | class X11Vnc : public ApplicationJsonConfig 33 | { 34 | int startInetd(void) const; 35 | int startSocket(int port) const; 36 | 37 | public: 38 | X11Vnc(int argc, const char** argv); 39 | 40 | int start(void); 41 | }; 42 | } 43 | 44 | #endif // _LTSM_CONNECTOR_ 45 | --------------------------------------------------------------------------------