Repository: eclipse-bluechi/bluechi (language: python)

Issue:
Move from POC: [Orchestrator] create peer bus
## Please describe what you would like to see

On a connection request from a node, the orchestrator creates a new peer dbus. 

## Please describe the solution you'd like

For reference, see [the implementation from the POC](https://github.com/alexlarsson/orch/blob/main/orch.c#L500-L562). 
Maybe use a factory pattern to create peer dbus (e.g. see [here](https://chuan-zhang.medium.com/implementing-factory-pattern-in-c-c6f9b02bd226) for factory pattern in C)

## Please describe your use case

Creating a peer dbus that does not use the dbus daemon. 

![image](https://user-images.githubusercontent.com/26504678/210589521-5d3620a8-882e-4fcf-bfab-5460c88e2934.png)



Discussion / hints:
I was curious about the factory pattern implemented in C so I played with it:
[factory_pattern_in_c.zip](https://github.com/engelmi/orch/files/10198547/factory_pattern_in_c.zip)

This is a primitive form of polymorphism; the object gets allocated in different ways depending on a variable that is set at runtime.  In fact, if you add an array of pointers to the various factory functions, you essentially have implemented a C++ vtable.

Note that in this example, malloc() is used 3 times without being explicitly freed.  The memory is automatically freed when the program exits.  However, valgrind will point to this as a potential memory leak.  In the valgrind log, look for "blocks are definitely lost".





Fix patch:
diff --git a/.clang-tidy b/.clang-tidy
index 4e4325d8a4..0a608eee49 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -15,6 +15,13 @@ Checks: >
     -altera-id-dependent-backward-branch,
     -bugprone-easily-swappable-parameters,
     -altera-struct-pack-align,
+    -readability-isolate-declaration,
+    -bugprone-assignment-in-if-condition,
+
+CheckOptions:
+    - key: readability-function-cognitive-complexity.Threshold
+      value: 50
+    
 
 # Turn all the warnings from the checks above into errors.,
 WarningsAsErrors: "*"
diff --git a/Makefile b/Makefile
index 6d145ef3f2..a5b18713d1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 
-ALL_SRC_FILES = 'find . -name "*.[ch]" ! -path "./binchihua/src/ini/ini.[ch]" ! -path "./binchihua/src/common/hashmap/*" ! -path "./binchihua/test/**" ! -path "./builddir/**" -print0'
+ALL_SRC_FILES = 'find . -name "*.[ch]" ! -path "./binchihua/src/ini/ini.[ch]" ! -path "./binchihua/src/common/hashmap/*" ! -path "./binchihua/test/**" ! -path "./libchihua-msg/test/**" ! -path "./builddir/**" -print0'
 
 fmt:
 	eval $(ALL_SRC_FILES) | xargs -0 -I {} clang-format -i --sort-includes {}
diff --git a/binchihua/src/node/node.c b/binchihua/src/node/node.c
index 5fd8c3bf14..de122cc3e6 100644
--- a/binchihua/src/node/node.c
+++ b/binchihua/src/node/node.c
@@ -18,7 +18,7 @@ int main(int argc, char *argv[]) {
 
         get_opts(argc, argv, &host);
 
-        char *ini_file_location = "../../../doc/example.ini";
+        char *ini_file_location = NULL;
         struct hashmap *ini_hashmap = NULL;
         ini_hashmap = parsing_ini_file(ini_file_location);
         if (ini_hashmap == NULL) {
diff --git a/binchihua/src/common/list.h b/libchihua-msg/include/common/list.h
similarity index 100%
rename from binchihua/src/common/list.h
rename to libchihua-msg/include/common/list.h
diff --git a/libchihua-msg/include/node.h b/libchihua-msg/include/node.h
index 2cbf6f595d..ecc4141f58 100644
--- a/libchihua-msg/include/node.h
+++ b/libchihua-msg/include/node.h
@@ -3,23 +3,28 @@
 #include <netinet/in.h>
 #include <stdbool.h>
 #include <sys/socket.h>
+#include <systemd/sd-bus.h>
 #include <systemd/sd-event.h>
 
-#include "./common/memory.h"
-
+#include "common/memory.h"
 typedef struct {
         struct sockaddr_in *orch_addr;
 } NodeParams;
 
 typedef struct {
         char *orch_addr;
+
         sd_event *event_loop;
+
+        sd_bus *user_dbus;
+        sd_bus *systemd_dbus;
+        sd_bus *peer_dbus;
 } Node;
 
 Node *node_new(const NodeParams *params);
 void node_unrefp(Node **node);
 
-bool node_start(const Node *node);
+bool node_start(Node *node);
 bool node_stop(const Node *node);
 
 #define _cleanup_node_ _cleanup_(node_unrefp)
diff --git a/libchihua-msg/include/node/peer-dbus.h b/libchihua-msg/include/node/peer-dbus.h
deleted file mode 100644
index b33f9e1546..0000000000
--- a/libchihua-msg/include/node/peer-dbus.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-#include <netinet/in.h>
-#include <stdbool.h>
-#include <sys/socket.h>
-#include <systemd/sd-bus.h>
-#include <systemd/sd-event.h>
-
-#include "../common/memory.h"
-
-typedef struct {
-        char *peer_dbus_addr;
-        sd_bus *internal_dbus;
-} PeerDBus;
-
-char *assemble_address(const struct sockaddr_in *addr);
-
-PeerDBus *peer_dbus_new(const char *peer_addr, sd_event *event);
-void peer_dbus_unrefp(PeerDBus **dbus);
-
-bool peer_dbus_start(PeerDBus *dbus);
-
-#define _cleanup_peer_dbus_ _cleanup_(peer_dbus_unrefp)
diff --git a/libchihua-msg/include/orchestrator.h b/libchihua-msg/include/orchestrator.h
index 5df0af6709..e3b5ba7375 100644
--- a/libchihua-msg/include/orchestrator.h
+++ b/libchihua-msg/include/orchestrator.h
@@ -5,6 +5,7 @@
 #include <systemd/sd-event.h>
 
 #include "./common/memory.h"
+#include "./orchestrator/peer-manager.h"
 
 typedef struct {
         uint16_t port;
@@ -12,7 +13,11 @@ typedef struct {
 
 typedef struct {
         uint16_t accept_port;
+
         sd_event *event_loop;
+        sd_event_source *peer_connection_source;
+
+        PeerManager *peer_manager;
 } Orchestrator;
 
 Orchestrator *orch_new(const OrchestratorParams *params);
diff --git a/libchihua-msg/include/orchestrator/controller.h b/libchihua-msg/include/orchestrator/controller.h
deleted file mode 100644
index 90b9a14fa0..0000000000
--- a/libchihua-msg/include/orchestrator/controller.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include <stdbool.h>
-#include <systemd/sd-event.h>
-
-#include "../common/memory.h"
-
-typedef struct {
-        int accept_fd;
-        sd_event_source *sd_event_source;
-} Controller;
-
-Controller *controller_new(uint16_t port, sd_event *event, sd_event_io_handler_t accept_handler);
-void controller_unrefp(Controller **controller);
-
-sd_event_io_handler_t default_accept_handler();
-
-#define _cleanup_controller_ _cleanup_(controller_unrefp)
diff --git a/libchihua-msg/include/orchestrator/peer-manager.h b/libchihua-msg/include/orchestrator/peer-manager.h
new file mode 100644
index 0000000000..7bc540607b
--- /dev/null
+++ b/libchihua-msg/include/orchestrator/peer-manager.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "../../include/common/common.h"
+#include "../../include/common/list.h"
+#include "../peer-bus.h"
+
+typedef struct {
+        sd_event *event_loop;
+
+        LIST_HEAD(PeerBusListItem, peers_head);
+} PeerManager;
+
+PeerManager *peer_manager_new(sd_event *event_loop);
+void peer_manager_unrefp(PeerManager **manager);
+
+int peer_manager_accept_connection_request(
+                UNUSED sd_event_source *source, int fd, UNUSED uint32_t revents, void *userdata);
+
+#define _cleanup_peer_manager_ _cleanup_(peer_manager_unrefp)
\ No newline at end of file
diff --git a/libchihua-msg/include/peer-bus.h b/libchihua-msg/include/peer-bus.h
new file mode 100644
index 0000000000..39a86d180b
--- /dev/null
+++ b/libchihua-msg/include/peer-bus.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <netinet/in.h>
+#include <systemd/sd-bus.h>
+#include <systemd/sd-event.h>
+
+#include "common/list.h"
+
+char *assemble_tcp_address(const struct sockaddr_in *addr);
+
+sd_bus *peer_bus_open(sd_event *event, char *dbus_description, char *dbus_server_addr);
+sd_bus *peer_bus_open_server(sd_event *event, char *dbus_description, int fd);
+
+typedef struct PeerBusListItem {
+        sd_bus *bus;
+        LIST_FIELDS(struct PeerBusListItem, peers);
+} PeerBusListItem;
+
+// peer_bus_list_item_new creates a new list item for a peer bus server.
+// It steals the pointer from the passed in and takes care of it being cleaned up.
+PeerBusListItem *peer_bus_list_item_new(sd_bus *bus);
\ No newline at end of file
diff --git a/libchihua-msg/include/socket.h b/libchihua-msg/include/socket.h
new file mode 100644
index 0000000000..e5aabf78b5
--- /dev/null
+++ b/libchihua-msg/include/socket.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include <inttypes.h>
+
+int create_tcp_socket(uint16_t port);
+int accept_tcp_connection_request(int fd);
diff --git a/libchihua-msg/meson.build b/libchihua-msg/meson.build
index 5670d5931f..d3ef1a03ae 100644
--- a/libchihua-msg/meson.build
+++ b/libchihua-msg/meson.build
@@ -1,16 +1,18 @@
 libchihua_src = [
-    'include/common/memory.h',
     'include/node.h',
-    'include/node/peer-dbus.h',
     'include/orchestrator.h',
-    'include/orchestrator/controller.h',
+    'include/peer-bus.h',
+    'include/socket.h',
+    'include/common/memory.h',
+    'include/orchestrator/peer-manager.h',
 
     'src/common/memory.h',
     'src/common/dbus.h',
     'src/node.c',
-    'src/node/peer-dbus.c',
     'src/orchestrator.c',
-    'src/orchestrator/controller.c',
+    'src/peer-bus.c',
+    'src/socket.c',
+    'src/orchestrator/peer-manager.c',
 ]
 
 # We use libtool-version numbers because it's easier to understand.
@@ -35,4 +37,8 @@ blue_chihuahua_shared = shared_library('-chihua-msg',
                                 systemd_dep
                             ],
                             version : libruntime_so_version,
-                            install : true)
\ No newline at end of file
+                            install : true)
+
+
+# build test binaries
+subdir('test')
diff --git a/libchihua-msg/src/node.c b/libchihua-msg/src/node.c
index 07b3d1439f..d6fb9e3207 100644
--- a/libchihua-msg/src/node.c
+++ b/libchihua-msg/src/node.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 
 #include "../include/node.h"
-#include "../include/node/peer-dbus.h"
+#include "../include/peer-bus.h"
 #include "./common/dbus.h"
 
 Node *node_new(const NodeParams *params) {
@@ -15,51 +15,61 @@ Node *node_new(const NodeParams *params) {
                 return NULL;
         }
 
-        char *orch_addr = assemble_address(params->orch_addr);
+        char *orch_addr = assemble_tcp_address(params->orch_addr);
         if (orch_addr == NULL) {
                 return NULL;
         }
 
+        _cleanup_sd_bus_ sd_bus *peer_dbus = peer_bus_open(event, "peer-bus-to-orchestrator", orch_addr);
+        if (peer_dbus == NULL) {
+                fprintf(stderr, "Failed to open peer dbus\n");
+                return false;
+        }
+
         Node *n = malloc0(sizeof(Node));
         n->event_loop = steal_pointer(&event);
         n->orch_addr = orch_addr;
+        n->peer_dbus = steal_pointer(&peer_dbus);
 
         return n;
 }
 
 void node_unrefp(Node **node) {
-        fprintf(stdout, "Freeing allocated memory of Orchestrator...\n");
-        if (node == NULL) {
+        fprintf(stdout, "Freeing allocated memory of Node...\n");
+        if (node == NULL || (*node) == NULL) {
                 return;
         }
         if ((*node)->event_loop != NULL) {
-                fprintf(stdout, "Freeing allocated sd-event of Orchestrator...\n");
+                fprintf(stdout, "Freeing allocated sd-event of Node...\n");
                 sd_event_unrefp(&(*node)->event_loop);
         }
         if ((*node)->orch_addr != NULL) {
-                fprintf(stdout, "Freeing allocated orch_addr of Orchestrator...\n");
-                freep((*node)->orch_addr);
+                fprintf(stdout, "Freeing allocated orch_addr of Node...\n");
+                free((*node)->orch_addr);
+        }
+        if ((*node)->peer_dbus != NULL) {
+                fprintf(stdout, "Freeing allocated peer dbus to Orchestrator...\n");
+                sd_bus_unrefp(&(*node)->peer_dbus);
+        }
+        if ((*node)->user_dbus != NULL) {
+                fprintf(stdout, "Freeing allocated dbus to local user dbus...\n");
+                sd_bus_unrefp(&(*node)->user_dbus);
+        }
+        if ((*node)->systemd_dbus != NULL) {
+                fprintf(stdout, "Freeing allocated dbus to local systemd dbus...\n");
+                sd_bus_unrefp(&(*node)->systemd_dbus);
         }
 
         free(*node);
 }
 
-bool node_start(const Node *node) {
+bool node_start(Node *node) {
         fprintf(stdout, "Starting Node...\n");
 
         if (node == NULL) {
                 return false;
         }
 
-        _cleanup_peer_dbus_ PeerDBus *orch_dbus = peer_dbus_new(node->orch_addr, node->event_loop);
-        if (orch_dbus == NULL) {
-                return false;
-        }
-        bool started_successful = peer_dbus_start(orch_dbus);
-        if (!started_successful) {
-                return false;
-        }
-
         int r = 0;
         r = sd_event_loop(node->event_loop);
         if (r < 0) {
diff --git a/libchihua-msg/src/node/peer-dbus.c b/libchihua-msg/src/node/peer-dbus.c
deleted file mode 100644
index 5b350040ae..0000000000
--- a/libchihua-msg/src/node/peer-dbus.c
+++ /dev/null
@@ -1,96 +0,0 @@
-#include <arpa/inet.h>
-#include <stdio.h>
-
-#include "../../include/node/peer-dbus.h"
-#include "../common/dbus.h"
-
-char *assemble_address(const struct sockaddr_in *addr) {
-        if (addr == NULL) {
-                fprintf(stderr, "Can not assemble an empty address\n");
-                return NULL;
-        }
-
-        char *dbus_addr = NULL;
-        int r = asprintf(&dbus_addr, "tcp:host=%s,port=%d", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
-        if (r < 0) {
-                fprintf(stderr, "Out of memory\n");
-                return NULL;
-        }
-        return dbus_addr;
-}
-
-PeerDBus *peer_dbus_new(const char *peer_addr, sd_event *event) {
-        if (peer_addr == NULL) {
-                fprintf(stderr, "Peer address must be initialized\n");
-                return NULL;
-        }
-        if (event == NULL) {
-                fprintf(stderr, "Event loop must be initialized\n");
-                return NULL;
-        }
-
-        int r = 0;
-        _cleanup_sd_bus_ sd_bus *dbus = NULL;
-
-        r = sd_bus_new(&dbus);
-        if (r < 0) {
-                fprintf(stderr, "Failed to create bus: %s\n", strerror(-r));
-                return NULL;
-        }
-        (void) sd_bus_set_description(dbus, "orchestrator");
-
-        /* we trust everything from the orchestrator, there is only one peer anyway */
-        r = sd_bus_set_trusted(dbus, true);
-        if (r < 0) {
-                fprintf(stderr, "Failed to trust orchestrator: %s\n", strerror(-r));
-                return NULL;
-        }
-
-        r = sd_bus_set_address(dbus, peer_addr);
-        if (r < 0) {
-                fprintf(stderr, "Failed to set address: %s\n", strerror(-r));
-                return NULL;
-        }
-
-        r = sd_bus_attach_event(dbus, event, SD_EVENT_PRIORITY_NORMAL);
-        if (r < 0) {
-                fprintf(stderr, "Failed to attach bus to event: %s\n", strerror(-r));
-                return NULL;
-        }
-
-        char *dbus_addr = NULL;
-        r = asprintf(&dbus_addr, "%s", peer_addr);
-        if (r < 0) {
-                fprintf(stderr, "Out of memory\n");
-                return NULL;
-        }
-
-        PeerDBus *p = malloc0(sizeof(PeerDBus));
-        p->peer_dbus_addr = dbus_addr;
-        p->internal_dbus = steal_pointer(&dbus);
-
-        return p;
-}
-
-void peer_dbus_unrefp(PeerDBus **dbus) {
-        fprintf(stdout, "Freeing allocated memory of PeerDBus...\n");
-        if (dbus == NULL) {
-                return;
-        }
-        if ((*dbus)->peer_dbus_addr != NULL) {
-                fprintf(stdout, "Freeing allocated sd-event-source of Controller...\n");
-                freep((*dbus)->peer_dbus_addr);
-        }
-        if ((*dbus)->internal_dbus != NULL) {
-                fprintf(stdout, "Freeing allocated internal dbus of PeerDBus...\n");
-                sd_bus_unrefp(&(*dbus)->internal_dbus);
-        }
-        free(*dbus);
-}
-
-bool peer_dbus_start(PeerDBus *dbus) {
-        if (dbus == NULL) {
-                return false;
-        }
-        return sd_bus_start(dbus->internal_dbus) >= 0;
-}
diff --git a/libchihua-msg/src/orchestrator.c b/libchihua-msg/src/orchestrator.c
index b234b2a2af..7a075953da 100644
--- a/libchihua-msg/src/orchestrator.c
+++ b/libchihua-msg/src/orchestrator.c
@@ -1,10 +1,62 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "../include/common/common.h"
 #include "../include/orchestrator.h"
-#include "../include/orchestrator/controller.h"
+#include "../include/orchestrator/peer-manager.h"
+#include "../include/socket.h"
 #include "./common/dbus.h"
 
+static bool orch_setup_connection_handler(
+                Orchestrator *orch, uint16_t listen_port, sd_event_io_handler_t connection_callback) {
+        if (orch == NULL) {
+                fprintf(stderr, "Orchestrator is NULL\n");
+                return false;
+        }
+        if (orch->event_loop == NULL) {
+                fprintf(stderr, "event loop of Orchestrator is NULL\n");
+                return false;
+        }
+        if (orch->peer_manager == NULL) {
+                fprintf(stderr, "peer manager of Orchestrator is NULL\n");
+                return false;
+        }
+
+        int r = 0;
+        _cleanup_sd_event_source_ sd_event_source *event_source = NULL;
+
+        _cleanup_fd_ int accept_fd = create_tcp_socket(listen_port);
+        if (accept_fd < 0) {
+                return false;
+        }
+
+        r = sd_event_add_io(
+                        orch->event_loop,
+                        &event_source,
+                        accept_fd,
+                        EPOLLIN,
+                        connection_callback,
+                        orch->peer_manager);
+        if (r < 0) {
+                fprintf(stderr, "Failed to add io event: %s\n", strerror(-r));
+                return false;
+        }
+        // sd_event_add_io takes care of closing accept_fd, setting it to -1 avoids closing it multiple times
+        // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
+        accept_fd = -1;
+
+        r = sd_event_source_set_io_fd_own(event_source, true);
+        if (r < 0) {
+                fprintf(stderr, "Failed to set io fd own: %s\n", strerror(-r));
+                return false;
+        }
+        (void) sd_event_source_set_description(event_source, "master-socket");
+
+        orch->peer_connection_source = steal_pointer(&event_source);
+
+        return true;
+}
+
 Orchestrator *orch_new(const OrchestratorParams *params) {
         fprintf(stdout, "Creating Orchestrator...\n");
 
@@ -16,22 +68,40 @@ Orchestrator *orch_new(const OrchestratorParams *params) {
                 return NULL;
         }
 
-        Orchestrator *o = malloc0(sizeof(Orchestrator));
-        o->event_loop = steal_pointer(&event);
-        o->accept_port = params->port;
+        Orchestrator *orch = malloc0(sizeof(Orchestrator));
+        orch->event_loop = steal_pointer(&event);
+        orch->accept_port = params->port;
+        orch->peer_manager = peer_manager_new(orch->event_loop);
+        orch->peer_connection_source = NULL;
 
-        return o;
+        bool successful = orch_setup_connection_handler(
+                        orch, orch->accept_port, &peer_manager_accept_connection_request);
+        if (!successful) {
+                orch_unrefp(&orch);
+                return NULL;
+        }
+
+        return orch;
 }
 
 void orch_unrefp(Orchestrator **orchestrator) {
         fprintf(stdout, "Freeing allocated memory of Orchestrator...\n");
-        if (orchestrator == NULL) {
+        if (orchestrator == NULL || (*orchestrator) == NULL) {
                 return;
         }
         if ((*orchestrator)->event_loop != NULL) {
                 fprintf(stdout, "Freeing allocated sd-event of Orchestrator...\n");
                 sd_event_unrefp(&(*orchestrator)->event_loop);
         }
+        if ((*orchestrator)->peer_connection_source != NULL) {
+                fprintf(stdout, "Freeing allocated sd-event-source for connections of Orchestrator...\n");
+                sd_event_source_unrefp(&(*orchestrator)->peer_connection_source);
+        }
+        if ((*orchestrator)->peer_manager != NULL) {
+                fprintf(stdout, "Freeing allocated peer manager of Orchestrator...\n");
+                peer_manager_unrefp(&(*orchestrator)->peer_manager);
+        }
+
         free(*orchestrator);
 }
 
@@ -45,10 +115,6 @@ bool orch_start(const Orchestrator *orchestrator) {
                 return false;
         }
 
-        _cleanup_controller_ Controller *c = NULL;
-        // NOLINTNEXTLINE
-        c = controller_new(orchestrator->accept_port, orchestrator->event_loop, default_accept_handler());
-
         int r = 0;
         r = sd_event_loop(orchestrator->event_loop);
         if (r < 0) {
diff --git a/libchihua-msg/src/orchestrator/controller.c b/libchihua-msg/src/orchestrator/controller.c
deleted file mode 100644
index 035cc1aad6..0000000000
--- a/libchihua-msg/src/orchestrator/controller.c
+++ /dev/null
@@ -1,114 +0,0 @@
-#include "../../include/orchestrator/controller.h"
-#include "../../include/common/common.h"
-#include "../common/dbus.h"
-
-#include <errno.h>
-#include <netinet/in.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/socket.h>
-
-static int create_master_socket(uint16_t port) {
-        struct sockaddr_in servaddr;
-
-        int fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
-        if (fd < 0) {
-                int errsv = errno;
-                fprintf(stderr, "Failed to create socket: %m\n");
-                return -errsv;
-        }
-
-        int yes = 1;
-        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
-                int errsv = errno;
-                fprintf(stderr, "Failed to create socket: %m\n");
-                return -errsv;
-        }
-
-        servaddr.sin_family = AF_INET;
-        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
-        servaddr.sin_port = htons(port);
-
-        if (bind(fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
-                int errsv = errno;
-                fprintf(stderr, "Failed to bind socket: %m\n");
-                return -errsv;
-        }
-
-        if ((listen(fd, SOMAXCONN)) != 0) {
-                int errsv = errno;
-                fprintf(stderr, "Failed to listen to socket: %m\n");
-                return -errsv;
-        }
-
-        return fd;
-}
-
-Controller *controller_new(uint16_t port, sd_event *event, sd_event_io_handler_t accept_handler) {
-        fprintf(stdout, "Creating Controller...\n");
-
-        int r = 0;
-        _cleanup_sd_event_source_ sd_event_source *event_source = NULL;
-
-        int accept_fd = create_master_socket(port);
-        if (accept_fd < 0) {
-                return NULL;
-        }
-
-        r = sd_event_add_io(event, &event_source, accept_fd, EPOLLIN, accept_handler, NULL);
-        if (r < 0) {
-                fprintf(stderr, "Failed to add io event: %s\n", strerror(-r));
-                return NULL;
-        }
-
-        r = sd_event_source_set_io_fd_own(event_source, true);
-        if (r < 0) {
-                fprintf(stderr, "Failed to set io fd own: %s\n", strerror(-r));
-                return NULL;
-        }
-
-        (void) sd_event_source_set_description(event_source, "master-socket");
-
-        Controller *c = malloc0(sizeof(Controller));
-        c->accept_fd = accept_fd;
-        c->sd_event_source = steal_pointer(&event_source);
-
-        return c;
-}
-
-void controller_unrefp(Controller **controller) {
-        fprintf(stdout, "Freeing allocated memory of Controller...\n");
-        if (controller == NULL) {
-                return;
-        }
-        if ((*controller)->sd_event_source != NULL) {
-                fprintf(stdout, "Freeing allocated sd-event-source of Controller...\n");
-                sd_event_source_unrefp(&(*controller)->sd_event_source);
-        }
-        if ((*controller)->accept_fd >= 0) {
-                closep(&(*controller)->accept_fd);
-        }
-        free(*controller);
-}
-
-static int accept_handler(UNUSED sd_event_source *source, int fd, UNUSED uint32_t revents, UNUSED void *userdata) {
-        _cleanup_fd_ int nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
-        if (nfd < 0) {
-                if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
-                        return 0;
-                }
-
-                int errsv = errno;
-                fprintf(stderr, "Failed to accept: %m\n");
-                return -errsv;
-        }
-
-        // TODO: setup peer dbus, incl. vtable with services, signals, properties
-        fprintf(stdout, "accepted connection request\n");
-
-        return 0;
-}
-
-sd_event_io_handler_t default_accept_handler() {
-        return &accept_handler;
-}
diff --git a/libchihua-msg/src/orchestrator/peer-manager.c b/libchihua-msg/src/orchestrator/peer-manager.c
new file mode 100644
index 0000000000..d3a5a9897a
--- /dev/null
+++ b/libchihua-msg/src/orchestrator/peer-manager.c
@@ -0,0 +1,45 @@
+#include <errno.h>
+#include <stdio.h>
+
+#include "../../include/orchestrator/peer-manager.h"
+#include "../../include/socket.h"
+#include "../../src/common/dbus.h"
+#include "../../src/common/memory.h"
+
+PeerManager *peer_manager_new(sd_event *event_loop) {
+        fprintf(stdout, "Creating Peer Manager...\n");
+
+        PeerManager *mgr = malloc0(sizeof(PeerManager));
+        mgr->event_loop = event_loop;
+        LIST_HEAD_INIT(mgr->peers_head);
+
+        return mgr;
+}
+
+void peer_manager_unrefp(PeerManager **manager) {
+        if (manager == NULL || (*manager) == NULL) {
+                return;
+        }
+
+        free(*manager);
+}
+
+int peer_manager_accept_connection_request(
+                UNUSED sd_event_source *source, int fd, UNUSED uint32_t revents, void *userdata) {
+        _cleanup_fd_ int nfd = accept_tcp_connection_request(fd);
+
+        PeerManager *mgr = (PeerManager *) userdata;
+
+        _cleanup_sd_bus_ sd_bus *dbus_server = peer_bus_open_server(mgr->event_loop, "peer-to-node", nfd);
+        if (dbus_server == NULL) {
+                return -1;
+        }
+        // peer dbus will take care of closing fd, setting to -1 prevents closing it twice
+        // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
+        nfd = -1;
+
+        PeerBusListItem *item = peer_bus_list_item_new(dbus_server);
+        LIST_APPEND(peers, mgr->peers_head, item);
+
+        return 0;
+}
\ No newline at end of file
diff --git a/libchihua-msg/src/peer-bus.c b/libchihua-msg/src/peer-bus.c
new file mode 100644
index 0000000000..320bc359d3
--- /dev/null
+++ b/libchihua-msg/src/peer-bus.c
@@ -0,0 +1,114 @@
+#include <arpa/inet.h>
+#include <stdio.h>
+
+#include "../include/peer-bus.h"
+#include "common/dbus.h"
+
+char *assemble_tcp_address(const struct sockaddr_in *addr) {
+        if (addr == NULL) {
+                fprintf(stderr, "Can not assemble an empty address\n");
+                return NULL;
+        }
+
+        char *dbus_addr = NULL;
+        int r = asprintf(&dbus_addr, "tcp:host=%s,port=%d", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
+        if (r < 0) {
+                fprintf(stderr, "Out of memory\n");
+                return NULL;
+        }
+        return dbus_addr;
+}
+
+static sd_bus *peer_bus_new(sd_event *event, char *dbus_description) {
+        if (event == NULL) {
+                fprintf(stderr, "Event loop must be initialized\n");
+                return NULL;
+        }
+
+        int r = 0;
+        _cleanup_sd_bus_ sd_bus *dbus = NULL;
+
+        r = sd_bus_new(&dbus);
+        if (r < 0) {
+                fprintf(stderr, "Failed to create bus: %s\n", strerror(-r));
+                return NULL;
+        }
+        (void) sd_bus_set_description(dbus, dbus_description);
+
+        r = sd_bus_attach_event(dbus, event, SD_EVENT_PRIORITY_NORMAL);
+        if (r < 0) {
+                fprintf(stderr, "Failed to attach bus to event: %s\n", strerror(-r));
+                return NULL;
+        }
+
+        return steal_pointer(&dbus);
+}
+
+sd_bus *peer_bus_open(sd_event *event, char *dbus_description, char *dbus_server_addr) {
+        if (dbus_server_addr == NULL) {
+                fprintf(stderr, "Peer address to connect to must be initialized\n");
+                return NULL;
+        }
+
+        int r = 0;
+        _cleanup_sd_bus_ sd_bus *dbus = peer_bus_new(event, dbus_description);
+        if (dbus == NULL) {
+                return NULL;
+        }
+        // trust everything from the orchestrator
+        r = sd_bus_set_trusted(dbus, true);
+        if (r < 0) {
+                fprintf(stderr, "Failed to trust orchestrator: %s\n", strerror(-r));
+                return NULL;
+        }
+        r = sd_bus_set_address(dbus, dbus_server_addr);
+        if (r < 0) {
+                fprintf(stderr, "Failed to set address: %s\n", strerror(-r));
+                return NULL;
+        }
+
+        r = sd_bus_start(dbus);
+        if (r < 0) {
+                fprintf(stderr, "Failed to start peer bus: %s", strerror(-r));
+                return NULL;
+        }
+
+        return steal_pointer(&dbus);
+}
+
+sd_bus *peer_bus_open_server(sd_event *event, char *dbus_description, int fd) {
+        int r = 0;
+        _cleanup_sd_bus_ sd_bus *dbus = peer_bus_new(event, dbus_description);
+        if (dbus == NULL) {
+                return NULL;
+        }
+        r = sd_bus_set_fd(dbus, fd, fd);
+        if (r < 0) {
+                fprintf(stderr, "Failed to set fd on new connection bus: %s\n", strerror(-r));
+                return 0;
+        }
+        sd_id128_t server_id;
+        r = sd_id128_randomize(&server_id);
+        if (r < 0) {
+                fprintf(stderr, "Failed to create server id: %s\n", strerror(-r));
+        }
+        r = sd_bus_set_server(dbus, 1, server_id);
+        if (r < 0) {
+                fprintf(stderr, "Failed to enable server support for new connection bus: %s\n", strerror(-r));
+                return 0;
+        }
+
+        r = sd_bus_start(dbus);
+        if (r < 0) {
+                fprintf(stderr, "Failed to start peer bus server: %s", strerror(-r));
+                return NULL;
+        }
+
+        return steal_pointer(&dbus);
+}
+
+PeerBusListItem *peer_bus_list_item_new(sd_bus *bus) {
+        PeerBusListItem *item = malloc0(sizeof(PeerBusListItem));
+        item->bus = steal_pointer(&bus);
+        return item;
+}
\ No newline at end of file
diff --git a/libchihua-msg/src/socket.c b/libchihua-msg/src/socket.c
new file mode 100644
index 0000000000..372b30a6af
--- /dev/null
+++ b/libchihua-msg/src/socket.c
@@ -0,0 +1,56 @@
+#include <errno.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <sys/socket.h>
+
+#include "../include/socket.h"
+
+int create_tcp_socket(uint16_t port) {
+        struct sockaddr_in servaddr;
+
+        int fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+        if (fd < 0) {
+                int errsv = errno;
+                fprintf(stderr, "Failed to create socket: %m\n");
+                return -errsv;
+        }
+
+        int yes = 1;
+        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
+                int errsv = errno;
+                fprintf(stderr, "Failed to create socket: %m\n");
+                return -errsv;
+        }
+
+        servaddr.sin_family = AF_INET;
+        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+        servaddr.sin_port = htons(port);
+
+        if (bind(fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
+                int errsv = errno;
+                fprintf(stderr, "Failed to bind socket: %m\n");
+                return -errsv;
+        }
+
+        if ((listen(fd, SOMAXCONN)) != 0) {
+                int errsv = errno;
+                fprintf(stderr, "Failed to listen to socket: %m\n");
+                return -errsv;
+        }
+
+        return fd;
+}
+
+int accept_tcp_connection_request(int fd) {
+        int nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
+        if (nfd < 0) {
+                if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
+                        return 0;
+                }
+
+                int errsv = errno;
+                fprintf(stderr, "Failed to accept: %m\n");
+                return -errsv;
+        }
+        return nfd;
+}
\ No newline at end of file


Test patch:
diff --git a/binchihua/test/common/meson.build b/binchihua/test/common/meson.build
index 8e077b3f0b..45784a31aa 100644
--- a/binchihua/test/common/meson.build
+++ b/binchihua/test/common/meson.build
@@ -3,15 +3,7 @@ parse_util_src = [
   'parse-util_test.c'
 ]
 
-list_src = [
-  'list_test.c'
-]
-
 parse_util_src += common_src
-list_src += common_src
 
 e = executable('parse-util_test', parse_util_src)
 test('parse-util_test', e)
-
-e = executable('list_test', list_src)
-test('list_test', e)
\ No newline at end of file
diff --git a/binchihua/test/common/list_test.c b/libchihua-msg/test/common/list_test.c
similarity index 99%
rename from binchihua/test/common/list_test.c
rename to libchihua-msg/test/common/list_test.c
index 06c19c9852..e0a1cf3168 100644
--- a/binchihua/test/common/list_test.c
+++ b/libchihua-msg/test/common/list_test.c
@@ -1,6 +1,6 @@
 #include <stdio.h>
 
-#include "../../src/common/list.h"
+#include "../../include/common/list.h"
 
 #define VOID_0 ((void) 0)
 
diff --git a/libchihua-msg/test/meson.build b/libchihua-msg/test/meson.build
new file mode 100644
index 0000000000..e2adf49e0f
--- /dev/null
+++ b/libchihua-msg/test/meson.build
@@ -0,0 +1,5 @@
+list_src = [
+  'common/list_test.c'
+]
+exec_list_test = executable('list_test', list_src)
+test('list_test', exec_list_test)