feature #1805 refactored protocol listeners

This commit is contained in:
Goran Jovic 2017-09-11 17:49:42 +02:00 committed by Roman Volosovskyi
parent debd51bfce
commit eac7e06f40
1 changed files with 80 additions and 59 deletions

View File

@ -6,70 +6,91 @@
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.utils.hex :as i])) [status-im.utils.hex :as i]))
(defn create-error [description] (defn empty-public-key? [public-key]
(log/debug :parse-payload-error description) (or (= "0x0" public-key)
(= "" public-key)
(nil? public-key)))
(defn create-error [step description]
(when (not= description :silent)
(log/debug step description))
{:error description}) {:error description})
(defn- parse-payload [payload] (defn init-scope [js-error js-message options]
(if js-error
(create-error :init-scope-error (-> js-error js->clj str))
{:message (js->clj js-message :keywordize-keys true)
:options options}))
(defn parse-payload [{:keys [message error options] :as scope}]
(log/debug :parse-payload) (log/debug :parse-payload)
(try (if error
;; todo figure why we have to call to-utf8 twice scope
(let [payload' (u/to-utf8 payload) (try
payload'' (r/read-string payload') ;; todo figure why we sometimes have to call to-utf8 twice and sometimes only once
payload''' (if (map? payload'') (let [payload (:payload message)
payload'' payload' (u/to-utf8 payload)
(r/read-string (u/to-utf8 payload')))] payload'' (r/read-string payload')
(if (map? payload''') payload''' (if (map? payload'')
{:payload payload'''} payload''
(create-error (str "Invalid payload type " (type payload'''))))) (r/read-string (u/to-utf8 payload')))]
(catch :default err (if (map? payload''')
(create-error err)))) {:message (assoc message :payload payload''')
:options options}
(create-error :parse-payload-error (str "Invalid payload type " (type payload''')))))
(catch :default err
(create-error :parse-payload-error err)))))
(defn- decrypt [key content] (defn filter-messages-from-same-user [{:keys [message error options] :as scope}]
(try (if error
{:content (r/read-string (e/decrypt key content))} scope
(catch :default err (if (or (not= (i/normalize-hex (:identity options))
(log/debug :decrypt-error err) (i/normalize-hex (:sig message)))
{:error err}))) ;; allow user to receive his own discoveries
(= type :discover))
scope
(create-error :filter-messages-error :silent))))
(defn- parse-content [key {:keys [content]} was-encrypted?] (defn parse-content [{:keys [message error options] :as scope}]
(log/debug :parse-content (if error
"Key exists:" (not (nil? key)) scope
"Content exists:" (not (nil? content))) (try
(if (and (not was-encrypted?) key content) (let [to (:recipientPublicKey message)
(decrypt key content) from (:sig message)
{:content content})) key (get-in options [:keypair :private])
raw-content (get-in message [:payload :content])
encrypted? (and (empty-public-key? to) key raw-content)
content (if encrypted?
(r/read-string (e/decrypt key raw-content))
raw-content)]
(log/debug :parse-content
"Key exists:" (not (nil? key))
"Content exists:" (not (nil? raw-content)))
{:message (-> message
(assoc-in [:payload :content] content)
(assoc :to to
:from from))
:options options})
(catch :default err
(create-error :parse-content-error err)))))
(defn handle-message [{:keys [message error options] :as scope}]
(if error
scope
(let [{:keys [web3 identity callback]} options
{:keys [payload sig]} message
ack? (get-in message [:payload :ack?])]
(log/debug :handle-message message)
(callback (if ack? :ack (:type payload)) message)
(ack/check-ack! web3 sig payload identity))))
(defn message-listener (defn message-listener
[{:keys [web3 identity callback keypair]}] "Valid options are: web3, identity, callback, keypair"
(fn [error js-message] [options]
;; todo handle error (fn [js-error js-message]
(when error (-> (init-scope js-error js-message options)
(log/debug :listener-error error)) parse-payload
(when-not error filter-messages-from-same-user
(log/debug :message-received (js->clj js-message)) parse-content
(let [{:keys [sig payload recipientPublicKey] :as message} handle-message)))
(js->clj js-message :keywordize-keys true)
{{:keys [type ack?] :as payload'} :payload
payload-error :error}
(parse-payload payload)]
(when (and (not payload-error)
(or (not= (i/normalize-hex identity)
(i/normalize-hex sig))
;; allow user to receive his own discoveries
(= type :discover)))
(let [{:keys [content error]} (parse-content (:private keypair)
payload'
(and (not= "0x0" recipientPublicKey)
(not= "" recipientPublicKey)
(not (nil? recipientPublicKey))))]
(if error
(log/debug :failed-to-handle-message error)
(let [payload'' (assoc payload' :content content)
message' (assoc message :payload payload''
:to recipientPublicKey
:from sig)]
(callback (if ack? :ack type) message')
(ack/check-ack! web3 sig payload'' identity)))))))))