diff options
author | Gyuhwan Park★ <unstabler@unstabler.pl> | 2022-05-24 16:54:48 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-24 16:54:48 +0300 |
commit | 7c60c626191cfc9d7ca5f52ee1f9a7654fabfb70 (patch) | |
tree | 778d40694578e8349b4a4d17c9e445c8d1f6190e | |
parent | 4c0058ad29f61b9e588d10bd0995281567bb70b5 (diff) | |
parent | 45cb4955cc52b928d639c6476ce030419dcadc3a (diff) |
Merge pull request #1 from unstabler/integrate-broker
feature: add sessionbroker integration
-rw-r--r-- | IPCConnection.cpp | 116 | ||||
-rw-r--r-- | IPCConnection.hpp | 86 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | ProjectionContext.hpp | 2 | ||||
-rw-r--r-- | ProjectionThread.cpp | 152 | ||||
-rw-r--r-- | ProjectionThread.hpp | 54 | ||||
-rw-r--r-- | UlalacaMessages.hpp | 132 | ||||
-rw-r--r-- | messages/_global.h | 28 | ||||
-rw-r--r-- | messages/broker.h | 41 | ||||
-rw-r--r-- | messages/projector.h | 96 | ||||
-rw-r--r-- | ulalaca.cpp | 86 | ||||
-rw-r--r-- | ulalaca.hpp | 10 |
12 files changed, 489 insertions, 316 deletions
diff --git a/IPCConnection.cpp b/IPCConnection.cpp new file mode 100644 index 0000000..c784a1d --- /dev/null +++ b/IPCConnection.cpp @@ -0,0 +1,116 @@ +// +// Created by Gyuhwan Park on 2022/05/24. +// + +#if defined(HAVE_CONFIG_H) +#include <config_ac.h> +#endif + +#include "IPCConnection.hpp" + +IPCConnection::IPCConnection(std::string socketPath): + _socket(socketPath), + _isWorkerTerminated(false), + + _messageId(0), + _ackId(0) +{ + +} + +void IPCConnection::connect() { + _socket.connect(); + + _workerThread = std::thread(&IPCConnection::workerLoop, this); +} + +void IPCConnection::disconnect() { + _isWorkerTerminated = true; + + if (_workerThread.joinable()) { + _workerThread.join(); + } + _socket.close(); +} + +std::unique_ptr<ULIPCHeader, IPCConnection::MallocFreeDeleter> IPCConnection::nextHeader() { + return std::move(read<ULIPCHeader>(sizeof(ULIPCHeader))); +} + +void IPCConnection::write(const void *pointer, size_t size) { + assert(pointer != nullptr); + assert(size > 0); + + std::scoped_lock<std::mutex> scopedWriteTasksLock(_writeTasksLock); + + std::unique_ptr<uint8_t, MallocFreeDeleter> data( + (uint8_t *) malloc(size), + free + ); + + std::memcpy(data.get(), pointer, size); + + _writeTasks.emplace(size, std::move(data)); +} + +void IPCConnection::workerLoop() { + const size_t MAX_READ_SIZE = 8192; + + size_t readBytes = 0; + std::unique_ptr<uint8_t> _currentReadTask; + + while (!_isWorkerTerminated) { + if (_writeTasks.empty() && _readTasks.empty()) { + using namespace std::chrono_literals; + std::this_thread::sleep_for(1ms); + } + + while (!_writeTasks.empty()) { + std::scoped_lock<std::mutex> scopedWriteTasksLock(_writeTasksLock); + auto writeTask = std::move(_writeTasks.front()); + _writeTasks.pop(); + + if (_socket.write(writeTask.second.get(), writeTask.first) < 0) { + throw std::runtime_error("could not perform write()"); + } + } + + while (!_readTasks.empty()) { + auto &readTask = _readTasks.front(); + + auto &contentLength = readTask.first; + auto &promise = readTask.second; + + if (_currentReadTask == nullptr) { + readBytes = 0; + _currentReadTask = std::unique_ptr<uint8_t>( + new uint8_t[readTask.first] + ); + } + + int bytes = std::min( + (size_t) MAX_READ_SIZE, + contentLength - readBytes + ); + + size_t retval = _socket.read(_currentReadTask.get() + readBytes, bytes); + if (retval < 0) { + throw std::runtime_error("failed to perform read()"); + } + + readBytes += retval; + + if (readBytes >= contentLength) { + promise.set_value(std::move(_currentReadTask)); + + { + std::scoped_lock<std::mutex> scopedReadTasksLock(_readTasksLock); + _readTasks.pop(); + } + + _currentReadTask = nullptr; + readBytes = 0; + } + } + } +} diff --git a/IPCConnection.hpp b/IPCConnection.hpp new file mode 100644 index 0000000..d3b1f1f --- /dev/null +++ b/IPCConnection.hpp @@ -0,0 +1,86 @@ +// +// Created by Gyuhwan Park on 2022/05/24. +// + +#ifndef ULALACA_IPCCONNECTION_HPP +#define ULALACA_IPCCONNECTION_HPP + +#include <memory> +#include <thread> +#include <queue> +#include <future> + +#include "UnixSocket.hpp" + +#include "messages/projector.h" + +#include "ulalaca.hpp" + + +class IPCConnection { +public: + using MallocFreeDeleter = std::function<void(void *)>; + + explicit IPCConnection(std::string socketPath); + IPCConnection(IPCConnection &) = delete; + + /** + * @throws SystemCallException + */ + void connect(); + void disconnect(); + + std::unique_ptr<ULIPCHeader, MallocFreeDeleter> nextHeader(); + + template <typename T> + void writeMessage(uint16_t messageType, T message) { + auto header = ULIPCHeader { + (uint16_t) messageType, + _messageId, + 0, // FIXME + 0, // FIXME + sizeof(T) + }; + + write(&header, sizeof(header)); + write(&message, sizeof(T)); + } + + template<typename T> + std::unique_ptr<T, MallocFreeDeleter> read(size_t size) { + assert(size != 0); + + auto promise = std::promise<std::unique_ptr<uint8_t>>(); + { + std::scoped_lock<std::mutex> scopedReadTasksLock(_readTasksLock); + _readTasks.emplace(size, promise); + } + auto pointer = promise.get_future().get(); + + return std::move(std::unique_ptr<T, MallocFreeDeleter>( + reinterpret_cast<T *>(pointer.release()), + free + )); + } + + void write(const void *pointer, size_t size); + +private: + void workerLoop(); + + std::atomic_uint64_t _messageId; + std::atomic_uint64_t _ackId; + + UnixSocket _socket; + std::thread _workerThread; + bool _isWorkerTerminated; + + std::mutex _writeTasksLock; + std::mutex _readTasksLock; + + std::queue<std::pair<size_t, std::unique_ptr<uint8_t, MallocFreeDeleter>>> _writeTasks; + std::queue<std::pair<size_t, std::promise<std::unique_ptr<uint8_t>> &>> _readTasks; +}; + + +#endif //XRDP_IPCCONNECTION_HPP diff --git a/Makefile.am b/Makefile.am index fd1f365..6099528 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,6 +24,8 @@ libulalaca_la_SOURCES = \ XrdpStream.hpp \ XrdpStream.cpp \ UlalacaMessages.hpp \ + IPCConnection.hpp \ + IPCConnection.cpp \ ProjectionThread.hpp \ ProjectionThread.cpp \ KeycodeMap.cpp \ diff --git a/ProjectionContext.hpp b/ProjectionContext.hpp index 9a957b6..16ca034 100644 --- a/ProjectionContext.hpp +++ b/ProjectionContext.hpp @@ -9,7 +9,7 @@ #include <utility> -#include "UlalacaMessages.hpp" +#include "messages/projector.h" class ProjectionContext { public: diff --git a/ProjectionThread.cpp b/ProjectionThread.cpp index 6828f49..8ebac61 100644 --- a/ProjectionThread.cpp +++ b/ProjectionThread.cpp @@ -13,46 +13,54 @@ extern "C" { #include "defines.h" #include "guid.h" #include "xrdp_client_info.h" -}; +} #include "ProjectionThread.hpp" #include "KeycodeMap.hpp" ProjectionThread::ProjectionThread( XrdpUlalaca &xrdpUlalaca, - UnixSocket &socket + const std::string &socketPath ): _xrdpUlalaca(xrdpUlalaca), - _socket(socket), + _ipcConnection(socketPath), _isTerminated(false) { } void ProjectionThread::start() { + _ipcConnection.connect(); _projectorThread = std::thread(&ProjectionThread::mainLoop, this); - _ioThread = std::thread(&ProjectionThread::ioLoop, this); } void ProjectionThread::stop() { _isTerminated = true; + + if (_projectorThread.joinable()) { + _projectorThread.join(); + } + + _ipcConnection.disconnect(); } void ProjectionThread::handleEvent(XrdpEvent &event) { - using namespace projector; + if (_isTerminated) { + return; + } if (event.isKeyEvent()) { auto keycode = event.param3; auto cgKeycode = rdpKeycodeToCGKeycode(keycode); auto eventType = event.type == XrdpEvent::KEY_DOWN ? - KeyboardEvent::TYPE_KEYDOWN : - KeyboardEvent::TYPE_KEYUP; + KEYBOARD_EVENT_TYPE_KEYDOWN : + KEYBOARD_EVENT_TYPE_KEYUP; if (cgKeycode == -1) { return; } - writeMessage(MessageType::OUT_KEYBOARD_EVENT, KeyboardEvent { + _ipcConnection.writeMessage(TYPE_EVENT_KEYBOARD, ULIPCKeyboardEvent { eventType, (uint32_t) cgKeycode, 0 }); } else if (event.type == XrdpEvent::KEY_SYNCHRONIZE_LOCK) { @@ -65,7 +73,7 @@ void ProjectionThread::handleEvent(XrdpEvent &event) { uint16_t posX = event.param1; uint16_t posY = event.param2; - writeMessage(MessageType::OUT_MOUSE_MOVE_EVENT, MouseMoveEvent { + _ipcConnection.writeMessage(TYPE_EVENT_MOUSE_MOVE, ULIPCMouseMoveEvent { posX, posY, 0 }); @@ -73,17 +81,17 @@ void ProjectionThread::handleEvent(XrdpEvent &event) { } case XrdpEvent::MOUSE_BUTTON_LEFT_DOWN: { - writeMessage(MessageType::OUT_MOUSE_BUTTON_EVENT, MouseButtonEvent { - MouseButtonEvent::TYPE_MOUSEDOWN, - MouseButtonEvent::BUTTON_LEFT, + _ipcConnection.writeMessage(TYPE_EVENT_MOUSE_BUTTON, ULIPCMouseButtonEvent { + MOUSE_EVENT_TYPE_DOWN, + MOUSE_EVENT_BUTTON_LEFT, 0 }); return; } case XrdpEvent::MOUSE_BUTTON_LEFT_UP: { - writeMessage(MessageType::OUT_MOUSE_BUTTON_EVENT, MouseButtonEvent { - MouseButtonEvent::TYPE_MOUSEUP, - MouseButtonEvent::BUTTON_LEFT, + _ipcConnection.writeMessage(TYPE_EVENT_MOUSE_BUTTON, ULIPCMouseButtonEvent { + MOUSE_EVENT_TYPE_UP, + MOUSE_EVENT_BUTTON_LEFT, 0 }); return; @@ -91,17 +99,17 @@ void ProjectionThread::handleEvent(XrdpEvent &event) { case XrdpEvent::MOUSE_BUTTON_RIGHT_DOWN: { - writeMessage(MessageType::OUT_MOUSE_BUTTON_EVENT, MouseButtonEvent { - MouseButtonEvent::TYPE_MOUSEDOWN, - MouseButtonEvent::BUTTON_RIGHT, + _ipcConnection.writeMessage(TYPE_EVENT_MOUSE_BUTTON, ULIPCMouseButtonEvent { + MOUSE_EVENT_TYPE_DOWN, + MOUSE_EVENT_BUTTON_RIGHT, 0 }); return; } case XrdpEvent::MOUSE_BUTTON_RIGHT_UP: { - writeMessage(MessageType::OUT_MOUSE_BUTTON_EVENT, MouseButtonEvent { - MouseButtonEvent::TYPE_MOUSEUP, - MouseButtonEvent::BUTTON_RIGHT, + _ipcConnection.writeMessage(TYPE_EVENT_MOUSE_BUTTON, ULIPCMouseButtonEvent { + MOUSE_EVENT_TYPE_UP, + MOUSE_EVENT_BUTTON_RIGHT, 0 }); return; @@ -146,114 +154,32 @@ void ProjectionThread::handleEvent(XrdpEvent &event) { void ProjectionThread::mainLoop() { while (!_isTerminated) { - auto header = nextHeader(); + auto header = _ipcConnection.nextHeader(); switch (header->messageType) { - case projector::IN_SCREEN_UPDATE_EVENT: { - auto updateEvent = read<projector::ScreenUpdateEvent>(header->length); + case TYPE_SCREEN_UPDATE_NOTIFY: { + auto notification = _ipcConnection.read<ULIPCScreenUpdateNotify>(header->length); LOG(LOG_LEVEL_DEBUG, "mainLoop(): adding dirty rect"); - _xrdpUlalaca.addDirtyRect(updateEvent->rect); + _xrdpUlalaca.addDirtyRect(notification->rect); continue; } - case projector::IN_SCREEN_COMMIT_UPDATE: { - auto commitUpdate = read<projector::ScreenCommitUpdate>(header->length); - auto bitmap = read<uint8_t>(commitUpdate->bitmapLength); + case TYPE_SCREEN_UPDATE_COMMIT: { + auto commit = _ipcConnection.read<ULIPCScreenUpdateCommit>(header->length); + auto bitmap = _ipcConnection.read<uint8_t>(commit->bitmapLength); LOG(LOG_LEVEL_DEBUG, "mainLoop(): commiting update"); _xrdpUlalaca.commitUpdate( bitmap.get(), - commitUpdate->screenRect.width, - commitUpdate->screenRect.height + commit->screenRect.width, + commit->screenRect.height ); continue; } default: { // ignore - read<uint8_t>(header->length); - } - } - } -} - -void ProjectionThread::ioLoop() { - const size_t MAX_READ_SIZE = 8192; - - size_t readBytes = 0; - std::unique_ptr<uint8_t> _currentReadTask; - - while (!_isTerminated) { - if (_writeTasks.empty() && _readTasks.empty()) { - using namespace std::chrono_literals; - std::this_thread::sleep_for(1ms); - } - - if (!_writeTasks.empty()) { - std::scoped_lock<std::mutex> scopedWriteTasksLock(_writeTasksLock); - auto writeTask = std::move(_writeTasks.front()); - _writeTasks.pop(); - - if (_socket.write(writeTask.second.get(), writeTask.first) < 0) { - throw std::runtime_error("failed to perform write()"); - } - } - - if (!_readTasks.empty()) { - auto &readTask = _readTasks.front(); - - auto &contentLength = readTask.first; - auto &promise = readTask.second; - - if (_currentReadTask == nullptr) { - readBytes = 0; - _currentReadTask = std::unique_ptr<uint8_t>( - new uint8_t[readTask.first] - ); - } - - int bytes = std::min( - (size_t) MAX_READ_SIZE, - contentLength - readBytes - ); - - size_t retval = _socket.read(_currentReadTask.get() + readBytes, bytes); - if (retval < 0) { - throw std::runtime_error("failed to perform read()"); - } - - readBytes += retval; - - if (readBytes >= contentLength) { - promise.set_value(std::move(_currentReadTask)); - - { - std::scoped_lock<std::mutex> scopedReadTasksLock(_readTasksLock); - _readTasks.pop(); - } - - _currentReadTask = nullptr; - readBytes = 0; + _ipcConnection.read<uint8_t>(header->length); } } } -} - -std::unique_ptr<projector::MessageHeader, MallocFreeDeleter> ProjectionThread::nextHeader() { - return std::move(read<projector::MessageHeader>(sizeof(projector::MessageHeader))); -} - -void ProjectionThread::write(const void *pointer, size_t size) { - assert(pointer != nullptr); - assert(size > 0); - - std::scoped_lock<std::mutex> scopedWriteTasksLock(_writeTasksLock); - - std::unique_ptr<uint8_t, MallocFreeDeleter> data( - (uint8_t *) malloc(size), - free - ); - - std::memcpy(data.get(), pointer, size); - - _writeTasks.emplace(size, std::move(data)); }
\ No newline at end of file diff --git a/ProjectionThread.hpp b/ProjectionThread.hpp index fe25eb3..c8be1bf 100644 --- a/ProjectionThread.hpp +++ b/ProjectionThread.hpp @@ -12,17 +12,19 @@ #include "UnixSocket.hpp" -#include "UlalacaMessages.hpp" +#include "IPCConnection.hpp" +#include "messages/projector.h" + #include "ulalaca.hpp" -using MallocFreeDeleter = std::function<void(void *)>; class ProjectionThread { public: explicit ProjectionThread( XrdpUlalaca &xrdpUlalaca, - UnixSocket &socket + const std::string &socketPath ); + ProjectionThread(ProjectionThread &) = delete; void start(); void stop(); @@ -30,56 +32,12 @@ public: void handleEvent(XrdpEvent &event); private: void mainLoop(); - void ioLoop(); - - std::unique_ptr<projector::MessageHeader, MallocFreeDeleter> nextHeader(); - - template<typename T> - std::unique_ptr<T, MallocFreeDeleter> read(size_t size) { - assert(size != 0); - - auto promise = std::promise<std::unique_ptr<uint8_t>>(); - { - std::scoped_lock<std::mutex> scopedReadTasksLock(_readTasksLock); - _readTasks.emplace(size, promise); - } - auto pointer = promise.get_future().get(); - - return std::move(std::unique_ptr<T, MallocFreeDeleter>( - reinterpret_cast<T *>(pointer.release()), - free - )); - } - - void write(const void *pointer, size_t size); - - template <typename T> - void writeMessage(projector::MessageType messageType, T message) { - auto header = projector::MessageHeader { - (uint16_t) messageType, - 0, 0, - 0, - sizeof(T) - }; - - write(&header, sizeof(header)); - write(&message, sizeof(T)); - } - XrdpUlalaca &_xrdpUlalaca; - UnixSocket &_socket; + IPCConnection _ipcConnection; bool _isTerminated; std::thread _projectorThread; - std::thread _ioThread; - - - std::mutex _writeTasksLock; - std::mutex _readTasksLock; - - std::queue<std::pair<size_t, std::unique_ptr<uint8_t, MallocFreeDeleter>>> _writeTasks; - std::queue<std::pair<size_t, std::promise<std::unique_ptr<uint8_t>> &>> _readTasks; }; #endif //ULALACA_PROJECTIONTHREAD_HPP diff --git a/UlalacaMessages.hpp b/UlalacaMessages.hpp deleted file mode 100644 index f640f6b..0000000 --- a/UlalacaMessages.hpp +++ /dev/null @@ -1,132 +0,0 @@ -// -// Created by Gyuhwan Park on 2022/05/06. -// - -#ifndef XRDP_ULALACAMESSAGES_HPP -#define XRDP_ULALACAMESSAGES_HPP - -#include <cstdint> - -#define FIXME_MARK_AS_PACKED_STRUCT __attribute__ ((packed)) - -struct Rect { - short x; - short y; - short width; - short height; -} __attribute__ ((packed)); - -namespace projector { - - enum MessageType: uint16_t { - IN_SCREEN_UPDATE_EVENT = 0x0101, - IN_SCREEN_COMMIT_UPDATE = 0x0102, - - OUT_SCREEN_UPDATE_REQUEST = 0x0201, - - OUT_KEYBOARD_EVENT = 0x0311, - - OUT_MOUSE_MOVE_EVENT = 0x0321, - OUT_MOUSE_BUTTON_EVENT = 0x0322, - OUT_MOUSE_WHEEL_EVENT = 0x0323 - }; - - struct MessageHeader { - uint16_t messageType; - - uint64_t id; - uint64_t replyTo; - - uint64_t timestamp; - - uint64_t length; - } FIXME_MARK_AS_PACKED_STRUCT; - - /** - * incoming message - */ - struct ScreenUpdateEvent { - uint8_t type; - - Rect rect; - } FIXME_MARK_AS_PACKED_STRUCT; - - struct ScreenCommitUpdate { - Rect screenRect; - - uint64_t bitmapLength; - } FIXME_MARK_AS_PACKED_STRUCT; - - struct ScreenUpdateRequest { - static const uint8_t TYPE_ENTIRE_SCREEN = 0; - static const uint8_t TYPE_PARTIAL = 1; - - uint8_t type; - - Rect rect; - }; - - struct KeyboardEvent { - static const uint8_t TYPE_NOOP = 0; - static const uint8_t TYPE_KEYUP = 1; - static const uint8_t TYPE_KEYDOWN = 2; - - /** - * force releases pressed keys - */ - static const uint8_t TYPE_RESET = 4; - - static const uint16_t FLAG_IGNORE_TIMESTAMP_QUEUE = 0b00000001; - static const uint16_t FLAG_EMIT_EVENT_USING_KARABINER = 0b00010000; - - - uint8_t type; - uint32_t keyCode; - - uint16_t flags; - } FIXME_MARK_AS_PACKED_STRUCT; - - struct MouseMoveEvent { - static const uint16_t FLAG_IGNORE_TIMESTAMP_QUEUE = 0b0001; - static const uint16_t FLAG_EMIT_EVENT_USING_KARABINER = 0b00010000; - - uint16_t x; - uint16_t y; - - uint16_t flags; - } FIXME_MARK_AS_PACKED_STRUCT; - - struct MouseButtonEvent { - static const uint8_t TYPE_NOOP = 0; - static const uint8_t TYPE_MOUSEUP = 1; - static const uint8_t TYPE_MOUSEDOWN = 2; - - static const uint8_t BUTTON_LEFT = 0; - static const uint8_t BUTTON_RIGHT = 1; - static const uint8_t BUTTON_MIDDLE = 2; - - static const uint16_t FLAG_IGNORE_TIMESTAMP_QUEUE = 0b0001; - static const uint16_t FLAG_EMIT_EVENT_USING_KARABINER = 0b00010000; - - // ... - - uint8_t type; - uint8_t button; - - uint16_t flags; - } FIXME_MARK_AS_PACKED_STRUCT; - - struct MouseWheelEvent { - static const uint16_t FLAG_IGNORE_TIMESTAMP_QUEUE = 0b0001; - static const uint16_t FLAG_EMIT_EVENT_USING_KARABINER = 0b00010000; - - int32_t deltaX; - int32_t deltaY; - - uint16_t flags; - } FIXME_MARK_AS_PACKED_STRUCT; - - -} - -#endif //XRDP_ULALACAMESSAGES_HPP diff --git a/messages/_global.h b/messages/_global.h new file mode 100644 index 0000000..e12de21 --- /dev/null +++ b/messages/_global.h @@ -0,0 +1,28 @@ +#ifndef ULALACA_CORE_IPC_MESSAGES_GLOBAL_H +#define ULALACA_CORE_IPC_MESSAGES_GLOBAL_H + +/** + * FIXME: naming + */ +#define FIXME_MARK_AS_PACKED_STRUCT __attribute__ ((packed)) + +struct ULIPCRect { + short x; + short y; + short width; + short height; +} FIXME_MARK_AS_PACKED_STRUCT; + +struct ULIPCHeader { + uint16_t messageType; + + uint64_t id; + uint64_t replyTo; + + uint64_t timestamp; + + uint64_t length; +} FIXME_MARK_AS_PACKED_STRUCT; + + +#endif
\ No newline at end of file diff --git a/messages/broker.h b/messages/broker.h new file mode 100644 index 0000000..131278f --- /dev/null +++ b/messages/broker.h @@ -0,0 +1,41 @@ +#ifndef ULALACA_CORE_IPC_MESSAGES_BROKER_H +#define ULALACA_CORE_IPC_MESSAGES_BROKER_H + +#include <stdint.h> + +#include "_global.h" + +/* constants: message type (server -> client) */ +static const uint16_t TYPE_SESSION_REQUEST_RESOLVED = 0xA100; +static const uint16_t TYPE_SESSION_REQUEST_REJECTED = 0xA101; + +/* constants: message type (client -> server) */ +static const uint16_t TYPE_SESSION_REQUEST = 0xA011; + + +/* constants: reject reason */ +static const uint8_t REJECT_REASON_INTERNAL_ERROR = 0; +static const uint8_t REJECT_REASON_AUTHENTICATION_FAILED = 1; +static const uint8_t REJECT_REASON_SESSION_NOT_AVAILABLE = 2; +static const uint8_t REJECT_REASON_INCOMPATIBLE_VERSION = 3; + + +/* message definition: server -> client */ +struct ULIPCSessionRequestResolved { + uint64_t sessionId; + uint8_t isLoginSession; + + char path[1024]; +} FIXME_MARK_AS_PACKED_STRUCT; + +struct ULIPCSessionRequestRejected { + uint8_t reason; +} FIXME_MARK_AS_PACKED_STRUCT; + +/* message definition: client -> server */ +struct ULIPCSessionRequest { + char username[64]; + char password[256]; +} FIXME_MARK_AS_PACKED_STRUCT; + +#endif
\ No newline at end of file diff --git a/messages/projector.h b/messages/projector.h new file mode 100644 index 0000000..bcd0e84 --- /dev/null +++ b/messages/projector.h @@ -0,0 +1,96 @@ +#ifndef ULALACA_CORE_IPC_MESSAGES_PROJECTOR_H +#define ULALACA_CORE_IPC_MESSAGES_PROJECTOR_H + +#include <stdint.h> + +#include "_global.h" + + +/* constants: message type (server -> client) */ +static const uint16_t TYPE_SCREEN_UPDATE_NOTIFY = 0x0101; +static const uint16_t TYPE_SCREEN_UPDATE_COMMIT = 0x0102; + +/* constants: message type (client -> server) */ +static const uint16_t TYPE_EVENT_INVALIDATION = 0x0201; +static const uint16_t TYPE_EVENT_KEYBOARD = 0x0311; +static const uint16_t TYPE_EVENT_MOUSE_MOVE = 0x0321; +static const uint16_t TYPE_EVENT_MOUSE_BUTTON = 0x0322; +static const uint16_t TYPE_EVENT_MOUSE_WHEEL = 0x0323; + +/* constants: Screen update notification */ +static const uint8_t SCREEN_UPDATE_NOTIFY_TYPE_ENTIRE_SCREEN = 0; +static const uint8_t SCREEN_UPDATE_NOTIFY_TYPE_PARTIAL = 1; + +/* constants: Event Flags */ +/** Ignores time-ordered queue. (event will be emitted immediately) */ +static const uint16_t EVENT_IGNORE_TIMESTAMP_QUEUE = 0b00000001; + + +/* constants: Invalidation Event Types */ +static const uint8_t INVALIDATION_EVENT_TYPE_ENTIRE_SCREEN = 0; +static const uint8_t INVALIDATION_EVENT_TYPE_PARTIAL = 1; + +/* constants: Keyboard Event Types */ +static const uint8_t KEYBOARD_EVENT_TYPE_NOOP = 0; +static const uint8_t KEYBOARD_EVENT_TYPE_KEYUP = 1; +static const uint8_t KEYBOARD_EVENT_TYPE_KEYDOWN = 2; +/** force release all pressed keys. */ +static const uint8_t KEY_EVENT_TYPE_RESET = 4; + + +/* constants: Mouse Button Event */ +static const uint8_t MOUSE_EVENT_TYPE_NOOP = 0; +static const uint8_t MOUSE_EVENT_TYPE_UP = 1; +static const uint8_t MOUSE_EVENT_TYPE_DOWN = 2; + +static const uint8_t MOUSE_EVENT_BUTTON_LEFT = 0; +static const uint8_t MOUSE_EVENT_BUTTON_RIGHT = 1; +static const uint8_t MOUSE_EVENT_BUTTON_MIDDLE = 2; + +/* message definition: server -> client */ +struct ULIPCScreenUpdateNotify { + uint8_t type; + struct ULIPCRect rect; +} FIXME_MARK_AS_PACKED_STRUCT; + +struct ULIPCScreenUpdateCommit { + struct ULIPCRect screenRect; + uint64_t bitmapLength; +} FIXME_MARK_AS_PACKED_STRUCT; + + +/* message definition: client -> server */ +struct ULIPCInvalidationEvent { + uint8_t type; + struct ULIPCRect rect; +}; + +struct ULIPCKeyboardEvent { + uint8_t type; + uint32_t keyCode; + + uint16_t flags; +} FIXME_MARK_AS_PACKED_STRUCT; + +struct ULIPCMouseMoveEvent { + uint16_t x; + uint16_t y; + + uint16_t flags; +} FIXME_MARK_AS_PACKED_STRUCT; + +struct ULIPCMouseButtonEvent { + uint8_t type; + uint8_t button; + + uint16_t flags; +} FIXME_MARK_AS_PACKED_STRUCT; + +struct ULIPCMouseWheelEvent { + int32_t deltaX; + int32_t deltaY; + + uint16_t flags; +} FIXME_MARK_AS_PACKED_STRUCT; + +#endif
\ No newline at end of file diff --git a/ulalaca.cpp b/ulalaca.cpp index 9b14d42..d80ab3c 100644 --- a/ulalaca.cpp +++ b/ulalaca.cpp @@ -13,6 +13,7 @@ #include <sstream> #include <string> +#include "messages/broker.h" #include "ulalaca.hpp" #include "SocketStream.hpp" @@ -122,24 +123,26 @@ int XrdpUlalaca::lib_mod_set_param(XrdpUlalaca *_this, const char *_name, const } int XrdpUlalaca::lib_mod_connect(XrdpUlalaca *_this) { - _this->serverMessage("establishing connection to SessionProjector", 0); - try { - _this->_socket = std::make_unique<UnixSocket>( - _this->getSessionSocketPath(_this->_username) + std::string socketPath = _this->getSessionSocketPathUsingCredential( + _this->_username, _this->_password ); - _this->_socket->connect(); + _this->_password.clear(); + + if (socketPath.empty()) { + return 1; + } + + _this->_projectionThread = std::make_unique<ProjectionThread>( + *_this, socketPath + ); + + _this->_projectionThread->start(); } catch (SystemCallException &e) { _this->serverMessage(e.what(), 0); return 1; } - - _this->_password.clear(); - - _this->_projectionThread = std::make_unique<ProjectionThread>( - *_this, *(_this->_socket) - ); - _this->_projectionThread->start(); + _this->serverMessage("welcome to the fantasy zone, get ready!", 0); return 0; @@ -152,6 +155,11 @@ int XrdpUlalaca::lib_mod_signal(XrdpUlalaca *_this) { int XrdpUlalaca::lib_mod_end(XrdpUlalaca *_this) { LOG(LOG_LEVEL_INFO, "lib_mod_end() called"); + + if (_this->_projectionThread != nullptr) { + _this->_projectionThread->stop(); + } + return 0; } @@ -195,22 +203,59 @@ int XrdpUlalaca::lib_mod_server_version_message(XrdpUlalaca *_this) { return 0; } -std::string XrdpUlalaca::getSessionSocketPath(std::string &username) { - std::stringstream sstream; - sstream << "/Users/" << username << "/.ulalaca_projector.sock"; +std::string XrdpUlalaca::getSessionSocketPathUsingCredential( + const std::string &username, + const std::string &password +) { + std::string socketPath; - return sstream.str(); + IPCConnection connection("/var/run/ulalaca_broker.sock"); + connection.connect(); + { + using namespace std::chrono_literals; + + ULIPCSessionRequest request {}; + std::strncpy(&request.username[0], username.c_str(), sizeof(request.username)); + std::strncpy(&request.password[0], password.c_str(), sizeof(request.password)); + + connection.writeMessage(TYPE_SESSION_REQUEST, request); + std::memset(&request.password, 0x00, sizeof(request.password)); + + auto responseHeader = connection.nextHeader(); + + switch (responseHeader->messageType) { + case TYPE_SESSION_REQUEST_RESOLVED: { + auto response = connection.read<ULIPCSessionRequestResolved>( + sizeof(ULIPCSessionRequestResolved) + ); + + socketPath = std::string(response->path); + } + break; + + case TYPE_SESSION_REQUEST_REJECTED: + default: { + this->serverMessage("invalid credential", 0); + } + break; + + } + } + connection.disconnect(); + + + return socketPath; } int XrdpUlalaca::decideCopyRectSize() const { bool isRFXCodec = _clientInfo.rfx_codec_id != 0; bool isJPEGCodec = _clientInfo.jpeg_codec_id != 0; bool isH264Codec = _clientInfo.h264_codec_id != 0; - + if (isRFXCodec || isJPEGCodec) { return 64; } - + if (isH264Codec) { // return 256; return RECT_SIZE_BYPASS_CREATE; @@ -219,7 +264,10 @@ int XrdpUlalaca::decideCopyRectSize() const { return RECT_SIZE_BYPASS_CREATE; } -std::unique_ptr<std::vector<Rect>> XrdpUlalaca::createCopyRects(std::vector<Rect> &dirtyRects, int rectSize) const { +std::unique_ptr<std::vector<XrdpUlalaca::Rect>> XrdpUlalaca::createCopyRects( + std::vector<Rect> &dirtyRects, + int rectSize +) const { auto blocks = std::make_unique<std::vector<Rect>>(); if (rectSize == RECT_SIZE_BYPASS_CREATE) { diff --git a/ulalaca.hpp b/ulalaca.hpp index 808cdb6..6960952 100644 --- a/ulalaca.hpp +++ b/ulalaca.hpp @@ -22,7 +22,7 @@ extern "C" { #include "UnixSocket.hpp" -#include "UlalacaMessages.hpp" +#include "messages/projector.h" class ProjectionThread; @@ -159,6 +159,8 @@ struct XrdpUlalaca { struct source_info *si; public: + using Rect = ULIPCRect; + static const int RECT_SIZE_BYPASS_CREATE = 0; constexpr static const int ULALACA_VERSION = 1; @@ -187,8 +189,10 @@ public: static int lib_mod_server_version_message(XrdpUlalaca *_this); /* session-broker related */ - /** @deprecated */ - inline std::string getSessionSocketPath(std::string &username); + inline std::string getSessionSocketPathUsingCredential( + const std::string &username, + const std::string &password + ); /* paint related */ inline int decideCopyRectSize() const; |