+#endif
+
+bool send_meta_sptps(void *handle, uint8_t type, const void *buffer, size_t length) {
+ (void)type;
+ connection_t *c = handle;
+
+ if(!c) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "send_meta_sptps() called with NULL pointer!");
+ abort();
+ }
+
+ buffer_add(&c->outbuf, buffer, length);
+ io_set(&c->io, IO_READ | IO_WRITE);
+
+ return true;
+}
+
+bool send_meta(connection_t *c, const void *buffer, size_t length) {
+ if(!c) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "send_meta() called with NULL pointer!");
+ abort();
+ }
+
+ logger(DEBUG_META, LOG_DEBUG, "Sending %lu bytes of metadata to %s (%s)",
+ (unsigned long)length, c->name, c->hostname);
+
+ if(c->protocol_minor >= 2) {
+ return sptps_send_record(&c->sptps, 0, buffer, length);
+ }
+
+ /* Add our data to buffer */
+ if(c->status.encryptout) {
+#ifdef DISABLE_LEGACY
+ return false;
+#else
+ assert(c->legacy);
+
+ if(!decrease_budget(&c->legacy->out, length)) {
+ logger(DEBUG_META, LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname);
+ return false;
+ }
+
+ size_t outlen = length;
+
+ if(!cipher_encrypt(&c->legacy->out.cipher, buffer, length, buffer_prepare(&c->outbuf, length), &outlen, false) || outlen != length) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting metadata to %s (%s)",
+ c->name, c->hostname);
+ return false;
+ }
+
+#endif
+ } else {
+ buffer_add(&c->outbuf, buffer, length);
+ }
+
+ io_set(&c->io, IO_READ | IO_WRITE);
+
+ return true;
+}
+
+void send_meta_raw(connection_t *c, const void *buffer, size_t length) {
+ if(!c) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "send_meta() called with NULL pointer!");
+ abort();
+ }
+
+ logger(DEBUG_META, LOG_DEBUG, "Sending %lu bytes of raw metadata to %s (%s)",
+ (unsigned long)length, c->name, c->hostname);
+
+ buffer_add(&c->outbuf, buffer, length);
+
+ io_set(&c->io, IO_READ | IO_WRITE);
+}
+
+void broadcast_meta(connection_t *from, const char *buffer, size_t length) {
+ for list_each(connection_t, c, &connection_list)
+ if(c != from && c->edge) {
+ send_meta(c, buffer, length);
+ }
+}
+
+bool receive_meta_sptps(void *handle, uint8_t type, const void *vdata, uint16_t length) {
+ const char *data = vdata;
+ connection_t *c = handle;
+
+ if(!c) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "receive_meta_sptps() called with NULL pointer!");
+ abort();
+ }
+
+ if(type == SPTPS_HANDSHAKE) {
+ if(c->allow_request == ACK) {
+ return send_ack(c);
+ } else {
+ return true;
+ }
+ }
+
+ if(!data) {
+ return true;
+ }
+
+ /* Are we receiving a TCPpacket? */
+
+ if(c->tcplen) {
+ if(length != c->tcplen) {
+ return false;
+ }
+
+ receive_tcppacket(c, data, length);
+ c->tcplen = 0;
+ return true;
+ }
+
+ /* Change newline to null byte, just like non-SPTPS requests */