diff options
author | David Barksdale <amatus.amongus@gmail.com> | 2010-10-03 00:18:45 -0700 |
---|---|---|
committer | David Barksdale <amatus.amongus@gmail.com> | 2010-10-03 00:18:45 -0700 |
commit | 2d75e9ace5d6741e662b2eb19aab8edd74f5aae0 (patch) | |
tree | ae5bb6b16c01de99094af594982f18b65b48ead9 | |
parent | 6ee3a243f49da5c91711bb39f8cd5c3a7b1105c0 (diff) |
Refactoring and cleaning up. More work on UDP transport.
-rw-r--r-- | src/org/gnu/clojure/gnunet/hello.clj | 56 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/hostlist.clj | 33 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/identity.clj | 9 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/inet.clj | 8 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/iostream.clj | 4 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/message.clj | 2 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/peer.clj | 42 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/tcp.clj | 2 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/transport.clj | 111 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/udp.clj | 25 |
10 files changed, 179 insertions, 113 deletions
diff --git a/src/org/gnu/clojure/gnunet/hello.clj b/src/org/gnu/clojure/gnunet/hello.clj index 3630b23..d25659e 100644 --- a/src/org/gnu/clojure/gnunet/hello.clj +++ b/src/org/gnu/clojure/gnunet/hello.clj @@ -1,7 +1,6 @@ (ns org.gnu.clojure.gnunet.hello - (:use (org.gnu.clojure.gnunet parser message identity crypto) - clojure.contrib.monads) - (:import java.util.Date)) + (:use (org.gnu.clojure.gnunet parser message peer crypto) + clojure.contrib.monads)) (def message-type-hello 16) @@ -9,9 +8,9 @@ [transport] (concat (encode-utf8 (:name transport)) - (encode-int16 (count (:bytes transport))) + (encode-int16 (count (:encoded-address transport))) (encode-date (:expiration transport)) - (:bytes transport))) + (:encoded-address transport))) (def parse-transport (domonad parser-m [name- parse-utf8 @@ -20,16 +19,7 @@ encoded-address (items address-length)] {:name name- :expiration expiration - :bytes encoded-address})) - -(defn list-transports - "Generate a list of transport descriptions." - [transport-map] - (for [transport transport-map - address (val transport)] - {:name (key transport) - :bytes (key address) - :expiration (val address)})) + :encoded-address encoded-address})) (defn encode-hello "Encode a hello message." @@ -37,39 +27,7 @@ (concat (encode-int32 0) (encode-rsa-public-key (:public-key hello)) - (mapcat encode-transport (list-transports (:transports hello))))) - -(defn my-max - "Return the maximum in a collection of comparable values." - [& coll] - (last (sort coll))) - -(defn merge-transports - "Merge a list of transport descriptions into a map of maps of - expiration times, keyed first by transport name and then by - transport address, and then filter by min-expiration" - [min-expiration transport-map transport-list] - (reduce (fn [transport-map transport] - (let [addresses (transport-map - (:name transport) - {(:bytes transport) (:expiration transport)}) - expiration (addresses - (:bytes transport) - (:expiration transport))] - (if (and - (< 0 (compare min-expiration expiration)) - (< 0 (compare min-expiration (:expiration transport)))) - (let [less-addresses (dissoc addresses (:bytes transport))] - (if (empty? less-addresses) - (dissoc transport-map (:name transport)) - (assoc transport-map (:name transport) less-addresses))) - (assoc transport-map - (:name transport) - (assoc addresses - (:bytes transport) - (my-max (:expiration transport) expiration)))))) - transport-map - transport-list)) + (mapcat encode-transport (:transports hello)))) (def parse-hello (domonad parser-m [padding parse-uint32 @@ -77,4 +35,4 @@ public-key parse-rsa-public-key transports (none-or-more parse-transport)] {:public-key public-key - :transports (merge-transports (Date. (long 0)) {} transports)})) + :transports transports})) diff --git a/src/org/gnu/clojure/gnunet/hostlist.clj b/src/org/gnu/clojure/gnunet/hostlist.clj index eab79f3..c7d5d17 100644 --- a/src/org/gnu/clojure/gnunet/hostlist.clj +++ b/src/org/gnu/clojure/gnunet/hostlist.clj @@ -1,39 +1,16 @@ (ns org.gnu.clojure.gnunet.hostlist - (:use (org.gnu.clojure.gnunet parser message hello iostream peer identity)) + (:use (org.gnu.clojure.gnunet parser message hello iostream peer transport)) (:import (java.util Date TimerTask))) +(def parse-hostlist + (none-or-more (parse-message-types {message-type-hello parse-hello}))) + (defn download-hostlist! "Calls hello-processor! on all parsed hello messages at the given URL." [hello-processor! url] - (doseq [{hello :message} (first - ((none-or-more (parse-message-types - {message-type-hello parse-hello})) - (read-url url)))] + (doseq [{hello :message} (first (parse-hostlist (read-url url)))] (hello-processor! hello))) -;; Event - Peer receives a HELLO message -(defn admit-hello! - "Updates the remote-peers map with new information contained in a hello." - [peer hello] - (letfn [(update-transports - [transports new-transports] - (merge-transports (Date.) - transports - (list-transports new-transports))) - (update-remote-peers - [remote-peers hello] - (let [id (vec (generate-id (:public-key hello))) - remote-peer (remote-peers id)] - (if remote-peer - (do - (send - (:transports-agent remote-peer) - update-transports - (:transports hello)) - remote-peers) - (assoc remote-peers id (new-remote-peer-from-hello hello)))))] - (send (:remote-peers-agent peer) update-remote-peers hello))) - (defn create-hostlist-timer-task "Creates a TimerTask that when run fetches the hostlist at url and updates peer." diff --git a/src/org/gnu/clojure/gnunet/identity.clj b/src/org/gnu/clojure/gnunet/identity.clj deleted file mode 100644 index adece97..0000000 --- a/src/org/gnu/clojure/gnunet/identity.clj +++ /dev/null @@ -1,9 +0,0 @@ -(ns org.gnu.clojure.gnunet.identity - (:use (org.gnu.clojure.gnunet crypto message))) - -(defn generate-id - "Generate the SHA-512 digest of the encoded public key." - [public-key] - (sha-512 (encode-rsa-public-key public-key))) - -(def id-size (count (sha-512 ()))) diff --git a/src/org/gnu/clojure/gnunet/inet.clj b/src/org/gnu/clojure/gnunet/inet.clj index 5b48d7b..ff8fa02 100644 --- a/src/org/gnu/clojure/gnunet/inet.clj +++ b/src/org/gnu/clojure/gnunet/inet.clj @@ -1,7 +1,7 @@ (ns org.gnu.clojure.gnunet.inet (:use (org.gnu.clojure.gnunet parser message) clojure.contrib.monads) - (:import (java.net InetAddress InetSocketAddress))) + (:import (java.net InetAddress InetSocketAddress NetworkInterface))) (defn encode-address [inet-socket-address] @@ -23,3 +23,9 @@ (and (not (.isAnyLocalAddress address)) (not (.isMulticastAddress address)))) + +(defn get-local-addresses + [] + (for [interface (enumeration-seq (NetworkInterface/getNetworkInterfaces)) + address (enumeration-seq (.getInetAddresses interface))] + address)) diff --git a/src/org/gnu/clojure/gnunet/iostream.clj b/src/org/gnu/clojure/gnunet/iostream.clj index b4cb066..fdc2fb9 100644 --- a/src/org/gnu/clojure/gnunet/iostream.clj +++ b/src/org/gnu/clojure/gnunet/iostream.clj @@ -4,7 +4,9 @@ (defn reader "Converts a java.io.InputStream into a lazy seq of bytes." [in] - (lazy-seq (let [c (.read in)] (when (>= c 0) (cons (byte c) (reader in)))))) + (lazy-seq + (let [c (.read in)] + (when (>= c 0) (cons (.byteValue c) (reader in)))))) (defn read-url "Open a URL and return a seq of its data." diff --git a/src/org/gnu/clojure/gnunet/message.clj b/src/org/gnu/clojure/gnunet/message.clj index 96c54b8..3266e0a 100644 --- a/src/org/gnu/clojure/gnunet/message.clj +++ b/src/org/gnu/clojure/gnunet/message.clj @@ -16,7 +16,7 @@ (defn encode-int16 "Convert a 16-bit integer to a sequence of bytes in network order." [x] - (list (byte (bit-shift-right x 8)) (byte (bit-and x 0xFF)))) + (list (.byteValue (bit-shift-right x 8)) (.byteValue (bit-and x 0xFF)))) (defn encode-int32 "Convert a 32-bit integer to a sequence of bytes in network order." diff --git a/src/org/gnu/clojure/gnunet/peer.clj b/src/org/gnu/clojure/gnunet/peer.clj index ed67a8d..e9f3b06 100644 --- a/src/org/gnu/clojure/gnunet/peer.clj +++ b/src/org/gnu/clojure/gnunet/peer.clj @@ -1,30 +1,40 @@ (ns org.gnu.clojure.gnunet.peer - (:use (org.gnu.clojure.gnunet identity))) + (:use (org.gnu.clojure.gnunet crypto message))) (defstruct remote-peer - :public-key ;; java.security.PublicKey - :id ;; 64 byte (512-bit) sequence - :transports-agent) ;; agent of a map associating transport names (strings) to - ;; maps associating transport addresses (usually - ;; java.net.InetSocketAddress) to expiration times - ;; (java.util.Date) - -(defn new-remote-peer-from-hello - [hello] - (struct-map remote-peer - :public-key (:public-key hello) - :id (generate-id (:public-key hello)) - :transports-agent (agent (:transports hello)))) + ;; java.security.PublicKey + :public-key + + ;; 64 byte (512-bit) sequence + :id + + ;; agent of a map associating transport names (strings) to maps associating + ;; transport addresses (byte vector) to maps containing {:expiration + ;; (java.util.Date) :latency (int, if ever connected)} + :transports-agent + + ;; agent of ?? + :connection-agent) (def peer (apply create-struct (concat (keys (struct-map remote-peer)) (list - :private-key ;; java.security.PrivateKey - :remote-peers-agent)))) ;; agent of a map of peer IDs to struct remote-peer + ;; java.security.PrivateKey + :private-key + + ;; agent of a map of peer IDs to struct remote-peer + :remote-peers-agent)))) (defstruct peer-options :keypair) +(defn generate-id + "Generate the SHA-512 digest of the encoded public key." + [public-key] + (sha-512 (encode-rsa-public-key public-key))) + +(def id-size (count (sha-512 ()))) + (defn new-peer [options] (struct-map peer :public-key (.getPublic (:keypair options)) diff --git a/src/org/gnu/clojure/gnunet/tcp.clj b/src/org/gnu/clojure/gnunet/tcp.clj index 8d35a20..832072f 100644 --- a/src/org/gnu/clojure/gnunet/tcp.clj +++ b/src/org/gnu/clojure/gnunet/tcp.clj @@ -1,5 +1,5 @@ (ns org.gnu.clojure.gnunet.tcp - (:use (org.gnu.clojure.gnunet identity parser) clojure.contrib.monads)) + (:use (org.gnu.clojure.gnunet peer parser) clojure.contrib.monads)) (def message-type-tcp-welcome 60) diff --git a/src/org/gnu/clojure/gnunet/transport.clj b/src/org/gnu/clojure/gnunet/transport.clj index 6428e74..7baeb67 100644 --- a/src/org/gnu/clojure/gnunet/transport.clj +++ b/src/org/gnu/clojure/gnunet/transport.clj @@ -1,12 +1,108 @@ (ns org.gnu.clojure.gnunet.transport - (:use (org.gnu.clojure.gnunet udp hello)) + (:use (org.gnu.clojure.gnunet parser message hello peer) + clojure.contrib.monads) (:import java.util.Date)) -(def my-transports {"udp" udp-send!}) +(defn my-min + "Return the non-nil minimum in a collection of comparable values." + [& coll] + (first (sort (filter #(not (nil? %)) coll)))) + +(defn my-max + "Return the non-nil maximum in a collection of comparable values." + [& coll] + (last (sort (filter #(not (nil? %)) coll)))) + +(defn list-transports + "Generate a list of transport descriptions." + [transport-map] + (for [transport transport-map + address (val transport)] + (conj + {:name (key transport) :encoded-address (key address)} + (val address)))) + +(defn merge-addresses + "Merge two address-info maps." + [a b] + (let [expiration (my-max (:expiration a) (:expiration b)) + latency (my-min (:latency a) (:latency b))] + (if latency + {:expiration expiration :latency latency} + {:expiration expiration}))) + +(defn merge-transports + "Merge a list of transport descriptions into a transports-agent map. The input + list is generated from parse-hello or list-transports. The input map is + described in peer.clj." + [transport-map transport-list] + (reduce (fn [transport-map transport] + (if-let [addresses (transport-map (:name transport))] + (if-let [address (addresses (:encoded-address transport))] + (assoc transport-map (:name transport) + (assoc addresses (:encoded-address transport) + (merge-addresses address transport))) + (assoc transport-map (:name transport) + (assoc addresses (:encoded-address transport) + (dissoc transport :name :encoded-address)))) + (assoc transport-map (:name transport) + {(:encoded-address transport) + (dissoc transport :name :encoded-address)}))) + transport-map + transport-list)) + +(defn expire-transports + [min-expiration transport-list] + (filter #(>= 0 (compare min-expiration (:expiration %))) transport-list)) + +(defn new-remote-peer-from-hello + [hello] + (struct-map remote-peer + :public-key (:public-key hello) + :id (generate-id (:public-key hello)) + :transports-agent (agent (merge-transports {} (:transports hello))))) + +;; Event - Peer receives a HELLO message +(defn admit-hello! + "Updates the remote-peers map with new information contained in a hello and + expires old addresses." + [peer hello] + (letfn [(update-transports + [transports new-transports] + (merge-transports {} + (expire-transports (Date.) (concat (list-transports transports) + new-transports)))) + (update-remote-peers + [remote-peers hello] + (let [id (vec (generate-id (:public-key hello))) + remote-peer (remote-peers id)] + (if remote-peer + (do + (send + (:transports-agent remote-peer) + update-transports + (:transports hello)) + remote-peers) + (assoc remote-peers id (new-remote-peer-from-hello hello)))))] + (send (:remote-peers-agent peer) update-remote-peers hello))) + +(def message-type-ping 32) + +(defn encode-ping + [ping] + (concat + (encode-int32 (:challenge ping)) + (encode-int (:peer-id ping)))) + +(def parse-ping + (domonad parser-m [challenge parse-uint32 + peer-id (parse-uint id-size)] + {:challenge challenge :peer-id peer-id})) (defn best-transport - [transports] - (let [current-transports (merge-transports (Date.) {} (list-transports + [remote-peer] + (let [transports (deref (:transports-agent remote-peer)) + current-transports (expire-transports (Date.) (list-transports transports)) usable-transports (filter #(contains? my-transports (key %)) current-transports) @@ -16,6 +112,9 @@ (defn send-message! "Sends message to remote-peer." [remote-peer message] - (let [[transport-send! addresses] (best-transport - (deref (:transports-agent remote-peer)))] + (let [[transport-send! addresses] (best-transport remote-peer)] (transport-send! remote-peer addresses message))) + +(defn connect-to-peer! + [remote-peer] + ) diff --git a/src/org/gnu/clojure/gnunet/udp.clj b/src/org/gnu/clojure/gnunet/udp.clj index 20d1755..10d4f9e 100644 --- a/src/org/gnu/clojure/gnunet/udp.clj +++ b/src/org/gnu/clojure/gnunet/udp.clj @@ -1,5 +1,23 @@ (ns org.gnu.clojure.gnunet.udp - (:use org.gnu.clojure.gnunet.inet)) + (:use (org.gnu.clojure.gnunet inet parser message peer transport) + clojure.contrib.monads) + (:import (java.util Date Calendar) java.net.InetSocketAddress)) + +(defn configure-udp-addresses! + "Adds new addresses for the udp transport to peer's transports-agent expiring + in 30 days and removes expired addresses." + [peer addresses port] + (send (:transports-agent peer) + (fn [transports] + (merge-transports {} + (expire-transports (Date.) + (concat (list-transports transports) + (for [address addresses] + {:name "udp" + :encoded-address (encode-address (InetSocketAddress. address + port)) + :expiration (.getTime (doto (Calendar/getInstance) + (.add Calendar/DAY_OF_MONTH 30)))}))))))) (defn pick-address [addresses] @@ -12,3 +30,8 @@ [remote-peer addresses encoded-message] (let [address (pick-address addresses)] )) + +(def parse-udp + (domonad parser-m [peer-id (parse-uint id-size) + messages (none-or-more parse-message)] + {:peer-id peer-id :messages messages})) |