summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Barksdale <amatus.amongus@gmail.com>2011-08-16 22:12:24 -0500
committerDavid Barksdale <amatus.amongus@gmail.com>2011-08-16 22:12:24 -0500
commit0d5338d650c4bfb2e348a9ba2fc9f96d95338bb4 (patch)
tree5af9a6068cde29a09f42ec1480d6bb28f48631bc /src
parentaf5a8c69b30930198bd91923353cf0119c44e75b (diff)
Some work on the new transport protocol.
Merged hello.clj and transport.clj. Split topology code from transport.clj into topology.clj. Many small changes of minor significance.
Diffstat (limited to 'src')
-rw-r--r--src/main/clojure/org/gnu/clojure/gnunet/core.clj22
-rw-r--r--src/main/clojure/org/gnu/clojure/gnunet/crypto.clj13
-rw-r--r--src/main/clojure/org/gnu/clojure/gnunet/hello.clj38
-rw-r--r--src/main/clojure/org/gnu/clojure/gnunet/hostlist.clj2
-rw-r--r--src/main/clojure/org/gnu/clojure/gnunet/peer.clj5
-rw-r--r--src/main/clojure/org/gnu/clojure/gnunet/topology.clj38
-rw-r--r--src/main/clojure/org/gnu/clojure/gnunet/transport.clj212
-rw-r--r--src/main/clojure/org/gnu/clojure/gnunet/util.clj18
-rw-r--r--src/main/clojure/org/gnu/clojure/gnunetapplet/applet.clj2
9 files changed, 159 insertions, 191 deletions
diff --git a/src/main/clojure/org/gnu/clojure/gnunet/core.clj b/src/main/clojure/org/gnu/clojure/gnunet/core.clj
index b759575..3980dc7 100644
--- a/src/main/clojure/org/gnu/clojure/gnunet/core.clj
+++ b/src/main/clojure/org/gnu/clojure/gnunet/core.clj
@@ -54,31 +54,29 @@
:signature signature}
(:parsed signed))))
+(def iv-context (encode-utf8 "initialization vector"))
(defn derive-iv
[aes-key seed peer-id]
- (derive-aes-iv aes-key
- (encode-int32 seed)
- (concat
- peer-id
- (encode-utf8 "initialization vector"))))
+ (derive-aes-iv aes-key (encode-int32 seed) (concat peer-id iv-context)))
+(def pong-iv-context (encode-utf8 "pong initialization vector"))
(defn derive-pong-iv
[aes-key seed challenge peer-id]
- (derive-aes-iv aes-key
+ (derive-aes-iv
+ aes-key
(encode-int32 seed)
- (concat
- peer-id
- (encode-int32 challenge)
- (encode-utf8 "pong initialization vector"))))
+ (concat peer-id (encode-int32 challenge) pong-iv-context)))
+(def auth-key-context (encode-utf8 "authentication key"))
(defn derive-auth-key
[aes-key seed aes-key-created]
- (derive-hmac-key aes-key
+ (derive-hmac-key
+ aes-key
(encode-int32 seed)
(concat
(.getEncoded aes-key)
(encode-date aes-key-created)
- (encode-utf8 "authentication key"))))
+ auth-key-context)))
(defn encode-core-ping
[ping aes-key iv-seed remote-peer-id]
diff --git a/src/main/clojure/org/gnu/clojure/gnunet/crypto.clj b/src/main/clojure/org/gnu/clojure/gnunet/crypto.clj
index 0d824e3..c5a9108 100644
--- a/src/main/clojure/org/gnu/clojure/gnunet/crypto.clj
+++ b/src/main/clojure/org/gnu/clojure/gnunet/crypto.clj
@@ -138,15 +138,14 @@
(defn encode-aes-key
[aes-key]
- (concat
- (.getEncoded aes-key)
- (encode-int32 (crc32 (.getEncoded aes-key)))))
+ (let [encoded-key (.getEncoded aes-key)]
+ (concat encoded-key (encode-int32 (crc32 encoded-key)))))
(def parse-aes-key
- (domonad parser-m [aes-key (items aes-key-size)
+ (domonad parser-m [encoded-key (items aes-key-size)
checksum parse-uint32
- :when (= checksum (crc32 aes-key))]
- (make-aes-key aes-key)))
+ :when (= checksum (crc32 encoded-key))]
+ (make-aes-key encoded-key)))
(defn generate-aes-key!
[random]
@@ -410,7 +409,7 @@
(with-test
(defn generate-kblock-key
- "Generates an RSA private key of a given bit-length."
+ "Generates an RSA private key of a given bit-length given a seed value."
[bit-length seed]
{:pre [(even? bit-length)]}
(loop [seed seed]
diff --git a/src/main/clojure/org/gnu/clojure/gnunet/hello.clj b/src/main/clojure/org/gnu/clojure/gnunet/hello.clj
deleted file mode 100644
index 6ad2b45..0000000
--- a/src/main/clojure/org/gnu/clojure/gnunet/hello.clj
+++ /dev/null
@@ -1,38 +0,0 @@
-(ns org.gnu.clojure.gnunet.hello
- (:use (org.gnu.clojure.gnunet parser message peer crypto)
- clojure.contrib.monads))
-
-(def message-type-hello 16)
-
-(defn encode-transport-address
- [address]
- (concat
- (encode-utf8 (:transport address))
- (encode-int16 (count (:encoded-address address)))
- (encode-date (:expiration address))
- (:encoded-address address)))
-
-(def parse-transport-address
- (domonad parser-m [transport parse-utf8
- address-length parse-uint16
- expiration parse-date
- encoded-address (items address-length)]
- {:transport transport
- :expiration expiration
- :encoded-address encoded-address}))
-
-(defn encode-hello
- "Encode a hello message."
- [hello]
- (concat
- (encode-int32 0)
- (encode-rsa-public-key (:public-key hello))
- (mapcat encode-transport-address (:transport-addresses hello))))
-
-(def parse-hello
- (domonad parser-m [padding parse-uint32
- :when (== padding 0)
- public-key parse-rsa-public-key
- addresses (none-or-more parse-transport-address)]
- {:public-key public-key
- :transport-addresses addresses}))
diff --git a/src/main/clojure/org/gnu/clojure/gnunet/hostlist.clj b/src/main/clojure/org/gnu/clojure/gnunet/hostlist.clj
index bd154e6..0501b55 100644
--- a/src/main/clojure/org/gnu/clojure/gnunet/hostlist.clj
+++ b/src/main/clojure/org/gnu/clojure/gnunet/hostlist.clj
@@ -1,5 +1,5 @@
(ns org.gnu.clojure.gnunet.hostlist
- (:use (org.gnu.clojure.gnunet parser message hello iostream peer transport))
+ (:use (org.gnu.clojure.gnunet parser message iostream peer transport))
(:import java.util.TimerTask))
(def parse-hostlist
diff --git a/src/main/clojure/org/gnu/clojure/gnunet/peer.clj b/src/main/clojure/org/gnu/clojure/gnunet/peer.clj
index 446aa9a..8f3b645 100644
--- a/src/main/clojure/org/gnu/clojure/gnunet/peer.clj
+++ b/src/main/clojure/org/gnu/clojure/gnunet/peer.clj
@@ -10,7 +10,7 @@
;; atom of java.security.PublicKey
:public-key-atom
- ;; 64 byte (512-bit) vector
+ ;; vector of 64 bytes (512 bits)
:id
;; agent of a map associating transport names (String) to maps associating
@@ -99,9 +99,6 @@
;; java.util.concurrent.ScheduledThreadPoolExecutor
:scheduled-executor))))
-(defstruct peer-options
- :keypair)
-
(defn generate-id
"Generate the SHA-512 digest of the encoded public key."
[public-key]
diff --git a/src/main/clojure/org/gnu/clojure/gnunet/topology.clj b/src/main/clojure/org/gnu/clojure/gnunet/topology.clj
new file mode 100644
index 0000000..96bbff9
--- /dev/null
+++ b/src/main/clojure/org/gnu/clojure/gnunet/topology.clj
@@ -0,0 +1,38 @@
+(ns org.gnu.clojure.gnunet.topology
+ (:use (org.gnu.clojure.gnunet peer transport)))
+
+(defn verify-transport-address!
+ [peer remote-peer address]
+ (second
+ ((domonad exception-m
+ [address (fetch-state)
+ :when-not (or (contains? address :latency)
+ (contains? address :send-time))
+ :when-let [transport ((deref (:transports-agent peer))
+ (:transport address))]
+ :let [challenge (.nextInt (:random peer))]
+ _ (set-state
+ (conj address
+ {:send-time (Date.) ;; TODO: Now is not the actual send time.
+ :challenge challenge}))]
+ ((:emit-messages! transport) transport remote-peer
+ (:encoded-address address) nil
+ [(hello-for-peer-message peer)
+ (ping-message remote-peer address challenge)])) address)))
+
+(defn verify-transport-addresses!
+ [addresses peer remote-peer]
+ (merge-transport-addresses {}
+ (map (partial verify-transport-address! peer remote-peer)
+ (list-transport-addresses addresses))))
+
+(defn verify-remote-peers!
+ [remote-peers peer]
+ (doseq [[_ remote-peer] remote-peers]
+ (send (:transport-addresses-agent remote-peer)
+ verify-transport-addresses! peer remote-peer))
+ remote-peers)
+
+(defn activate-topology!
+ [peer]
+ )
diff --git a/src/main/clojure/org/gnu/clojure/gnunet/transport.clj b/src/main/clojure/org/gnu/clojure/gnunet/transport.clj
index 4f8e38a..642b362 100644
--- a/src/main/clojure/org/gnu/clojure/gnunet/transport.clj
+++ b/src/main/clojure/org/gnu/clojure/gnunet/transport.clj
@@ -1,6 +1,6 @@
(ns org.gnu.clojure.gnunet.transport
- (:use (org.gnu.clojure.gnunet core crypto exception hello message metrics
- parser peer util)
+ (:use (org.gnu.clojure.gnunet core crypto exception message metrics parser
+ peer util)
clojure.contrib.monads)
(:import (java.util Date Calendar)))
@@ -16,20 +16,56 @@
[]
(.getTime (doto (Calendar/getInstance) (.add Calendar/MINUTE 5))))
-(def message-type-ping 32)
-(def message-type-pong 33)
+(def message-type-hello 16)
+(def message-type-transport-ping 32)
+(def message-type-transport-pong 33)
+(def message-type-transport-connect 35)
+(def message-type-transport-disconnect 36)
+(def message-type-transport-keepalive 39)
(def signature-purpose-pong-own 1)
-(def signature-purpose-pong-using 2)
+
+(defn encode-transport-address
+ [address]
+ (concat
+ (encode-utf8 (:transport address))
+ (encode-int16 (count (:encoded-address address)))
+ (encode-date (:expiration address))
+ (:encoded-address address)))
+
+(def parse-transport-address
+ (domonad parser-m [transport parse-utf8
+ address-length parse-uint16
+ expiration parse-date
+ encoded-address (items address-length)]
+ {:transport transport
+ :expiration expiration
+ :encoded-address encoded-address}))
+
+(defn encode-hello
+ "Encode a hello message."
+ [hello]
+ (concat
+ (encode-int32 0)
+ (encode-rsa-public-key (:public-key hello))
+ (mapcat encode-transport-address (:transport-addresses hello))))
+
+(def parse-hello
+ (domonad parser-m [padding parse-uint32
+ :when (== padding 0)
+ public-key parse-rsa-public-key
+ addresses (none-or-more parse-transport-address)]
+ {:public-key public-key
+ :transport-addresses addresses}))
(defn encode-ping
[ping]
(concat
(encode-int32 (:challenge ping))
(:peer-id ping)
- (if-let [transport (:transport ping)]
+ (when-let [transport (:transport ping)]
(concat
- (encode-utf8 (:transport ping))
+ (encode-utf8 transport)
(:encoded-address ping)))))
(def parse-ping
@@ -81,8 +117,7 @@
:transport (String. (byte-array transport) "UTF-8")
:encoded-address encoded-address}))
:let [signature-purpose (:purpose signed)]
- :when (or (== signature-purpose signature-purpose-pong-own)
- (== signature-purpose signature-purpose-pong-using))
+ :when (== signature-purpose signature-purpose-pong-own)
residue (optional item)
:when (nil? residue)]
(conj {:challenge challenge
@@ -92,7 +127,7 @@
(:parsed signed))))
(defn list-transport-addresses
- "Generate a list of transport descriptions."
+ "Generate a list of transport addresses."
[addresses-map]
(for [transport addresses-map
address (val transport)]
@@ -106,23 +141,17 @@
(conj a b {:expiration (my-max (:expiration a) (:expiration b))}))
(defn merge-transport-addresses
- "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
+ "Merge a list of transport addresses into a transports-agent map. The input
+ list is generated from parse-hello or list-transport-addresses. The map is
described in peer.clj."
[address-map address-list]
- (reduce (fn [address-map new-address]
- (if-let [transport (address-map (:transport new-address))]
- (if-let [address-info (transport (:encoded-address new-address))]
- (assoc address-map (:transport new-address)
- (assoc transport (:encoded-address new-address)
- (merge-address-info address-info
- (dissoc new-address :transport :encoded-address))))
- (assoc address-map (:transport new-address)
- (assoc transport (:encoded-address new-address)
- (dissoc new-address :transport :encoded-address))))
- (assoc address-map (:transport new-address)
- {(:encoded-address new-address)
- (dissoc new-address :transport :encoded-address)})))
+ (reduce
+ (fn [address-map new-address]
+ (assoc-deep
+ address-map
+ (dissoc new-address :transport :encoded-address)
+ (:transport new-address)
+ (:encoded-address new-address)))
address-map
address-list))
@@ -141,7 +170,7 @@
(defn ping-message
[remote-peer address challenge]
- {:message-type message-type-ping
+ {:message-type message-type-transport-ping
:bytes (encode-ping {:challenge challenge
:peer-id (:id remote-peer)
:transport (:transport address)
@@ -155,65 +184,30 @@
(defn update-remote-peers!
[remote-peers peer-id hello]
- (let [remote-peer (remote-peers peer-id)]
- (if remote-peer
- (do
- (if (:public-key hello)
- (swap! (:public-key-atom remote-peer)
- #(if (nil? %) (:public-key hello))))
- (send (:transport-addresses-agent remote-peer)
- update-transport-addresses
- (:transport-addresses hello))
- remote-peers)
- (assoc remote-peers peer-id
- (struct-map remote-peer-struct
- :public-key-atom (atom (:public-key hello))
- :id peer-id
- :transport-addresses-agent (agent
- (merge-transport-addresses {}
- (:transport-addresses hello)))
- :state-agent (agent {:is-connected false}))))))
-
-(defn verify-transport-address!
- [peer remote-peer address]
- (second
- ((domonad exception-m
- [address (fetch-state)
- :when (not (or (contains? address :latency)
- (contains? address :send-time)))
- :when-let [transport ((deref (:transports-agent peer))
- (:transport address))]
- :let [challenge (.nextInt (:random peer))]
- _ (set-state
- (conj address
- {:send-time (Date.) ;; TODO: Now is not the actual send time.
- :challenge challenge}))]
- ((:emit-messages! transport) transport remote-peer
- (:encoded-address address) nil
- [(hello-for-peer-message peer)
- (ping-message remote-peer address challenge)])) address)))
-
-(defn verify-transport-addresses!
- [addresses peer remote-peer]
- (merge-transport-addresses {}
- (map (partial verify-transport-address! peer remote-peer)
- (list-transport-addresses addresses))))
-
-(defn verify-remote-peers!
- [remote-peers peer]
- (doseq [[_ remote-peer] remote-peers]
- (send (:transport-addresses-agent remote-peer)
- verify-transport-addresses! peer remote-peer))
- remote-peers)
+ (if-let [remote-peer (remote-peers peer-id)]
+ (do
+ (if (:public-key hello)
+ (swap! (:public-key-atom remote-peer)
+ #(if (nil? %) (:public-key hello))))
+ (send (:transport-addresses-agent remote-peer)
+ update-transport-addresses
+ (:transport-addresses hello))
+ remote-peers)
+ (assoc remote-peers peer-id
+ (struct-map remote-peer-struct
+ :public-key-atom (atom (:public-key hello))
+ :id peer-id
+ :transport-addresses-agent (agent
+ (merge-transport-addresses {}
+ (:transport-addresses hello)))
+ :state-agent (agent {:is-connected false})))))
(defn admit-hello!
"Updates peer:remote-peers-agent with new information contained in hello."
[peer hello]
(let [peer-id (generate-id (:public-key hello))]
- (if (not (= peer-id (:id peer)))
- (let [remote-peers-agent (:remote-peers-agent peer)]
- (send remote-peers-agent update-remote-peers! peer-id hello)
- (send remote-peers-agent verify-remote-peers! peer)))))
+ (when-not (= peer-id (:id peer))
+ (send (:remote-peers-agent peer) update-remote-peers! peer-id hello))))
(defn handle-hello!
[peer message]
@@ -244,56 +238,29 @@
(if (:is-connected state)
(let [transport (:connected-transport state)
encoded-address (:connected-address state)]
- ((:emit-messages! transport) transport remote-peer encoded-address
- nil [{:message-type message-type-pong :bytes encoded-pong}]))
+ ((:emit-messages! transport)
+ transport remote-peer encoded-address nil
+ [{:message-type message-type-transport-pong
+ :bytes encoded-pong}]))
(doseq [transports (deref (:transport-addresses-agent remote-peer))
address (val transports)]
(when-let [transport ((deref (:transports-agent peer))
(key transports))]
- ((:emit-messages! transport) transport remote-peer (key address)
- nil
- [{:message-type message-type-pong :bytes encoded-pong}]))))))))
-
-(defn send-pong-using!
- [peer remote-peer address ping]
- (.execute (:cpu-bound-executor peer)
- (fn []
- (let
- [state (deref (:state-agent remote-peer))
- pong {:challenge (:challenge ping)
- :signature-purpose signature-purpose-pong-using
- :expiration (pong-expiration)
- :peer-id (:id remote-peer)
- :transport (:transport address)
- :encoded-address (:encoded-address address)}
- signed-material (encode-pong-signed-material pong)
- signature (rsa-sign (:private-key peer) signed-material)
- pong (assoc pong :signature signature)
- encoded-pong (encode-pong pong signed-material)
- state (deref (:state-agent remote-peer))]
- (if (:is-connected state)
- (let [transport (:connected-transport state)
- encoded-address (:connected-address state)]
- ((:emit-messages! transport) transport remote-peer encoded-address
- nil [{:message-type message-type-pong :bytes encoded-pong}]))
- (doseq [transports (deref (:transport-addresses-agent remote-peer))
- address (val transports)]
- (when-let [transport ((deref (:transports-agent peer))
- (key transports))]
- ((:emit-messages! transport) transport remote-peer (key address)
- nil
- [{:message-type message-type-pong :bytes encoded-pong}]))))))))
+ ((:emit-messages! transport)
+ transport remote-peer (key address) nil
+ [{:message-type message-type-transport-pong
+ :bytes encoded-pong}]))))))))
(defn handle-ping!
[peer remote-peer address message]
(when-let [ping (first (parse-ping (:bytes message)))]
(cond
(not (= (:peer-id ping) (:id peer))) nil
- (:transport ping) (send-pong-own! peer remote-peer ping)
- :else (send-pong-using! peer remote-peer address ping))))
+ (:transport ping) (send-pong-own! peer remote-peer ping))))
(defn handle-pong-own!
[peer remote-peer pong]
+ ;; TODO - test that the challenge matches before wasting time with RSA
(.execute (:cpu-bound-executor peer)
(fn []
(domonad maybe-m
@@ -311,11 +278,6 @@
(.getTime (:send-time address)))}))]
(metric-add! peer "Peer addresses considered valid" 1))))))
-(defn handle-pong-using!
- [peer remote-peer pong]
- ;; TODO - fill in this case
- (.write *out* "We don't handle PONG_USING yet!\n"))
-
(defn handle-pong!
[peer message]
(domonad maybe-m
@@ -324,7 +286,6 @@
remote-peer ((deref (:remote-peers-agent peer)) (:peer-id pong))]
(condp == (:signature-purpose pong)
signature-purpose-pong-own (handle-pong-own! peer remote-peer pong)
- signature-purpose-pong-using (handle-pong-using! peer remote-peer pong)
nil)))
(defn emit-callback!
@@ -350,7 +311,8 @@
remote-peer (remote-peers sender-id)]
(condp = (:message-type message)
message-type-hello (handle-hello! peer message)
- message-type-ping (handle-ping! peer remote-peer address message)
- message-type-pong (handle-pong! peer message)
+ message-type-transport-ping (handle-ping!
+ peer remote-peer address message)
+ message-type-transport-pong (handle-pong! peer message)
(handle-receive! peer remote-peer message))
remote-peers))))
diff --git a/src/main/clojure/org/gnu/clojure/gnunet/util.clj b/src/main/clojure/org/gnu/clojure/gnunet/util.clj
index ea813e3..34fe34d 100644
--- a/src/main/clojure/org/gnu/clojure/gnunet/util.clj
+++ b/src/main/clojure/org/gnu/clojure/gnunet/util.clj
@@ -9,22 +9,34 @@
(list* `assert-args fnname more)))))
(defn queue-seq!
- "Consume a queue and present it as a sequence."
+ "Returns a lazy seq that consumes a
+ java.util.concurrent.ConcurrentLinkedQueue."
[queue]
(lazy-seq (when-let [c (.poll queue)] (cons c (queue-seq! queue)))))
(defn buffer-seq!
+ "Returns a lazy seq that consumes a subclass of java.nio.Buffer."
[buffer]
(lazy-seq (when (.hasRemaining buffer)
(cons (.get buffer) (buffer-seq! buffer)))))
(defn my-max
- "Return the maximum in a collection of comparable values."
+ "Returns the maximum in a collection of comparable values."
[& coll]
(last (sort coll)))
(defn available-processors
+ "Returns the number of processors available to this Java runtime."
[]
(.availableProcessors (Runtime/getRuntime)))
-(defn skip [& _])
+(defn skip
+ "Takes any number of arguments and returns nil."
+ [& _])
+
+(defn assoc-deep
+ "Associates val with the 'path' of keys in a nested map."
+ [map val key & keys]
+ (if (nil? keys)
+ (assoc map key val)
+ (assoc map key (apply assoc-deep (map key) val keys))))
diff --git a/src/main/clojure/org/gnu/clojure/gnunetapplet/applet.clj b/src/main/clojure/org/gnu/clojure/gnunetapplet/applet.clj
index 52c3c0d..12f825b 100644
--- a/src/main/clojure/org/gnu/clojure/gnunetapplet/applet.clj
+++ b/src/main/clojure/org/gnu/clojure/gnunetapplet/applet.clj
@@ -169,7 +169,7 @@
[(encode-ascii-hash (:id peer))
(merge-transport-addresses {}
(for [address (list-transport-addresses new-state)]
- (dissoc address :expiration :send-time :challenge)))]}))))
+ (dissoc address :send-time :challenge)))]}))))
(defn remote-peers-watcher
[applet f watched-agent old-state new-state]