1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
/* SPDX-License-Identifier: GPL-2.0 */
#include <inttypes.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include "main.h"
#include "uring.h"
#include "announce.h"
#include "server.h"
#include "ptimer.h"
struct announce {
uint64_t value;
struct uring_task task;
struct ptimer_task ptask;
int mcast_fd;
};
static void announce_cb(struct ptimer_task *ptask)
{
struct announce *announce = container_of(ptask, struct announce, ptask);
struct server *server;
assert_return(ptask);
assert_task_alive(DBG_ANN, &announce->task);
debug(DBG_ANN, "announcing servers");
list_for_each_entry(server, &cfg->servers, list)
server_announce(server, announce->mcast_fd);
}
static void announce_free(struct uring_task *task)
{
struct announce *announce = container_of(task, struct announce, task);
assert_return(task);
debug(DBG_ANN, "task %p, announce 0x%p, mcast_fd: %i", task, announce,
announce->mcast_fd);
close(announce->mcast_fd);
xfree(announce);
}
void announce_refdump()
{
assert_return_silent(cfg->announce);
uring_task_refdump(&cfg->announce->task);
}
void announce_delete()
{
assert_return_silent(cfg->announce);
debug(DBG_ANN, "called");
announce_stop();
uring_task_destroy(&cfg->announce->task);
cfg->announce = NULL;
}
void announce_stop()
{
struct announce *announce = cfg->announce;
assert_return_silent(announce);
ptimer_del_task(&announce->ptask);
}
void announce_start(unsigned duration)
{
struct announce *announce = cfg->announce;
unsigned times;
assert_return_silent(announce);
if (duration == 0)
times = 0;
else
times = MAX(announce->ptask.times,
DIV_ROUND_UP(duration, cfg->announce_interval));
announce->ptask.times = times;
ptimer_add_task(&announce->ptask);
}
void announce_init()
{
struct announce *announce;
int sfd;
assert_return(!cfg->announce);
assert_return_silent(cfg->announce_interval > 0);
announce = zmalloc(sizeof(*announce));
if (!announce)
die("malloc: %m");
sfd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (sfd < 0)
die("socket: %m");
uring_task_init(&announce->task, "announce", uring_parent(),
announce_free);
ptask_init(&announce->ptask, cfg->announce_interval, 0, announce_cb);
announce->mcast_fd = sfd;
cfg->announce = announce;
}
|