#include "edge.h"
#include "net.h"
#include "node.h"
+#include "submesh.h"
typedef struct connection_t {
char *name; /* name he claims to have */
ecdsa_t *ecdsa; /* his public ECDSA key */
sptps_t sptps;
+ struct submesh_t *submesh; /* his submesh handle if available in invitation file */
int incompression;
int outcompression;
meshlink_log_cb_t global_log_cb;
meshlink_log_level_t global_log_level;
+typedef bool (*search_node_by_condition_t)(const node_t *, const void *);
+
//TODO: this can go away completely
const var_t variables[] = {
/* Server configuration */
return NULL;
}
- s = (meshlink_submesh_t *)lookup_submesh(mesh, submesh);
-
- if(s) {
- logger(NULL, MESHLINK_ERROR, "SubMesh Already exists!\n");
- meshlink_errno = MESHLINK_EEXIST;
- return NULL;
- }
+ //lock mesh->nodes
+ pthread_mutex_lock(&(mesh->mesh_mutex));
- s = (meshlink_submesh_t *)new_submesh();
- s->name = xstrdup(submesh);
+ s = (meshlink_submesh_t *)create_submesh(mesh, submesh);
- submesh_add(mesh, (submesh_t *)s);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
- meshlink_errno = MESHLINK_OK;
return s;
}
return result;
}
-meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, dev_class_t devclass, meshlink_node_t **nodes, size_t *nmemb) {
- if(!mesh || ((int)devclass < 0) || (devclass > _DEV_CLASS_MAX) || !nmemb) {
- meshlink_errno = MESHLINK_EINVAL;
- return NULL;
- }
-
+static meshlink_node_t **meshlink_get_all_nodes_by_condition(meshlink_handle_t *mesh, const void *condition, meshlink_node_t **nodes, size_t *nmemb, search_node_by_condition_t search_node) {
meshlink_node_t **result;
pthread_mutex_lock(&(mesh->mesh_mutex));
*nmemb = 0;
for splay_each(node_t, n, mesh->nodes) {
- if(n->devclass == devclass) {
+ if(true == search_node(n, condition)) {
*nmemb = *nmemb + 1;
}
}
meshlink_node_t **p = result;
for splay_each(node_t, n, mesh->nodes) {
- if(n->devclass == devclass) {
+ if(true == search_node(n, condition)) {
*p++ = (meshlink_node_t *)n;
}
}
return result;
}
+static bool search_node_by_dev_class(const node_t *node, const void *condition) {
+ dev_class_t *devclass = (dev_class_t *)condition;
+
+ if(*devclass == node->devclass) {
+ return true;
+ }
+
+ return false;
+}
+
+static bool search_node_by_submesh(const node_t *node, const void *condition) {
+ if(condition == node->submesh) {
+ return true;
+ }
+
+ return false;
+}
+
+meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, dev_class_t devclass, meshlink_node_t **nodes, size_t *nmemb) {
+ if(!mesh || ((int)devclass < 0) || (devclass > _DEV_CLASS_MAX) || !nmemb) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ return meshlink_get_all_nodes_by_condition(mesh, &devclass, nodes, nmemb, search_node_by_dev_class);
+}
+
+meshlink_node_t **meshlink_get_all_nodes_by_submesh(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, meshlink_node_t **nodes, size_t *nmemb) {
+ if(!mesh || !submesh || !nmemb) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ return meshlink_get_all_nodes_by_condition(mesh, submesh, nodes, nmemb, search_node_by_submesh);
+}
+
dev_class_t meshlink_get_node_dev_class(meshlink_handle_t *mesh, meshlink_node_t *node) {
if(!mesh || !node) {
meshlink_errno = MESHLINK_EINVAL;
return devclass;
}
+meshlink_submesh_t *meshlink_get_node_submesh(meshlink_handle_t *mesh, meshlink_node_t *node) {
+ if(!mesh || !node) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ node_t *n = (node_t *)node;
+
+ meshlink_submesh_t *s;
+
+ s = (meshlink_submesh_t *)n->submesh;
+
+ return s;
+}
+
bool meshlink_sign(meshlink_handle_t *mesh, const void *data, size_t len, void *signature, size_t *siglen) {
if(!mesh || !data || !len || !signature || !siglen) {
meshlink_errno = MESHLINK_EINVAL;
meshlink_errno = MESHLINK_EINVAL;
return NULL;
}
+ } else {
+ s = (meshlink_submesh_t *)mesh->self->submesh;
}
pthread_mutex_lock(&(mesh->mesh_mutex));
*/
extern meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, dev_class_t devclass, meshlink_node_t **nodes, size_t *nmemb);
+/// Get the list of all nodes by Submesh.
+/** This function returns a list with handles for all the nodes that matches with the given @a Submesh @a .
+ *
+ * @param mesh A handle which represents an instance of MeshLink.
+ * @param submesh Submesh handle of the nodes for which the list has to be obtained.
+ * @param nodes A pointer to a previously allocated array of pointers to meshlink_node_t, or NULL in which case MeshLink will allocate a new array.
+ * The application can supply an array it allocated itself with malloc, or the return value from the previous call to this function (which is the preferred way).
+ * The application is allowed to call free() on the array whenever it wishes.
+ * The pointers in the array are valid until meshlink_close() is called.
+ * @param nmemb A pointer to a variable holding the number of nodes with the same @a device class @a that are stored in the array.
+ * In case the @a nodes @a argument is not NULL, MeshLink might call realloc() on the array to change its size.
+ * The contents of this variable will be changed to reflect the new size of the array.
+ *
+ * @return A pointer to an array containing pointers to all known nodes of the given Submesh, or NULL in case of an error.
+ * If the @a nodes @a argument was not NULL, then the return value can either be the same value or a different value.
+ * If it is a new value, the old value of @a nodes @a should not be used anymore.
+ * If the new value is NULL, then the old array will have been freed by MeshLink.
+ */
+extern meshlink_node_t **meshlink_get_all_nodes_by_submesh(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, meshlink_node_t **nodes, size_t *nmemb);
+
/// Get the node's device class.
/** This function returns the device class of the given node.
*
*/
extern dev_class_t meshlink_get_node_dev_class(meshlink_handle_t *mesh, meshlink_node_t *node);
+/// Get the node's submesh handle.
+/** This function returns the submesh handle of the given node.
+ *
+ * @param mesh A handle which represents an instance of MeshLink.
+ * @param node A pointer to a meshlink_node_t describing the node.
+ *
+ * @return This function returns the submesh handle of the @a node @a , or NULL in case of an error.
+ */
+extern meshlink_submesh_t *meshlink_get_node_submesh(meshlink_handle_t *mesh, meshlink_node_t *node);
+
/// Verify the signature generated by another node of a piece of data.
/** This function verifies the signature that another node generated for a piece of data.
*
}
}
+void broadcast_submesh_meta(meshlink_handle_t *mesh, connection_t *from, submesh_t *s,
+ const char *buffer, int length) {
+ for list_each(connection_t, c, mesh->connections)
+ if(c != from && c->status.active) {
+ if(c->node && submesh_allows_node(s, c->node)) {
+ send_meta(mesh, c, buffer, length);
+ }
+ }
+}
+
bool receive_meta_sptps(void *handle, uint8_t type, const void *data, uint16_t length) {
connection_t *c = handle;
meshlink_handle_t *mesh = c->mesh;
extern bool send_meta_sptps(void *, uint8_t, const void *, size_t);
extern bool receive_meta_sptps(void *, uint8_t, const void *, uint16_t);
extern void broadcast_meta(struct meshlink_handle *mesh, struct connection_t *, const char *, int);
+extern void broadcast_submesh_meta(struct meshlink_handle *mesh, connection_t *from, submesh_t *s,
+ const char *buffer, int length);
extern bool receive_meta(struct meshlink_handle *mesh, struct connection_t *);
#endif
to ensure we get to learn the reflexive UDP address. */
if(!to->status.validkey) {
to->incompression = mesh->self->incompression;
- return send_request(mesh, to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, to->incompression);
+ return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, to->incompression);
} else {
- return send_request(mesh, to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf);
+ return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf);
}
}
#include "protocol.h"
#include "utils.h"
#include "xalloc.h"
+#include "submesh.h"
/* Jumptable for the request handlers */
/* Generic request routines - takes care of logging and error
detection as well */
-bool send_request(meshlink_handle_t *mesh, connection_t *c, const char *format, ...) {
+bool send_request(meshlink_handle_t *mesh, connection_t *c, submesh_t *s, const char *format, ...) {
va_list args;
char request[MAXBUFSIZE];
int len;
+ if(!c) {
+ return false;
+ }
+
/* Use vsnprintf instead of vxasprintf: faster, no memory
fragmentation, cleanup is automatic, and there is a limit on the
input buffer anyway */
request[len++] = '\n';
if(c == mesh->everyone) {
- broadcast_meta(mesh, NULL, request, len);
+
+ if(s) {
+ broadcast_submesh_meta(mesh, NULL, s, request, len);
+ } else {
+ broadcast_meta(mesh, NULL, request, len);
+ }
+
return true;
} else {
return send_meta(mesh, c, request, len);
}
}
-void forward_request(meshlink_handle_t *mesh, connection_t *from, const char *request) {
+void forward_request(meshlink_handle_t *mesh, connection_t *from, submesh_t *s, const char *request) {
logger(mesh, MESHLINK_DEBUG, "Forwarding %s from %s: %s", request_name[atoi(request)], from->name, request);
// Create a temporary newline-terminated copy of the request
int len = strlen(request);
char tmp[len + 1];
+
memcpy(tmp, request, len);
tmp[len] = '\n';
- broadcast_meta(mesh, from, tmp, sizeof(tmp));
+
+ if(s) {
+ broadcast_submesh_meta(mesh, from, s, tmp, sizeof(tmp));
+ } else {
+ broadcast_meta(mesh, from, tmp, sizeof(tmp));
+ }
}
bool receive_request(meshlink_handle_t *mesh, connection_t *c, const char *request) {
/* Basic functions */
-extern bool send_request(struct meshlink_handle *mesh, struct connection_t *, const char *, ...) __attribute__((__format__(printf, 3, 4)));
-extern void forward_request(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool send_request(struct meshlink_handle *mesh, struct connection_t *, struct submesh_t *s, const char *, ...) __attribute__((__format__(printf, 4, 5)));
+extern void forward_request(struct meshlink_handle *mesh, struct connection_t *, struct submesh_t *, const char *);
extern bool receive_request(struct meshlink_handle *mesh, struct connection_t *, const char *);
extern bool check_id(const char *);
char *port;
sockaddr2str(&c->address, &host, &port);
- send_request(mesh, c, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port);
+ send_request(mesh, c, NULL, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port);
free(host);
free(port);
return true;
return false;
}
- return send_request(mesh, c, "%d %s %d.%d %s", ID, mesh->self->connection->name, mesh->self->connection->protocol_major, minor, mesh->appname);
+ return send_request(mesh, c, NULL, "%d %s %d.%d %s", ID, mesh->self->connection->name, mesh->self->connection->protocol_major, minor, mesh->appname);
}
static bool finalize_invitation(meshlink_handle_t *mesh, connection_t *c, const void *data, uint16_t len) {
}
fprintf(f, "ECDSAPublicKey = %s\n", (const char *)data);
+
+ if(c->submesh) {
+ fprintf(f, "SubMesh = %s\n", c->submesh->name);
+ }
+
fclose(f);
logger(mesh, MESHLINK_INFO, "Key succesfully received from %s", c->name);
free(c->name);
c->name = xstrdup(name);
+ // Check if the file contains Sub-Mesh information
+ buf[0] = 0;
+ fgets(buf, sizeof(buf), f);
+
+ if(*buf) {
+ buf[strlen(buf) - 1] = 0;
+ }
+
+ if(!strncmp(buf, "SubMesh", 7)) {
+ len = strcspn(buf, " \t=");
+ char *submesh_name = buf + len;
+ submesh_name += strspn(submesh_name, " \t");
+
+ if(*submesh_name == '=') {
+ submesh_name++;
+ submesh_name += strspn(submesh_name, " \t");
+ }
+
+ if(!check_id(submesh_name)) {
+ logger(mesh, MESHLINK_ERROR, "Invalid invitation file %s\n", cookie);
+ fclose(f);
+ return false;
+ }
+
+ c->submesh = NULL;
+ c->submesh = lookup_or_create_submesh(mesh, submesh_name);
+
+ if(!c->submesh) {
+ return false;
+ }
+ }
+
// Send the node the contents of the invitation file
rewind(f);
size_t result;
return false;
}
- if(!send_request(mesh, c, "%d %s", ACK, mykey)) {
+ if(!send_request(mesh, c, NULL, "%d %s", ACK, mykey)) {
return false;
}
c->options |= OPTION_PMTU_DISCOVERY;
}
- return send_request(mesh, c, "%d %s %d %x", ACK, mesh->myport, mesh->devclass, (c->options & 0xffffff) | (PROT_MINOR << 24));
+ return send_request(mesh, c, NULL, "%d %s %d %x", ACK, mesh->myport, mesh->devclass, (c->options & 0xffffff) | (PROT_MINOR << 24));
}
static void send_everything(meshlink_handle_t *mesh, connection_t *c) {
#include "protocol.h"
#include "utils.h"
#include "xalloc.h"
+#include "submesh.h"
extern bool node_write_devclass(meshlink_handle_t *mesh, node_t *n);
+extern bool node_write_submesh(meshlink_handle_t *mesh, node_t *n);
bool send_add_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e, int contradictions) {
bool x;
char *address, *port;
+ char *from_submesh, *to_submesh;
+ submesh_t *s = NULL;
+
+ if(c->node && c->node->submesh) {
+ if(!submesh_allows_node(e->from->submesh, c->node)) {
+ return true;
+ }
+
+ if(!submesh_allows_node(e->to->submesh, c->node)) {
+ return true;
+ }
+ }
+
+ if(e->from->submesh && e->to->submesh && (e->from->submesh != e->to->submesh)) {
+ return true;
+ }
sockaddr2str(&e->address, &address, &port);
- x = send_request(mesh, c, "%d %x %s %d %s %s %s %d %x %d %d", ADD_EDGE, rand(),
- e->from->name, e->from->devclass, e->to->name, address, port, e->to->devclass,
- e->options, e->weight, contradictions);
+ if(e->from->submesh) {
+ from_submesh = e->from->submesh->name;
+ } else {
+ from_submesh = CORE_MESH;
+ }
+
+ if(e->to->submesh) {
+ to_submesh = e->to->submesh->name;
+ } else {
+ to_submesh = CORE_MESH;
+ }
+
+ if(e->from->submesh) {
+ s = e->from->submesh;
+ } else {
+ s = e->to->submesh;
+ }
+
+ x = send_request(mesh, c, s, "%d %x %s %d %s %s %s %s %d %s %x %d %d", ADD_EDGE, rand(),
+ e->from->name, e->from->devclass, from_submesh, e->to->name, address, port,
+ e->to->devclass, to_submesh, e->options, e->weight, contradictions);
free(address);
free(port);
node_t *from, *to;
char from_name[MAX_STRING_SIZE];
int from_devclass;
+ char from_submesh_name[MAX_STRING_SIZE] = "";
char to_name[MAX_STRING_SIZE];
char to_address[MAX_STRING_SIZE];
char to_port[MAX_STRING_SIZE];
int to_devclass;
+ char to_submesh_name[MAX_STRING_SIZE] = "";
sockaddr_t address;
uint32_t options;
int weight;
int contradictions = 0;
+ submesh_t *s = NULL;
- if(sscanf(request, "%*d %*x "MAX_STRING" %d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %x %d %d",
- from_name, &from_devclass, to_name, to_address, to_port, &to_devclass, &options, &weight, &contradictions) < 8) {
+ if(sscanf(request, "%*d %*x "MAX_STRING" %d "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %d "MAX_STRING" %x %d %d",
+ from_name, &from_devclass, from_submesh_name, to_name, to_address, to_port, &to_devclass, to_submesh_name,
+ &options, &weight, &contradictions) < 10) {
logger(mesh, MESHLINK_ERROR, "Got bad %s from %s", "ADD_EDGE", c->name);
return false;
}
- /* Check if names are valid */
-
- if(!check_id(from_name) || !check_id(to_name)) {
- logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "ADD_EDGE", c->name, "invalid name");
- return false;
- }
-
// Check if devclasses are valid
if(from_devclass < 0 || from_devclass > _DEV_CLASS_MAX) {
return false;
}
+ if(0 == strcmp(from_submesh_name, "")) {
+ logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "ADD_EDGE", c->name, "invalid submesh id");
+ return false;
+ }
+
+ if(0 == strcmp(to_submesh_name, "")) {
+ logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "ADD_EDGE", c->name, "invalid submesh id");
+ return false;
+ }
+
if(seen_request(mesh, request)) {
return true;
}
from = new_node();
from->status.blacklisted = mesh->default_blacklist;
from->name = xstrdup(from_name);
+
+ from->submesh = NULL;
+
+ if(0 != strcmp(from_submesh_name, CORE_MESH)) {
+ if(!(from->submesh = lookup_or_create_submesh(mesh, from_submesh_name))) {
+ return false;
+ }
+ }
+
node_add(mesh, from);
}
from->devclass = from_devclass;
node_write_devclass(mesh, from);
+ if(from->submesh) {
+ node_write_submesh(mesh, from);
+ }
+
if(!to) {
to = new_node();
to->status.blacklisted = mesh->default_blacklist;
to->name = xstrdup(to_name);
+
+ to->submesh = NULL;
+
+ if(0 != strcmp(to_submesh_name, CORE_MESH)) {
+ if(!(to->submesh = lookup_or_create_submesh(mesh, to_submesh_name))) {
+ return false;
+
+ }
+ }
+
node_add(mesh, to);
}
to->devclass = to_devclass;
node_write_devclass(mesh, to);
+ if(to->submesh) {
+ node_write_submesh(mesh, to);
+ }
+
/* Convert addresses */
address = str2sockaddr(to_address, to_port);
e->weight = weight;
edge_add(mesh, e);
- /* Tell the rest about the new edge */
-
- forward_request(mesh, c, request);
-
/* Run MST before or after we tell the rest? */
graph(mesh);
+ if(e->from->submesh && e->to->submesh && (e->from->submesh != e->to->submesh)) {
+ logger(mesh, MESHLINK_ERROR, "Dropping add edge ( %s to %s )", e->from->submesh->name, e->to->submesh->name);
+ return false;
+ }
+
+ if(e->from->submesh) {
+ s = e->from->submesh;
+ } else {
+ s = e->to->submesh;
+ }
+
+ /* Tell the rest about the new edge */
+
+ forward_request(mesh, c, s, request);
+
return true;
}
bool send_del_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e, int contradictions) {
- return send_request(mesh, c, "%d %x %s %s %d", DEL_EDGE, rand(),
+ submesh_t *s = NULL;
+
+ if(c->node && c->node->submesh) {
+ if(!submesh_allows_node(e->from->submesh, c->node)) {
+ return true;
+ }
+
+ if(!submesh_allows_node(e->to->submesh, c->node)) {
+ return true;
+ }
+ }
+
+ if(e->from->submesh && e->to->submesh && (e->from->submesh != e->to->submesh)) {
+ return true;
+ }
+
+
+ if(e->from->submesh) {
+ s = e->from->submesh;
+ } else {
+ s = e->to->submesh;
+ }
+
+ return send_request(mesh, c, s, "%d %x %s %s %d", DEL_EDGE, rand(),
e->from->name, e->to->name, contradictions);
}
char to_name[MAX_STRING_SIZE];
node_t *from, *to;
int contradictions = 0;
+ submesh_t *s = NULL;
if(sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING" %d", from_name, to_name, &contradictions) < 2) {
logger(mesh, MESHLINK_ERROR, "Got bad %s from %s", "DEL_EDGE", c->name);
return false;
}
- /* Check if names are valid */
-
- if(!check_id(from_name) || !check_id(to_name)) {
- logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "DEL_EDGE", c->name, "invalid name");
- return false;
- }
-
if(seen_request(mesh, request)) {
return true;
}
/* Tell the rest about the deleted edge */
- forward_request(mesh, c, request);
+
+ if(!e->from->submesh || !e->to->submesh || (e->from->submesh == e->to->submesh)) {
+ if(e->from->submesh) {
+ s = e->from->submesh;
+ } else {
+ s = e->to->submesh;
+ }
+
+ /* Tell the rest about the deleted edge */
+ forward_request(mesh, c, s, request);
+
+ } else {
+ logger(mesh, MESHLINK_ERROR, "Dropping del edge ( %s to %s )", e->from->submesh->name, e->to->submesh->name);
+ return false;
+ }
/* Delete the edge */
#include "xalloc.h"
void send_key_changed(meshlink_handle_t *mesh) {
- send_request(mesh, mesh->everyone, "%d %x %s", KEY_CHANGED, rand(), mesh->self->name);
+ send_request(mesh, mesh->everyone, NULL, "%d %x %s", KEY_CHANGED, rand(), mesh->self->name);
/* Force key exchange for connections using SPTPS */
/* Tell the others */
- forward_request(mesh, c, request);
+ forward_request(mesh, c, NULL, request);
return true;
}
to->sptps.send_data = send_sptps_data;
char buf[len * 4 / 3 + 5];
b64encode(data, buf, len);
- return send_request(mesh, to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_KEY, buf);
+ return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_KEY, buf);
}
bool send_req_key(meshlink_handle_t *mesh, node_t *to) {
if(!node_read_ecdsa_public_key(mesh, to)) {
logger(mesh, MESHLINK_DEBUG, "No ECDSA key known for %s", to->name);
- send_request(mesh, to->nexthop->connection, "%d %s %s %d", REQ_KEY, mesh->self->name, to->name, REQ_PUBKEY);
+ send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %d", REQ_KEY, mesh->self->name, to->name, REQ_PUBKEY);
return true;
}
switch(reqno) {
case REQ_PUBKEY: {
char *pubkey = ecdsa_get_base64_public_key(mesh->self->connection->ecdsa);
- send_request(mesh, from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, from->name, ANS_PUBKEY, pubkey);
+
+ if(!from->nexthop || !from->nexthop->connection) {
+ return false;
+ }
+
+ send_request(mesh, from->nexthop->connection, NULL, "%d %s %s %d %s", REQ_KEY, mesh->self->name, from->name, ANS_PUBKEY, pubkey);
free(pubkey);
return true;
}
case REQ_KEY: {
if(!node_read_ecdsa_public_key(mesh, from)) {
logger(mesh, MESHLINK_DEBUG, "No ECDSA key known for %s", from->name);
- send_request(mesh, from->nexthop->connection, "%d %s %s %d", REQ_KEY, mesh->self->name, from->name, REQ_PUBKEY);
+ send_request(mesh, from->nexthop->connection, NULL, "%d %s %s %d", REQ_KEY, mesh->self->name, from->name, REQ_PUBKEY);
return true;
}
return true;
}
- send_request(mesh, to->nexthop->connection, "%s", request);
+ send_request(mesh, to->nexthop->connection, NULL, "%s", request);
}
return true;
char *address, *port;
logger(mesh, MESHLINK_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
sockaddr2str(&from->address, &address, &port);
- send_request(mesh, to->nexthop->connection, "%s %s %s", request, address, port);
+ send_request(mesh, to->nexthop->connection, NULL, "%s %s %s", request, address, port);
free(address);
free(port);
return true;
}
- return send_request(mesh, to->nexthop->connection, "%s", request);
+ return send_request(mesh, to->nexthop->connection, NULL, "%s", request);
}
/* Don't use key material until every check has passed. */
c->status.pinged = true;
c->last_ping_time = mesh->loop.now.tv_sec;
- return send_request(mesh, c, "%d", PING);
+ return send_request(mesh, c, NULL, "%d", PING);
}
bool ping_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
}
bool send_pong(meshlink_handle_t *mesh, connection_t *c) {
- return send_request(mesh, c, "%d", PONG);
+ return send_request(mesh, c, NULL, "%d", PONG);
}
bool pong_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
/*
- node.c -- node tree management
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>,
+ submesh.c -- submesh management
+ Copyright (C) 2019 Guus Sliepen <guus@meshlink.io>,
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
#include "splay_tree.h"
#include "utils.h"
#include "xalloc.h"
+#include "protocol.h"
void init_submeshes(meshlink_handle_t *mesh) {
mesh->submeshes = list_alloc((list_action_t)free_submesh);
free(s);
}
+static submesh_t *submesh_new(meshlink_handle_t *mesh, const char *submesh) {
+ submesh_t *s = NULL;
+
+ s = new_submesh();
+ s->name = xstrdup(submesh);
+
+ submesh_add(mesh, (submesh_t *)s);
+ return s;
+}
+
+submesh_t *create_submesh(meshlink_handle_t *mesh, const char *submesh) {
+ submesh_t *s = NULL;
+
+ if(0 == strcmp(submesh, CORE_MESH)) {
+ logger(NULL, MESHLINK_ERROR, "Cannot create submesh handle for core mesh!\n");
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ if(!check_id(submesh)) {
+ logger(NULL, MESHLINK_ERROR, "Invalid SubMesh Id!\n");
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ s = lookup_submesh(mesh, submesh);
+
+ if(s) {
+ logger(NULL, MESHLINK_ERROR, "SubMesh Already exists!\n");
+ meshlink_errno = MESHLINK_EEXIST;
+ return NULL;
+ }
+
+ s = submesh_new(mesh, submesh);
+
+ meshlink_errno = MESHLINK_OK;
+ return s;
+}
+
+submesh_t *lookup_or_create_submesh(meshlink_handle_t *mesh, const char *submesh) {
+ submesh_t *s = NULL;
+
+ if(0 == strcmp(submesh, CORE_MESH)) {
+ logger(NULL, MESHLINK_ERROR, "Cannot create submesh handle for core mesh!\n");
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ if(!check_id(submesh)) {
+ logger(NULL, MESHLINK_ERROR, "Invalid SubMesh Id!\n");
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ s = lookup_submesh(mesh, submesh);
+
+ if(s) {
+ meshlink_errno = MESHLINK_OK;
+ return s;
+ }
+
+ s = submesh_new(mesh, submesh);
+
+ meshlink_errno = MESHLINK_OK;
+ return s;
+}
+
void submesh_add(meshlink_handle_t *mesh, submesh_t *s) {
s->mesh = mesh;
list_insert_tail(mesh->submeshes, (void *)s);
return submesh;
}
+
+bool submesh_allows_node(const submesh_t *submesh, const node_t *node) {
+ if(!node->submesh || !submesh || submesh == node->submesh) {
+ return true;
+ } else {
+ return false;
+ }
+}
\ No newline at end of file
#define MESHLINK_SUBMESH_H
/*
- submesh.h -- header for node.c
- Copyright (C) 2014, 2017 Guus Sliepen <guus@meshlink.io>
+ submesh.h -- header for submesh.c
+ Copyright (C) 2019 Guus Sliepen <guus@meshlink.io>
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
#include "meshlink_internal.h"
+#define CORE_MESH "."
+
typedef struct submesh_t {
char *name; /* name of this Sub-Mesh */
void *priv;
extern void exit_submeshes(struct meshlink_handle *mesh);
extern submesh_t *new_submesh(void) __attribute__((__malloc__));
extern void free_submesh(submesh_t *);
+extern submesh_t *create_submesh(struct meshlink_handle *mesh, const char *);
extern void submesh_add(struct meshlink_handle *mesh, submesh_t *);
extern void submesh_del(struct meshlink_handle *mesh, submesh_t *);
extern submesh_t *lookup_submesh(struct meshlink_handle *mesh, const char *);
+extern submesh_t *lookup_or_create_submesh(struct meshlink_handle *mesh, const char *);
+extern bool submesh_allows_node(const submesh_t *submesh, const struct node_t *node);
#endif