xref: /openbmc/slpd-lite/slp_server.cpp (revision 7f70ddf52c6ae82047af1059ba7bc3d7dbb5e0b2)
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