aboutsummaryrefslogtreecommitdiff
path: root/src/Rpc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Rpc.cpp')
-rw-r--r--src/Rpc.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/Rpc.cpp b/src/Rpc.cpp
new file mode 100644
index 0000000..206b1cf
--- /dev/null
+++ b/src/Rpc.cpp
@@ -0,0 +1,133 @@
+#include "../include/Rpc.hpp"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+namespace gsr {
+ static void get_runtime_filepath(char *buffer, size_t buffer_size, const char *filename) {
+ char dir[PATH_MAX];
+
+ const char *runtime_dir = getenv("XDG_RUNTIME_DIR");
+ if(runtime_dir)
+ snprintf(dir, sizeof(dir), "%s", runtime_dir);
+ else
+ snprintf(dir, sizeof(dir), "/run/user/%d", geteuid());
+
+ if(access(dir, F_OK) != 0)
+ snprintf(dir, sizeof(dir), "/tmp");
+
+ snprintf(buffer, buffer_size, "%s/%s", dir, filename);
+ }
+
+ Rpc::~Rpc() {
+ if(fd > 0)
+ close(fd);
+
+ if(file)
+ fclose(file);
+
+ if(!fifo_filepath.empty())
+ remove(fifo_filepath.c_str());
+ }
+
+ bool Rpc::create(const char *name) {
+ if(file) {
+ fprintf(stderr, "Error: Rpc::create: already created/opened\n");
+ return false;
+ }
+
+ char fifo_filepath_tmp[PATH_MAX];
+ get_runtime_filepath(fifo_filepath_tmp, sizeof(fifo_filepath_tmp), name);
+ fifo_filepath = fifo_filepath_tmp;
+ remove(fifo_filepath.c_str());
+
+ if(mkfifo(fifo_filepath.c_str(), 0600) != 0) {
+ fprintf(stderr, "Error: mkfifo failed, error: %s, %s\n", strerror(errno), fifo_filepath.c_str());
+ return false;
+ }
+
+ if(!open_filepath(fifo_filepath.c_str())) {
+ remove(fifo_filepath.c_str());
+ fifo_filepath.clear();
+ return false;
+ }
+
+ return true;
+ }
+
+ bool Rpc::open(const char *name) {
+ if(file) {
+ fprintf(stderr, "Error: Rpc::open: already created/opened\n");
+ return false;
+ }
+
+ char fifo_filepath_tmp[PATH_MAX];
+ get_runtime_filepath(fifo_filepath_tmp, sizeof(fifo_filepath_tmp), name);
+ return open_filepath(fifo_filepath_tmp);
+ }
+
+ bool Rpc::open_filepath(const char *filepath) {
+ fd = ::open(filepath, O_RDWR | O_NONBLOCK);
+ if(fd <= 0)
+ return false;
+
+ file = fdopen(fd, "r+");
+ if(!file) {
+ close(fd);
+ fd = 0;
+ return false;
+ }
+ fd = 0;
+ return true;
+ }
+
+ bool Rpc::write(const char *str, size_t size) {
+ if(!file) {
+ fprintf(stderr, "Error: Rpc::write: fifo not created/opened yet\n");
+ return false;
+ }
+
+ ssize_t offset = 0;
+ while(offset < (ssize_t)size) {
+ const ssize_t bytes_written = fwrite(str + offset, 1, size - offset, file);
+ fflush(file);
+ if(bytes_written > 0)
+ offset += bytes_written;
+ }
+ return true;
+ }
+
+ void Rpc::poll() {
+ if(!file) {
+ //fprintf(stderr, "Error: Rpc::poll: fifo not created/opened yet\n");
+ return;
+ }
+
+ std::string name;
+ char line[1024];
+ while(fgets(line, sizeof(line), file)) {
+ int line_len = strlen(line);
+ if(line_len == 0)
+ continue;
+
+ if(line[line_len - 1] == '\n') {
+ line[line_len - 1] = '\0';
+ --line_len;
+ }
+
+ name = line;
+ auto it = handlers_by_name.find(name);
+ if(it != handlers_by_name.end())
+ it->second(name);
+ }
+ }
+
+ bool Rpc::add_handler(const std::string &name, RpcCallback callback) {
+ return handlers_by_name.insert(std::make_pair(name, std::move(callback))).second;
+ }
+} \ No newline at end of file