Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/neutrinolabs/ulalaca-xrdp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGyuhwan Park★ <unstabler@unstabler.pl>2023-01-28 18:38:50 +0300
committerGyuhwan Park★ <unstabler@unstabler.pl>2023-01-28 18:38:50 +0300
commitdd4b1559c0e59a93927ef3925f0c9ea5cd21b43a (patch)
treee733a62d5adc4d7046efb3b4ddc94f76640b07ad
parent7ef772c54ff216fee6c8a73198bf6c219887f8d3 (diff)
refactor: clean-up code, try to fix incomprehensible naming
-rw-r--r--Makefile.am2
-rw-r--r--ProjectionTarget.hpp (renamed from ProjectionContext.hpp)5
-rw-r--r--ProjectionThread.cpp8
-rw-r--r--ProjectionThread.hpp6
-rw-r--r--SessionBrokerClient.cpp89
-rw-r--r--SessionBrokerClient.hpp37
-rw-r--r--XrdpUlalacaPrivate.cpp179
-rw-r--r--XrdpUlalacaPrivate.hpp13
-rw-r--r--XrdpUlalacaPrivate.xrdpmodule.cpp59
-rw-r--r--ulalaca.cpp206
-rw-r--r--ulalaca.hpp4
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"