summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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]