blob: 58345b21d6e2f2581563c0030ad6e51a5b83e807 [file] [log] [blame]
Ratan Gupta309ac442016-12-13 20:40:06 +05301#include "slp_server.hpp"
2
Patrick Venture537ff142018-11-01 16:37:09 -07003#include "sock_channel.hpp"
Ratan Gupta309ac442016-12-13 20:40:06 +05304
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <unistd.h>
9
Patrick Venture537ff142018-11-01 16:37:09 -070010#include <memory>
Ratan Gupta309ac442016-12-13 20:40:06 +053011
12/** General udp server which waits for the POLLIN event
13 on the port and calls the call back once it gets the event.
14 usage would be create the server with the port and the call back
15 and call the run method.
16 */
17int slp::udp::Server::run()
18{
Patrick Venture537ff142018-11-01 16:37:09 -070019 struct sockaddr_in6 serverAddr
Manojkiran Edaee12f482021-10-26 22:16:29 +053020 {};
Ratan Gupta309ac442016-12-13 20:40:06 +053021
22 sd_event* event = nullptr;
23
Patrick Venture537ff142018-11-01 16:37:09 -070024 slp::deleted_unique_ptr<sd_event> eventPtr(event, [](sd_event* event) {
Ratan Gupta309ac442016-12-13 20:40:06 +053025 if (!event)
26 {
27 event = sd_event_unref(event);
28 }
29 });
30
31 int fd = -1, r;
32 sigset_t ss;
33
34 r = sd_event_default(&event);
35 if (r < 0)
36 {
37 goto finish;
38 }
39
40 eventPtr.reset(event);
41 event = nullptr;
42
43 if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
44 sigaddset(&ss, SIGINT) < 0)
45 {
46 r = -errno;
47 goto finish;
48 }
49 /* Block SIGTERM first, so that the event loop can handle it */
50 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
51 {
52 r = -errno;
53 goto finish;
54 }
55
56 /* Let's make use of the default handler and "floating"
57 reference features of sd_event_add_signal() */
58
59 r = sd_event_add_signal(eventPtr.get(), NULL, SIGTERM, NULL, NULL);
60 if (r < 0)
61 {
62 goto finish;
63 }
64
65 r = sd_event_add_signal(eventPtr.get(), NULL, SIGINT, NULL, NULL);
66 if (r < 0)
67 {
68 goto finish;
69 }
70
Ratan Gupta70b85272017-01-05 20:52:18 +053071 fd = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
Ratan Gupta309ac442016-12-13 20:40:06 +053072 if (fd < 0)
73 {
74 r = -errno;
75 goto finish;
76 }
77
Ratan Gupta70b85272017-01-05 20:52:18 +053078 serverAddr.sin6_family = AF_INET6;
79 serverAddr.sin6_port = htons(this->port);
Ratan Gupta309ac442016-12-13 20:40:06 +053080
Ratan Gupta70b85272017-01-05 20:52:18 +053081 if (bind(fd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0)
Ratan Gupta309ac442016-12-13 20:40:06 +053082 {
83 r = -errno;
84 goto finish;
85 }
86
87 r = sd_event_add_io(eventPtr.get(), nullptr, fd, EPOLLIN, this->callme,
88 nullptr);
89 if (r < 0)
90 {
91 goto finish;
92 }
93
94 r = sd_event_loop(eventPtr.get());
95
96finish:
97
98 if (fd >= 0)
99 {
Patrick Venture537ff142018-11-01 16:37:09 -0700100 (void)close(fd);
Ratan Gupta309ac442016-12-13 20:40:06 +0530101 }
102
103 if (r < 0)
104 {
105 fprintf(stderr, "Failure: %s\n", strerror(-r));
106 }
107
108 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
109}