+static void buffer_exit(struct buffer *buf) {
+ free(buf->data);
+ memset(buf, 0, sizeof *buf);
+}
+
+static uint32_t buffer_free(const struct buffer *buf) {
+ return buf->maxsize - buf->used;
+}
+
+// Connections are stored in a sorted list.
+// This gives O(log(N)) lookup time, O(N log(N)) insertion time and O(N) deletion time.
+
+static int compare(const void *va, const void *vb) {
+ assert(va && vb);
+
+ const struct utcp_connection *a = *(struct utcp_connection **)va;
+ const struct utcp_connection *b = *(struct utcp_connection **)vb;
+
+ assert(a && b);
+ assert(a->src && b->src);
+
+ int c = (int)a->src - (int)b->src;
+ if(c)
+ return c;
+ c = (int)a->dst - (int)b->dst;
+ return c;
+}
+
+static struct utcp_connection *find_connection(const struct utcp *utcp, uint16_t src, uint16_t dst) {
+ if(!utcp->nconnections)
+ return NULL;
+ struct utcp_connection key = {
+ .src = src,
+ .dst = dst,
+ }, *keyp = &key;
+ struct utcp_connection **match = bsearch(&keyp, utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
+ return match ? *match : NULL;
+}
+
+static void free_connection(struct utcp_connection *c) {
+ struct utcp *utcp = c->utcp;
+ struct utcp_connection **cp = bsearch(&c, utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
+
+ assert(cp);
+
+ int i = cp - utcp->connections;
+ memmove(cp, cp + 1, (utcp->nconnections - i - 1) * sizeof *cp);
+ utcp->nconnections--;
+
+ buffer_exit(&c->sndbuf);
+ free(c);
+}
+
+static struct utcp_connection *allocate_connection(struct utcp *utcp, uint16_t src, uint16_t dst) {
+ // Check whether this combination of src and dst is free
+
+ if(src) {
+ if(find_connection(utcp, src, dst)) {
+ errno = EADDRINUSE;
+ return NULL;
+ }
+ } else { // If src == 0, generate a random port number with the high bit set
+ if(utcp->nconnections >= 32767) {