2 protocol_edge.c -- handle the meta-protocol, edges
3 Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "connection.h"
35 bool send_add_edge(connection_t *c, const edge_t *e) {
39 sockaddr2str(&e->address, &address, &port);
41 x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(),
42 e->from->name, e->to->name, address, port,
43 e->options, e->weight);
50 bool add_edge_h(connection_t *c, const char *request) {
53 char from_name[MAX_STRING_SIZE];
54 char to_name[MAX_STRING_SIZE];
55 char to_address[MAX_STRING_SIZE];
56 char to_port[MAX_STRING_SIZE];
61 if(sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d",
62 from_name, to_name, to_address, to_port, &options, &weight) != 6) {
63 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name,
68 /* Check if names are valid */
70 if(!check_id(from_name) || !check_id(to_name)) {
71 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name,
72 c->hostname, "invalid name");
76 if(seen_request(request))
81 from = lookup_node(from_name);
82 to = lookup_node(to_name);
86 from->name = xstrdup(from_name);
92 to->name = xstrdup(to_name);
97 /* Convert addresses */
99 address = str2sockaddr(to_address, to_port);
101 /* Check if edge already exists */
103 e = lookup_edge(from, to);
106 if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) {
108 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry",
109 "ADD_EDGE", c->name, c->hostname);
113 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) which does not match existing entry",
114 "ADD_EDGE", c->name, c->hostname);
120 } else if(from == myself) {
121 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist",
122 "ADD_EDGE", c->name, c->hostname);
123 contradicting_add_edge++;
135 e->address = address;
136 e->options = options;
140 /* Tell the rest about the new edge */
142 forward_request(c, request);
144 /* Run MST before or after we tell the rest? */
151 bool send_del_edge(connection_t *c, const edge_t *e) {
152 return send_request(c, "%d %x %s %s", DEL_EDGE, rand(),
153 e->from->name, e->to->name);
156 bool del_edge_h(connection_t *c, const char *request) {
158 char from_name[MAX_STRING_SIZE];
159 char to_name[MAX_STRING_SIZE];
162 if(sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING, from_name, to_name) != 2) {
163 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "DEL_EDGE", c->name,
168 /* Check if names are valid */
170 if(!check_id(from_name) || !check_id(to_name)) {
171 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_EDGE", c->name,
172 c->hostname, "invalid name");
176 if(seen_request(request))
181 from = lookup_node(from_name);
182 to = lookup_node(to_name);
185 logger(DEBUG_PROTOCOL, LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree",
186 "DEL_EDGE", c->name, c->hostname);
191 logger(DEBUG_PROTOCOL, LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree",
192 "DEL_EDGE", c->name, c->hostname);
196 /* Check if edge exists */
198 e = lookup_edge(from, to);
201 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) which does not appear in the edge tree",
202 "DEL_EDGE", c->name, c->hostname);
206 if(e->from == myself) {
207 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself",
208 "DEL_EDGE", c->name, c->hostname);
209 contradicting_del_edge++;
210 send_add_edge(c, e); /* Send back a correction */
214 /* Tell the rest about the deleted edge */
216 forward_request(c, request);
218 /* Delete the edge */
222 /* Run MST before or after we tell the rest? */
226 /* If the node is not reachable anymore but we remember it had an edge to us, clean it up */
228 if(!to->status.reachable) {
229 e = lookup_edge(to, myself);
231 send_del_edge(everyone, e);