aboutsummaryrefslogtreecommitdiff
path: root/src/cljs/gnunet_web/hello.cljs
blob: feded4567640b09f5c0dcd6c676445913066c238 (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
101
102
103
104
105
106
107
108
109
110
111
112
113
;; hello.cljs - HELLO parser for gnunet-web website
;; Copyright (C) 2013,2014  David Barksdale <amatus@amatus.name>
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

(ns gnunet-web.hello
  (:require [amatus.datastructures :refer [flatten-nested-maps nested-group-by]]
            [clojure.set :refer [difference union]]
            [gnunet-web.encoder :refer [encode-absolute-time encode-uint16
                                        encode-uint32 encode-utf8]]
            [gnunet-web.message :refer [encode-message parse-peer-identity]]
            [gnunet-web.parser :refer [items none-or-more parser
                                       parse-absolute-time parse-uint16
                                       parse-uint32 parse-utf8]])
  (:require-macros [monads.macros :as monadic]))

(def message-type-hello 17)

(def parse-transport-address
  (monadic/do parser
              [transport parse-utf8
               address-length parse-uint16
               expiration parse-absolute-time
               encoded-address (items address-length)]
              {:transport transport
               :expiration expiration
               :encoded-address (vec (.apply js/Array nil encoded-address))}))

(defn encode-transport-address
  [{transport :transport
    expiration :expiration
    encoded-address :encoded-address}]
  (concat
    (encode-utf8 transport)
    (encode-uint16 (count encoded-address))
    (encode-absolute-time expiration)
    encoded-address))

(defn latest-expiration
  [transport-addresses]
  [(first (reverse (sort (map :expiration transport-addresses))))])

(defn transport-addresses-map
  [transport-addresses-list]
  (nested-group-by [:transport :encoded-address]
                   latest-expiration
                   transport-addresses-list))

(defn flatten-transport-addresses
  [transport-addresses-nested-map]
  (flatten-nested-maps transport-addresses-nested-map
                       [:transport :encoded-address :expiration]))

(def parse-hello
  (with-meta
    (monadic/do parser
                [friend-only parse-uint32
                 public-key parse-peer-identity
                 addresses (none-or-more parse-transport-address)]
                {:friend-only (not (zero? friend-only))
                 :public-key public-key
                 :transport-addresses (transport-addresses-map addresses)})
    {:message-type message-type-hello}))

(defn encode-hello
  [{friend-only :friend-only
    public-key :public-key
    transport-addresses :transport-addresses}]
  (encode-message
    {:message-type message-type-hello
     :message
     (concat
       (encode-uint32 (if friend-only 1 0))
       public-key
       (mapcat encode-transport-address
               (flatten-transport-addresses transport-addresses)))}))

(defn merge-hello
  [a b]
  {:public-key (:public-key a)
   :friend-only (or (:friend-only a) (:friend-only b))
   :transport-addresses
   (transport-addresses-map
     (concat
       (flatten-transport-addresses (:transport-addresses a))
       (flatten-transport-addresses (:transport-addresses b))))})

(defn equals-hello
  [a b expiration]
  (when (= (:public-key a) (:public-key b))
    (let [as (set (filter
                    #(>= (:expiration %) expiration)
                    (flatten-transport-addresses (:transport-addresses a))))
          bs (set (filter
                    #(>= (:expiration %) expiration)
                    (flatten-transport-addresses (:transport-addresses b))))]
      (if (empty? (union (difference as bs) (difference bs as)))
        :equal
        (let [eas (set (map #(dissoc % :expiration) as))
              ebs (set (map #(dissoc % :expiration) bs))]
          (when (empty? (union (difference eas ebs) (difference ebs eas)))
            (:expiration (first (sort-by :expiration (union as bs))))))))))