summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Barksdale <amatus.amongus@gmail.com>2010-10-03 00:18:45 -0700
committerDavid Barksdale <amatus.amongus@gmail.com>2010-10-03 00:18:45 -0700
commit2d75e9ace5d6741e662b2eb19aab8edd74f5aae0 (patch)
treeae5bb6b16c01de99094af594982f18b65b48ead9
parent6ee3a243f49da5c91711bb39f8cd5c3a7b1105c0 (diff)
Refactoring and cleaning up. More work on UDP transport.
-rw-r--r--src/org/gnu/clojure/gnunet/hello.clj56
-rw-r--r--src/org/gnu/clojure/gnunet/hostlist.clj33
-rw-r--r--src/org/gnu/clojure/gnunet/identity.clj9
-rw-r--r--src/org/gnu/clojure/gnunet/inet.clj8
-rw-r--r--src/org/gnu/clojure/gnunet/iostream.clj4
-rw-r--r--src/org/gnu/clojure/gnunet/message.clj2
-rw-r--r--src/org/gnu/clojure/gnunet/peer.clj42
-rw-r--r--src/org/gnu/clojure/gnunet/tcp.clj2
-rw-r--r--src/org/gnu/clojure/gnunet/transport.clj111
-rw-r--r--src/org/gnu/clojure/gnunet/udp.clj25
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}))