summaryrefslogtreecommitdiff
path: root/src/org/gnu/clojure/gnunet/peer.clj
blob: 2eac9785c7e7cacbf53047ad51f5e86a5866d812 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
(ns org.gnu.clojure.gnunet.peer
  (:use (org.gnu.clojure.gnunet crypto message util))
  (:import java.nio.channels.Selector
    java.util.concurrent.ConcurrentLinkedQueue
    java.security.SecureRandom))

(defstruct remote-peer-struct
  ;; atom of java.security.PublicKey
  :public-key-atom
  
  ;; 64 byte (512-bit) vector
  :id
  
  ;; agent of a map associating transport names (String) to maps associating
  ;; transport addresses (byte vector) to maps containing {:expiration
  ;; (java.util.Date) :latency (int, if validated)}
  :transport-addresses-agent
  
  ;; agent of a map of state (nil for local peer?)
  ;; { (shared between layers)
  ;;  :is-connected (boolean)
  ;;  :connected-transport (value from peer-struct:transports-agent)
  ;;  :connected-address (byte vector)
  ;;   (core layer)
  ;;  :status peer-status-down (int)
  ;;  :decrypt-key-created (java.util.Date)
  ;;  :encrypt-key (java.security.Key)
  ;;  :encrypt-key-created (java.util.Date)
  ;;  :ping-challenge (int)
  ;;  :bw-in (int)
  ;;   (filesharing layer)
  ;;  :trust (int)
  ;;  :average-priority (float)}
  :state-agent)

(def peer-struct (apply create-struct (concat
  (keys (struct-map remote-peer-struct))
  (list
    ;; java.security.PrivateKey
    :private-key
    
    ;; agent of a map of peer IDs to struct remote-peer
    :remote-peers-agent
    
    ;; agent of a map of transport names (String) to maps of {:emit-message!}
    :transports-agent
    
    ;; agent of a map of message types to sets of dispatch handlers
    :dispatch-agent
    
    ;; java.nio.channels.Selector
    :selector
    
    ;; Thread which selects on :selector
    :selector-thread
    
    ;; java.util.concurrent.ConcurrentLinkedQueue of continuations, in order to
    ;; access the selector while the selector-thread is running add a
    ;; continuation to this queue and call .wakeup on the selector
    :selector-continuations-queue
    
    ;; java.security.SecureRandom
    :random))))

(defstruct peer-options
  :keypair)

(defn generate-id
  "Generate the SHA-512 digest of the encoded public key."
  [public-key]
  (vec (sha-512 (encode-rsa-public-key public-key))))

(def id-size hash-size)

(defn selector-loop!
  [selector continuations]
  (doseq [continuation (queue-seq! continuations)]
    (continuation))
  (.select selector)
  (let [selected-keys (.selectedKeys selector)]
    (doseq [selection-key selected-keys]
      ((.attachment selection-key) selection-key))
    (.clear selected-keys))
  (recur selector continuations))

(defn new-peer [options]
  (let [selector (Selector/open)
        continuations (ConcurrentLinkedQueue.)]
    (struct-map peer-struct
      :public-key-atom (atom (.getPublic (:keypair options)))
      :id (generate-id (.getPublic (:keypair options)))
      :transport-addresses-agent (agent {})
      :private-key (.getPrivate (:keypair options))
      :remote-peers-agent (agent {})
      :transports-agent (agent {})
      :dispatch-agent (agent {})
      :selector selector
      :selector-thread (Thread. (partial selector-loop! selector continuations))
      :selector-continuations-queue continuations
      :random (:random options))))