--- /dev/null
+/* Module for (ab)using DNS as a transport */
+
+/* This provides two new kinds of closure, both of type comm.
+ * dns-transport-server
+ * which takes an underlying udp comm
+ * and which never supports lookup by address
+ * dns-transport-client
+ */
+
+
+/*
+ * Query format: create assoc:
+ * 1 bit set this a create assoc query
+ * 32 bits clientnonce
+ * 10 bits offset of this data fragment in packet
+ * 1 bit is this the last fragment ?
+ * remainder data packet fragment
+ * data packet sequence number is always implicitly zero
+ *
+ * Query format: submit:
+ * 1 bit clear this is not a create assoc query
+ * 32 bits associd
+ * 16 bits data packet sequence number
+ * 10 bits offset of this data fragment in packet
+ * 1 bit is this the last fragment
+ * remainder data packet fragment
+ *
+ * Query format: fetch:
+ * 1 bit clear this is not a create assoc query
+ * 32 bits associd
+ * 16 bits client query distinguishper (for defeating dns cache)
+ *
+ * Response format:
+ * [ 32 bits associd - only for responses to create assoc ]
+ * 4 bits log_2( number of bytes of outstanding data on server)
+ * 10 bits offset of this data fragment in packet
+ * 1 bit is this the last fragment ?
+ * remainder data packet fragment
+ */
+
+/*
+ * Query bitstring, from above, is encoded as follows:
+ * 1.
+ * . append our server's domain
+
+struct expires {
+ struct expires *next;
+ struct timeval expires;
+};
+
+struct dedupe {
+ uint8_t *qsubdomhash; /* of length dns_server->hash->len */
+ struct expires expires;
+ int responselen; /* -1 if we are holding this query */
+ uint8_t *response; /* 0 if we are holding this query */
+};
+
+struct holding {
+ struct holding *next, *back;
+ struct expires expires;
+ int qsubdomlen; /* in octets */
+ uint8_t *qsubdom; /* in dns format ready for packet */
+ struct dedupe *dedupe;
+};
+
+struct assoc {
+ uint32_t associd;
+ struct expires expires; /* clock is running once the clientinit expires */
+ /* table of incoming partial messages */
+ int incoming_used, incoming_allocd;
+ uint32_t incoming_firstseq;
+ struct incomingmsg *incoming;
+ /* table of outgoing messages */
+ int outgoing_used, outgoing_allocd;
+ uint32_t outgoingmsg *outgoing;
+ /* dedupe table */
+ HASHTABLE(struct dedupe) dedupe;
+ /* holding responses */
+ SLIST(struct holding) holding;
+};
+
+struct clientinit {
+ struct sockaddr_in clientaddr;
+ uint32_t clientnonce;
+ struct expires expires;
+ struct assoc *assoc;
+};
+
+struct dns_server {
+ closure_t cl;
+ struct comm_if ops;
+ struct comm_if *port;
+ struct hash_if *hash; /* used for dedupe */
+ HASHTABLE(struct clientinit) clientinits;
+ HASHTABLE(struct assoc) assocs;
+};
+
+/*
+ * Incoming packet
+ *
+ * 1. decode dns packet, check it is for us, etc.
+ * 2. hash qsubdom
+ * 3. check qsubdomhash in dedupe
+ * if found, send response (or discard, if we are holding), done.
+ * 4a. create assoc packet
+ * look up {clientaddr,clientnonce} in clientinit
+ * if not then create an assoc
+ *