1309ac445SRatan Gupta #include "slp_server.hpp"
2309ac445SRatan Gupta
3537ff140SPatrick Venture #include "sock_channel.hpp"
4309ac445SRatan Gupta
5309ac445SRatan Gupta #include <stdio.h>
6309ac445SRatan Gupta #include <stdlib.h>
7309ac445SRatan Gupta #include <string.h>
8309ac445SRatan Gupta #include <unistd.h>
9309ac445SRatan Gupta
10537ff140SPatrick Venture #include <memory>
11309ac445SRatan Gupta
12309ac445SRatan Gupta /** General udp server which waits for the POLLIN event
13309ac445SRatan Gupta on the port and calls the call back once it gets the event.
14309ac445SRatan Gupta usage would be create the server with the port and the call back
15309ac445SRatan Gupta and call the run method.
16309ac445SRatan Gupta */
run()17309ac445SRatan Gupta int slp::udp::Server::run()
18309ac445SRatan Gupta {
19*7f70ddf5SPatrick Williams struct sockaddr_in6 serverAddr{};
20309ac445SRatan Gupta
21309ac445SRatan Gupta sd_event* event = nullptr;
22309ac445SRatan Gupta
23537ff140SPatrick Venture slp::deleted_unique_ptr<sd_event> eventPtr(event, [](sd_event* event) {
24309ac445SRatan Gupta if (!event)
25309ac445SRatan Gupta {
26309ac445SRatan Gupta event = sd_event_unref(event);
27309ac445SRatan Gupta }
28309ac445SRatan Gupta });
29309ac445SRatan Gupta
30309ac445SRatan Gupta int fd = -1, r;
31309ac445SRatan Gupta sigset_t ss;
32309ac445SRatan Gupta
33309ac445SRatan Gupta r = sd_event_default(&event);
34309ac445SRatan Gupta if (r < 0)
35309ac445SRatan Gupta {
36309ac445SRatan Gupta goto finish;
37309ac445SRatan Gupta }
38309ac445SRatan Gupta
39309ac445SRatan Gupta eventPtr.reset(event);
40309ac445SRatan Gupta event = nullptr;
41309ac445SRatan Gupta
42309ac445SRatan Gupta if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
43309ac445SRatan Gupta sigaddset(&ss, SIGINT) < 0)
44309ac445SRatan Gupta {
45309ac445SRatan Gupta r = -errno;
46309ac445SRatan Gupta goto finish;
47309ac445SRatan Gupta }
48309ac445SRatan Gupta /* Block SIGTERM first, so that the event loop can handle it */
49309ac445SRatan Gupta if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
50309ac445SRatan Gupta {
51309ac445SRatan Gupta r = -errno;
52309ac445SRatan Gupta goto finish;
53309ac445SRatan Gupta }
54309ac445SRatan Gupta
55309ac445SRatan Gupta /* Let's make use of the default handler and "floating"
56309ac445SRatan Gupta reference features of sd_event_add_signal() */
57309ac445SRatan Gupta
58309ac445SRatan Gupta r = sd_event_add_signal(eventPtr.get(), NULL, SIGTERM, NULL, NULL);
59309ac445SRatan Gupta if (r < 0)
60309ac445SRatan Gupta {
61309ac445SRatan Gupta goto finish;
62309ac445SRatan Gupta }
63309ac445SRatan Gupta
64309ac445SRatan Gupta r = sd_event_add_signal(eventPtr.get(), NULL, SIGINT, NULL, NULL);
65309ac445SRatan Gupta if (r < 0)
66309ac445SRatan Gupta {
67309ac445SRatan Gupta goto finish;
68309ac445SRatan Gupta }
69309ac445SRatan Gupta
7070b85271SRatan Gupta fd = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
71309ac445SRatan Gupta if (fd < 0)
72309ac445SRatan Gupta {
73309ac445SRatan Gupta r = -errno;
74309ac445SRatan Gupta goto finish;
75309ac445SRatan Gupta }
76309ac445SRatan Gupta
7770b85271SRatan Gupta serverAddr.sin6_family = AF_INET6;
7870b85271SRatan Gupta serverAddr.sin6_port = htons(this->port);
79309ac445SRatan Gupta
8070b85271SRatan Gupta if (bind(fd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0)
81309ac445SRatan Gupta {
82309ac445SRatan Gupta r = -errno;
83309ac445SRatan Gupta goto finish;
84309ac445SRatan Gupta }
85309ac445SRatan Gupta
86309ac445SRatan Gupta r = sd_event_add_io(eventPtr.get(), nullptr, fd, EPOLLIN, this->callme,
87309ac445SRatan Gupta nullptr);
88309ac445SRatan Gupta if (r < 0)
89309ac445SRatan Gupta {
90309ac445SRatan Gupta goto finish;
91309ac445SRatan Gupta }
92309ac445SRatan Gupta
93309ac445SRatan Gupta r = sd_event_loop(eventPtr.get());
94309ac445SRatan Gupta
95309ac445SRatan Gupta finish:
96309ac445SRatan Gupta
97309ac445SRatan Gupta if (fd >= 0)
98309ac445SRatan Gupta {
99309ac445SRatan Gupta (void)close(fd);
100309ac445SRatan Gupta }
101309ac445SRatan Gupta
102309ac445SRatan Gupta if (r < 0)
103309ac445SRatan Gupta {
104309ac445SRatan Gupta fprintf(stderr, "Failure: %s\n", strerror(-r));
105309ac445SRatan Gupta }
106309ac445SRatan Gupta
107309ac445SRatan Gupta return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
108309ac445SRatan Gupta }
109