-int ack_h(connection_t *c)
-{
- char myaddress[MAX_STRING_SIZE];
- char hisport[MAX_STRING_SIZE];
- char *hisaddress, *dummy;
- int weight;
- long int options;
- node_t *n;
- connection_t *other;
- avl_node_t *node;
-cp
- if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" %d %lx", hisport, myaddress, &weight, &options) != 4)
- {
- syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ACK", c->name, c->hostname);
- return -1;
- }
-
- /* Check if we already have a node_t for him */
-
- n = lookup_node(c->name);
-
- if(!n)
- {
- n = new_node();
- n->name = xstrdup(c->name);
- node_add(n);
- }
- else
- {
- if(n->connection)
- {
- /* Oh dear, we already have a connection to this node. */
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_DEBUG, _("Established a second connection with %s (%s), closing old connection"), n->name, n->hostname);
- terminate_connection(n->connection, 0);
- }
-
- /* FIXME: check if information in existing node matches that of the other end of this connection */
- }
-
- n->connection = c;
- c->node = n;
- c->options |= options;
-
- /* Create an edge_t for this connection */
-
- c->edge = new_edge();
-cp
- c->edge->from.node = myself;
-// c->edge->from.tcpaddress = str2sockaddr(address, port);
- c->edge->from.udpaddress = str2sockaddr(myaddress, myport);
- c->edge->to.node = n;
-// c->edge->to.tcpaddress = c->address;
- sockaddr2str(&c->address, &hisaddress, &dummy);
- c->edge->to.udpaddress = str2sockaddr(hisaddress, hisport);
- free(hisaddress);
- free(dummy);
- c->edge->weight = (weight + c->estimated_weight) / 2;
- c->edge->connection = c;
- c->edge->options = c->options;
-cp
- edge_add(c->edge);
-
- /* Activate this connection */
-
- c->allow_request = ALL;
- c->status.active = 1;
-
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), c->name, c->hostname);
-
-cp
- /* Send him everything we know */
-
- send_everything(c);
-
- /* Notify others of this connection */
-
- for(node = connection_tree->head; node; node = node->next)
- {
- other = (connection_t *)node->data;
-
- if(other->status.active && other != c)
- send_add_edge(other, c->edge);
- }
-
- /* Run MST and SSSP algorithms */
-
- graph();
-
- /* Succesful connection, reset timeout if this is an outgoing connection. */
-
- if(c->outgoing)
- c->outgoing->timeout = 0;
-cp
- return 0;
+bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
+ assert(request);
+ assert(*request);
+
+ char hisport[MAX_STRING_SIZE];
+ int devclass;
+ uint32_t options;
+ node_t *n;
+
+ if(sscanf(request, "%*d " MAX_STRING " %d %x", hisport, &devclass, &options) != 3) {
+ logger(mesh, MESHLINK_ERROR, "Got bad %s from %s", "ACK", c->name);
+ return false;
+ }
+
+ if(devclass < 0 || devclass >= DEV_CLASS_COUNT) {
+ logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "ACK", c->name, "devclass invalid");
+ return false;
+ }
+
+ /* Check if we already have a node_t for him */
+
+ n = lookup_node(mesh, c->name);
+
+ if(!n) {
+ n = new_node();
+ n->name = xstrdup(c->name);
+ node_add(mesh, n);
+ } else {
+ if(n->connection) {
+ /* Oh dear, we already have a connection to this node. */
+ logger(mesh, MESHLINK_INFO, "Established a second connection with %s, closing old connection", n->connection->name);
+
+ if(n->connection->outgoing) {
+ if(c->outgoing) {
+ logger(mesh, MESHLINK_WARNING, "Two outgoing connections to the same node!");
+ } else {
+ c->outgoing = n->connection->outgoing;
+ }
+
+ n->connection->outgoing = NULL;
+ }
+
+ /* Remove the edge before terminating the connection, to prevent a graph update. */
+ edge_del(mesh, n->connection->edge);
+ n->connection->edge = NULL;
+
+ terminate_connection(mesh, n->connection, false);
+ }
+ }
+
+ n->devclass = devclass;
+ n->status.dirty = true;
+ n->status.tiny = c->flags & PROTOCOL_TINY;
+
+ n->last_successfull_connection = mesh->loop.now.tv_sec;
+
+ n->connection = c;
+ n->nexthop = n;
+ c->node = n;
+
+ /* Activate this connection */
+
+ c->allow_request = ALL;
+ c->last_key_renewal = mesh->loop.now.tv_sec;
+ c->status.active = true;
+
+ logger(mesh, MESHLINK_INFO, "Connection with %s activated", c->name);
+
+ if(mesh->meta_status_cb) {
+ mesh->meta_status_cb(mesh, (meshlink_node_t *)n, true);
+ }
+
+ /* Terminate any connections to this node that are not activated yet */
+
+ for list_each(connection_t, other, mesh->connections) {
+ if(!other->status.active && !strcmp(other->name, c->name)) {
+ if(other->outgoing) {
+ if(c->outgoing) {
+ logger(mesh, MESHLINK_WARNING, "Two outgoing connections to the same node!");
+ } else {
+ c->outgoing = other->outgoing;
+ }
+
+ other->outgoing = NULL;
+ }
+
+ logger(mesh, MESHLINK_DEBUG, "Terminating pending second connection with %s", n->name);
+ terminate_connection(mesh, other, false);
+ }
+ }
+
+ /* Send him everything we know */
+
+ if(!(c->flags & PROTOCOL_TINY)) {
+ send_everything(mesh, c);
+ }
+
+ /* Create an edge_t for this connection */
+
+ assert(devclass >= 0 && devclass < DEV_CLASS_COUNT);
+
+ c->edge = new_edge();
+ c->edge->from = mesh->self;
+ c->edge->to = n;
+ sockaddrcpy_setport(&c->edge->address, &c->address, atoi(hisport));
+ c->edge->weight = mesh->dev_class_traits[devclass].edge_weight;
+ c->edge->connection = c;
+
+ node_add_recent_address(mesh, n, &c->address);
+ edge_add(mesh, c->edge);
+
+ /* Notify everyone of the new edge */
+
+ send_add_edge(mesh, mesh->everyone, c->edge, 0);
+
+ /* Run MST and SSSP algorithms */
+
+ graph(mesh);
+
+ /* Request a session key to jump start UDP traffic */
+
+ if(c->status.initiator) {
+ send_req_key(mesh, n);
+ }
+
+ return true;