diff options
author | Gyuhwan Park★ <unstabler@unstabler.pl> | 2023-01-28 18:38:50 +0300 |
---|---|---|
committer | Gyuhwan Park★ <unstabler@unstabler.pl> | 2023-01-28 18:38:50 +0300 |
commit | dd4b1559c0e59a93927ef3925f0c9ea5cd21b43a (patch) | |
tree | e733a62d5adc4d7046efb3b4ddc94f76640b07ad | |
parent | 7ef772c54ff216fee6c8a73198bf6c219887f8d3 (diff) |
refactor: clean-up code, try to fix incomprehensible naming
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | ProjectionTarget.hpp (renamed from ProjectionContext.hpp) | 5 | ||||
-rw-r--r-- | ProjectionThread.cpp | 8 | ||||
-rw-r--r-- | ProjectionThread.hpp | 6 | ||||
-rw-r--r-- | SessionBrokerClient.cpp | 89 | ||||
-rw-r--r-- | SessionBrokerClient.hpp | 37 | ||||
-rw-r--r-- | XrdpUlalacaPrivate.cpp | 179 | ||||
-rw-r--r-- | XrdpUlalacaPrivate.hpp | 13 | ||||
-rw-r--r-- | XrdpUlalacaPrivate.xrdpmodule.cpp | 59 | ||||
-rw-r--r-- | ulalaca.cpp | 206 | ||||
-rw-r--r-- | ulalaca.hpp | 4 |
11 files changed, 356 insertions, 252 deletions
diff --git a/Makefile.am b/Makefile.am index 018681e..e81345b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,6 +27,8 @@ libulalaca_la_SOURCES = \ UlalacaMessages.hpp \ IPCConnection.hpp \ IPCConnection.cpp \ + SessionBrokerClient.hpp \ + SessionBrokerClient.cpp \ ProjectionThread.hpp \ ProjectionThread.cpp \ KeycodeMap.cpp \ diff --git a/ProjectionContext.hpp b/ProjectionTarget.hpp index 16ca034..89c6da2 100644 --- a/ProjectionContext.hpp +++ b/ProjectionTarget.hpp @@ -6,14 +6,13 @@ #define ULALACA_PROJECTIONCONTEXT_HPP #include <cstdint> - #include <utility> #include "messages/projector.h" -class ProjectionContext { +class ProjectionTarget { public: - virtual void addDirtyRect(Rect &rect) = 0; + virtual void addDirtyRect(ULIPCRect &rect) = 0; virtual void commitUpdate( const uint8_t *image, diff --git a/ProjectionThread.cpp b/ProjectionThread.cpp index 0e48a2c..41d7d4d 100644 --- a/ProjectionThread.cpp +++ b/ProjectionThread.cpp @@ -19,10 +19,10 @@ extern "C" { #include "KeycodeMap.hpp" ProjectionThread::ProjectionThread( - XrdpUlalaca &xrdpUlalaca, + ProjectionTarget &target, const std::string &socketPath ): - _xrdpUlalaca(xrdpUlalaca), + _target(target), _ipcConnection(socketPath), _isTerminated(false) { @@ -180,7 +180,7 @@ void ProjectionThread::mainLoop() { auto notification = _ipcConnection.read<ULIPCScreenUpdateNotify>(header->length); LOG(LOG_LEVEL_DEBUG, "mainLoop(): adding dirty rect"); - _xrdpUlalaca.addDirtyRect(notification->rect); + _target.addDirtyRect(notification->rect); continue; } case TYPE_SCREEN_UPDATE_COMMIT: { @@ -188,7 +188,7 @@ void ProjectionThread::mainLoop() { auto bitmap = _ipcConnection.read<uint8_t>(commit->bitmapLength); LOG(LOG_LEVEL_DEBUG, "mainLoop(): commiting update"); - _xrdpUlalaca.commitUpdate( + _target.commitUpdate( bitmap.get(), commit->screenRect.width, commit->screenRect.height diff --git a/ProjectionThread.hpp b/ProjectionThread.hpp index 2e4a3b3..aea6a36 100644 --- a/ProjectionThread.hpp +++ b/ProjectionThread.hpp @@ -15,13 +15,13 @@ #include "IPCConnection.hpp" #include "messages/projector.h" -#include "ulalaca.hpp" +#include "ProjectionTarget.hpp" class ProjectionThread { public: explicit ProjectionThread( - XrdpUlalaca &xrdpUlalaca, + ProjectionTarget &target, const std::string &socketPath ); ProjectionThread(ProjectionThread &) = delete; @@ -36,7 +36,7 @@ public: private: void mainLoop(); - XrdpUlalaca &_xrdpUlalaca; + ProjectionTarget &_target; IPCConnection _ipcConnection; bool _isTerminated; diff --git a/SessionBrokerClient.cpp b/SessionBrokerClient.cpp new file mode 100644 index 0000000..22edb84 --- /dev/null +++ b/SessionBrokerClient.cpp @@ -0,0 +1,89 @@ +// +// Created by Gyuhwan Park on 2023/01/28. +// + +#include "SessionBrokerClient.hpp" + +#include "messages/broker.h" + +SessionBrokerClient::SessionBrokerClient(const std::string &socketPath): + _socketPath(socketPath) +{ + +} + +SessionBrokerClient::~SessionBrokerClient() { + // TODO: ipcClient.close(); +} + +std::string SessionBrokerClient::getMessage(int reason) { + switch (reason) { + case REJECT_REASON_INTERNAL_ERROR: + return "Unknown error (REJECT_REASON_INTERNAL_ERROR)"; + case REJECT_REASON_AUTHENTICATION_FAILED: + return "Authentication Failed"; + case REJECT_REASON_SESSION_NOT_AVAILABLE: + return "Session not available"; + case REJECT_REASON_INCOMPATIBLE_VERSION: + return "Incompatible version"; + default: + return "Unknown error"; + } + +} + +SessionBrokerResponse SessionBrokerClient::requestSession(const std::string &username, const std::string &password) { + // FIXME: use std::promise instaead + IPCConnection connection(_socketPath); + SessionBrokerResponse response; + + connection.connect(); + { + 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 body = connection.read<ULIPCSessionRequestResolved>( + sizeof(ULIPCSessionRequestResolved) + ); + + response = SessionBrokerResponse { + true, + std::string(body->path), + 0 + }; + } + break; + + case TYPE_SESSION_REQUEST_REJECTED: { + auto body = connection.read<ULIPCSessionRequestRejected>( + sizeof(ULIPCSessionRequestRejected) + ); + + response = SessionBrokerResponse { + false, + "", + body->reason + }; + } + break; + default: + response = SessionBrokerResponse { + false, + "", + -1 + }; + } + } + + connection.disconnect(); + + return std::move(response); +} diff --git a/SessionBrokerClient.hpp b/SessionBrokerClient.hpp new file mode 100644 index 0000000..0626d5c --- /dev/null +++ b/SessionBrokerClient.hpp @@ -0,0 +1,37 @@ +// +// Created by Gyuhwan Park on 2023/01/28. +// + +#ifndef ULALACA_SESSIONBROKERCLIENT_HPP +#define ULALACA_SESSIONBROKERCLIENT_HPP + +#include <string> + +#include "IPCConnection.hpp" + +struct SessionBrokerResponse { + bool isSuccessful; + std::string sessionPath; + int reason; +}; + +class SessionBrokerClient { +public: + SessionBrokerClient(const std::string &socketPath); + ~SessionBrokerClient(); + + static std::string getMessage(int reason); + + /** + * authenticate and requests session + * @return SessionBrokerResponse + */ + SessionBrokerResponse requestSession + (const std::string &username, const std::string &password); + +private: + std::string _socketPath; +}; + + +#endif //ULALACA_SESSIONBROKERCLIENT_HPP diff --git a/XrdpUlalacaPrivate.cpp b/XrdpUlalacaPrivate.cpp index 60ca516..f8086b1 100644 --- a/XrdpUlalacaPrivate.cpp +++ b/XrdpUlalacaPrivate.cpp @@ -40,4 +40,183 @@ XrdpUlalacaPrivate::XrdpUlalacaPrivate(XrdpUlalaca *mod): } +void XrdpUlalacaPrivate::serverMessage(const char *message, int code) { + _mod->server_msg(_mod, message, code); + LOG(LOG_LEVEL_INFO, "server_msg: %s", message); +} + +void XrdpUlalacaPrivate::attachToSession(std::string sessionPath) { + if (_projectionThread != nullptr) { + LOG(LOG_LEVEL_ERROR, "already attached to session"); + // TODO: throw runtime_error + return; + } + + _projectionThread = std::make_unique<ProjectionThread>( + *this, sessionPath + ); + + _projectionThread->start(); + + LOG(LOG_LEVEL_TRACE, "sessionSize: %d, %d", _sessionSize.width, _sessionSize.height); + _projectionThread->setViewport(_sessionSize); + _projectionThread->setOutputSuppression(false); +} + +int XrdpUlalacaPrivate::decideCopyRectSize() const { + if (isRFXCodec()) { + return 64; + } + + if (isH264Codec() || isGFXH264Codec()) { + // ??? FIXME + return RECT_SIZE_BYPASS_CREATE; + } + + return RECT_SIZE_BYPASS_CREATE; +} + +std::unique_ptr<std::vector<ULIPCRect>> XrdpUlalacaPrivate::createCopyRects( + std::vector<ULIPCRect> &dirtyRects, + int rectSize +) const { + auto blocks = std::make_unique<std::vector<ULIPCRect>>(); + blocks->reserve(128); + + if (rectSize == RECT_SIZE_BYPASS_CREATE) { + std::copy(dirtyRects.begin(), dirtyRects.end(), std::back_insert_iterator(*blocks)); + return std::move(blocks); + } + + for (auto &dirtyRect : dirtyRects) { + if (_sessionSize.width <= dirtyRect.x || + _sessionSize.height <= dirtyRect.y) { + continue; + } + + auto width = std::min(dirtyRect.width, (short) (_sessionSize.width - dirtyRect.x)); + auto height = std::min(dirtyRect.height, (short) (_sessionSize.height - dirtyRect.y)); + + auto baseX = dirtyRect.x - (dirtyRect.x % rectSize); + auto baseY = dirtyRect.y - (dirtyRect.y % rectSize); + + auto blockCountX = ((width + dirtyRect.x % rectSize) + (rectSize - 1)) / rectSize; + auto blockCountY = ((height + dirtyRect.y % rectSize) + (rectSize - 1)) / rectSize; + + for (int j = 0; j < blockCountY; j++) { + for (int i = 0; i < blockCountX; i++) { + short x = baseX + (rectSize * i); + short y = baseY + (rectSize * j); + + blocks->push_back(ULIPCRect {x, y, (short) rectSize, (short) rectSize }); + } + } + } + + return std::move(blocks); +} + +void XrdpUlalacaPrivate::addDirtyRect(ULIPCRect &rect) { + std::scoped_lock<std::mutex> scopedCommitLock(_commitUpdateLock); + _dirtyRects.push_back(rect); +} + +void XrdpUlalacaPrivate::commitUpdate(const uint8_t *image, int32_t width, int32_t height) { + LOG(LOG_LEVEL_DEBUG, "updating screen: %d, %d", width, height); + + if (!_commitUpdateLock.try_lock()) { + _dirtyRects.clear(); + return; + } + + if (_sessionSize.width != width || _sessionSize.height != height) { + // server_reset(this, width, height, _bpp); + } + + if (_frameId > 0 && _dirtyRects.empty()) { + return; + } + + _mod->server_begin_update(_mod); + + ULIPCRect screenRect {0, 0, (short) width, (short) height}; + auto copyRectSize = decideCopyRectSize(); + + if (_frameId > 0 || !_fullInvalidate) { + auto copyRects = createCopyRects(_dirtyRects, copyRectSize); + + _mod->server_paint_rects( + _mod, + _dirtyRects.size(), reinterpret_cast<short *>(_dirtyRects.data()), + copyRects->size(), reinterpret_cast<short *>(copyRects->data()), + (char *) image, + width, height, + 0, (_frameId++ % INT32_MAX) + ); + } else { + // paint entire screen + auto dirtyRects = std::vector<ULIPCRect> { screenRect } ; + auto copyRects = createCopyRects(dirtyRects, copyRectSize); + + if (isRawBitmap()) { + _mod->server_paint_rect( + _mod, + screenRect.x, screenRect.y, + screenRect.width, screenRect.height, + (char *) image, + screenRect.width, screenRect.height, + 0, 0 + ); + } else { + _mod->server_paint_rects( + _mod, + dirtyRects.size(), reinterpret_cast<short *>(dirtyRects.data()), + copyRects->size(), reinterpret_cast<short *>(copyRects->data()), + (char *) image, + width, height, + 0, (_frameId++ % INT32_MAX) + ); + } + + _fullInvalidate = false; + } + + _dirtyRects.clear(); + _mod->server_end_update(_mod); + + _commitUpdateLock.unlock(); +} + +void XrdpUlalacaPrivate::calculateSessionSize() { + // TODO: calculate session size to support multiple display environments + if (_screenLayouts.empty()) { + _sessionSize = ULIPCRect { + 0, 0, 640, 480 + }; + return; + } + + _sessionSize = _screenLayouts.front(); +} + +bool XrdpUlalacaPrivate::isRFXCodec() const { + return _clientInfo.rfx_codec_id != 0; +} + +bool XrdpUlalacaPrivate::isJPEGCodec() const { + return _clientInfo.jpeg_codec_id != 0; +} + +bool XrdpUlalacaPrivate::isH264Codec() const { + return _clientInfo.h264_codec_id != 0; +} + +bool XrdpUlalacaPrivate::isGFXH264Codec() const { + return _clientInfo.capture_code & 3; +} + +bool XrdpUlalacaPrivate::isRawBitmap() const { + return !(isRFXCodec() || isJPEGCodec() || isH264Codec() || isGFXH264Codec()); +} + diff --git a/XrdpUlalacaPrivate.hpp b/XrdpUlalacaPrivate.hpp index 45b0136..588d52d 100644 --- a/XrdpUlalacaPrivate.hpp +++ b/XrdpUlalacaPrivate.hpp @@ -22,12 +22,12 @@ extern "C" { #include "UnixSocket.hpp" -#include "messages/projector.h" +#include "ProjectionTarget.hpp" struct XrdpUlalaca; class ProjectionThread; -class XrdpUlalacaPrivate { +class XrdpUlalacaPrivate: public ProjectionTarget { public: constexpr static const int RECT_SIZE_BYPASS_CREATE = 0; @@ -63,11 +63,16 @@ public: const std::string &password ); + /** + * attach to projector session + */ + void attachToSession(std::string sessionPath); + /* paint related */ inline int decideCopyRectSize() const; - inline std::unique_ptr<std::vector<Rect>> createCopyRects(std::vector<Rect> &dirtyRects, int rectSize) const; + inline std::unique_ptr<std::vector<ULIPCRect>> createCopyRects(std::vector<ULIPCRect> &dirtyRects, int rectSize) const; - void addDirtyRect(Rect &rect); + void addDirtyRect(ULIPCRect &rect); void commitUpdate(const uint8_t *image, int32_t width, int32_t height); void calculateSessionSize(); diff --git a/XrdpUlalacaPrivate.xrdpmodule.cpp b/XrdpUlalacaPrivate.xrdpmodule.cpp index 1400046..1276dcd 100644 --- a/XrdpUlalacaPrivate.xrdpmodule.cpp +++ b/XrdpUlalacaPrivate.xrdpmodule.cpp @@ -1,5 +1,8 @@ #include "XrdpUlalacaPrivate.hpp" + #include "ulalaca.hpp" +#include "SessionBrokerClient.hpp" +#include "ProjectionThread.hpp" int XrdpUlalacaPrivate::libModStart(int width, int height, int bpp) { // #517eb9 @@ -16,9 +19,11 @@ int XrdpUlalacaPrivate::libModStart(int width, int height, int bpp) { _mod->server_fill_rect(_mod, 0, 0, width, height); _mod->server_end_update(_mod); + /* if (!isBPPSupported(bpp)) { return 1; } + */ _bpp = bpp; // _this->updateBpp(bpp); @@ -27,32 +32,22 @@ int XrdpUlalacaPrivate::libModStart(int width, int height, int bpp) { } int XrdpUlalacaPrivate::libModConnect() { - try { - std::string socketPath = _this->getSessionSocketPathUsingCredential( - _this->_username, _this->_password - ); - _this->_password.clear(); - - if (socketPath.empty()) { - return 1; - } - - _this->_projectionThread = std::make_unique<ProjectionThread>( - *_this, socketPath - ); - - _this->_projectionThread->start(); - - LOG(LOG_LEVEL_TRACE, "sessionSize: %d, %d", _this->_sessionSize.width, _this->_sessionSize.height); - _this->_projectionThread->setViewport(_this->_sessionSize); - _this->_projectionThread->setOutputSuppression(false); - } catch (SystemCallException &e) { - _this->serverMessage(e.what(), 0); + const std::string sessionBrokerIPCPath("/var/run/ulalaca_broker.sock"); + + SessionBrokerClient brokerClient(sessionBrokerIPCPath); + auto response = brokerClient.requestSession(_username, _password); + + std::fill(_password.begin(), _password.end(), '\0'); + _password.clear(); + + if (!response.isSuccessful) { + serverMessage("failed to request session", response.reason); + LOG(LOG_LEVEL_ERROR, "failed to request session: code %d (user %s)", response.reason, _username.c_str()); return 1; } - _this->serverMessage("welcome to the fantasy zone, get ready!", 0); - + // TODO: try-catch + attachToSession(response.sessionPath); return 0; } @@ -63,7 +58,7 @@ int XrdpUlalacaPrivate::libModEvent(int type, long arg1, long arg2, long arg3, l }; if (_projectionThread != nullptr) { - _projectionThread->handleEvent(std::move(event)); + _projectionThread->handleEvent(event); } return 0; @@ -77,8 +72,8 @@ int XrdpUlalacaPrivate::libModSignal() { int XrdpUlalacaPrivate::libModEnd() { LOG(LOG_LEVEL_INFO, "lib_mod_end() called"); - if (_this->_projectionThread != nullptr) { - _this->_projectionThread->stop(); + if (_projectionThread != nullptr) { + _projectionThread->stop(); } return 0; @@ -101,12 +96,12 @@ int XrdpUlalacaPrivate::libModSetParam(const char *cstrName, const char *cstrVal } else if (name == "delay_ms") { _delayMs = std::stoi(value); } else if (name == "guid") { - auto *_guid = reinterpret_cast<const guid *>(value); - _guid = *_guid; + auto *guid = reinterpret_cast<const struct guid *>(cstrValue); + _guid = *guid; } else if (name == "disabled_encodings_mask") { _encodingsMask = ~std::stoi(value); } else if (name == "client_info") { - auto *clientInfo = reinterpret_cast<const xrdp_client_info *>(value); + auto *clientInfo = reinterpret_cast<const struct xrdp_client_info *>(cstrValue); _clientInfo = *clientInfo; } @@ -126,8 +121,8 @@ int XrdpUlalacaPrivate::libModCheckWaitObjs() { } int XrdpUlalacaPrivate::libModFrameAck(int flags, int frameId) { - LOG(LOG_LEVEL_TRACE, "lib_mod_frame_ack() called: %d", frame_id); - _this->_ackFrameId = frame_id; + LOG(LOG_LEVEL_TRACE, "lib_mod_frame_ack() called: %d", frameId); + _ackFrameId = frameId; return 0; } @@ -141,7 +136,7 @@ int XrdpUlalacaPrivate::libModServerMonitorResize(int width, int height) { } int XrdpUlalacaPrivate::libModServerMonitorFullInvalidate(int width, int height) { - _this->_fullInvalidate = true; + _fullInvalidate = true; return 0; } diff --git a/ulalaca.cpp b/ulalaca.cpp index b660d40..cf4df44 100644 --- a/ulalaca.cpp +++ b/ulalaca.cpp @@ -105,212 +105,6 @@ int XrdpUlalaca::lib_mod_server_version_message(XrdpUlalaca *_this) { return _this->_impl->libModServerVersionMessage(); } -std::string XrdpUlalaca::getSessionSocketPathUsingCredential( - const std::string &username, - const std::string &password -) { - std::string socketPath; - - 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; -} - -bool XrdpUlalaca::isRFXCodec() const { - return _clientInfo.rfx_codec_id != 0; -} - -bool XrdpUlalaca::isJPEGCodec() const { - return _clientInfo.jpeg_codec_id != 0; -} - -bool XrdpUlalaca::isH264Codec() const { - return _clientInfo.h264_codec_id != 0; -} - -bool XrdpUlalaca::isGFXH264Codec() const { - return _clientInfo.capture_code & 3; -} - -bool XrdpUlalaca::isRawBitmap() const { - return !(isRFXCodec() || isJPEGCodec() || isH264Codec() || isGFXH264Codec()); -} - -int XrdpUlalaca::decideCopyRectSize() const { - if (isRFXCodec()) { - return 64; - } - - if (isH264Codec() || isGFXH264Codec()) { - return RECT_SIZE_BYPASS_CREATE; - } - - return RECT_SIZE_BYPASS_CREATE; -} - -std::unique_ptr<std::vector<XrdpUlalaca::Rect>> XrdpUlalaca::createCopyRects( - std::vector<Rect> &dirtyRects, - int rectSize -) const { - auto blocks = std::make_unique<std::vector<Rect>>(); - blocks->reserve(128); - - if (rectSize == RECT_SIZE_BYPASS_CREATE) { - std::copy(dirtyRects.begin(), dirtyRects.end(), std::back_insert_iterator(*blocks)); - return std::move(blocks); - } - - for (auto &dirtyRect : dirtyRects) { - if (_sessionSize.width <= dirtyRect.x || - _sessionSize.height <= dirtyRect.y) { - continue; - } - - auto width = std::min(dirtyRect.width, (short) (_sessionSize.width - dirtyRect.x)); - auto height = std::min(dirtyRect.height, (short) (_sessionSize.height - dirtyRect.y)); - - auto baseX = dirtyRect.x - (dirtyRect.x % rectSize); - auto baseY = dirtyRect.y - (dirtyRect.y % rectSize); - - auto blockCountX = ((width + dirtyRect.x % rectSize) + (rectSize - 1)) / rectSize; - auto blockCountY = ((height + dirtyRect.y % rectSize) + (rectSize - 1)) / rectSize; - - for (int j = 0; j < blockCountY; j++) { - for (int i = 0; i < blockCountX; i++) { - short x = baseX + (rectSize * i); - short y = baseY + (rectSize * j); - - blocks->push_back(Rect {x, y, (short) rectSize, (short) rectSize }); - } - } - } - - return std::move(blocks); -} - -void XrdpUlalaca::addDirtyRect(Rect &rect) { - std::scoped_lock<std::mutex> scopedCommitLock(_commitUpdateLock); - _dirtyRects.push_back(rect); -} - -void XrdpUlalaca::commitUpdate(const uint8_t *image, int32_t width, int32_t height) { - LOG(LOG_LEVEL_DEBUG, "updating screen: %d, %d", width, height); - - if (!_commitUpdateLock.try_lock()) { - _dirtyRects.clear(); - return; - } - - if (_sessionSize.width != width || _sessionSize.height != height) { - // server_reset(this, width, height, _bpp); - } - - if (_frameId > 0 && _dirtyRects.empty()) { - return; - } - - server_begin_update(this); - - Rect screenRect = {0, 0, (short) width, (short) height}; - auto copyRectSize = decideCopyRectSize(); - - if (_frameId > 0 || !_fullInvalidate) { - auto copyRects = createCopyRects(_dirtyRects, copyRectSize); - - server_paint_rects( - this, - _dirtyRects.size(), reinterpret_cast<short *>(_dirtyRects.data()), - copyRects->size(), reinterpret_cast<short *>(copyRects->data()), - (char *) image, - width, height, - 0, (_frameId++ % INT32_MAX) - ); - } else { - // paint entire screen - auto dirtyRects = std::vector<Rect>{screenRect}; - auto copyRects = createCopyRects(dirtyRects, copyRectSize); - - if (isRawBitmap()) { - server_paint_rect( - this, - screenRect.x, screenRect.y, - screenRect.width, screenRect.height, - (char *) image, - screenRect.width, screenRect.height, - 0, 0 - ); - } else { - server_paint_rects( - this, - dirtyRects.size(), reinterpret_cast<short *>(dirtyRects.data()), - copyRects->size(), reinterpret_cast<short *>(copyRects->data()), - (char *) image, - width, height, - 0, (_frameId++ % INT32_MAX) - ); - } - - _fullInvalidate = false; - } - - _dirtyRects.clear(); - server_end_update(this); - - _commitUpdateLock.unlock(); -} - -void XrdpUlalaca::calculateSessionSize() { - // TODO: calculate session size to support multiple display environments - if (_screenLayouts.empty()) { - _sessionSize = Rect { - 0, 0, 640, 480 - }; - return; - } - - _sessionSize = _screenLayouts.front(); -} - - -void XrdpUlalaca::serverMessage(const char *message, int code) { - this->server_msg(this, message, code); - LOG(LOG_LEVEL_INFO, "%s", message); -} - - tintptr EXPORT_CC mod_init(void) { auto *ulalaca = (XrdpUlalaca *) g_malloc(sizeof(XrdpUlalaca), 1); new (ulalaca) XrdpUlalaca(); diff --git a/ulalaca.hpp b/ulalaca.hpp index 62e386c..df50eea 100644 --- a/ulalaca.hpp +++ b/ulalaca.hpp @@ -7,6 +7,10 @@ #include <thread> +#if defined(HAVE_CONFIG_H) +#include <config_ac.h> +#endif + extern "C" { #include "arch.h" #include "parse.h" |