+ char buf[MAX_STRING_SIZE];
+ int len;
+
+ if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
+ logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "REQ_SPTPS_START", from->name, "invalid SPTPS data");
+ return true;
+ }
+
+ char label[sizeof(meshlink_udp_label) + strlen(from->name) + strlen(mesh->self->name) + 2];
+ snprintf(label, sizeof(label), "%s %s %s", meshlink_udp_label, from->name, mesh->self->name);
+ sptps_stop(&from->sptps);
+ from->status.validkey = false;
+ from->status.waitingforkey = true;
+ from->last_req_key = mesh->loop.now.tv_sec;
+
+ /* Send our canonical address to help with UDP hole punching */
+ send_canonical_address(mesh, from);
+
+ if(!sptps_start(&from->sptps, from, false, true, mesh->private_key, from->ecdsa, label, sizeof(label) - 1, send_sptps_data, receive_sptps_record)) {
+ logger(mesh, MESHLINK_ERROR, "Could not start SPTPS session with %s: %s", from->name, strerror(errno));
+ return true;
+ }
+
+ if(!sptps_receive_data(&from->sptps, buf, len)) {
+ logger(mesh, MESHLINK_ERROR, "Could not process SPTPS data from %s: %s", from->name, strerror(errno));
+ return true;
+ }
+
+ return true;
+ }
+
+ case REQ_SPTPS: {
+ if(!from->status.validkey) {
+ logger(mesh, MESHLINK_ERROR, "Got REQ_SPTPS from %s but we don't have a valid key yet", from->name);
+ return true;
+ }
+
+ char buf[MAX_STRING_SIZE];
+ int len;
+
+ if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
+ logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "REQ_SPTPS", from->name, "invalid SPTPS data");
+ return true;
+ }
+
+ if(!sptps_receive_data(&from->sptps, buf, len)) {
+ logger(mesh, MESHLINK_ERROR, "Could not process SPTPS data from %s: %s", from->name, strerror(errno));
+ return true;
+ }
+
+ return true;
+ }
+
+ case REQ_CANONICAL: {
+ char host[MAX_STRING_SIZE];
+ char port[MAX_STRING_SIZE];
+
+ if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING " " MAX_STRING, host, port) != 2) {
+ logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "REQ_CANONICAL", from->name, "invalid canonical address");
+ return true;
+ }
+
+ char *canonical_address;
+ xasprintf(&canonical_address, "%s %s", host, port);
+
+ if(mesh->log_level <= MESHLINK_DEBUG && (!from->canonical_address || strcmp(from->canonical_address, canonical_address))) {
+ logger(mesh, MESHLINK_DEBUG, "Updating canonical address of %s to %s", from->name, canonical_address);
+ }
+
+ free(from->canonical_address);
+ from->canonical_address = canonical_address;
+ return true;
+ }
+
+ default:
+ logger(mesh, MESHLINK_ERROR, "Unknown extended REQ_KEY request from %s: %s", from->name, request);
+ return true;
+ }