-
Notifications
You must be signed in to change notification settings - Fork 80
/
Copy pathdirectory_client.c
159 lines (132 loc) · 5.14 KB
/
directory_client.c
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
Serval DNA directory service client
Copyright (C) 2013 Serval Project Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
Serval Directory Service client
When servald starts, load the SID, IP (or domain name) & port of a directory server.
When an interface comes up with a route to this server, and periodically thereafter,
send our SID name and number to the configured server.
When we perform a lookup, send an additional copy of the request to the directory server.
*/
#include "serval_types.h"
#include "cli.h"
#include "str.h"
#include "overlay_address.h"
#include "overlay_packet.h"
#include "overlay_buffer.h"
#include "conf.h"
#include "overlay_interface.h"
#include "keyring.h"
#include "serval.h" // for overlay_send_frame()
#include "route_link.h"
#include "server.h"
#include "feature.h"
DEFINE_FEATURE(directory_client);
__thread struct subscriber *directory_service;
static void directory_update(struct sched_ent *alarm);
static struct profile_total directory_timing={
.name="directory_update",
};
struct sched_ent directory_alarm={
.function=directory_update,
.stats=&directory_timing,
};
#define DIRECTORY_UPDATE_INTERVAL 120000
// send a registration packet
static void directory_send(struct subscriber *directory_service, struct subscriber *source, const char *did, const char *name)
{
// Used by tests
INFOF("Sending directory registration for %s*, %s, %s to %s*",
alloca_tohex_sid_t_trunc(source->sid, 14), did, name, alloca_tohex_sid_t_trunc(directory_service->sid, 14));
struct internal_mdp_header header;
bzero(&header, sizeof header);
header.source = source;
header.source_port = MDP_PORT_NOREPLY;
header.destination = directory_service;
header.destination_port = MDP_PORT_DIRECTORY;
header.qos = OQ_ORDINARY;
char buff[256];
struct overlay_buffer *payload = ob_static((unsigned char*)buff, sizeof buff);
ob_limitsize(payload, snprintf(buff, sizeof buff, "%s|%s", did, name));
overlay_send_frame(&header, payload);
ob_free(payload);
}
// send a registration packet for each unlocked identity
static void directory_send_keyring(struct subscriber *directory_service){
assert(keyring != NULL);
keyring_iterator it;
keyring_iterator_start(keyring, &it);
while(keyring_next_keytype(&it, KEYTYPE_DID)){
if (it.identity->subscriber && it.identity->subscriber->reachable == REACHABLE_SELF){
const char *unpackedDid = (const char *) it.keypair->private_key;
const char *name = (const char *) it.keypair->public_key;
directory_send(directory_service, it.identity->subscriber, unpackedDid, name);
}
}
}
static void directory_update(struct sched_ent *alarm){
if (directory_service){
if (directory_service->reachable & REACHABLE){
directory_send_keyring(directory_service);
unschedule(alarm);
alarm->alarm = gettime_ms() + DIRECTORY_UPDATE_INTERVAL;
alarm->deadline = alarm->alarm + 10000;
schedule(alarm);
}else{
// always attempt to reload the address, may depend on DNS resolution
struct network_destination *destination = load_subscriber_address(directory_service);
if (destination){
overlay_send_probe(directory_service, destination, OQ_MESH_MANAGEMENT);
release_destination_ref(destination);
}
}
}
}
static void directory_service_init(){
if (is_sid_t_any(config.directory.service)) {
directory_service = NULL;
}else{
directory_service = find_subscriber(config.directory.service.binary, SID_SIZE, 1);
if (!directory_service){
WHYF("Failed to create subscriber record");
}else{
// used by tests
INFOF("ADD DIRECTORY SERVICE %s", alloca_tohex_sid_t(directory_service->sid));
}
}
unschedule(&directory_alarm);
directory_update(&directory_alarm);
}
DEFINE_TRIGGER(conf_change, directory_service_init);
// called when we discover a route to the directory service SID
int directory_registration(){
// give the route & SAS keys a moment to propagate
unschedule(&directory_alarm);
directory_alarm.alarm = gettime_ms() + 200;
directory_alarm.deadline = directory_alarm.alarm + 10000;
schedule(&directory_alarm);
return 0;
}
static void interface_change(struct overlay_interface *UNUSED(interface), unsigned count){
unschedule(&directory_alarm);
if (count)
directory_update(&directory_alarm);
}
DEFINE_TRIGGER(iupdown, interface_change);
static void directory_link_changed(struct subscriber *subscriber, int UNUSED(prior_reachable)){
if (subscriber==directory_service)
directory_registration();
}
DEFINE_TRIGGER(link_change, directory_link_changed);