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>2022-05-24 16:54:48 +0300
committerGitHub <noreply@github.com>2022-05-24 16:54:48 +0300
commit7c60c626191cfc9d7ca5f52ee1f9a7654fabfb70 (patch)
tree778d40694578e8349b4a4d17c9e445c8d1f6190e
parent4c0058ad29f61b9e588d10bd0995281567bb70b5 (diff)
parent45cb4955cc52b928d639c6476ce030419dcadc3a (diff)
Merge pull request #1 from unstabler/integrate-broker
feature: add sessionbroker integration
-rw-r--r--IPCConnection.cpp116
-rw-r--r--IPCConnection.hpp86
-rw-r--r--Makefile.am2
-rw-r--r--ProjectionContext.hpp2
-rw-r--r--ProjectionThread.cpp152
-rw-r--r--ProjectionThread.hpp54
-rw-r--r--UlalacaMessages.hpp132
-rw-r--r--messages/_global.h28
-rw-r--r--messages/broker.h41
-rw-r--r--messages/projector.h96
-rw-r--r--ulalaca.cpp86
-rw-r--r--ulalaca.hpp10
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;