SLP Server

This contains the entry point for the SLP
and starts the SLP Server.

Change-Id: I5976c8168a1af2703143c9bead61583197949115
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/slp_server.cpp b/slp_server.cpp
new file mode 100644
index 0000000..e307dab
--- /dev/null
+++ b/slp_server.cpp
@@ -0,0 +1,110 @@
+#include "slp_server.hpp"
+
+#include <memory>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "sock_channel.hpp"
+
+/** General udp server which waits for the POLLIN event
+    on the port and calls the call back once it gets the event.
+    usage would be create the server with the port and the call back
+    and call the run method.
+ */
+int slp::udp::Server::run()
+{
+    struct sockaddr_in in {};
+
+    sd_event* event = nullptr;
+
+    slp::deleted_unique_ptr<sd_event> eventPtr(event, [](sd_event * event)
+    {
+        if (!event)
+        {
+            event = sd_event_unref(event);
+        }
+    });
+
+    int fd = -1, r;
+    sigset_t ss;
+
+    r = sd_event_default(&event);
+    if (r < 0)
+    {
+        goto finish;
+    }
+
+    eventPtr.reset(event);
+    event = nullptr;
+
+    if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
+        sigaddset(&ss, SIGINT) < 0)
+    {
+        r = -errno;
+        goto finish;
+    }
+    /* Block SIGTERM first, so that the event loop can handle it */
+    if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
+    {
+        r = -errno;
+        goto finish;
+    }
+
+    /* Let's make use of the default handler and "floating"
+       reference features of sd_event_add_signal() */
+
+    r = sd_event_add_signal(eventPtr.get(), NULL, SIGTERM, NULL, NULL);
+    if (r < 0)
+    {
+        goto finish;
+    }
+
+    r = sd_event_add_signal(eventPtr.get(), NULL, SIGINT, NULL, NULL);
+    if (r < 0)
+    {
+        goto finish;
+    }
+
+    fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+    if (fd < 0)
+    {
+        r = -errno;
+        goto finish;
+    }
+
+    in.sin_family = AF_INET;
+    in.sin_port = htons(this->port);
+    in.sin_addr.s_addr = INADDR_ANY;
+
+    if (bind(fd, (struct sockaddr*)&in, sizeof(in)) < 0)
+    {
+        r = -errno;
+        goto finish;
+    }
+
+    r = sd_event_add_io(eventPtr.get(), nullptr, fd, EPOLLIN, this->callme,
+                        nullptr);
+    if (r < 0)
+    {
+        goto finish;
+    }
+
+    r = sd_event_loop(eventPtr.get());
+
+finish:
+
+    if (fd >= 0)
+    {
+        (void) close(fd);
+    }
+
+    if (r < 0)
+    {
+        fprintf(stderr, "Failure: %s\n", strerror(-r));
+    }
+
+    return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}