2019-06-29 01:27:59 +03:00
:: Ames extends Arvo's %pass/%give move semantics across the network.
::
2019-12-21 09:56:51 +03:00
:: Ames receives packets as Arvo events and emits packets as Arvo
:: effects. The runtime is responsible for transferring the bytes in
:: an Ames packet across a physical network to another ship.
::
:: The runtime tells Ames which physical address a packet came from,
:: represented as an opaque atom. Ames can emit a packet effect to
:: one of those opaque atoms or to the Urbit address of a galaxy
:: (root node), which the runtime is responsible for translating to a
:: physical address. One runtime implementation sends UDP packets
:: using IPv4 addresses for ships and DNS lookups for galaxies, but
:: other implementations may overlay over other kinds of networks.
::
:: A local vane can pass Ames a %plea request message. Ames
:: transmits the message over the wire to the peer ship's Ames, which
:: passes the message to the destination vane.
::
:: Once the peer has processed the %plea message, it sends a
:: message-acknowledgment packet over the wire back to the local
:: Ames. This ack can either be positive to indicate the request was
:: processed, or negative to indicate the request failed, in which
:: case it's called a "nack". (Don't confuse Ames nacks with TCP
:: nacks, which are a different concept).
::
:: When the local Ames receives either a positive message-ack or a
:: combination of a nack and naxplanation (explained in more detail
2019-06-29 01:27:59 +03:00
:: below), it gives an %done move to the local vane that had
2019-12-21 09:56:51 +03:00
:: requested the original %plea message be sent.
::
:: A local vane can give Ames zero or more %boon response messages in
:: response to a %plea, on the same duct that Ames used to pass the
:: %plea to the vane. Ames transmits a %boon over the wire to the
:: peer's Ames, which gives it to the destination vane on the same
:: duct the vane had used to pass the original %plea to Ames.
::
:: %boon messages are acked automatically by the receiver Ames. They
:: cannot be nacked, and Ames only uses the ack internally, without
:: notifying the client vane that gave Ames the %boon.
::
:: If the Arvo event that completed receipt of a %boon message
:: crashes, Ames instead sends the client vane a %lost message
:: indicating the %boon was missed.
::
:: %plea messages can be nacked, in which case the peer will send
:: both a message-nack packet and a naxplanation message, which is
:: sent in a way that does not interfere with normal operation. The
:: naxplanation is sent as a full Ames message, instead of just a
:: packet, because the contained error information can be arbitrarily
:: large. A naxplanation can only give rise to a positive ack --
:: never ack an ack, and never nack a naxplanation.
::
:: Ames guarantees a total ordering of messages within a "flow",
:: identified in other vanes by a duct and over the wire by a "bone":
:: an opaque number. Each flow has a FIFO queue of %plea requests
:: from the requesting ship to the responding ship and a FIFO queue
:: of %boon's in the other direction.
::
:: Message order across flows is not specified and may vary based on
:: network conditions.
::
:: Ames guarantees that a message will only be delivered once to the
:: destination vane.
::
:: Ames encrypts every message using symmetric-key encryption by
:: performing an elliptic curve Diffie-Hellman using our private key
:: and the public key of the peer. For ships in the Jael PKI
:: (public-key infrastructure), Ames looks up the peer's public key
:: from Jael. Comets (128-bit ephemeral addresses) are not
:: cryptographic assets and must self-attest over Ames by sending a
:: single self-signed packet containing their public key.
::
:: When a peer suffers a continuity breach, Ames removes all
:: messaging state related to it. Ames does not guarantee that all
:: messages will be fully delivered to the now-stale peer. From
:: Ames's perspective, the newly restarted peer is a new ship.
:: Ames's guarantees are not maintained across a breach.
::
:: A vane can pass Ames a %heed $task to request Ames track a peer's
:: responsiveness. If our %boon's to it start backing up locally,
:: Ames will give a %clog back to the requesting vane containing the
:: unresponsive peer's urbit address. This interaction does not use
:: ducts as unique keys. Stop tracking a peer by sending Ames a
:: %jilt $task.
::
:: Debug output can be adjusted using %sift and %spew $task's.
2019-06-29 01:27:59 +03:00
::
2022-01-27 16:32:49 +03:00
::TODO fine
:: - receiving packets: +on-hear (1st) -> +on-hear-packet -> %fine
:: - sending packets: +on-plea -> +make-peer-core (make a function kind of like +on-memo) -> call +on-pump-send kind of like how +run-message-pump does
:: (assuming as event, scry just stateless)
::
2019-06-29 02:43:52 +03:00
!:
=, ames
2020-12-08 03:47:06 +03:00
=* point point:jael
=* public-keys-result public-keys-result:jael
2019-12-03 02:46:40 +03:00
:: veb: verbosity flags
::
=/ veb-all-off
:* snd=`?`%.n :: sending packets
rcv=`?`%.n :: receiving packets
odd=`?`%.n :: unusual events
2019-12-11 21:55:16 +03:00
msg=`?`%.n :: message-level events
2019-12-03 02:46:40 +03:00
ges=`?`%.n :: congestion control
2019-12-11 21:55:16 +03:00
for=`?`%.n :: packet forwarding
2019-12-03 02:46:40 +03:00
rot=`?`%.n :: routing attempts
2019-11-15 03:10:48 +03:00
==
2019-12-03 02:46:40 +03:00
=>
2020-12-05 07:32:17 +03:00
~% %ames ..part ~
2019-11-15 03:10:48 +03:00
|%
2020-12-01 17:51:14 +03:00
+| %helpers
2019-12-11 21:55:16 +03:00
:: +trace: print if .verb is set and we're tracking .ship
2019-12-03 02:46:40 +03:00
::
2019-11-15 03:10:48 +03:00
++ trace
2019-12-11 21:55:16 +03:00
|= [verb=? =ship ships=(set ship) print=(trap tape)]
^+ same
2019-11-15 03:10:48 +03:00
?. verb
same
2019-12-11 21:55:16 +03:00
?. => [ship=ship ships=ships in=in]
~+ |(=(~ ships) (~(has in ships) ship))
same
(slog leaf/"ames: {(scow %p ship)}: {(print)}" ~)
2020-12-01 17:51:14 +03:00
:: +qos-update-text: notice text for if connection state changes
::
++ qos-update-text
|= [=ship old=qos new=qos]
^- (unit tape)
::
?+ [-.old -.new] ~
[%unborn %live] `"; {(scow %p ship)} is your neighbor"
[%dead %live] `"; {(scow %p ship)} is ok"
[%live %dead] `"; {(scow %p ship)} not responding still trying"
[%unborn %dead] `"; {(scow %p ship)} not responding still trying"
[%live %unborn] `"; {(scow %p ship)} has sunk"
[%dead %unborn] `"; {(scow %p ship)} has sunk"
==
:: +lte-packets: yes if a is before b
::
++ lte-packets
|= [a=live-packet-key b=live-packet-key]
^- ?
::
?: (lth message-num.a message-num.b)
%.y
?: (gth message-num.a message-num.b)
%.n
(lte fragment-num.a fragment-num.b)
:: +split-message: split message into kilobyte-sized fragments
::
:: We don't literally split it here since that would allocate many
:: large atoms with no structural sharing. Instead, each
:: static-fragment has the entire message and a counter. In
:: +encrypt, we interpret this to get the actual fragment.
::
++ split-message
~/ %split-message
|= [=message-num =message-blob]
^- (list static-fragment)
::
=/ num-fragments=fragment-num (met 13 message-blob)
=| counter=@
::
|- ^- (list static-fragment)
?: (gte counter num-fragments)
~
::
:- [message-num num-fragments counter `@`message-blob]
$(counter +(counter))
:: +assemble-fragments: concatenate fragments into a $message
::
++ assemble-fragments
~/ %assemble-fragments
|= [num-fragments=fragment-num fragments=(map fragment-num fragment)]
^- *
::
=| sorted=(list fragment)
=. sorted
=/ index=fragment-num 0
|- ^+ sorted
?: =(index num-fragments)
sorted
$(index +(index), sorted [(~(got by fragments) index) sorted])
::
2020-12-04 01:26:55 +03:00
(cue (rep 13 (flop sorted)))
2021-01-20 23:29:45 +03:00
:: +jim: caching +jam
::
++ jim |=(n=* ~+((jam n)))
2020-12-01 17:51:14 +03:00
:: +bind-duct: find or make new $bone for .duct in .ossuary
::
++ bind-duct
|= [=ossuary =duct]
^+ [next-bone.ossuary ossuary]
::
?^ existing=(~(get by by-duct.ossuary) duct)
[u.existing ossuary]
::
:- next-bone.ossuary
:+ (add 4 next-bone.ossuary)
(~(put by by-duct.ossuary) duct next-bone.ossuary)
(~(put by by-bone.ossuary) next-bone.ossuary duct)
2022-02-22 18:04:42 +03:00
:: +make-bone-wire: encode ship, rift and bone in wire for sending to vane
2020-12-01 17:51:14 +03:00
::
++ make-bone-wire
2022-02-22 18:04:42 +03:00
|= [her=ship =rift =bone]
2020-12-01 17:51:14 +03:00
^- wire
::
2022-02-22 18:04:42 +03:00
/bone/(scot %p her)/(scot %ud rift)/(scot %ud bone)
:: +parse-bone-wire: decode ship, bone and rift from wire from local vane
2020-12-01 17:51:14 +03:00
::
++ parse-bone-wire
|= =wire
2022-02-22 18:04:42 +03:00
^- %- unit
2022-03-11 11:40:14 +03:00
$% [%old her=ship =bone]
[%new her=ship =rift =bone]
2022-02-22 18:04:42 +03:00
==
?. ?| ?=([%bone @ @ @ ~] wire)
?=([%bone @ @ ~] wire)
==
2022-03-11 11:40:14 +03:00
:: ignore malformed wires
2022-02-22 18:04:42 +03:00
::
~
?+ wire ~
[%bone @ @ ~]
`[%old `@p`(slav %p i.t.wire) `@ud`(slav %ud i.t.t.wire)]
::
[%bone @ @ @ ~]
%- some
:^ %new
`@p`(slav %p i.t.wire)
`@ud`(slav %ud i.t.t.wire)
`@ud`(slav %ud i.t.t.t.wire)
==
2020-12-01 17:51:14 +03:00
:: +make-pump-timer-wire: construct wire for |packet-pump timer
::
++ make-pump-timer-wire
|= [her=ship =bone]
^- wire
/pump/(scot %p her)/(scot %ud bone)
:: +parse-pump-timer-wire: parse .her and .bone from |packet-pump wire
::
++ parse-pump-timer-wire
|= =wire
^- (unit [her=ship =bone])
::
~| %ames-wire-timer^wire
?. ?=([%pump @ @ ~] wire)
~
?~ ship=`(unit @p)`(slaw %p i.t.wire)
~
?~ bone=`(unit @ud)`(slaw %ud i.t.t.wire)
~
`[u.ship u.bone]
:: +derive-symmetric-key: $symmetric-key from $private-key and $public-key
::
:: Assumes keys have a tag on them like the result of the |ex:crub core.
::
++ derive-symmetric-key
~/ %derive-symmetric-key
|= [=public-key =private-key]
^- symmetric-key
::
2020-12-04 01:25:31 +03:00
?> =('b' (end 3 public-key))
=. public-key (rsh 8 (rsh 3 public-key))
2020-12-01 17:51:14 +03:00
::
2020-12-04 01:25:31 +03:00
?> =('B' (end 3 private-key))
=. private-key (rsh 8 (rsh 3 private-key))
2020-12-01 17:51:14 +03:00
::
`@`(shar:ed:crypto public-key private-key)
2022-05-20 06:20:00 +03:00
:: +encode-keys-packet: create key request $packet
::
++ encode-keys-packet
~/ %encode-keys-packet
|= [sndr=ship rcvr=ship sndr-life=life]
2022-06-30 17:27:02 +03:00
^- shot
2022-05-20 06:20:00 +03:00
:* [sndr rcvr]
2022-06-30 17:27:02 +03:00
&
&
2022-05-20 06:20:00 +03:00
(mod sndr-life 16)
`@`1
origin=~
content=`@`%keys
==
2022-02-01 14:42:13 +03:00
::
2022-05-19 18:07:35 +03:00
++ response-size 13 :: 1kb
2022-06-04 06:58:50 +03:00
:: +sift-roar: assemble scry response fragments into full message
2022-02-01 14:42:13 +03:00
::
2022-06-04 06:58:50 +03:00
++ sift-roar
2022-02-12 04:30:40 +03:00
|= [total=@ud hav=(list have)]
2022-02-01 14:42:13 +03:00
^- roar
2022-05-29 04:23:37 +03:00
=/ mes=@
2022-02-17 00:35:59 +03:00
%+ rep response-size
2022-02-12 04:30:40 +03:00
%+ turn (flop hav)
|= =have
dat.have
2022-06-01 02:31:38 +03:00
=+ sig=(end 9 mes)
:- sig
2022-05-29 04:23:37 +03:00
=+ dat=(rsh 9 mes)
2022-02-04 15:36:32 +03:00
?~ dat ~
2022-02-01 14:42:13 +03:00
~| [%fine %response-not-cask]
2022-02-04 15:36:32 +03:00
;;((cask) (cue dat))
2022-02-12 04:30:40 +03:00
:: +welt: like +weld but first argument is reversed
:: TODO: move to hoon.hoon
++ welt
~/ %welt
|* [a=(list) b=(list)]
=> .(a ^.(homo a), b ^.(homo b))
|- ^+ b
?~ a b
$(a t.a, b [i.a b])
2022-06-04 06:58:50 +03:00
:: +etch-open-packet: convert $open-packet attestation to $shot
2020-12-01 17:51:14 +03:00
::
2022-06-04 06:58:50 +03:00
++ etch-open-packet
~/ %etch-open-packet
2020-12-01 17:51:14 +03:00
|= [pac=open-packet =acru:ames]
2022-06-04 06:58:50 +03:00
^- shot
2020-12-01 17:51:14 +03:00
:* [sndr rcvr]:pac
2022-05-27 21:14:53 +03:00
req=& sam=&
2020-12-01 17:51:14 +03:00
(mod sndr-life.pac 16)
(mod rcvr-life.pac 16)
origin=~
content=`@`(sign:as:acru (jam pac))
==
2022-06-04 06:58:50 +03:00
:: +sift-open-packet: decode comet attestation into an $open-packet
2020-12-01 17:51:14 +03:00
::
2022-06-04 06:58:50 +03:00
++ sift-open-packet
~/ %sift-open-packet
|= [=shot our=ship our-life=@]
2020-12-01 17:51:14 +03:00
^- open-packet
:: deserialize and type-check packet contents
::
2022-06-04 06:58:50 +03:00
=+ ;; [signature=@ signed=@] (cue content.shot)
2020-12-01 17:51:14 +03:00
=+ ;; =open-packet (cue signed)
:: assert .our and .her and lives match
::
2022-06-04 06:58:50 +03:00
?> .= sndr.open-packet sndr.shot
2020-12-01 17:51:14 +03:00
?> .= rcvr.open-packet our
?> .= sndr-life.open-packet 1
?> .= rcvr-life.open-packet our-life
:: only a star can sponsor a comet
::
2022-06-04 06:58:50 +03:00
?> =(%king (clan:title (^sein:title sndr.shot)))
2022-02-03 00:16:16 +03:00
=/ crub (com:nu:crub:crypto public-key.open-packet)
2020-12-01 17:51:14 +03:00
:: comet public-key must hash to its @p address
::
2022-06-04 06:58:50 +03:00
?> =(sndr.shot fig:ex:crub)
2020-12-01 17:51:14 +03:00
:: verify signature
::
2022-02-03 00:16:16 +03:00
?> (safe:as:crub signature signed)
2020-12-01 17:51:14 +03:00
open-packet
2022-06-04 06:58:50 +03:00
:: +etch-shut-packet: encrypt and packetize a $shut-packet
2020-12-01 17:51:14 +03:00
::
2022-06-04 06:58:50 +03:00
++ etch-shut-packet
~/ %etch-shut-packet
2022-02-22 18:04:42 +03:00
:: TODO add rift to signed messages to prevent replay attacks?
::
2020-12-01 17:51:14 +03:00
|= $: =shut-packet
=symmetric-key
sndr=ship
rcvr=ship
sndr-life=@
rcvr-life=@
==
2022-06-04 06:58:50 +03:00
^- shot
2020-12-01 17:51:14 +03:00
::
=? meat.shut-packet
?& ?=(%& -.meat.shut-packet)
(gth (met 13 fragment.p.meat.shut-packet) 1)
==
%_ meat.shut-packet
fragment.p
(cut 13 [[fragment-num 1] fragment]:p.meat.shut-packet)
==
::
=/ vec ~[sndr rcvr sndr-life rcvr-life]
=/ [siv=@uxH len=@ cyf=@ux]
(~(en sivc:aes:crypto (shaz symmetric-key) vec) (jam shut-packet))
2022-05-27 21:14:53 +03:00
::
:* ^= dyad [sndr rcvr]
^= req ?=(%& -.meat.shut-packet)
^= sam &
^= sndr-tick (mod sndr-life 16)
^= sndr-tick (mod rcvr-life 16)
^= origin ~
^= content :(mix siv (lsh 7 len) (lsh [3 18] cyf))
==
2022-06-04 06:58:50 +03:00
:: +sift-shut-packet: decrypt a $shut-packet from a $shot
2020-12-01 17:51:14 +03:00
::
2022-06-04 06:58:50 +03:00
++ sift-shut-packet
~/ %sift-shut-packet
|= [=shot =symmetric-key sndr-life=@ rcvr-life=@]
2020-12-01 17:51:14 +03:00
^- shut-packet
2022-06-04 06:58:50 +03:00
?. =(sndr-tick.shot (mod sndr-life 16))
~| ames-sndr-tick+sndr-tick.shot !!
?. =(rcvr-tick.shot (mod rcvr-life 16))
~| ames-rcvr-tick+rcvr-tick.shot !!
=/ siv (end 7 content.shot)
=/ len (end 4 (rsh 7 content.shot))
=/ cyf (rsh [3 18] content.shot)
~| ames-decrypt+[[sndr rcvr origin]:shot len siv]
=/ vec ~[sndr.shot rcvr.shot sndr-life rcvr-life]
2020-12-01 17:51:14 +03:00
;; shut-packet %- cue %- need
(~(de sivc:aes:crypto (shaz symmetric-key) vec) siv len cyf)
2019-05-25 08:53:29 +03:00
+| %atomics
2019-05-25 05:03:33 +03:00
::
2019-06-11 23:22:24 +03:00
+$ private-key @uwprivatekey
2019-05-27 02:54:23 +03:00
+$ signature @uwsignature
2022-02-01 14:42:13 +03:00
+$ byuts [wid=@ud dat=@ux]
2019-05-25 08:53:29 +03:00
::
2019-05-27 06:22:38 +03:00
+| %kinetics
2019-05-27 04:48:41 +03:00
:: $channel: combined sender and receiver identifying data
2019-05-25 08:53:29 +03:00
::
2019-05-27 04:48:41 +03:00
+$ channel
2019-05-27 04:52:31 +03:00
$: [our=ship her=ship]
2019-05-29 01:05:59 +03:00
now=@da
2019-05-27 04:48:41 +03:00
:: our data, common to all dyads
::
$: =our=life
crypto-core=acru:ames
2019-12-11 21:55:16 +03:00
=bug
2019-05-27 04:48:41 +03:00
==
:: her data, specific to this dyad
::
$: =symmetric-key
=her=life
2022-02-22 18:04:42 +03:00
=her=rift
2019-05-27 04:48:41 +03:00
=her=public-key
2019-06-22 03:07:19 +03:00
her-sponsor=ship
2019-05-27 04:48:41 +03:00
== ==
2019-05-27 02:54:23 +03:00
:: $open-packet: unencrypted packet payload, for comet self-attestation
::
2019-11-27 09:15:05 +03:00
:: This data structure gets signed and jammed to form the .contents
:: field of a $packet.
2019-06-18 02:23:32 +03:00
::
2022-02-22 18:04:42 +03:00
:: TODO add rift to prevent replay attacks
::
2019-05-27 02:54:23 +03:00
+$ open-packet
2019-11-27 09:15:05 +03:00
$: =public-key
2019-06-18 02:23:32 +03:00
sndr=ship
2019-05-27 02:54:23 +03:00
=sndr=life
rcvr=ship
2019-06-18 02:23:32 +03:00
=rcvr=life
2019-05-27 02:54:23 +03:00
==
:: $shut-packet: encrypted packet payload
::
+$ shut-packet
2020-12-01 17:51:14 +03:00
$: =bone
2019-05-27 02:54:23 +03:00
=message-num
meat=(each fragment-meat ack-meat)
==
:: $fragment-meat: contents of a message-fragment packet
::
+$ fragment-meat
$: num-fragments=fragment-num
=fragment-num
=fragment
==
:: $ack-meat: contents of an acknowledgment packet; fragment or message
::
:: Fragment acks reference the $fragment-num of the target packet.
::
:: Message acks contain a success flag .ok, which is %.n in case of
:: negative acknowledgment (nack), along with .lag that describes the
:: time it took to process the message. .lag is zero if the message
:: was processed during a single Arvo event. At the moment, .lag is
:: always zero.
::
+$ ack-meat (each fragment-num [ok=? lag=@dr])
2019-11-03 03:52:48 +03:00
:: $naxplanation: nack trace; explains which message failed and why
::
+$ naxplanation [=message-num =error]
2019-05-25 08:53:29 +03:00
::
2022-03-11 11:40:14 +03:00
+$ ames-state-4 ames-state-5
2022-01-27 16:32:49 +03:00
+$ ames-state-5
2022-01-29 01:09:50 +03:00
$: peers=(map ship ship-state-5)
2022-01-27 16:32:49 +03:00
=unix=duct
=life
2022-06-30 17:27:02 +03:00
crypto-core=acru-6
2022-01-27 16:32:49 +03:00
=bug
==
2022-03-11 11:40:14 +03:00
::
+$ ship-state-4 ship-state-5
2022-01-29 01:09:50 +03:00
+$ ship-state-5
2022-03-11 20:07:51 +03:00
$% [%alien alien-agenda-6]
2022-02-23 22:17:53 +03:00
[%known peer-state-5]
2022-01-29 01:09:50 +03:00
==
2022-02-23 22:17:53 +03:00
::
+$ peer-state-5
$: $: =symmetric-key
=life
=public-key
sponsor=ship
==
route=(unit [direct=? =lane])
=qos
=ossuary
snd=(map bone message-pump-state)
rcv=(map bone message-sink-state)
nax=(set [=bone =message-num])
heeds=(set duct)
==
::
2022-03-11 20:07:51 +03:00
+$ ship-state-6
$% [%alien alien-agenda-6]
[%known peer-state-6]
==
::
2022-06-30 17:27:02 +03:00
+$ alien-agenda-6
$: messages=(list [=duct =plea])
packets=(set =blob)
heeds=(set duct)
==
::
2022-03-11 20:07:51 +03:00
+$ peer-state-6
$: $: =symmetric-key
=life
=rift
=public-key
sponsor=ship
==
route=(unit [direct=? =lane])
=qos
=ossuary
snd=(map bone message-pump-state)
rcv=(map bone message-sink-state)
nax=(set [=bone =message-num])
2022-01-29 01:09:50 +03:00
heeds=(set duct)
==
2022-06-30 17:27:02 +03:00
::
++ acru-6 $_ ^?
|%
++ as ^?
|% ++ seal |~([a=pass b=@] *@)
++ sign |~(a=@ *@)
++ sure |~(a=@ *(unit @))
++ tear |~([a=pass b=@] *(unit @))
--
++ de |~([a=@ b=@] *(unit @))
++ dy |~([a=@ b=@] *@)
++ en |~([a=@ b=@] *@)
++ ex ^?
|% ++ fig *@uvH
++ pac *@uvG
++ pub *pass
++ sec *ring
--
++ nu ^?
|% ++ pit |~([a=@ b=@] ^?(..nu))
++ nol |~(a=ring ^?(..nu))
++ com |~(a=pass ^?(..nu))
--
--
::
2022-03-11 20:07:51 +03:00
+$ ames-state-6
$: peers=(map ship ship-state-6)
=unix=duct
=life
2022-06-30 17:27:02 +03:00
crypto-core=acru-6
2022-03-11 20:07:51 +03:00
=bug
==
::
2019-05-27 04:52:31 +03:00
+| %statics
2019-05-25 08:53:29 +03:00
::
:: $ames-state: state for entire vane
::
2019-12-11 21:55:16 +03:00
:: peers: states of connections to other ships
:: unix-duct: handle to give moves to unix
:: life: our $life; how many times we've rekeyed
:: crypto-core: interface for encryption and signing
:: bug: debug printing configuration
::
2019-05-25 08:53:29 +03:00
+$ ames-state
$: peers=(map ship ship-state)
2019-06-08 13:13:38 +03:00
=unix=duct
2019-05-25 08:53:29 +03:00
=life
2022-03-11 20:07:51 +03:00
=rift
2019-05-25 08:53:29 +03:00
crypto-core=acru:ames
2019-12-11 21:55:16 +03:00
=bug
==
2022-03-11 20:07:51 +03:00
::
2022-02-03 15:49:38 +03:00
++ acru-5 $_ ^?
|%
++ as ^?
|% ++ seal |~([a=pass b=@] *@)
++ sign |~(a=@ *@)
++ sure |~(a=@ *(unit @))
++ tear |~([a=pass b=@] *(unit @))
--
++ de |~([a=@ b=@] *(unit @))
++ dy |~([a=@ b=@] *@)
++ en |~([a=@ b=@] *@)
++ ex ^?
|% ++ fig *@uvH
++ pac *@uvG
++ pub *pass
++ sec *ring
--
++ nu ^?
|% ++ pit |~([a=@ b=@] ^?(..nu))
++ nol |~(a=ring ^?(..nu))
++ com |~(a=pass ^?(..nu))
--
--
2019-12-11 21:55:16 +03:00
:: $bug: debug printing configuration
::
:: veb: verbosity toggles
:: ships: identity filter; if ~, print for all
::
+$ bug
$: veb=_veb-all-off
ships=(set ship)
2019-05-25 08:53:29 +03:00
==
2019-05-27 06:22:38 +03:00
::
+| %dialectics
::
2019-05-28 05:43:47 +03:00
:: $move: output effect; either request or response
::
2019-05-28 06:15:17 +03:00
+$ move [=duct card=(wind note gift)]
2019-06-29 00:26:40 +03:00
:: $queued-event: event to be handled after initial boot completes
2019-05-28 05:43:47 +03:00
::
2019-06-29 00:26:40 +03:00
+$ queued-event
2020-12-06 11:38:37 +03:00
$% [%call =duct wrapped-task=(hobo task)]
[%take =wire =duct =sign]
2019-05-28 04:43:10 +03:00
==
:: $note: request to other vane
::
2019-07-28 10:50:32 +03:00
:: Ames passes a %plea note to another vane when it receives a
2019-06-19 02:15:50 +03:00
:: message on a "forward flow" from a peer, originally passed from
:: one of the peer's vanes to the peer's Ames.
::
2019-07-28 10:50:32 +03:00
:: Ames passes a %plea to itself to trigger a heartbeat message to
2019-06-25 01:18:18 +03:00
:: our sponsor.
::
2019-06-25 02:52:22 +03:00
:: Ames passes a %private-keys to Jael to request our private keys.
:: Ames passes a %public-keys to Jael to request a peer's public
:: keys.
::
2019-05-28 04:43:10 +03:00
+$ note
2019-06-29 00:26:40 +03:00
$~ [%b %wait *@da]
$% $: %b
2019-05-28 04:43:10 +03:00
$% [%wait date=@da]
[%rest date=@da]
== ==
2022-02-02 05:30:11 +03:00
$: %c
$% $>(%warp task:clay)
== ==
2019-08-08 07:57:04 +03:00
$: %d
$% [%flog flog:dill]
2019-05-28 04:43:10 +03:00
== ==
$: %j
2019-06-29 00:26:40 +03:00
$% [%private-keys ~]
2019-06-29 01:27:59 +03:00
[%public-keys ships=(set ship)]
2019-05-28 04:43:10 +03:00
[%turf ~]
== ==
2019-06-29 00:26:40 +03:00
$: @tas
2019-07-28 10:50:32 +03:00
$% [%plea =ship =plea]
2019-05-28 04:43:10 +03:00
== == ==
:: $sign: response from other vane
::
+$ sign
2020-12-08 03:22:26 +03:00
$~ [%behn %wake ~]
$% $: %behn
2020-12-08 05:51:58 +03:00
$% $>(%wake gift:behn)
2019-05-28 04:43:10 +03:00
== ==
2020-12-08 03:22:26 +03:00
$: %jael
2019-07-23 05:16:19 +03:00
$% [%private-keys =life vein=(map life ring)]
2019-07-29 12:08:26 +03:00
[%public-keys =public-keys-result]
2019-06-22 01:17:09 +03:00
[%turf turfs=(list turf)]
2019-06-18 21:21:12 +03:00
== ==
2019-06-29 00:26:40 +03:00
$: @tas
2019-06-20 10:21:37 +03:00
$% [%done error=(unit error)]
2019-07-28 10:50:32 +03:00
[%boon payload=*]
2019-05-28 04:43:10 +03:00
== == ==
2019-05-27 06:22:38 +03:00
:: $message-pump-task: job for |message-pump
::
2019-06-25 19:00:03 +03:00
:: %memo: packetize and send application-level message
2019-06-20 10:21:37 +03:00
:: %hear: handle receipt of ack on fragment or message
2019-12-02 23:20:57 +03:00
:: %near: handle receipt of naxplanation
2021-08-28 22:39:57 +03:00
:: $prod: reset congestion control
2019-05-27 06:22:38 +03:00
:: %wake: handle timer firing
::
+$ message-pump-task
2019-07-28 10:50:32 +03:00
$% [%memo =message-blob]
2019-06-20 10:21:37 +03:00
[%hear =message-num =ack-meat]
2019-12-02 23:20:57 +03:00
[%near =naxplanation]
2021-08-28 22:39:57 +03:00
[%prod ~]
2019-05-27 06:22:38 +03:00
[%wake ~]
==
:: $message-pump-gift: effect from |message-pump
::
2019-06-20 10:21:37 +03:00
:: %done: report message acknowledgment
2019-05-31 03:20:42 +03:00
:: %send: emit message fragment
:: %wait: set a new timer at .date
:: %rest: cancel timer at .date
2019-05-27 06:22:38 +03:00
::
+$ message-pump-gift
2019-12-02 23:20:57 +03:00
$% [%done =message-num error=(unit error)]
2019-05-31 03:20:42 +03:00
[%send =static-fragment]
[%wait date=@da]
[%rest date=@da]
2019-05-27 06:22:38 +03:00
==
:: $packet-pump-task: job for |packet-pump
::
2019-06-20 10:21:37 +03:00
:: %hear: deal with a packet acknowledgment
:: %done: deal with message acknowledgment
:: %halt: finish event, possibly updating timer
2019-05-27 06:22:38 +03:00
:: %wake: handle timer firing
2021-08-28 22:39:57 +03:00
:: %prod: reset congestion control
2019-05-27 06:22:38 +03:00
::
+$ packet-pump-task
2019-06-20 10:21:37 +03:00
$% [%hear =message-num =fragment-num]
[%done =message-num lag=@dr]
[%halt ~]
2019-12-10 10:14:06 +03:00
[%wake current=message-num]
2021-08-28 22:39:57 +03:00
[%prod ~]
2019-05-27 06:22:38 +03:00
==
:: $packet-pump-gift: effect from |packet-pump
::
2019-05-31 03:20:42 +03:00
:: %send: emit message fragment
:: %wait: set a new timer at .date
:: %rest: cancel timer at .date
2019-05-27 06:22:38 +03:00
::
+$ packet-pump-gift
2019-05-31 03:20:42 +03:00
$% [%send =static-fragment]
[%wait date=@da]
[%rest date=@da]
2019-05-27 06:22:38 +03:00
==
2019-10-30 23:12:57 +03:00
:: $message-sink-task: job for |message-sink
2019-05-29 01:05:59 +03:00
::
2019-06-18 21:21:12 +03:00
:: %done: receive confirmation from vane of processing or failure
2019-06-20 10:21:37 +03:00
:: %drop: clear .message-num from .nax.state
2019-06-11 03:31:50 +03:00
:: %hear: handle receiving a message fragment packet
2019-08-06 02:05:40 +03:00
:: .ok: %.y unless previous failed attempt
2019-05-29 01:05:59 +03:00
::
2019-10-30 23:12:57 +03:00
+$ message-sink-task
2019-06-18 21:21:12 +03:00
$% [%done ok=?]
2019-06-20 10:21:37 +03:00
[%drop =message-num]
2019-08-06 02:05:40 +03:00
[%hear =lane =shut-packet ok=?]
2019-05-29 01:05:59 +03:00
==
2019-10-30 23:12:57 +03:00
:: $message-sink-gift: effect from |message-sink
2019-05-29 01:05:59 +03:00
::
2019-07-28 10:50:32 +03:00
:: %memo: assembled from received packets
2019-06-20 10:21:37 +03:00
:: %send: emit an ack packet
2019-05-29 01:05:59 +03:00
::
2019-10-30 23:12:57 +03:00
+$ message-sink-gift
2019-07-28 10:50:32 +03:00
$% [%memo =message-num message=*]
2019-06-20 10:21:37 +03:00
[%send =message-num =ack-meat]
2019-05-29 01:05:59 +03:00
==
2019-05-25 05:03:33 +03:00
--
2019-05-28 04:43:10 +03:00
:: external vane interface
::
2020-12-06 11:38:37 +03:00
|= our=ship
2019-06-29 00:26:40 +03:00
:: larval ames, before %born sets .unix-duct; wraps adult ames core
::
=< =* adult-gate .
=| queued-events=(qeu queued-event)
2022-06-30 17:27:02 +03:00
=| cached-state=(unit $%([%5 ames-state-5] [%6 ames-state-6]))
2019-06-29 00:26:40 +03:00
::
2020-12-06 11:38:37 +03:00
|= [now=@da eny=@ rof=roof]
2019-06-29 00:26:40 +03:00
=* larval-gate .
=* adult-core (adult-gate +<)
2022-05-17 08:49:15 +03:00
=< |%
2022-05-17 08:11:09 +03:00
++ call ^call
++ load ^load
++ scry ^scry
++ stay ^stay
++ take ^take
--
2019-06-29 00:26:40 +03:00
|%
:: +call: handle request $task
::
++ call
2020-12-06 11:38:37 +03:00
|= [=duct dud=(unit goof) wrapped-task=(hobo task)]
2019-07-23 05:16:19 +03:00
::
2020-01-21 02:01:36 +03:00
=/ =task ((harden task) wrapped-task)
2020-12-08 05:01:48 +03:00
:: reject larval error notifications
2020-02-24 22:09:37 +03:00
::
2020-12-08 05:01:48 +03:00
?^ dud
~|(%ames-larval-call-dud (mean tang.u.dud))
2020-02-24 22:09:37 +03:00
::
2022-05-17 08:11:09 +03:00
?: &(?=(^ cached-state) ?=(~ queued-events))
2022-05-18 18:36:40 +03:00
=^ moves adult-gate (call:adult-core duct dud task)
(molt moves)
2019-06-29 00:26:40 +03:00
:: %born: set .unix-duct and start draining .queued-events
::
2019-07-23 05:16:19 +03:00
?: ?=(%born -.task)
2019-06-29 00:26:40 +03:00
:: process %born using wrapped adult ames
::
2020-12-06 11:38:37 +03:00
=^ moves adult-gate (call:adult-core duct dud task)
2019-06-29 00:26:40 +03:00
:: if no events were queued up, metamorphose
::
?~ queued-events
2019-08-10 21:48:40 +03:00
~> %slog.0^leaf/"ames: metamorphosis"
2019-06-29 00:26:40 +03:00
[moves adult-gate]
:: kick off a timer to process the first of .queued-events
::
=. moves :_(moves [duct %pass /larva %b %wait now])
[moves larval-gate]
:: any other event: enqueue it until we have a .unix-duct
::
2020-02-11 01:03:03 +03:00
:: XX what to do with errors?
::
2020-12-06 11:38:37 +03:00
=. queued-events (~(put to queued-events) %call duct task)
2019-06-29 00:26:40 +03:00
[~ larval-gate]
:: +take: handle response $sign
::
++ take
2020-12-06 11:38:37 +03:00
|= [=wire =duct dud=(unit goof) =sign]
2020-02-25 01:10:59 +03:00
?^ dud
~|(%ames-larval-take-dud (mean tang.u.dud))
2019-06-29 00:26:40 +03:00
:: enqueue event if not a larval drainage timer
::
2022-05-17 08:11:09 +03:00
=? queued-events !=(/larva wire)
(~(put to queued-events) %take wire duct sign)
:: start drainage timer if have regressed from adult ames
::
?: ?& !=(/larva wire)
?=(^ cached-state)
==
[[duct %pass /larva %b %wait now]~ larval-gate]
2020-02-11 01:03:03 +03:00
:: XX what to do with errors?
::
2022-05-17 08:11:09 +03:00
?. =(/larva wire) [~ larval-gate]
2019-06-29 00:26:40 +03:00
:: larval event drainage timer; pop and process a queued event
::
2020-12-08 03:22:26 +03:00
?. ?=([%behn %wake *] sign)
2019-08-10 21:48:40 +03:00
~> %slog.0^leaf/"ames: larva: strange sign"
2019-07-23 05:16:19 +03:00
[~ larval-gate]
2019-12-04 19:04:09 +03:00
:: if crashed, print, dequeue, and set next drainage timer
::
2019-12-04 17:45:52 +03:00
?^ error.sign
2019-12-04 21:43:07 +03:00
:: .queued-events should never be ~ here, but if it is, don't crash
::
?: =(~ queued-events)
=/ =tang [leaf/"ames: cursed metamorphosis" u.error.sign]
=/ moves [duct %pass /larva-crash %d %flog %crud %larva tang]~
[moves adult-gate]
:: dequeue and discard crashed event
::
2019-12-04 19:04:09 +03:00
=. queued-events +:~(get to queued-events)
:: .queued-events has been cleared; metamorphose
::
?~ queued-events
~> %slog.0^leaf/"ames: metamorphosis"
[~ adult-gate]
:: set timer to drain next event
::
2019-12-04 19:29:01 +03:00
=/ moves
=/ =tang [leaf/"ames: larva: drain crash" u.error.sign]
:~ [duct %pass /larva-crash %d %flog %crud %larva tang]
[duct %pass /larva %b %wait now]
==
2019-12-04 17:45:52 +03:00
[moves larval-gate]
:: normal drain timer; dequeue and run event
::
2019-06-29 00:26:40 +03:00
=^ first-event queued-events ~(get to queued-events)
=^ moves adult-gate
?- -.first-event
2020-12-06 11:38:37 +03:00
%call (call:adult-core [duct ~ wrapped-task]:+.first-event)
%take (take:adult-core [wire duct ~ sign]:+.first-event)
2019-06-29 00:26:40 +03:00
==
:: .queued-events has been cleared; metamorphose
::
?~ queued-events
2022-05-17 08:11:09 +03:00
?: ?=(^ cached-state) (molt moves)
2019-08-10 21:48:40 +03:00
~> %slog.0^leaf/"ames: metamorphosis"
2019-06-29 00:26:40 +03:00
[moves adult-gate]
:: set timer to drain next event
::
=. moves :_(moves [duct %pass /larva %b %wait now])
[moves larval-gate]
:: lifecycle arms; mostly pass-throughs to the contained adult ames
::
++ scry scry:adult-core
2022-03-11 20:07:51 +03:00
++ stay [%7 %larva queued-events ames-state.adult-gate]
2019-06-29 00:26:40 +03:00
++ load
2019-07-31 21:51:31 +03:00
|= $= old
2020-06-12 08:55:08 +03:00
$% $: %4
$% $: %larva
events=(qeu queued-event)
2022-03-11 11:40:14 +03:00
state=ames-state-4
2020-06-12 08:55:08 +03:00
==
2022-03-11 11:40:14 +03:00
[%adult state=ames-state-4]
2020-06-12 08:55:08 +03:00
== ==
2021-02-27 07:53:27 +03:00
$: %5
2022-01-27 16:32:49 +03:00
$% $: %larva
events=(qeu queued-event)
state=ames-state-5
==
[%adult state=ames-state-5]
== ==
$: %6
2022-03-11 20:07:51 +03:00
$% $: %larva
events=(qeu queued-event)
state=ames-state-6
==
[%adult state=ames-state-6]
== ==
$: %7
2021-02-27 07:53:27 +03:00
$% $: %larva
events=(qeu queued-event)
state=_ames-state.adult-gate
==
[%adult state=_ames-state.adult-gate]
2022-02-22 18:04:42 +03:00
== == ==
2019-12-01 10:47:24 +03:00
?- old
2022-05-09 15:13:51 +03:00
[%4 %adult *]
$(old [%5 %adult (state-4-to-5:load:adult-core state.old)])
2019-12-11 21:55:16 +03:00
::
2020-06-12 08:55:08 +03:00
[%4 %larva *]
2022-05-09 15:13:51 +03:00
=. state.old (state-4-to-5:load:adult-core state.old)
$(-.old %5)
2021-02-27 07:53:27 +03:00
::
2022-06-30 17:27:02 +03:00
:: [%5 %larva *]
:: ~> %slog.0^leaf/"ames: larva: load"
:: =. queued-events events.old
:: larval-gate
:: ::
:: [%5 %adult *]
:: ~> %slog.1^leaf/"ames: larva reload"
:: =. adult-gate (load:adult-core %5 state.old)
:: larval-gate
::
[%5 %adult *]
2022-03-15 20:07:13 +03:00
=. cached-state `[%5 state.old]
2022-05-15 09:52:09 +03:00
~> %slog.0^leaf/"ames: larva reload"
2022-04-22 13:25:55 +03:00
larval-gate
2021-02-27 07:53:27 +03:00
::
[%5 %larva *]
2022-05-15 09:52:09 +03:00
~> %slog.0^leaf/"ames: larva: load"
2019-12-11 21:55:16 +03:00
=. queued-events events.old
2020-06-12 08:55:08 +03:00
larval-gate
2021-02-27 07:53:27 +03:00
::
2022-06-30 17:27:02 +03:00
[%6 %adult *]
=. cached-state `[%6 state.old]
~> %slog.0^leaf/"ames: larva reload"
2022-02-22 18:04:42 +03:00
larval-gate
2022-01-27 16:32:49 +03:00
::
[%6 %larva *]
2022-05-15 09:52:09 +03:00
~> %slog.0^leaf/"ames: larva: load"
2022-01-27 16:32:49 +03:00
=. queued-events events.old
larval-gate
2022-03-11 20:07:51 +03:00
::
[%7 %adult *] (load:adult-core %7 state.old)
::
[%7 %larva *]
~> %slog.1^leaf/"ames: larva: load"
=. queued-events events.old
=. adult-gate (load:adult-core %7 state.old)
larval-gate
2019-07-24 02:55:35 +03:00
==
2022-05-17 08:11:09 +03:00
:: +molt: re-evolve to adult-ames
::
++ molt
|= moves=(list move)
^- (quip move _adult-gate)
2022-06-30 17:27:02 +03:00
~& [%hmm now]
2022-05-17 08:11:09 +03:00
=. ames-state.adult-gate
?> ?=(^ cached-state)
2022-06-30 17:27:02 +03:00
=? u.cached-state ?=(%5 -.u.cached-state)
[%6 (state-5-to-6:load:adult-core +.u.cached-state)]
?> ?=(%6 -.u.cached-state)
2022-05-19 18:07:35 +03:00
(state-6-to-7:load:adult-core +.u.cached-state)
2022-05-17 08:11:09 +03:00
=. cached-state ~
2022-05-18 00:07:05 +03:00
~> %slog.0^leaf/"ames: metamorphosis reload"
2022-05-18 18:36:40 +03:00
[moves adult-gate]
2019-06-29 00:26:40 +03:00
--
:: adult ames, after metamorphosis from larva
::
=<
2019-05-28 04:43:10 +03:00
=| =ames-state
2020-12-06 11:38:37 +03:00
|= [now=@da eny=@ rof=roof]
2019-05-28 04:43:10 +03:00
=* ames-gate .
2019-12-11 21:55:16 +03:00
=* veb veb.bug.ames-state
2019-05-28 04:43:10 +03:00
|%
:: +call: handle request $task
::
++ call
2020-12-06 11:38:37 +03:00
|= [=duct dud=(unit goof) wrapped-task=(hobo task)]
2019-05-28 04:43:10 +03:00
^- [(list move) _ames-gate]
::
2020-01-21 02:01:36 +03:00
=/ =task ((harden task) wrapped-task)
2020-12-06 13:55:19 +03:00
=/ event-core (per-event [now eny rof] duct ames-state)
2019-05-28 05:43:47 +03:00
::
=^ moves ames-state
2022-01-29 01:54:01 +03:00
=< abet
2020-12-08 05:01:48 +03:00
:: handle error notifications
::
?^ dud
?+ -.task
(on-crud:event-core -.task tang.u.dud)
2020-12-12 03:49:55 +03:00
%hear (on-hear:event-core lane.task blob.task dud)
2020-12-08 05:01:48 +03:00
==
::
2019-05-28 05:43:47 +03:00
?- -.task
2019-06-22 01:26:26 +03:00
%born on-born:event-core
2020-12-12 03:49:55 +03:00
%hear (on-hear:event-core [lane blob ~]:task)
2019-11-04 04:35:45 +03:00
%heed (on-heed:event-core ship.task)
2020-12-06 11:38:37 +03:00
%init on-init:event-core
2019-11-04 04:35:45 +03:00
%jilt (on-jilt:event-core ship.task)
2021-08-28 22:39:57 +03:00
%prod (on-prod:event-core ships.task)
2019-12-11 21:55:16 +03:00
%sift (on-sift:event-core ships.task)
2019-12-03 02:46:40 +03:00
%spew (on-spew:event-core veb.task)
2020-05-28 20:24:29 +03:00
%stir (on-stir:event-core arg.task)
2020-05-20 10:29:54 +03:00
%trim on-trim:event-core
2019-06-22 01:19:24 +03:00
%vega on-vega:event-core
2019-07-28 10:50:32 +03:00
%plea (on-plea:event-core [ship plea]:task)
2022-01-29 01:54:01 +03:00
::
2022-03-15 00:04:14 +03:00
%pine (on-pine:fine:event-core +.task)
2022-01-29 01:54:01 +03:00
%keen (on-keen:fine:event-core +.task)
%yawn (on-yawn:fine:event-core +.task)
2019-05-28 05:43:47 +03:00
==
::
[moves ames-gate]
2019-05-28 04:43:10 +03:00
:: +take: handle response $sign
::
++ take
2020-12-06 11:38:37 +03:00
|= [=wire =duct dud=(unit goof) =sign]
2019-05-28 04:43:10 +03:00
^- [(list move) _ames-gate]
2020-02-25 01:10:59 +03:00
?^ dud
~|(%ames-take-dud (mean tang.u.dud))
::
2019-05-28 04:43:10 +03:00
::
2020-12-06 13:55:19 +03:00
=/ event-core (per-event [now eny rof] duct ames-state)
2019-06-18 21:21:12 +03:00
::
=^ moves ames-state
=< abet
?- sign
2019-06-29 00:26:40 +03:00
[@ %done *] (on-take-done:event-core wire error.sign)
2019-07-28 10:50:32 +03:00
[@ %boon *] (on-take-boon:event-core wire payload.sign)
2019-06-19 02:15:50 +03:00
::
2020-12-08 03:22:26 +03:00
[%behn %wake *] (on-take-wake:event-core wire error.sign)
2019-06-19 02:15:50 +03:00
::
2020-12-08 03:22:26 +03:00
[%jael %turf *] (on-take-turf:event-core turfs.sign)
[%jael %private-keys *] (on-priv:event-core [life vein]:sign)
[%jael %public-keys *] (on-publ:event-core wire public-keys-result.sign)
2019-06-18 21:21:12 +03:00
==
::
[moves ames-gate]
2019-05-28 04:43:10 +03:00
:: +stay: extract state before reload
::
2022-03-15 00:04:14 +03:00
++ stay [%7 %adult ames-state]
2019-05-28 04:43:10 +03:00
:: +load: load in old state after reload
::
++ load
2022-06-30 17:27:02 +03:00
|^ |= old-state=[%7 ^ames-state]
2022-04-22 13:25:55 +03:00
^+ ames-gate
2022-06-30 17:27:02 +03:00
?> ?=(%7 -.old-state)
2022-04-22 13:25:55 +03:00
ames-gate(ames-state +.old-state)
2021-02-27 07:53:27 +03:00
::
2022-03-11 20:07:51 +03:00
++ state-6-to-7
|= old=ames-state-6
2022-01-27 16:32:49 +03:00
^- ^ames-state
2022-03-11 20:07:51 +03:00
=+ !< =rift
2022-06-30 17:27:02 +03:00
~& :- %uhh `beam`[[our %rift %da now] /(scot %p our)]
2022-03-11 20:07:51 +03:00
q:(need (need (rof ~ %j `beam`[[our %rift %da now] /(scot %p our)])))
:* peers=(~(run by peers.old) ship-state-6-to-7)
2022-02-23 22:17:53 +03:00
unix-duct.old
life.old
2022-03-11 20:07:51 +03:00
rift
2022-02-23 22:17:53 +03:00
crypto-core=(nol:nu:crub:crypto sec:ex:crypto-core.old)
bug.old
2022-01-29 01:09:50 +03:00
==
::
2022-03-11 20:07:51 +03:00
++ ship-state-6-to-7
|= old=ship-state-6
2022-01-29 01:09:50 +03:00
^- ship-state
2022-05-19 18:07:35 +03:00
?: ?=(%alien -.old)
2022-03-15 19:40:34 +03:00
old(heeds [heeds.old ~ ~])
2022-02-23 22:17:53 +03:00
old(heeds [heeds.old *scry-state])
2022-01-27 16:32:49 +03:00
::
2022-02-22 18:04:42 +03:00
++ state-5-to-6
2022-03-11 11:40:14 +03:00
|= ames-state=ames-state-5
2022-03-11 20:07:51 +03:00
^- ames-state-6
2022-02-22 18:04:42 +03:00
:_ +.ames-state
%- ~(rut by peers.ames-state)
2022-03-11 11:40:14 +03:00
|= [=ship ship-state=ship-state-5]
2022-03-11 20:07:51 +03:00
^- ship-state-6
2022-02-22 18:04:42 +03:00
?. ?=(%known -.ship-state)
ship-state
2022-03-11 11:40:14 +03:00
=/ peer-state=peer-state-5 +.ship-state
2022-03-15 20:07:13 +03:00
=/ =rift
2022-04-27 07:24:55 +03:00
:: harcoded because %jael doesn't have data about comets
::
?: ?=(%pawn (clan:title ship)) 0
2022-03-15 20:07:13 +03:00
;; @ud
=< q.q %- need %- need
2022-02-22 18:04:42 +03:00
(rof ~ %j `beam`[[our %rift %da now] /(scot %p ship)])
2022-03-11 20:07:51 +03:00
=/ peer-state=peer-state-6
2022-02-22 18:04:42 +03:00
:_ +.peer-state
=, -.peer-state
[symmetric-key life rift public-key sponsor]
2022-03-11 20:07:51 +03:00
^- ship-state-6
2022-02-22 18:04:42 +03:00
[-.ship-state peer-state]
2022-03-11 20:07:51 +03:00
::
2021-02-27 07:53:27 +03:00
++ state-4-to-5
2022-05-19 18:07:35 +03:00
|= ames-state=ames-state-4
^- ames-state-4
2021-02-27 07:53:27 +03:00
=. peers.ames-state
%- ~(run by peers.ames-state)
2022-05-19 18:07:35 +03:00
|= ship-state=ship-state-4
2021-02-27 07:53:27 +03:00
?. ?=(%known -.ship-state)
ship-state
=. snd.ship-state
%- ~(run by snd.ship-state)
|= =message-pump-state
=. num-live.metrics.packet-pump-state.message-pump-state
~(wyt in live.packet-pump-state.message-pump-state)
message-pump-state
ship-state
ames-state
--
2019-05-28 04:43:10 +03:00
:: +scry: dereference namespace
::
++ scry
2020-12-08 00:52:12 +03:00
^- roon
|= [lyc=gang car=term bem=beam]
2019-05-28 04:43:10 +03:00
^- (unit (unit cage))
2020-12-08 00:52:12 +03:00
=* ren car
2020-11-24 00:06:50 +03:00
=* why=shop &/p.bem
=* syd q.bem
=* lot=coin $/r.bem
=* tyl s.bem
::
2020-06-25 21:20:57 +03:00
::TODO don't special-case whey scry
::
?: &(=(%$ ren) =(tyl /whey))
2020-05-07 11:51:08 +03:00
=/ maz=(list mass)
=+ [known alien]=(skid ~(val by peers.ames-state) |=(^ =(%known +<-)))
:~ peers-known+&+known
peers-alien+&+alien
==
``mass+!>(maz)
2020-06-25 21:20:57 +03:00
:: only respond for the local identity, %$ desk, current timestamp
::
?. ?& =(&+our why)
=([%$ %da now] lot)
=(%$ syd)
==
2020-09-18 23:06:13 +03:00
?. for.veb.bug.ames-state ~
~> %slog.0^leaf/"ames: scry-fail {<[why=why lot=lot now=now syd=syd]>}"
2020-06-25 21:20:57 +03:00
~
2020-07-03 01:51:54 +03:00
:: /ax/protocol/version @
:: /ax/peers (map ship ?(%alien %known))
:: /ax/peers/[ship] ship-state
:: /ax/peers/[ship]/forward-lane (list lane)
:: /ax/bones/[ship] [snd=(set bone) rcv=(set bone)]
:: /ax/snd-bones/[ship]/[bone] vase
2022-06-01 02:31:38 +03:00
:: /ax/fine/hunk/[path/...] (list @ux) scry response fragments
2020-06-25 21:20:57 +03:00
::
?. ?=(%x ren) ~
2022-05-26 01:30:35 +03:00
=> .(tyl `(pole knot)`tyl)
2020-07-03 01:51:54 +03:00
?+ tyl ~
[%protocol %version ~]
``noun+!>(protocol-version)
::
2020-06-25 21:20:57 +03:00
[%peers ~]
2020-05-08 02:37:07 +03:00
:^ ~ ~ %noun
!> ^- (map ship ?(%alien %known))
(~(run by peers.ames-state) head)
::
2022-05-26 01:30:35 +03:00
[%peers her=@ req=*]
2022-05-27 05:23:09 +03:00
=/ who (slaw %p her.tyl)
2020-01-11 01:41:49 +03:00
?~ who [~ ~]
2020-12-06 07:02:31 +03:00
=/ peer (~(get by peers.ames-state) u.who)
2022-05-27 05:23:09 +03:00
?+ req.tyl [~ ~]
2020-12-06 07:02:31 +03:00
~
?~ peer
[~ ~]
``noun+!>(u.peer)
2020-07-03 01:51:54 +03:00
::
[%forward-lane ~]
2020-10-23 03:37:46 +03:00
::
:: this duplicates the routing hack from +send-blob:event-core
:: so long as neither the peer nor the peer's sponsoring galaxy is us:
::
:: - no route to the peer: send to the peer's sponsoring galaxy
:: - direct route to the peer: use that
:: - indirect route to the peer: send to both that route and the
:: the peer's sponsoring galaxy
2020-07-03 01:51:54 +03:00
::
:^ ~ ~ %noun
!> ^- (list lane)
2022-06-03 07:26:42 +03:00
?: =(our u.who)
2020-07-03 01:51:54 +03:00
~
2022-06-03 07:26:42 +03:00
?. ?=([~ %known *] peer)
=/ sax (rof ~ %j `beam`[[our %saxo %da now] /(scot %p u.who)])
?. ?=([~ ~ *] sax)
~
2022-06-03 19:24:03 +03:00
=/ gal (rear ;;((list ship) q.q.u.u.sax))
2022-06-03 07:43:22 +03:00
?: =(our gal)
~
[%& gal]~
2020-10-23 03:37:46 +03:00
=; zar=(trap (list lane))
?~ route.u.peer $:zar
=* rot u.route.u.peer
?:(direct.rot [lane.rot ~] [lane.rot $:zar])
::
|. ^- (list lane)
?: ?=(%czar (clan:title sponsor.u.peer))
?: =(our sponsor.u.peer)
~
[%& sponsor.u.peer]~
=/ next (~(get by peers.ames-state) sponsor.u.peer)
2020-07-03 01:51:54 +03:00
?. ?=([~ %known *] next)
~
2020-10-23 03:37:46 +03:00
$(peer next)
2020-07-03 01:51:54 +03:00
==
2020-01-11 01:41:49 +03:00
::
2022-05-26 01:30:35 +03:00
[%bones her=@ ~]
2022-05-27 05:23:09 +03:00
=/ who (slaw %p her.tyl)
2020-01-11 01:41:49 +03:00
?~ who [~ ~]
=/ per (~(get by peers.ames-state) u.who)
?. ?=([~ %known *] per) [~ ~]
=/ res
=, u.per
[snd=~(key by snd) rcv=~(key by rcv)]
``noun+!>(res)
::
2022-05-26 01:30:35 +03:00
[%snd-bones her=@ bon=@ ~]
2022-05-27 05:23:09 +03:00
=/ who (slaw %p her.tyl)
2020-01-11 01:41:49 +03:00
?~ who [~ ~]
2022-05-27 05:23:09 +03:00
=/ ost (slaw %ud bon.tyl)
2020-01-11 01:41:49 +03:00
?~ ost [~ ~]
=/ per (~(get by peers.ames-state) u.who)
?. ?=([~ %known *] per) [~ ~]
=/ mps (~(get by snd.u.per) u.ost)
?~ mps [~ ~]
=/ res
u.mps
``noun+!>(!>(res))
2022-01-27 16:32:49 +03:00
::
2022-05-26 01:30:35 +03:00
[%fine %hunk lop=@t len=@t pax=^]
2022-01-29 01:54:01 +03:00
::TODO separate endpoint for the full message (instead of packet list)
2022-05-26 01:30:35 +03:00
:: .pax is expected to be a scry path of the shape /vc/desk/rev/etc,
2022-01-27 16:32:49 +03:00
:: so we need to give it the right shape
::
2022-05-27 05:23:09 +03:00
?~ blk=(de-path-soft:balk pax.tyl) ~
2022-03-15 00:04:14 +03:00
=+ nom=(en-roof:balk u.blk)
2022-05-19 18:07:35 +03:00
~| nom
2022-01-29 01:54:01 +03:00
:: we only support scrying into clay,
:: and only if the data is fully public.
::
2022-05-18 21:25:57 +03:00
?. =(%c ?@(vis.nom (end 3 vis.nom) way.vis.nom)) ~
=+ pem=(rof lyc nom(vis %cp))
2022-05-19 18:07:35 +03:00
?. ?=(^ pem) ~
?. ?=(^ u.pem) ~
~| u.u.pem
2022-05-18 21:25:57 +03:00
=+ per=!<([r=dict:clay w=dict:clay] q.u.u.pem)
2022-05-19 18:07:35 +03:00
?. =([%black ~ ~] rul.r.per) ~
2022-03-15 00:04:14 +03:00
=+ res=(rof lyc nom)
2022-05-27 05:23:09 +03:00
=/ =hunk [(slav %ud lop.tyl) (slav %ud len.tyl)]
2022-01-29 01:54:01 +03:00
::TODO suggests we need to factor differently
2022-05-26 01:30:35 +03:00
=/ fin fine:(per-event [now 0v0 rof] *duct ames-state)
2022-01-29 01:54:01 +03:00
?- res
~ ~
2022-06-04 06:58:50 +03:00
[~ ~] ``noun+!>((etch-hunk:fin pax.tyl hunk ~))
[~ ~ *] ``noun+!>((etch-hunk:fin pax.tyl hunk [p q.q]:u.u.res))
2022-01-29 01:54:01 +03:00
==
2020-01-11 01:41:49 +03:00
==
2019-05-28 04:43:10 +03:00
--
2020-12-01 17:51:14 +03:00
:: |per-event: inner event-handling core
2019-05-28 04:43:10 +03:00
::
2022-04-20 01:09:00 +03:00
~% %per-event ..trace ~
2019-05-25 05:03:33 +03:00
|%
2019-05-28 05:43:47 +03:00
++ per-event
=| moves=(list move)
2020-12-01 17:51:14 +03:00
~% %event-gate ..per-event ~
2020-12-06 13:55:19 +03:00
|= [[now=@da eny=@ rof=roof] =duct =ames-state]
2019-12-11 21:55:16 +03:00
=* veb veb.bug.ames-state
2020-12-01 17:51:14 +03:00
~% %event-core ..$ ~
2019-05-28 05:43:47 +03:00
|%
++ event-core .
++ abet [(flop moves) ames-state]
2019-05-28 06:15:17 +03:00
++ emit |=(=move event-core(moves [move moves]))
2022-01-29 01:54:01 +03:00
++ emil |=(mos=(list move) event-core(moves (weld (flop mos) moves)))
2019-12-11 21:55:16 +03:00
++ channel-state [life crypto-core bug]:ames-state
++ trace
|= [verb=? =ship print=(trap tape)]
^+ same
(^trace verb ship ships.bug.ames-state print)
2019-06-20 10:47:13 +03:00
:: +on-take-done: handle notice from vane that it processed a message
2019-05-28 05:43:47 +03:00
::
2019-06-20 10:47:13 +03:00
++ on-take-done
2019-06-19 02:59:25 +03:00
|= [=wire error=(unit error)]
2019-06-18 21:21:12 +03:00
^+ event-core
2019-08-10 00:20:16 +03:00
:: relay the vane ack to the foreign peer
2019-06-25 01:18:18 +03:00
::
2022-03-15 00:04:14 +03:00
?: ?=([%fine %pine *] wire)
event-core
2022-02-22 18:04:42 +03:00
?~ parsed=(parse-bone-wire wire)
2022-04-14 17:36:01 +03:00
:: no-op
2022-02-22 18:04:42 +03:00
::
2022-04-22 11:06:53 +03:00
~> %slog.0^leaf/"ames: dropping malformed wire: {(spud wire)}"
event-core
2022-02-22 18:04:42 +03:00
?> ?=([@ her=ship *] u.parsed)
2022-04-14 17:36:01 +03:00
=* her her.u.parsed
2019-06-25 00:32:53 +03:00
=/ =peer-state (got-peer-state her)
2019-12-03 02:46:40 +03:00
=/ =channel [[our her] now channel-state -.peer-state]
2022-03-11 11:40:14 +03:00
2019-06-25 00:32:53 +03:00
=/ peer-core (make-peer-core peer-state channel)
2022-02-22 18:04:42 +03:00
|^
2022-04-14 17:36:01 +03:00
?: ?& ?=([%new *] u.parsed)
(lth rift.u.parsed rift.peer-state)
==
:: ignore events from an old rift
2022-02-22 18:04:42 +03:00
::
2022-04-22 11:06:53 +03:00
%- %^ trace odd.veb her
|.("dropping old rift wire: {(spud wire)}")
event-core
2022-04-14 17:36:01 +03:00
=/ =bone
?-(u.parsed [%new *] bone.u.parsed, [%old *] bone.u.parsed)
2022-04-22 11:06:53 +03:00
=? peer-core ?=([%old *] u.parsed)
%- %^ trace odd.veb her
|.("parsing old wire: {(spud wire)}")
peer-core
2022-04-14 17:36:01 +03:00
?~ error
(send-ack bone)
(send-nack bone u.error)
2022-02-22 18:04:42 +03:00
::
2019-07-28 10:50:32 +03:00
:: if processing succeded, send positive ack packet and exit
2019-06-19 03:38:25 +03:00
::
2022-02-22 18:04:42 +03:00
++ send-ack
|= =bone
^+ event-core
2019-10-30 23:12:57 +03:00
abet:(run-message-sink:peer-core bone %done ok=%.y)
2019-07-28 10:50:32 +03:00
:: failed; send message nack packet
2019-06-19 03:38:25 +03:00
::
2022-02-22 18:04:42 +03:00
++ send-nack
|= [=bone =^error]
^+ event-core
2022-04-14 17:36:01 +03:00
=. event-core abet:(run-message-sink:peer-core bone %done ok=%.n)
2022-02-22 18:04:42 +03:00
=/ =^peer-state (got-peer-state her)
2022-03-11 11:40:14 +03:00
=/ =^channel [[our her] now channel-state -.peer-state]
2022-02-22 18:04:42 +03:00
:: construct nack-trace message, referencing .failed $message-num
::
=/ failed=message-num last-acked:(~(got by rcv.peer-state) bone)
=/ =naxplanation [failed error]
=/ =message-blob (jam naxplanation)
:: send nack-trace message on associated .nack-trace-bone
::
=. peer-core (make-peer-core peer-state channel)
=/ nack-trace-bone=^bone (mix 0b10 bone)
::
abet:(run-message-pump:peer-core nack-trace-bone %memo message-blob)
--
2019-12-11 21:55:16 +03:00
:: +on-sift: handle request to filter debug output by ship
::
++ on-sift
|= ships=(list ship)
^+ event-core
=. ships.bug.ames-state (sy ships)
event-core
:: +on-spew: handle request to set verbosity toggles on debug output
2019-12-03 02:46:40 +03:00
::
++ on-spew
|= verbs=(list verb)
^+ event-core
:: start from all %.n's, then flip requested toggles
::
2019-12-11 21:55:16 +03:00
=. veb.bug.ames-state
2019-12-03 02:46:40 +03:00
%+ roll verbs
|= [=verb acc=_veb-all-off]
2019-12-11 21:55:16 +03:00
^+ veb.bug.ames-state
2019-12-03 02:46:40 +03:00
?- verb
%snd acc(snd %.y)
%rcv acc(rcv %.y)
%odd acc(odd %.y)
%msg acc(msg %.y)
%ges acc(ges %.y)
%for acc(for %.y)
%rot acc(rot %.y)
==
event-core
2021-08-28 22:39:57 +03:00
:: +on-prod: re-send a packet per flow to each of .ships
::
++ on-prod
|= ships=(list ship)
^+ event-core
=? ships =(~ ships) ~(tap in ~(key by peers.ames-state))
|^ ^+ event-core
?~ ships event-core
$(ships t.ships, event-core (prod-peer i.ships))
::
++ prod-peer
|= her=ship
^+ event-core
=/ par (get-peer-state her)
?~ par event-core
=/ =channel [[our her] now channel-state -.u.par]
=/ peer-core (make-peer-core u.par channel)
=/ bones ~(tap in ~(key by snd.u.par))
|- ^+ event-core
?~ bones abet:peer-core
=. peer-core (run-message-pump:peer-core i.bones %prod ~)
$(bones t.bones)
--
2020-05-28 20:24:29 +03:00
:: +on-stir: start timers for any flow that lack them
::
:: .arg is unused, meant to ease future debug commands
::
++ on-stir
|= arg=@t
=/ states=(list [ship peer-state])
%+ murn ~(tap by peers.ames-state)
|= [=ship =ship-state]
^- (unit [^ship peer-state])
?. ?=(%known -.ship-state)
~
`[ship +.ship-state]
=/ snds=(list (list [ship bone message-pump-state]))
%+ turn states
|= [=ship peer-state]
%+ turn ~(tap by snd)
|= [=bone =message-pump-state]
[ship bone message-pump-state]
=/ next-wakes
%+ turn `(list [ship bone message-pump-state])`(zing snds)
|= [=ship =bone message-pump-state]
[ship bone next-wake.packet-pump-state]
=/ next-real-wakes=(list [=ship =bone =@da])
%+ murn next-wakes
|= [=ship =bone tym=(unit @da)]
^- (unit [^ship ^bone @da])
?~(tym ~ `[ship bone u.tym])
=/ timers
%- silt
;; (list [@da ^duct])
=< q.q %- need %- need
2020-12-06 13:55:19 +03:00
(rof ~ %b [[our %timers da+now] /])
2020-05-28 20:24:29 +03:00
=/ to-stir
%+ skip next-real-wakes
|= [=ship =bone =@da]
(~(has in timers) [da `^duct`~[a+(make-pump-timer-wire ship bone) /ames]])
~& [%stirring to-stir]
|- ^+ event-core
?~ to-stir
event-core
=/ =wire (make-pump-timer-wire [ship bone]:i.to-stir)
=. event-core (emit duct %pass wire %b %wait da.i.to-stir)
$(to-stir t.to-stir)
2019-08-08 07:57:04 +03:00
:: +on-crud: handle event failure; print to dill
::
++ on-crud
|= =error
^+ event-core
(emit duct %pass /crud %d %flog %crud error)
2019-11-04 04:35:45 +03:00
:: +on-heed: handle request to track .ship's responsiveness
::
++ on-heed
|= =ship
^+ event-core
=/ ship-state (~(get by peers.ames-state) ship)
?. ?=([~ %known *] ship-state)
%+ enqueue-alien-todo ship
|= todos=alien-agenda
todos(heeds (~(put in heeds.todos) duct))
::
=/ =peer-state +.u.ship-state
2019-12-03 02:46:40 +03:00
=/ =channel [[our ship] now channel-state -.peer-state]
2019-11-04 04:35:45 +03:00
abet:on-heed:(make-peer-core peer-state channel)
:: +on-jilt: handle request to stop tracking .ship's responsiveness
::
++ on-jilt
|= =ship
^+ event-core
=/ ship-state (~(get by peers.ames-state) ship)
?. ?=([~ %known *] ship-state)
%+ enqueue-alien-todo ship
|= todos=alien-agenda
todos(heeds (~(del in heeds.todos) duct))
::
=/ =peer-state +.u.ship-state
2019-12-03 02:46:40 +03:00
=/ =channel [[our ship] now channel-state -.peer-state]
2019-11-04 04:35:45 +03:00
abet:on-jilt:(make-peer-core peer-state channel)
2019-06-25 03:48:05 +03:00
:: +on-hear: handle raw packet receipt
2019-07-26 00:50:08 +03:00
::
2020-12-12 03:49:55 +03:00
++ on-hear
|= [l=lane b=blob d=(unit goof)]
2022-01-29 01:54:01 +03:00
^+ event-core
2022-06-04 06:58:50 +03:00
=/ =shot (sift-shot b)
?: sam.shot
(on-hear-packet l shot d)
?: req.shot
2022-01-29 01:54:01 +03:00
~|([%fine %request-events-forbidden] !!)
2022-06-04 06:58:50 +03:00
(on-hear-response:fine l shot d)
2019-06-25 03:48:05 +03:00
:: +on-hear-packet: handle mildly processed packet receipt
::
++ on-hear-packet
2020-12-01 17:51:14 +03:00
~/ %on-hear-packet
2022-06-04 06:58:50 +03:00
|= [=lane =shot dud=(unit goof)]
2019-06-25 03:48:05 +03:00
^+ event-core
2022-06-30 17:27:02 +03:00
%- %^ trace odd.veb sndr.shot
2022-05-20 06:20:00 +03:00
|.("received packet")
2019-06-25 03:48:05 +03:00
::
2022-06-04 06:58:50 +03:00
?: =(our sndr.shot)
2019-07-24 03:31:51 +03:00
event-core
::
2019-07-28 10:50:32 +03:00
%. +<
2019-05-28 05:43:47 +03:00
::
2022-06-04 06:58:50 +03:00
?. =(our rcvr.shot)
2019-05-28 05:43:47 +03:00
on-hear-forward
::
2022-06-30 17:27:02 +03:00
?: =(%keys content.shot)
2022-05-20 06:20:00 +03:00
on-hear-keys
2022-06-04 06:58:50 +03:00
?: ?& ?=(%pawn (clan:title sndr.shot))
!?=([~ %known *] (~(get by peers.ames-state) sndr.shot))
2020-12-01 17:51:14 +03:00
==
on-hear-open
on-hear-shut
2019-06-22 00:21:58 +03:00
:: +on-hear-forward: maybe forward a packet to someone else
2019-05-28 05:43:47 +03:00
::
2019-10-30 23:12:57 +03:00
:: Note that this performs all forwarding requests without
:: filtering. Any protection against DDoS amplification will be
:: provided by Vere.
2019-06-22 00:35:07 +03:00
::
2019-05-28 05:43:47 +03:00
++ on-hear-forward
2020-12-01 17:51:14 +03:00
~/ %on-hear-forward
2022-06-04 06:58:50 +03:00
|= [=lane =shot dud=(unit goof)]
2019-05-28 05:43:47 +03:00
^+ event-core
2022-06-04 06:58:50 +03:00
%- %^ trace for.veb sndr.shot
|.("forward: {<sndr.shot>} -> {<rcvr.shot>}")
:: set .origin.shot if it doesn't already have one, re-encode, and send
2019-05-28 05:43:47 +03:00
::
2022-06-04 06:58:50 +03:00
=? origin.shot
&(?=(~ origin.shot) !=(%czar (clan:title sndr.shot)))
2020-12-01 17:51:14 +03:00
?: ?=(%& -.lane)
~
?. (lte (met 3 p.lane) 6)
~| ames-lane-size+p.lane !!
`p.lane
::
2022-06-04 06:58:50 +03:00
=/ =blob (etch-shot shot)
(send-blob & rcvr.shot blob)
2022-05-20 06:20:00 +03:00
:: +on-hear-keys: handle receipt of attestion request
::
++ on-hear-keys
~/ %on-hear-keys
2022-06-30 17:27:02 +03:00
|= [=lane =shot dud=(unit goof)]
=+ %^ trace msg.veb sndr.shot
2022-05-20 06:20:00 +03:00
|.("requested attestation")
?. =(%pawn (clan:title our))
event-core
2022-06-30 17:27:02 +03:00
(send-blob | sndr.shot (attestation-packet sndr.shot 1))
2019-06-18 02:23:32 +03:00
:: +on-hear-open: handle receipt of plaintext comet self-attestation
2019-05-28 05:43:47 +03:00
::
++ on-hear-open
2020-12-01 17:51:14 +03:00
~/ %on-hear-open
2022-06-04 06:58:50 +03:00
|= [=lane =shot dud=(unit goof)]
2019-05-28 05:43:47 +03:00
^+ event-core
2022-06-30 17:27:02 +03:00
=+ %^ trace msg.veb sndr.shot
2022-05-20 06:20:00 +03:00
|.("got attestation")
2020-10-28 00:20:25 +03:00
:: assert the comet can't pretend to be a moon or other address
::
2022-06-04 06:58:50 +03:00
?> ?=(%pawn (clan:title sndr.shot))
2019-06-18 02:23:32 +03:00
:: if we already know .sndr, ignore duplicate attestation
2019-05-28 05:43:47 +03:00
::
2022-06-04 06:58:50 +03:00
=/ ship-state (~(get by peers.ames-state) sndr.shot)
2019-06-18 02:23:32 +03:00
?: ?=([~ %known *] ship-state)
event-core
::
2022-06-04 06:58:50 +03:00
=/ =open-packet (sift-open-packet shot our life.ames-state)
2022-01-30 01:12:18 +03:00
:: add comet as an %alien if we haven't already
::
=? peers.ames-state ?=(~ ship-state)
2022-06-04 06:58:50 +03:00
(~(put by peers.ames-state) sndr.shot %alien *alien-agenda)
2022-01-30 01:12:18 +03:00
:: upgrade comet to %known via on-publ-full
::
=. event-core
=/ crypto-suite=@ud 1
2022-05-20 06:20:00 +03:00
=/ keys
(my [sndr-life.open-packet crypto-suite public-key.open-packet]~)
2022-01-30 01:12:18 +03:00
=/ =point
:* ^= rift 0
^= life sndr-life.open-packet
2022-05-20 06:20:00 +03:00
^= keys keys
2022-06-04 06:58:50 +03:00
^= sponsor `(^sein:title sndr.shot)
2022-01-30 01:12:18 +03:00
==
2022-06-04 06:58:50 +03:00
(on-publ / [%full (my [sndr.shot point]~)])
2022-01-30 01:12:18 +03:00
:: manually add the lane to the peer state
2019-06-18 02:23:32 +03:00
::
=. peers.ames-state
2022-06-04 06:58:50 +03:00
=/ =peer-state (gut-peer-state sndr.shot)
2022-01-30 01:12:18 +03:00
=. route.peer-state `[direct=%.n lane]
2022-06-04 06:58:50 +03:00
(~(put by peers.ames-state) sndr.shot %known peer-state)
2019-06-18 02:23:32 +03:00
::
event-core
2019-06-22 00:35:07 +03:00
:: +on-hear-shut: handle receipt of encrypted packet
2019-05-28 05:43:47 +03:00
::
++ on-hear-shut
2020-12-01 17:51:14 +03:00
~/ %on-hear-shut
2022-06-04 06:58:50 +03:00
|= [=lane =shot dud=(unit goof)]
2019-05-28 05:43:47 +03:00
^+ event-core
2022-06-04 06:58:50 +03:00
=/ sndr-state (~(get by peers.ames-state) sndr.shot)
2022-05-20 06:20:00 +03:00
:: If we don't know them, ask Jael for their keys. If they're a
:: comet, this will also cause us to request a self-attestation
:: from the sender. The packet itself is dropped; we can assume it
:: will be resent.
2019-11-28 04:58:18 +03:00
::
2019-05-28 05:43:47 +03:00
?. ?=([~ %known *] sndr-state)
2022-06-04 06:58:50 +03:00
(enqueue-alien-todo sndr.shot |=(alien-agenda +<))
2019-11-22 05:17:43 +03:00
:: decrypt packet contents using symmetric-key.channel
2019-06-01 06:32:13 +03:00
::
:: If we know them, we have a $channel with them, which we've
:: populated with a .symmetric-key derived from our private key
:: and their public key using elliptic curve Diffie-Hellman.
2019-05-28 05:43:47 +03:00
::
2019-05-28 06:59:53 +03:00
=/ =peer-state +.u.sndr-state
2022-06-04 06:58:50 +03:00
=/ =channel [[our sndr.shot] now channel-state -.peer-state]
2019-11-22 16:42:19 +03:00
~| %ames-crash-on-packet-from^her.channel
2020-12-01 17:51:14 +03:00
=/ =shut-packet
2022-06-04 06:58:50 +03:00
(sift-shut-packet shot [symmetric-key her-life our-life]:channel)
2019-08-08 07:57:04 +03:00
:: non-galaxy: update route with heard lane or forwarded lane
2019-06-22 00:40:38 +03:00
::
2020-12-01 17:51:14 +03:00
=? route.peer-state !=(%czar (clan:title her.channel))
ames: fix lane discovery during some lane changes
We used to not accept new indirect lanes if we already have a direct
lane. This means that if Bob, with a publicly-accessible lane, changes
lanes (eg by restarting the process and getting a new port or changing
ip addresses), tries to talk to Alice, who is behind a NAT, then Bob
will try directly but fail (because Alice is behind a NAT), so he will
route the message through her galaxy. This is good -- the message gets
to Alice. However, Alice had a direct route to Bob's old lane, so she
will try to ack on that lane, which fails. She will not time out this
lane because she doesn't know that Bob isn't getting the acks (acks
don't have their own acks).
The solution is that if Alice receives an indirect lane for Bob when she
already has a direct lane, she shouldn't ignore it. If the lane is the
same as what she has, she shouldn't change anything (in particular, she
shouldn't mark it as indirect). But if it's a new lane, she should
discard her old direct lane and use the new indirect lane.
2020-07-25 06:41:48 +03:00
:: if new packet is direct, use that. otherwise, if the new new
:: and old lanes are indirect, use the new one. if the new lane
:: is indirect but the old lane is direct, then if the lanes are
:: identical, don't mark it indirect; if they're not identical,
:: use the new lane and mark it indirect.
::
:: if you mark lane as indirect because you got an indirect
:: packet even though you already had a direct identical lane,
:: then delayed forwarded packets will come later and reset to
:: indirect, so you're unlikely to get a stable direct route
:: (unless the forwarder goes offline for a while).
::
:: conversely, if you don't accept indirect routes with different
:: lanes, then if your lane is stale and they're trying to talk
:: to you, your acks will go to the stale lane, and you'll never
:: time it out unless you reach out to them. this manifests as
:: needing to |hi or dotpost to get a response when the other
:: ship has changed lanes.
2020-01-13 00:06:27 +03:00
::
2022-06-04 06:58:50 +03:00
?: ?=(~ origin.shot)
2019-08-16 12:26:03 +03:00
`[direct=%.y lane]
ames: fix lane discovery during some lane changes
We used to not accept new indirect lanes if we already have a direct
lane. This means that if Bob, with a publicly-accessible lane, changes
lanes (eg by restarting the process and getting a new port or changing
ip addresses), tries to talk to Alice, who is behind a NAT, then Bob
will try directly but fail (because Alice is behind a NAT), so he will
route the message through her galaxy. This is good -- the message gets
to Alice. However, Alice had a direct route to Bob's old lane, so she
will try to ack on that lane, which fails. She will not time out this
lane because she doesn't know that Bob isn't getting the acks (acks
don't have their own acks).
The solution is that if Alice receives an indirect lane for Bob when she
already has a direct lane, she shouldn't ignore it. If the lane is the
same as what she has, she shouldn't change anything (in particular, she
shouldn't mark it as indirect). But if it's a new lane, she should
discard her old direct lane and use the new indirect lane.
2020-07-25 06:41:48 +03:00
?: ?=([~ %& *] route.peer-state)
2022-06-04 06:58:50 +03:00
?: =(lane.u.route.peer-state |+u.origin.shot)
ames: fix lane discovery during some lane changes
We used to not accept new indirect lanes if we already have a direct
lane. This means that if Bob, with a publicly-accessible lane, changes
lanes (eg by restarting the process and getting a new port or changing
ip addresses), tries to talk to Alice, who is behind a NAT, then Bob
will try directly but fail (because Alice is behind a NAT), so he will
route the message through her galaxy. This is good -- the message gets
to Alice. However, Alice had a direct route to Bob's old lane, so she
will try to ack on that lane, which fails. She will not time out this
lane because she doesn't know that Bob isn't getting the acks (acks
don't have their own acks).
The solution is that if Alice receives an indirect lane for Bob when she
already has a direct lane, she shouldn't ignore it. If the lane is the
same as what she has, she shouldn't change anything (in particular, she
shouldn't mark it as indirect). But if it's a new lane, she should
discard her old direct lane and use the new indirect lane.
2020-07-25 06:41:48 +03:00
route.peer-state
2022-06-04 06:58:50 +03:00
`[direct=%.n |+u.origin.shot]
`[direct=%.n |+u.origin.shot]
2019-08-08 07:57:04 +03:00
:: perform peer-specific handling of packet
2019-05-29 01:05:59 +03:00
::
2019-06-10 19:23:33 +03:00
=/ peer-core (make-peer-core peer-state channel)
2020-12-12 03:49:55 +03:00
abet:(on-hear-shut-packet:peer-core lane shut-packet dud)
2019-07-28 10:50:32 +03:00
:: +on-take-boon: receive request to give message to peer
2019-06-19 02:51:06 +03:00
::
2019-07-28 10:50:32 +03:00
++ on-take-boon
|= [=wire payload=*]
2019-06-19 02:51:06 +03:00
^+ event-core
2022-03-15 00:04:14 +03:00
?: ?=([%fine %pine @ *] wire)
?~ her=(slaw %p i.t.t.wire)
=/ =tape "; fine dropping malformed wire {<wire>}"
(emit duct %pass /parse-wire %d %flog %text tape)
(on-pine-boon:fine u.her t.t.t.wire payload)
2019-06-19 02:51:06 +03:00
::
2022-02-22 18:04:42 +03:00
?~ parsed=(parse-bone-wire wire)
2022-04-22 11:06:53 +03:00
~> %slog.0^leaf/"ames: dropping malformed wire: {(spud wire)}"
event-core
2019-06-21 00:46:31 +03:00
::
2022-02-22 18:04:42 +03:00
?> ?=([@ her=ship *] u.parsed)
2022-04-14 17:36:01 +03:00
=* her her.u.parsed
=/ =peer-state (got-peer-state her)
=/ =channel [[our her] now channel-state -.peer-state]
2022-04-15 10:14:53 +03:00
=/ peer-core (make-peer-core peer-state channel)
2019-06-19 02:51:06 +03:00
::
2022-04-14 17:36:01 +03:00
?: ?& ?=([%new *] u.parsed)
(lth rift.u.parsed rift.peer-state)
==
:: ignore events from an old rift
::
2022-04-22 11:06:53 +03:00
%- %^ trace odd.veb her
|.("dropping old rift wire: {(spud wire)}")
event-core
2022-04-14 17:36:01 +03:00
=/ =bone
?-(u.parsed [%new *] bone.u.parsed, [%old *] bone.u.parsed)
2022-04-22 11:06:53 +03:00
=? peer-core ?=([%old *] u.parsed)
%- %^ trace odd.veb her
|.("parsing old wire: {(spud wire)}")
peer-core
2022-04-15 10:14:53 +03:00
abet:(on-memo:peer-core bone payload %boon)
2019-07-28 10:50:32 +03:00
:: +on-plea: handle request to send message
2019-06-09 09:26:01 +03:00
::
2019-07-28 10:50:32 +03:00
++ on-plea
|= [=ship =plea]
2019-06-09 09:26:01 +03:00
^+ event-core
2019-08-08 07:57:04 +03:00
:: .plea is from local vane to foreign ship
2019-06-09 09:26:01 +03:00
::
2019-06-22 00:35:07 +03:00
=/ ship-state (~(get by peers.ames-state) ship)
2019-06-09 09:26:01 +03:00
::
2019-06-22 00:35:07 +03:00
?. ?=([~ %known *] ship-state)
2019-06-25 00:13:45 +03:00
%+ enqueue-alien-todo ship
2019-10-30 23:12:57 +03:00
|= todos=alien-agenda
todos(messages [[duct plea] messages.todos])
2022-03-15 00:04:14 +03:00
::
?: &(=(/pine path.plea) =(our her:;;(balk payload.plea)))
(on-pine-plea:fine ship payload.plea)
2019-06-09 09:26:01 +03:00
::
2019-06-22 00:35:07 +03:00
=/ =peer-state +.u.ship-state
2019-12-03 02:46:40 +03:00
=/ =channel [[our ship] now channel-state -.peer-state]
2019-06-09 09:26:01 +03:00
::
2019-08-05 23:58:53 +03:00
=^ =bone ossuary.peer-state (bind-duct ossuary.peer-state duct)
2019-12-11 21:55:16 +03:00
%- %^ trace msg.veb ship
2019-11-15 03:10:48 +03:00
|. ^- tape
=/ sndr [our our-life.channel]
=/ rcvr [ship her-life.channel]
2020-12-12 03:45:13 +03:00
"plea {<sndr^rcvr^bone=bone^vane.plea^path.plea>}"
2019-06-21 00:46:31 +03:00
::
2019-11-27 07:52:43 +03:00
abet:(on-memo:(make-peer-core peer-state channel) bone plea %plea)
2019-06-19 02:59:25 +03:00
:: +on-take-wake: receive wakeup or error notification from behn
::
++ on-take-wake
|= [=wire error=(unit tang)]
^+ event-core
2022-02-12 04:30:40 +03:00
?: ?=([%fine %behn %wake *] wire)
(on-take-wake:fine t.t.t.wire error)
2019-06-19 02:59:25 +03:00
::
2022-02-28 07:32:12 +03:00
?: ?=([%alien @ ~] wire)
:: if we haven't received an attestation, ask again
::
?^ error
%- (slog leaf+"ames: attestation timer failed: {<u.error>}" ~)
event-core
?~ ship=`(unit @p)`(slaw %p i.t.wire)
%- (slog leaf+"ames: got timer for strange wire: {<wire>}" ~)
event-core
=/ ship-state (~(get by peers.ames-state) u.ship)
?: ?=([~ %known *] ship-state)
event-core
(request-attestation u.ship)
::
2019-12-02 03:00:32 +03:00
=/ res=(unit [her=ship =bone]) (parse-pump-timer-wire wire)
?~ res
2019-12-03 10:13:48 +03:00
%- (slog leaf+"ames: got timer for strange wire: {<wire>}" ~)
2019-12-02 03:00:32 +03:00
event-core
2019-06-22 00:35:07 +03:00
::
2019-12-02 03:00:32 +03:00
=/ state=(unit peer-state) (get-peer-state her.u.res)
?~ state
2019-12-03 10:13:48 +03:00
%- (slog leaf+"ames: got timer for strange ship: {<her.u.res>}, ignoring" ~)
2019-12-02 03:00:32 +03:00
event-core
::
2019-12-03 02:46:40 +03:00
=/ =channel [[our her.u.res] now channel-state -.u.state]
2019-06-22 00:35:07 +03:00
::
2019-12-02 03:00:32 +03:00
abet:(on-wake:(make-peer-core u.state channel) bone.u.res error)
2019-06-22 01:25:18 +03:00
:: +on-init: first boot; subscribe to our info from jael
::
++ on-init
^+ event-core
::
2019-08-20 00:43:39 +03:00
=~ (emit duct %pass /turf %j %turf ~)
(emit duct %pass /private-keys %j %private-keys ~)
2019-06-25 00:48:53 +03:00
==
2019-06-25 02:52:22 +03:00
:: +on-priv: set our private key to jael's response
::
++ on-priv
2019-07-23 05:16:19 +03:00
|= [=life vein=(map life private-key)]
2019-06-25 02:52:22 +03:00
^+ event-core
::
2019-07-23 05:16:19 +03:00
=/ =private-key (~(got by vein) life)
2019-06-25 02:52:22 +03:00
=. life.ames-state life
=. crypto-core.ames-state (nol:nu:crub:crypto private-key)
2019-06-25 22:55:51 +03:00
:: recalculate each peer's symmetric key
::
=/ our-private-key sec:ex:crypto-core.ames-state
=. peers.ames-state
%- ~(run by peers.ames-state)
|= =ship-state
^+ ship-state
::
?. ?=(%known -.ship-state)
ship-state
::
=/ =peer-state +.ship-state
=. symmetric-key.peer-state
(derive-symmetric-key public-key.+.ship-state our-private-key)
::
[%known peer-state]
2019-06-25 02:52:22 +03:00
::
event-core
:: +on-publ: update pki data for peer or self
::
++ on-publ
2019-07-29 12:08:26 +03:00
|= [=wire =public-keys-result]
2019-06-25 02:52:22 +03:00
^+ event-core
::
|^ ^+ event-core
::
2019-07-29 12:08:26 +03:00
?- public-keys-result
[%diff @ %rift *]
2022-02-22 18:04:42 +03:00
:: event-core
(on-publ-rift [who to.diff]:public-keys-result)
2019-06-25 02:52:22 +03:00
::
2019-07-29 12:08:26 +03:00
[%diff @ %keys *]
(on-publ-rekey [who to.diff]:public-keys-result)
2019-06-25 02:52:22 +03:00
::
2019-07-29 12:08:26 +03:00
[%diff @ %spon *]
(on-publ-sponsor [who to.diff]:public-keys-result)
2019-06-25 02:52:22 +03:00
::
2019-10-30 23:12:57 +03:00
[%full *]
(on-publ-full points.public-keys-result)
2019-11-03 07:07:51 +03:00
::
[%breach *]
(on-publ-breach who.public-keys-result)
2019-06-25 02:52:22 +03:00
==
2019-06-25 02:56:27 +03:00
:: +on-publ-breach: handle continuity breach of .ship; wipe its state
::
2019-08-23 06:53:45 +03:00
:: Abandon all pretense of continuity and delete all messaging state
2019-06-25 02:56:27 +03:00
:: associated with .ship, including sent and unsent messages.
2019-12-21 09:56:51 +03:00
:: Also cancel all timers related to .ship.
2019-06-25 02:56:27 +03:00
::
2019-06-25 02:52:22 +03:00
++ on-publ-breach
2019-11-03 07:07:51 +03:00
|= =ship
2019-06-25 02:52:22 +03:00
^+ event-core
::
2019-08-23 05:51:51 +03:00
=/ ship-state (~(get by peers.ames-state) ship)
:: we shouldn't be hearing about ships we don't care about
::
?~ ship-state
2019-11-03 07:07:51 +03:00
~> %slog.0^leaf/"ames: breach unknown {<our^ship>}"
2019-08-23 05:51:51 +03:00
event-core
:: if an alien breached, this doesn't affect us
::
2019-08-23 06:53:45 +03:00
?: ?=([~ %alien *] ship-state)
2019-11-03 07:07:51 +03:00
~> %slog.0^leaf/"ames: breach alien {<our^ship>}"
2019-08-23 05:51:51 +03:00
event-core
2019-11-03 07:07:51 +03:00
~> %slog.0^leaf/"ames: breach peer {<our^ship>}"
2019-08-23 05:51:51 +03:00
:: a peer breached; drop messaging state
::
=/ =peer-state +.u.ship-state
2019-08-23 06:53:45 +03:00
=/ old-qos=qos qos.peer-state
2019-11-22 05:20:39 +03:00
:: cancel all timers related to .ship
::
2019-11-22 05:22:05 +03:00
=. event-core
2019-11-22 05:20:39 +03:00
%+ roll ~(tap by snd.peer-state)
2019-11-22 05:22:05 +03:00
|= [[=snd=bone =message-pump-state] core=_event-core]
2019-11-22 05:20:39 +03:00
^+ core
::
2019-11-22 05:23:34 +03:00
?~ next-wake=next-wake.packet-pump-state.message-pump-state
2019-11-22 05:20:39 +03:00
core
:: note: copies +on-pump-rest:message-pump
::
2019-11-22 05:24:34 +03:00
=/ wire (make-pump-timer-wire ship snd-bone)
=/ duct ~[/ames]
2019-11-22 05:20:39 +03:00
(emit:core duct %pass wire %b %rest u.next-wake)
2019-08-23 06:53:45 +03:00
:: reset all peer state other than pki data
::
=. +.peer-state +:*^peer-state
:: print change to quality of service, if any
::
=/ text=(unit tape) (qos-update-text ship old-qos qos.peer-state)
::
=? event-core ?=(^ text)
(emit duct %pass /qos %d %flog %text u.text)
:: reinitialize galaxy route if applicable
::
=? route.peer-state =(%czar (clan:title ship))
`[direct=%.y lane=[%& ship]]
::
2019-08-23 05:51:51 +03:00
=. peers.ames-state
2019-08-23 06:53:45 +03:00
(~(put by peers.ames-state) ship [%known peer-state])
2019-08-23 05:51:51 +03:00
::
2019-06-25 02:56:27 +03:00
event-core
2019-06-25 03:14:02 +03:00
:: +on-publ-rekey: handle new key for peer
::
:: TODO: assert .crypto-suite compatibility
2019-06-25 02:52:22 +03:00
::
++ on-publ-rekey
|= $: =ship
=life
crypto-suite=@ud
2019-07-23 05:16:19 +03:00
=public-key
2019-06-25 02:52:22 +03:00
==
^+ event-core
::
2019-08-14 03:56:56 +03:00
=/ ship-state (~(get by peers.ames-state) ship)
?. ?=([~ %known *] ship-state)
=| =point
=. life.point life
=. keys.point (my [life crypto-suite public-key]~)
2021-09-25 23:52:53 +03:00
=. sponsor.point `(^^sein:title rof our now ship)
2019-08-14 03:56:56 +03:00
::
(on-publ-full (my [ship point]~))
::
=/ =peer-state +.u.ship-state
::
=/ =private-key sec:ex:crypto-core.ames-state
=. symmetric-key.peer-state
(derive-symmetric-key public-key private-key)
::
=. life.peer-state life
=. public-key.peer-state public-key
::
=. peers.ames-state (~(put by peers.ames-state) ship %known peer-state)
event-core
2019-08-10 00:20:16 +03:00
:: +on-publ-sponsor: handle new or lost sponsor for peer
2019-06-25 03:30:43 +03:00
::
:: TODO: handle sponsor loss
2019-06-25 02:52:22 +03:00
::
++ on-publ-sponsor
|= [=ship sponsor=(unit ship)]
^+ event-core
::
2019-06-25 03:16:32 +03:00
?~ sponsor
2019-08-10 21:48:40 +03:00
~| %ames-lost-sponsor^our^ship !!
2019-06-25 03:16:32 +03:00
::
2022-01-18 22:34:32 +03:00
=/ state=(unit peer-state) (get-peer-state ship)
?~ state
%- (slog leaf+"ames: missing peer-state, ignoring" ~)
event-core
=. sponsor.u.state u.sponsor
=. peers.ames-state (~(put by peers.ames-state) ship %known u.state)
2019-06-25 03:16:32 +03:00
event-core
2019-06-25 03:30:43 +03:00
:: +on-publ-full: handle new pki data for peer(s)
2019-06-25 02:52:22 +03:00
::
++ on-publ-full
|= points=(map ship point)
^+ event-core
::
2019-06-25 03:30:43 +03:00
=> .(points ~(tap by points))
|^ ^+ event-core
?~ points event-core
::
2019-08-06 03:00:04 +03:00
=+ ^- [=ship =point] i.points
2019-06-25 03:30:43 +03:00
::
2019-12-05 01:03:13 +03:00
?. (~(has by keys.point) life.point)
$(points t.points)
::
2019-08-14 03:56:56 +03:00
=/ old-ship-state (~(get by peers.ames-state) ship)
::
=. event-core (insert-peer-state ship point)
::
=? event-core ?=([~ %alien *] old-ship-state)
(meet-alien ship point +.u.old-ship-state)
2019-06-25 03:30:43 +03:00
::
$(points t.points)
::
++ meet-alien
2019-10-30 23:12:57 +03:00
|= [=ship =point todos=alien-agenda]
2019-06-25 03:30:43 +03:00
^+ event-core
2019-08-23 08:53:38 +03:00
:: if we're a comet, send self-attestation packet first
2019-06-26 21:45:07 +03:00
::
=? event-core =(%pawn (clan:title our))
2019-12-11 03:20:12 +03:00
(send-blob | ship (attestation-packet ship life.point))
2019-11-27 01:56:20 +03:00
:: save current duct
::
=/ original-duct duct
:: apply heeds
::
=. event-core
%+ roll ~(tap in heeds.todos)
|= [=^duct core=_event-core]
(on-heed:core(duct duct) ship)
2019-10-05 06:38:32 +03:00
:: apply outgoing messages, reversing for FIFO order
2019-06-25 03:48:05 +03:00
::
=. event-core
2019-10-30 23:12:57 +03:00
%+ reel messages.todos
2019-10-05 06:21:29 +03:00
|= [[=^duct =plea] core=_event-core]
(on-plea:core(duct duct) ship plea)
2019-06-26 21:45:07 +03:00
:: apply outgoing packet blobs
2019-06-25 03:48:05 +03:00
::
=. event-core
2019-10-30 23:12:57 +03:00
%+ roll ~(tap in packets.todos)
2019-10-05 06:21:29 +03:00
|= [=blob core=_event-core]
2019-12-11 03:20:12 +03:00
(send-blob:core | ship blob)
2022-01-29 01:09:50 +03:00
:: apply remote scry requests
::
2022-01-29 01:54:01 +03:00
=. event-core
2022-03-15 19:40:34 +03:00
=+ pe-core=(need (pe-abed:fine-peer:fine ship))
=. pe-core (pe-meet-alien-keen:pe-core keens.todos)
=. pe-core (pe-meet-alien-pine:pe-core pines.todos)
pe-abet:pe-core
2019-06-25 03:48:05 +03:00
::
2019-11-27 01:56:20 +03:00
event-core(duct original-duct)
2019-06-25 03:30:43 +03:00
--
2022-02-22 18:04:42 +03:00
:: on-publ-rift: XX
::
++ on-publ-rift
|= [=ship =rift]
^+ event-core
?~ ship-state=(~(get by peers.ames-state) ship)
:: print error here? %rift was probably called before %keys
::
2022-03-11 11:40:14 +03:00
~> %slog.1^leaf/"ames: missing peer-state on-publ-rift"
2022-02-22 18:04:42 +03:00
event-core
?: ?=([%alien *] u.ship-state)
:: ignore aliens
::
event-core
=/ =peer-state +.u.ship-state
=. rift.peer-state rift
=. peers.ames-state (~(put by peers.ames-state) ship %known peer-state)
event-core
2019-06-25 03:48:05 +03:00
::
++ insert-peer-state
2019-08-14 03:56:56 +03:00
|= [=ship =point]
2019-06-25 03:48:05 +03:00
^+ event-core
::
2019-08-14 03:56:56 +03:00
=/ =peer-state (gut-peer-state ship)
=/ =public-key pass:(~(got by keys.point) life.point)
2019-06-25 03:48:05 +03:00
=/ =private-key sec:ex:crypto-core.ames-state
=/ =symmetric-key (derive-symmetric-key public-key private-key)
::
2019-12-01 09:37:04 +03:00
=. qos.peer-state [%unborn now]
2019-08-14 03:56:56 +03:00
=. life.peer-state life.point
2019-06-25 03:48:05 +03:00
=. public-key.peer-state public-key
=. symmetric-key.peer-state symmetric-key
2019-12-05 01:03:13 +03:00
=. sponsor.peer-state
?^ sponsor.point
u.sponsor.point
2021-09-25 23:52:53 +03:00
(^^sein:title rof our now ship)
2019-07-24 02:55:35 +03:00
:: automatically set galaxy route, since unix handles lookup
::
=? route.peer-state ?=(%czar (clan:title ship))
`[direct=%.y lane=[%& ship]]
2019-06-25 03:48:05 +03:00
::
=. peers.ames-state
(~(put by peers.ames-state) ship %known peer-state)
::
event-core
2019-06-25 02:52:22 +03:00
--
2019-06-22 01:17:09 +03:00
:: +on-take-turf: relay %turf move from jael to unix
::
++ on-take-turf
|= turfs=(list turf)
^+ event-core
::
(emit unix-duct.ames-state %give %turf turfs)
2019-06-22 01:26:26 +03:00
:: +on-born: handle unix process restart
2019-07-25 01:56:13 +03:00
::
2019-07-31 05:31:15 +03:00
++ on-born
^+ event-core
::
=. unix-duct.ames-state duct
::
=/ turfs
;; (list turf)
=< q.q %- need %- need
2020-12-06 13:55:19 +03:00
(rof ~ %j `beam`[[our %turf %da now] /])
2019-07-31 05:31:15 +03:00
::
(emit unix-duct.ames-state %give %turf turfs)
2019-06-22 01:19:24 +03:00
:: +on-vega: handle kernel reload
2020-05-20 10:29:54 +03:00
:: +on-trim: handle request to free memory
2019-06-22 01:19:24 +03:00
::
++ on-vega event-core
2022-01-27 16:32:49 +03:00
++ on-trim event-core ::TODO trim fine parts on high prio
2019-06-25 00:13:45 +03:00
:: +enqueue-alien-todo: helper to enqueue a pending request
::
2019-06-26 21:45:07 +03:00
:: Also requests key and life from Jael on first request.
2022-02-28 07:32:12 +03:00
:: If talking to a comet, requests attestation packet.
2019-06-25 00:13:45 +03:00
::
++ enqueue-alien-todo
2019-10-30 23:12:57 +03:00
|= [=ship mutate=$-(alien-agenda alien-agenda)]
2019-06-25 00:13:45 +03:00
^+ event-core
::
=/ ship-state (~(get by peers.ames-state) ship)
2019-10-30 23:12:57 +03:00
:: create a default $alien-agenda on first contact
2019-06-25 00:13:45 +03:00
::
2019-10-30 23:12:57 +03:00
=+ ^- [already-pending=? todos=alien-agenda]
2019-06-25 00:13:45 +03:00
?~ ship-state
2019-10-30 23:12:57 +03:00
[%.n *alien-agenda]
2019-06-25 00:13:45 +03:00
[%.y ?>(?=(%alien -.u.ship-state) +.u.ship-state)]
:: mutate .todos and apply to permanent state
::
=. todos (mutate todos)
=. peers.ames-state (~(put by peers.ames-state) ship %alien todos)
?: already-pending
event-core
2022-01-30 01:12:18 +03:00
::
2022-02-28 07:32:12 +03:00
?: =(%pawn (clan:title ship))
(request-attestation ship)
2020-05-29 00:27:08 +03:00
:: NB: we specifically look for this wire in +public-keys-give in
:: Jael. if you change it here, you must change it there.
::
2019-08-20 00:43:39 +03:00
(emit duct %pass /public-keys %j %public-keys [n=ship ~ ~])
2022-02-28 07:32:12 +03:00
:: +request-attestation: helper to request attestation from comet
::
:: Also sets a timer to resend the request every 30s.
::
++ request-attestation
|= =ship
^+ event-core
2022-05-21 04:28:20 +03:00
=+ (trace msg.veb ship |.("requesting attestion"))
2022-05-20 06:20:00 +03:00
=. event-core (send-blob | ship (sendkeys-packet ship))
2022-02-28 07:32:12 +03:00
=/ =wire /alien/(scot %p ship)
(emit duct %pass wire %b %wait (add now ~s30))
2019-06-22 03:07:19 +03:00
:: +send-blob: fire packet at .ship and maybe sponsors
::
2019-11-28 07:06:39 +03:00
:: Send to .ship and sponsors until we find a direct lane,
:: skipping .our in the sponsorship chain.
2019-08-16 12:26:03 +03:00
::
2019-06-22 03:07:19 +03:00
:: If we have no PKI data for a recipient, enqueue the packet and
:: request the information from Jael if we haven't already.
::
++ send-blob
2020-12-01 17:51:14 +03:00
~/ %send-blob
2019-12-11 03:20:12 +03:00
|= [for=? =ship =blob]
2019-06-22 03:07:19 +03:00
::
2019-12-12 04:59:21 +03:00
=/ final-ship ship
%- (trace rot.veb final-ship |.("send-blob: to {<ship>}"))
ames: don't overwrite lane if already direct
This is why basically all packets are going through the galaxies right
now. Most of the time, the flow right now is:
* talking to ~dopzod but don't know where it is, so ask ~zod to forward,
which it does
* ~dopzod responds both directly (on the origin lane) and through ~zod
* (if NAT, the direct response doesn't get back, but the one through
~zod does. Then you respond directly to ~dopzod because their lane
piggybacked on the response. ~dopzod responds both directly and
through ~zod, and the story picks up the same as if you weren't behind a
NAT)
* now you have a direct lane to ~dopzod, so all is well.
* now the duplicate response from ~dopzod through ~zod comes in (takes a
little longer because it's bouncing off ~zod), resetting your lane to
"provisional"
* since your lane is provisional, you send your next packet both
directly and through ~zod
* GOTO 2
This change says "if I already have a direct lane, don't overwrite it
with a provisional one". This way, the only way the direct lane can be
overwritten is if they stop responding on it (cleared on "not
responding; still trying").
I also added |- to +send-blob to make |ames-verb %rot less confusing.
2019-12-05 06:39:34 +03:00
|-
2019-08-16 12:26:03 +03:00
|^ ^+ event-core
::
=/ ship-state (~(get by peers.ames-state) ship)
::
?. ?=([~ %known *] ship-state)
2022-02-03 05:17:05 +03:00
?: ?=(%pawn (clan:title ship))
(try-next-sponsor (^sein:title ship))
2019-08-16 12:26:03 +03:00
%+ enqueue-alien-todo ship
2019-10-30 23:12:57 +03:00
|= todos=alien-agenda
todos(packets (~(put in packets.todos) blob))
2019-08-16 12:26:03 +03:00
::
=/ =peer-state +.u.ship-state
::
2019-12-17 09:57:11 +03:00
:: XX routing hack to mimic old ames.
::
:: Before removing this, consider: moons when their planet is
:: behind a NAT; a planet receiving initial acknowledgment
:: from a star; a planet talking to another planet under
:: another galaxy.
::
?: ?| =(our ship)
?& !=(final-ship ship)
!=(%czar (clan:title ship))
==
==
(try-next-sponsor sponsor.peer-state)
::
2019-11-28 07:06:39 +03:00
?: =(our ship)
2019-12-11 03:20:12 +03:00
:: if forwarding, don't send to sponsor to avoid loops
::
?: for
event-core
2019-11-28 07:06:39 +03:00
(try-next-sponsor sponsor.peer-state)
::
2019-08-16 12:26:03 +03:00
?~ route=route.peer-state
2019-12-12 04:59:21 +03:00
%- (trace rot.veb final-ship |.("no route to: {<ship>}"))
2019-08-16 12:26:03 +03:00
(try-next-sponsor sponsor.peer-state)
::
2019-12-12 04:59:21 +03:00
%- (trace rot.veb final-ship |.("trying route: {<ship>}"))
2019-08-16 12:26:03 +03:00
=. event-core
(emit unix-duct.ames-state %give %send lane.u.route blob)
::
?: direct.u.route
event-core
(try-next-sponsor sponsor.peer-state)
2019-06-22 03:07:19 +03:00
::
2019-08-16 12:26:03 +03:00
++ try-next-sponsor
|= sponsor=^ship
^+ event-core
::
?: =(ship sponsor)
2019-06-22 03:07:19 +03:00
event-core
2019-08-16 12:26:03 +03:00
^$(ship sponsor)
--
2019-07-30 04:03:40 +03:00
:: +attestation-packet: generate signed self-attestation for .her
::
:: Sent by a comet on first contact with a peer. Not acked.
::
++ attestation-packet
|= [her=ship =her=life]
^- blob
2022-06-04 06:58:50 +03:00
%- etch-shot
%- etch-open-packet
2020-12-01 17:51:14 +03:00
:_ crypto-core.ames-state
:* ^= public-key pub:ex:crypto-core.ames-state
^= sndr our
^= sndr-life life.ames-state
^= rcvr her
^= rcvr-life her-life
==
2022-02-09 09:59:30 +03:00
:: +sendkeys-packet: generate a request for a self-attestation.
::
:: Sent by non-comets to comets. Not acked.
::
++ sendkeys-packet
|= her=ship
^- blob
?> ?=(%pawn (clan:title her))
2022-06-04 06:58:50 +03:00
%- etch-shot
2022-05-20 06:20:00 +03:00
(encode-keys-packet our her life.ames-state)
2019-12-02 03:00:32 +03:00
:: +get-peer-state: lookup .her state or ~
::
++ get-peer-state
|= her=ship
^- (unit peer-state)
::
=- ?.(?=([~ %known *] -) ~ `+.u)
(~(get by peers.ames-state) her)
2019-06-25 00:32:53 +03:00
:: +got-peer-state: lookup .her state or crash
::
++ got-peer-state
|= her=ship
^- peer-state
::
~| %freaky-alien^her
=- ?>(?=(%known -<) ->)
(~(got by peers.ames-state) her)
2019-08-14 03:56:56 +03:00
:: +gut-peer-state: lookup .her state or default
::
++ gut-peer-state
|= her=ship
^- peer-state
=/ ship-state (~(get by peers.ames-state) her)
?. ?=([~ %known *] ship-state)
*peer-state
+.u.ship-state
2019-06-09 09:26:01 +03:00
:: +make-peer-core: create nested |peer-core for per-peer processing
2019-06-05 07:36:10 +03:00
::
++ make-peer-core
|= [=peer-state =channel]
2019-12-11 21:55:16 +03:00
=* veb veb.bug.channel
2019-06-05 07:36:10 +03:00
|%
++ peer-core .
++ emit |=(move peer-core(event-core (^emit +<)))
++ abet
^+ event-core
::
=. peers.ames-state
(~(put by peers.ames-state) her.channel %known peer-state)
::
event-core
2019-12-11 21:55:16 +03:00
++ trace
|= [verb=? print=(trap tape)]
^+ same
(^trace verb her.channel print)
2019-11-04 04:35:45 +03:00
++ on-heed peer-core(heeds.peer-state (~(put in heeds.peer-state) duct))
++ on-jilt peer-core(heeds.peer-state (~(del in heeds.peer-state) duct))
2019-08-08 07:57:04 +03:00
:: +update-qos: update and maybe print connection status
::
++ update-qos
|= =new=qos
^+ peer-core
::
=^ old-qos qos.peer-state [qos.peer-state new-qos]
2019-11-04 04:35:45 +03:00
:: if no update worth reporting, we're done
2019-08-08 07:57:04 +03:00
::
?~ text=(qos-update-text her.channel old-qos new-qos)
peer-core
2019-11-04 04:35:45 +03:00
:: print message
::
=. peer-core (emit duct %pass /qos %d %flog %text u.text)
2019-11-27 07:52:43 +03:00
:: if peer has stopped responding, check if %boon's are backing up
2019-11-04 04:35:45 +03:00
::
?. ?=(?(%dead %unborn) -.qos.peer-state)
peer-core
2019-11-27 07:52:43 +03:00
check-clog
:: +check-clog: notify clients if peer has stopped responding
::
++ check-clog
^+ peer-core
2019-11-04 04:35:45 +03:00
::
2019-11-22 16:43:08 +03:00
:: Only look at response bones. Request bones are unregulated,
:: since requests tend to be much smaller than responses.
::
=/ pumps=(list message-pump-state)
%+ murn ~(tap by snd.peer-state)
|= [=bone =message-pump-state]
2020-12-04 01:25:31 +03:00
?: =(0 (end 0 bone))
2019-11-22 16:43:08 +03:00
~
`u=message-pump-state
:: clogged: are five or more response messages unsent to this peer?
::
=/ clogged=?
=| acc=@ud
|- ^- ?
?~ pumps
%.n
2019-11-28 02:58:38 +03:00
=. acc
%+ add acc
%+ add
:: in-flight messages
::
(sub [next current]:i.pumps)
:: queued messages
::
~(wyt in unsent-messages.i.pumps)
::
2019-11-22 16:43:08 +03:00
?: (gte acc 5)
%.y
$(pumps t.pumps)
:: if clogged, notify client vanek
::
?. clogged
peer-core
2019-11-04 04:35:45 +03:00
%+ roll ~(tap in heeds.peer-state)
|=([d=^duct core=_peer-core] (emit:core d %give %clog her.channel))
2019-06-10 19:23:33 +03:00
:: +on-hear-shut-packet: handle receipt of ack or message fragment
2019-06-05 07:36:10 +03:00
::
2019-06-10 19:23:33 +03:00
++ on-hear-shut-packet
2020-12-12 03:49:55 +03:00
|= [=lane =shut-packet dud=(unit goof)]
2019-06-05 07:36:10 +03:00
^+ peer-core
2019-08-08 07:57:04 +03:00
:: update and print connection status
::
2019-08-08 08:18:25 +03:00
=. peer-core (update-qos %live last-contact=now)
2019-06-05 07:36:10 +03:00
::
2019-06-11 23:22:24 +03:00
=/ =bone bone.shut-packet
2019-06-05 07:36:10 +03:00
::
2019-06-10 19:13:11 +03:00
?: ?=(%& -.meat.shut-packet)
2021-03-19 03:04:08 +03:00
=+ ?. &(?=(^ dud) msg.veb) ~
2021-02-19 05:47:02 +03:00
%. ~
2021-03-19 03:04:08 +03:00
%- slog
:_ tang.u.dud
leaf+"ames: {<her.channel>} fragment crashed {<mote.u.dud>}"
2020-12-12 03:49:55 +03:00
(run-message-sink bone %hear lane shut-packet ?=(~ dud))
:: Just try again on error, printing trace
2019-08-06 02:05:40 +03:00
::
2019-12-10 11:21:03 +03:00
:: Note this implies that vanes should never crash on %done,
:: since we have no way to continue using the flow if they do.
::
2020-12-12 03:49:55 +03:00
=+ ?~ dud ~
%. ~
2021-02-19 19:54:34 +03:00
%+ slog leaf+"ames: {<her.channel>} ack crashed {<mote.u.dud>}"
2021-02-27 07:53:27 +03:00
?. msg.veb ~
:- >[bone=bone message-num=message-num meat=meat]:shut-packet<
tang.u.dud
2019-06-20 10:21:37 +03:00
(run-message-pump bone %hear [message-num +.meat]:shut-packet)
2019-06-20 11:18:07 +03:00
:: +on-memo: handle request to send message
::
++ on-memo
2019-11-27 07:52:43 +03:00
|= [=bone payload=* valence=?(%plea %boon)]
2019-06-20 11:18:07 +03:00
^+ peer-core
2021-01-20 23:29:45 +03:00
=/ =message-blob (dedup-message (jim payload))
2019-11-27 07:52:43 +03:00
=. peer-core (run-message-pump bone %memo message-blob)
::
2021-05-04 00:33:56 +03:00
?: ?& =(%boon valence)
(gte now (add ~s30 last-contact.qos.peer-state))
==
2019-11-27 07:52:43 +03:00
check-clog
peer-core
2020-05-02 08:55:14 +03:00
:: +dedup-message: replace with any existing copy of this message
::
++ dedup-message
|= =message-blob
^+ message-blob
2020-05-05 07:18:26 +03:00
?: (lte (met 13 message-blob) 1)
message-blob
2020-05-02 08:55:14 +03:00
=/ peers-l=(list [=ship =ship-state]) ~(tap by peers.ames-state)
|- ^+ message-blob
=* peer-loop $
?~ peers-l
message-blob
?. ?=(%known -.ship-state.i.peers-l)
peer-loop(peers-l t.peers-l)
=/ snd-l=(list [=bone =message-pump-state])
~(tap by snd.ship-state.i.peers-l)
|- ^+ message-blob
=* bone-loop $
?~ snd-l
peer-loop(peers-l t.peers-l)
=/ blob-l=(list ^message-blob)
~(tap to unsent-messages.message-pump-state.i.snd-l)
|- ^+ message-blob
=* blob-loop $
2020-05-02 13:33:28 +03:00
?^ blob-l
?: =(i.blob-l message-blob)
i.blob-l
blob-loop(blob-l t.blob-l)
?~ unsent-fragments.message-pump-state.i.snd-l
2020-05-02 08:55:14 +03:00
bone-loop(snd-l t.snd-l)
2020-05-02 13:33:28 +03:00
?: =(message-blob fragment.i.unsent-fragments.message-pump-state.i.snd-l)
`@`fragment.i.unsent-fragments.message-pump-state.i.snd-l
bone-loop(snd-l t.snd-l)
2019-06-22 00:35:07 +03:00
:: +on-wake: handle timer expiration
::
++ on-wake
|= [=bone error=(unit tang)]
^+ peer-core
2019-11-22 03:52:57 +03:00
:: if we previously errored out, print and reset timer for later
2019-06-22 00:35:07 +03:00
::
2019-11-22 03:52:57 +03:00
:: This really shouldn't happen, but if it does, make sure we
:: don't brick either this messaging flow or Behn.
::
?^ error
=. peer-core
(emit duct %pass /wake-fail %d %flog %crud %ames-wake u.error)
::
2019-11-22 05:13:09 +03:00
?~ message-pump-state=(~(get by snd.peer-state) bone)
peer-core
?~ next-wake.packet-pump-state.u.message-pump-state
peer-core
2020-05-28 03:38:18 +03:00
:: If we crashed because we woke up too early, assume another
:: timer is already set.
::
?: (lth now.channel u.next-wake.packet-pump-state.u.message-pump-state)
peer-core
2019-11-22 05:13:09 +03:00
::
2019-11-22 03:52:57 +03:00
=/ =wire (make-pump-timer-wire her.channel bone)
2019-11-22 04:41:17 +03:00
(emit duct %pass wire %b %wait (add now.channel ~s30))
2019-08-08 07:57:04 +03:00
:: update and print connection state
::
=. peer-core %- update-qos
2019-12-01 09:37:04 +03:00
=/ expiry=@da (add ~s30 last-contact.qos.peer-state)
=? -.qos.peer-state
(gte now.channel expiry)
%dead
qos.peer-state
2019-06-25 00:09:42 +03:00
:: expire direct route
::
2019-12-01 09:37:04 +03:00
:: If the peer is not responding, mark the .lane.route as
2019-06-25 00:09:42 +03:00
:: indirect. The next packets we emit will be sent to the
:: receiver's sponsorship chain in case the receiver's
:: transport address has changed and this lane is no longer
:: valid.
::
2019-07-30 04:03:40 +03:00
:: If .her is a galaxy, the lane will always remain direct.
::
2019-07-24 02:20:21 +03:00
=? route.peer-state
2019-12-01 09:37:04 +03:00
?& ?=(%dead -.qos.peer-state)
?=(^ route.peer-state)
2019-07-24 02:55:35 +03:00
direct.u.route.peer-state
!=(%czar (clan:title her.channel))
==
2019-07-24 02:20:21 +03:00
route.peer-state(direct.u %.n)
2019-07-30 04:03:40 +03:00
:: resend comet attestation packet if first message times out
::
:: The attestation packet doesn't get acked, so if we tried to
:: send a packet but it timed out, maybe they didn't get our
:: attestation.
::
:: Only resend on timeout of packets in the first message we
:: send them, since they should remember forever.
::
=? event-core
?& ?=(%pawn (clan:title our))
=(1 current:(~(got by snd.peer-state) bone))
==
2019-12-11 03:20:12 +03:00
(send-blob | her.channel (attestation-packet [her her-life]:channel))
2019-07-30 04:03:40 +03:00
:: maybe resend some timed out packets
2019-06-25 00:09:42 +03:00
::
2019-06-22 00:35:07 +03:00
(run-message-pump bone %wake ~)
2019-07-28 10:50:32 +03:00
:: +send-shut-packet: fire encrypted packet at rcvr and maybe sponsors
::
++ send-shut-packet
|= =shut-packet
^+ peer-core
2019-12-21 09:56:51 +03:00
:: swizzle last bone bit before sending
::
:: The peer has the opposite perspective from ours about what
:: kind of flow this is (forward/backward), so flip the bit
:: here.
2019-07-28 10:50:32 +03:00
::
2020-12-01 17:51:14 +03:00
=. event-core
%^ send-blob | her.channel
2022-06-04 06:58:50 +03:00
%- etch-shot
%: etch-shut-packet
2020-12-01 17:51:14 +03:00
shut-packet(bone (mix 1 bone.shut-packet))
symmetric-key.channel
our her.channel
our-life.channel her-life.channel
==
2019-07-28 10:50:32 +03:00
peer-core
2019-08-05 23:58:53 +03:00
:: +got-duct: look up $duct by .bone, asserting already bound
::
++ got-duct
|= =bone
^- ^duct
~| %dangling-bone^her.channel^bone
(~(got by by-bone.ossuary.peer-state) bone)
2019-06-10 19:13:11 +03:00
:: +run-message-pump: process $message-pump-task and its effects
2019-06-09 09:26:01 +03:00
::
++ run-message-pump
|= [=bone task=message-pump-task]
^+ peer-core
:: pass .task to the |message-pump and apply state mutations
::
=/ =message-pump-state
2019-06-30 15:50:00 +03:00
(~(gut by snd.peer-state) bone *message-pump-state)
2019-06-05 07:36:10 +03:00
::
2019-06-09 09:26:01 +03:00
=/ message-pump (make-message-pump message-pump-state channel)
=^ pump-gifts message-pump-state (work:message-pump task)
=. snd.peer-state (~(put by snd.peer-state) bone message-pump-state)
2019-06-05 07:36:10 +03:00
:: process effects from |message-pump
::
2019-06-09 09:26:01 +03:00
|^ ^+ peer-core
?~ pump-gifts peer-core
=* gift i.pump-gifts
=. peer-core
?- -.gift
2019-12-03 00:20:37 +03:00
%done (on-pump-done [message-num error]:gift)
2019-06-20 11:13:54 +03:00
%send (on-pump-send static-fragment.gift)
%wait (on-pump-wait date.gift)
%rest (on-pump-rest date.gift)
2019-06-09 09:26:01 +03:00
==
$(pump-gifts t.pump-gifts)
2019-06-20 11:13:54 +03:00
:: +on-pump-done: handle |message-pump's report of message (n)ack
2019-06-05 07:36:10 +03:00
::
2019-06-20 11:13:54 +03:00
++ on-pump-done
2019-12-03 00:20:37 +03:00
|= [=message-num error=(unit error)]
2019-06-09 09:26:01 +03:00
^+ peer-core
2019-06-20 03:48:29 +03:00
:: if odd bone, ack is on "subscription update" message; no-op
2019-06-19 03:52:10 +03:00
::
2020-12-04 01:25:31 +03:00
?: =(1 (end 0 bone))
2019-06-19 03:52:10 +03:00
peer-core
2019-06-20 03:48:29 +03:00
:: even bone; is this bone a nack-trace bone?
2019-06-19 03:38:25 +03:00
::
2020-12-04 01:25:31 +03:00
?: =(1 (end 0 (rsh 0 bone)))
2019-10-30 23:12:57 +03:00
:: nack-trace bone; assume .ok, clear nack from |message-sink
2019-06-19 03:52:10 +03:00
::
=/ target-bone=^bone (mix 0b10 bone)
::
2019-10-30 23:12:57 +03:00
(run-message-sink target-bone %drop message-num)
2019-12-03 00:20:37 +03:00
:: not a nack-trace bone; relay ack to client vane
2019-06-05 07:36:10 +03:00
::
2019-12-03 00:20:37 +03:00
(emit (got-duct bone) %give %done error)
2019-07-24 02:20:21 +03:00
:: +on-pump-send: emit message fragment requested by |message-pump
2019-06-09 09:26:01 +03:00
::
2019-06-20 11:13:54 +03:00
++ on-pump-send
2020-12-01 17:51:14 +03:00
|=(f=static-fragment (send-shut-packet bone [message-num %& +]:f))
2019-06-20 11:13:54 +03:00
:: +on-pump-wait: relay |message-pump's set-timer request
2019-06-09 09:26:01 +03:00
::
2019-06-20 11:13:54 +03:00
++ on-pump-wait
2019-06-09 09:26:01 +03:00
|= date=@da
^+ peer-core
::
2019-06-19 02:59:25 +03:00
=/ =wire (make-pump-timer-wire her.channel bone)
2019-09-27 14:45:22 +03:00
=/ duct ~[/ames]
2019-08-05 23:58:53 +03:00
(emit duct %pass wire %b %wait date)
2019-06-20 11:13:54 +03:00
:: +on-pump-rest: relay |message-pump's unset-timer request
2019-06-09 09:26:01 +03:00
::
2019-06-20 11:13:54 +03:00
++ on-pump-rest
2019-06-09 09:26:01 +03:00
|= date=@da
^+ peer-core
::
2019-06-19 02:59:25 +03:00
=/ =wire (make-pump-timer-wire her.channel bone)
2019-09-27 14:45:22 +03:00
=/ duct ~[/ames]
2019-08-05 23:58:53 +03:00
(emit duct %pass wire %b %rest date)
2019-06-09 09:26:01 +03:00
--
2019-10-30 23:12:57 +03:00
:: +run-message-sink: process $message-sink-task and its effects
2019-06-05 07:36:10 +03:00
::
2019-10-30 23:12:57 +03:00
++ run-message-sink
|= [=bone task=message-sink-task]
2019-06-05 07:36:10 +03:00
^+ peer-core
2019-10-30 23:12:57 +03:00
:: pass .task to the |message-sink and apply state mutations
2019-06-08 12:45:30 +03:00
::
2019-10-30 23:12:57 +03:00
=/ =message-sink-state
(~(gut by rcv.peer-state) bone *message-sink-state)
2019-06-08 12:45:30 +03:00
::
2019-10-30 23:12:57 +03:00
=/ message-sink (make-message-sink message-sink-state channel)
=^ sink-gifts message-sink-state (work:message-sink task)
=. rcv.peer-state (~(put by rcv.peer-state) bone message-sink-state)
:: process effects from |message-sink
2019-06-08 12:45:30 +03:00
::
2019-06-20 11:13:54 +03:00
|^ ^+ peer-core
2019-11-28 03:58:26 +03:00
?~ sink-gifts peer-core
2019-10-30 23:12:57 +03:00
=* gift i.sink-gifts
2019-06-20 11:13:54 +03:00
=. peer-core
?- -.gift
2019-10-30 23:12:57 +03:00
%memo (on-sink-memo [message-num message]:gift)
%send (on-sink-send [message-num ack-meat]:gift)
2019-06-20 11:13:54 +03:00
==
2019-10-30 23:12:57 +03:00
$(sink-gifts t.sink-gifts)
:: +on-sink-send: emit ack packet as requested by |message-sink
2019-06-05 07:36:10 +03:00
::
2019-10-30 23:12:57 +03:00
++ on-sink-send
2020-12-01 17:51:14 +03:00
|=([num=message-num ack=ack-meat] (send-shut-packet bone num %| ack))
2019-10-30 23:12:57 +03:00
:: +on-sink-memo: dispatch message received by |message-sink
2019-06-20 11:13:54 +03:00
::
2019-07-28 10:50:32 +03:00
:: odd bone: %plea request message
:: even bone, 0 second bit: %boon response message
:: even bone, 1 second bit: nack-trace %boon message
2019-06-20 11:13:54 +03:00
::
2019-10-30 23:12:57 +03:00
++ on-sink-memo
2020-12-04 01:25:31 +03:00
?: =(1 (end 0 bone))
2019-10-30 23:12:57 +03:00
on-sink-plea
2020-12-04 01:25:31 +03:00
?: =(0 (end 0 (rsh 0 bone)))
2019-10-30 23:12:57 +03:00
on-sink-boon
on-sink-nack-trace
:: +on-sink-boon: handle response message received by |message-sink
2019-07-28 10:50:32 +03:00
::
2019-08-05 23:58:53 +03:00
:: .bone must be mapped in .ossuary.peer-state, or we crash.
2019-12-21 09:56:51 +03:00
:: This means a malformed message will kill a flow. We
2019-08-05 23:58:53 +03:00
:: could change this to a no-op if we had some sort of security
:: reporting.
::
2019-12-03 01:49:10 +03:00
:: Note that if we had several consecutive packets in the queue
:: and crashed while processing any of them, the %hole card
:: will turn *all* of them into losts/nacks.
::
2019-08-28 06:12:56 +03:00
:: TODO: This handles a previous crash in the client vane, but not in
:: Ames itself.
::
2019-10-30 23:12:57 +03:00
++ on-sink-boon
2019-07-28 10:50:32 +03:00
|= [=message-num message=*]
2019-06-20 11:13:54 +03:00
^+ peer-core
2019-08-05 23:58:53 +03:00
:: send ack unconditionally
2019-06-20 11:13:54 +03:00
::
2019-12-18 06:20:32 +03:00
=. peer-core (emit (got-duct bone) %give %boon message)
2019-10-30 23:12:57 +03:00
=. peer-core (run-message-sink bone %done ok=%.y)
2019-06-20 11:13:54 +03:00
::
2019-08-28 06:12:56 +03:00
?. ?=([%hear * * ok=%.n] task)
:: fresh boon; give message to client vane
2019-06-25 01:18:18 +03:00
::
2021-02-19 05:47:02 +03:00
%- %+ trace msg.veb
=/ dat [her.channel bone=bone message-num=message-num -.task]
|.("sink boon {<dat>}")
2019-12-18 06:20:32 +03:00
peer-core
2019-08-28 06:12:56 +03:00
:: we previously crashed on this message; notify client vane
2019-06-20 11:13:54 +03:00
::
2020-12-12 03:45:13 +03:00
%- %+ trace msg.veb
2021-02-19 05:47:02 +03:00
=/ dat [her.channel bone=bone message-num=message-num -.task]
|.("crashed on sink boon {<dat>}")
2019-12-18 06:20:32 +03:00
boon-to-lost
:: +boon-to-lost: convert all boons to losts
::
++ boon-to-lost
^+ peer-core
=. moves
%+ turn moves
|= =move
?. ?=([* %give %boon *] move)
move
[duct.move %give %lost ~]
peer-core
2019-10-30 23:12:57 +03:00
:: +on-sink-nack-trace: handle nack-trace received by |message-sink
2019-07-28 10:50:32 +03:00
::
2019-10-30 23:12:57 +03:00
++ on-sink-nack-trace
2019-07-28 10:50:32 +03:00
|= [=message-num message=*]
^+ peer-core
2021-02-19 05:47:02 +03:00
%- %+ trace msg.veb
=/ dat [her.channel bone=bone message-num=message-num]
|.("sink naxplanation {<dat>}")
2019-06-20 11:13:54 +03:00
::
2019-11-03 03:52:48 +03:00
=+ ;; =naxplanation message
2019-08-05 23:58:53 +03:00
:: ack nack-trace message (only applied if we don't later crash)
2019-06-20 11:13:54 +03:00
::
2019-10-30 23:12:57 +03:00
=. peer-core (run-message-sink bone %done ok=%.y)
2019-06-20 11:13:54 +03:00
:: flip .bone's second bit to find referenced flow
::
=/ target-bone=^bone (mix 0b10 bone)
2019-12-02 23:20:57 +03:00
:: notify |message-pump that this message got naxplained
2019-06-20 11:13:54 +03:00
::
2019-12-02 23:20:57 +03:00
(run-message-pump target-bone %near naxplanation)
2019-10-30 23:12:57 +03:00
:: +on-sink-plea: handle request message received by |message-sink
2019-06-09 09:40:30 +03:00
::
2019-10-30 23:12:57 +03:00
++ on-sink-plea
2019-07-28 10:50:32 +03:00
|= [=message-num message=*]
^+ peer-core
2021-02-19 05:47:02 +03:00
%- %+ trace msg.veb
=/ dat [her.channel bone=bone message-num=message-num]
|.("sink plea {<dat>}")
2019-08-06 02:05:40 +03:00
:: is this the first time we're trying to process this message?
2019-07-28 10:50:32 +03:00
::
2019-08-06 02:05:40 +03:00
?. ?=([%hear * * ok=%.n] task)
:: fresh plea; pass to client vane
::
2019-08-08 07:57:04 +03:00
=+ ;; =plea message
::
2022-02-22 18:04:42 +03:00
=/ =wire (make-bone-wire her.channel her-rift.channel bone)
2019-08-08 07:57:04 +03:00
::
?+ vane.plea ~| %ames-evil-vane^our^her.channel^vane.plea !!
2019-08-06 02:05:40 +03:00
%c (emit duct %pass wire %c %plea her.channel plea)
%g (emit duct %pass wire %g %plea her.channel plea)
2019-08-20 00:43:39 +03:00
%j (emit duct %pass wire %j %plea her.channel plea)
2019-08-06 02:05:40 +03:00
==
:: we previously crashed on this message; send nack
::
2019-10-30 23:12:57 +03:00
=. peer-core (run-message-sink bone %done ok=%.n)
2019-11-03 03:52:48 +03:00
:: also send nack-trace with blank .error for security
2019-08-06 02:05:40 +03:00
::
=/ nack-trace-bone=^bone (mix 0b10 bone)
2019-11-03 03:52:48 +03:00
=/ =naxplanation [message-num *error]
=/ =message-blob (jam naxplanation)
2019-08-06 02:05:40 +03:00
::
(run-message-pump nack-trace-bone %memo message-blob)
2019-07-28 10:50:32 +03:00
--
2019-06-05 07:36:10 +03:00
--
2022-01-29 01:54:01 +03:00
::
++ fine
=< |%
2022-02-12 04:30:40 +03:00
++ fine-peer
|_ $: =ship
peer=peer-state
==
+* scry scry.peer
++ pe-core .
++ pe-abed
|= s=^ship
^- (unit _pe-core)
?~ sta=(get-peer-state s)
~
`pe-core(ship s, peer u.sta)
::
++ pe-abet
^+ event-core
2022-05-19 18:07:35 +03:00
=. peers.ames-state
2022-02-12 04:30:40 +03:00
(~(put by peers.ames-state) ship known/peer)
event-core
++ pe-keen
2022-02-24 00:52:05 +03:00
|= [=path =^duct]
2022-02-12 04:30:40 +03:00
?: (~(has by order.scry) path)
2022-06-04 02:22:55 +03:00
~> %slog.0^leaf/"fine: dupe {(spud path)}"
2022-02-24 00:52:05 +03:00
ke-abet:(ke-sub:(ke-abed:keen-core path) duct)
2022-05-26 01:30:35 +03:00
=^ keen-id=@ud seq.scry [seq.scry +(seq.scry)]
=. order.scry (~(put by order.scry) path keen-id)
=. keens.scry (put:orm keens.scry keen-id *keen-state)
2022-02-24 00:52:05 +03:00
ke-abet:(ke-start:(ke-abed:keen-core path) duct)
::
2022-03-15 00:04:14 +03:00
++ pe-pine
2022-03-15 19:40:34 +03:00
|= [=path =^duct]
2022-03-15 00:04:14 +03:00
^+ pe-core
?~ blk=(de-part:balk ship rift.peer life.peer path)
!! :: XX: ???
=+ wir=`wire`[%fine %pine (scot %p ship) path]
=. event-core
(emit duct %pass wir %a %plea ship %a /pine `*`u.blk)
pe-core
::
++ pe-pine-boon
|= [=path payload=*]
^+ pe-core
?~ blk=(de-part:balk ship rift.peer life.peer path)
!!
=+ ;;(case=@ud payload)
2022-03-15 19:40:34 +03:00
=. cas.u.blk ud+case
(pe-keen (slag 3 (en-path:balk u.blk)) duct)
::
++ pe-meet-alien-pine
|= pines=(jug path ^duct)
%+ roll ~(tap by pines)
|= [[=path ducts=(set ^duct)] cor=_pe-core]
^+ cor
%+ roll ~(tap in ducts)
|= [=^duct c=_cor]
^+ c
(pe-pine:c path duct)
2022-03-15 00:04:14 +03:00
::
2022-03-15 19:40:34 +03:00
++ pe-meet-alien-keen
|= keens=(jug path ^duct)
%+ roll ~(tap by keens)
2022-02-24 00:52:05 +03:00
|= [[=path ducts=(set ^duct)] cor=_pe-core]
^+ cor
%+ roll ~(tap in ducts)
|= [=^duct c=_cor]
^+ c
(pe-keen:c path duct)
2022-02-12 04:30:40 +03:00
::
2022-02-24 01:00:20 +03:00
++ pe-yawn
|= =path
2022-02-24 00:52:05 +03:00
ke-abet:(ke-unsub:(ke-abed:keen-core path) duct)
2022-02-24 01:00:20 +03:00
::
2022-02-12 04:30:40 +03:00
++ pe-hear
2022-06-04 06:58:50 +03:00
|= [=lane =shot]
?> =(sndr-tick.shot (mod life.peer 16))
2022-02-12 04:30:40 +03:00
::
2022-06-04 06:58:50 +03:00
=/ [=peep =meow] (sift-purr `@ux`content.shot)
2022-03-15 00:04:14 +03:00
=/ =path (slag 3 path.peep)
?. (~(has by order.scry) path)
2022-02-12 04:30:40 +03:00
~&(dead-response/peep pe-core)
=< ke-abet
2022-06-04 06:58:50 +03:00
(ke-rcv:(ke-abed:keen-core path) peep meow lane)
2022-02-12 04:30:40 +03:00
::
++ pe-update-qos
|= =new=qos
=^ old-qos qos.peer [qos.peer new-qos]
?~ text=(qos-update-text ship old-qos new-qos)
pe-core
:: print message
::
=. event-core (emit duct %pass /qos %d %flog %text u.text)
pe-core
::
++ pe-take-wake
|= =wire
^+ pe-core
ke-abet:ke-take-wake:(ke-abed:keen-core wire)
::
++ keen-core
|_ $: =path
keen-id=@ud
keen=keen-state
==
++ ke-core .
2022-05-19 18:07:35 +03:00
++ ke-abet
2022-02-15 17:47:38 +03:00
^+ pe-core
2022-02-12 04:30:40 +03:00
=/ gone=?
=, keen
:: num-fragments is 0 when unknown (i.e. no response
:: yet)
2022-02-24 00:10:11 +03:00
:: if no-one is listening, kill request
?| =(~ listeners.keen)
&(!=(0 num-fragments) =(num-fragments num-received))
==
2022-02-15 17:47:38 +03:00
?: gone
ke-abet-gone
=. ke-core ke-set-wake
2022-05-19 18:07:35 +03:00
=. keens.scry
2022-02-12 04:30:40 +03:00
(put:orm keens.scry keen-id keen)
2022-02-15 17:47:38 +03:00
pe-core
::
++ ke-show
=, keen
2022-05-19 18:07:35 +03:00
:* nex=(lent nex)
2022-02-15 17:47:38 +03:00
hav=(lent hav)
num-fragments=num-fragments
num-received=num-received
next-wake=next-wake
metrics=metrics
==
::
++ ke-abet-gone
2022-05-16 23:52:07 +03:00
=? ke-core ?=(^ next-wake.keen)
(ke-rest u.next-wake.keen)
2022-02-15 17:47:38 +03:00
=. keens.scry
+:(del:orm keens.scry keen-id)
=. order.scry
2022-02-12 04:30:40 +03:00
(~(del by order.scry) path)
pe-core
::
2022-05-19 18:07:35 +03:00
++ ke-abed
2022-02-12 04:30:40 +03:00
|= p=^path
2022-02-17 00:35:59 +03:00
~| no-keen-for-path/p
2022-02-12 04:30:40 +03:00
=. keen-id (~(got by order.scry) p)
ke-core(path p, keen (got:orm keens.scry keen-id))
::
++ ke-abed-id
|= id=@ud
%- ke-abed
~| no-path-for-id/id
2022-05-19 18:07:35 +03:00
%- need
2022-02-12 04:30:40 +03:00
^- (unit ^path)
%- ~(rep by order.scry)
|= [[p=^path i=@ud] out=(unit ^path)]
^- (unit ^path)
?^ out out
?:(=(id i) `p ~)
2022-02-17 00:35:59 +03:00
++ ke-deq
(deq want)
2022-03-15 00:04:14 +03:00
++ ke-full-path
:^ (scot %p ship)
(scot %ud rift.peer)
(scot %ud life.peer)
path
2022-02-12 04:30:40 +03:00
::
2022-06-04 06:58:50 +03:00
++ ke-etch-keen
2022-02-12 04:30:40 +03:00
|= frag=@ud
2022-06-04 06:58:50 +03:00
(etch-keen ship ke-full-path frag)
2022-06-06 16:50:02 +03:00
::
2022-02-12 04:30:40 +03:00
++ ke-on-ack
=| marked=(list want)
2022-05-19 18:07:35 +03:00
|= fra=@ud
2022-02-17 00:35:59 +03:00
^- [? _ke-core]
=; [[found=? cor=_ke-core] wan=(pha want)]
?. found
[found ke-core]
[found cor(wan.keen wan)]
%^ (dip-left:ke-deq ,[found=? cor=_ke-core]) wan.keen
[| ke-core]
|= [[found=? cor=_ke-core] =want]
^- [(unit _want) stop=? [found=? cor=_ke-core]]
=. ke-core cor
2022-02-12 04:30:40 +03:00
?: =(fra fra.want)
2022-02-17 00:35:59 +03:00
=. metrics.keen
2022-02-15 17:47:38 +03:00
(on-ack:ke-gauge +>.want)
2022-02-17 00:35:59 +03:00
[~ %.y %.y ke-core]
2022-02-12 04:30:40 +03:00
=. skips.want +(skips.want)
2022-02-15 17:47:38 +03:00
=^ resend=? metrics.keen
2022-02-12 04:30:40 +03:00
(on-skipped-packet:ke-gauge +>.want)
?. resend
2022-02-17 00:35:59 +03:00
[`want %.n found ke-core]
2022-02-12 04:30:40 +03:00
=. tries.want +(tries.want)
=. last-sent.want now
2022-06-04 02:22:55 +03:00
=. ke-core (ke-send hoot.want)
2022-02-17 00:35:59 +03:00
[`want %.n found ke-core]
2022-02-12 04:30:40 +03:00
::
++ ke-start
2022-02-24 00:52:05 +03:00
|= =^duct
2022-06-02 01:08:12 +03:00
~> %slog.0^leaf/"fine: keen {(spud ke-full-path)}"
2022-02-24 00:52:05 +03:00
=. ke-core (ke-sub duct)
2022-02-12 04:30:40 +03:00
?> =(num-fragments.keen 0)
=/ fra=@ 1
2022-06-04 06:58:50 +03:00
=/ req (ke-etch-keen fra)
2022-02-15 17:47:38 +03:00
=/ =want [fra req now 1 0]
2022-02-17 00:35:59 +03:00
=. wan.keen (cons:ke-deq *(pha ^want) want)
2022-02-15 17:47:38 +03:00
=. metrics.keen (on-sent:ke-gauge 1)
2022-06-04 02:22:55 +03:00
(ke-send req)
2022-02-12 04:30:40 +03:00
::
++ ke-done
|= [sig=@ data=$@(~ (cask))]
2022-03-15 00:04:14 +03:00
?> (meri:keys ship life.peer ke-full-path sig data)
2022-06-02 01:08:12 +03:00
~> %slog.0^leaf/"fine: done {(spud ke-full-path)}"
2022-02-24 01:00:20 +03:00
=/ listeners ~(tap in listeners.keen)
=/ dat=(unit (cask))
?~(data ~ `data)
|- ^+ ke-core
?~ listeners
ke-core
=. event-core
2022-03-15 19:40:34 +03:00
(emit i.listeners %give %tune ke-full-path sig dat)
2022-02-24 01:00:20 +03:00
$(listeners t.listeners)
2022-02-12 04:30:40 +03:00
::
++ ke-first-rcv
2022-05-26 01:30:35 +03:00
|= =meow
2022-02-12 04:30:40 +03:00
^+ ke-core
=- ke-core(keen -)
::
2022-02-14 19:34:26 +03:00
=/ paz=(list want)
2022-05-29 04:23:37 +03:00
%+ turn (gulf 1 num.meow)
2022-02-12 04:30:40 +03:00
|= fra=@ud
^- want
2022-06-04 06:58:50 +03:00
[fra (ke-etch-keen fra) now 0 0]
2022-02-14 19:34:26 +03:00
::
%_ keen
2022-05-29 04:23:37 +03:00
num-fragments num.meow
2022-02-15 17:47:38 +03:00
nex (tail paz)
2022-02-12 04:30:40 +03:00
==
:: +ke-continue: send packets according to normal congestion flow
2022-02-14 19:34:26 +03:00
::
2022-02-12 04:30:40 +03:00
++ ke-continue
2022-02-14 19:34:26 +03:00
=| inx=@ud
2022-02-15 17:47:38 +03:00
=| sent=(list @ud)
2022-02-14 19:34:26 +03:00
=/ max num-slots:ke-gauge
|- ^+ ke-core
2022-02-15 17:47:38 +03:00
?: |(=(~ nex.keen) =(inx max))
ke-core
2022-02-17 00:35:59 +03:00
=^ =want nex.keen nex.keen
2022-02-15 17:47:38 +03:00
=. last-sent.want now
=. tries.want +(tries.want)
2022-02-17 00:35:59 +03:00
=. wan.keen (snoc:ke-deq wan.keen want)
=. metrics.keen (on-sent:ke-gauge 1)
2022-06-04 02:22:55 +03:00
=. ke-core (ke-send hoot.want)
2022-02-17 00:35:59 +03:00
$(inx +(inx))
2022-02-15 17:47:38 +03:00
::
2022-02-23 21:31:56 +03:00
++ ke-sub
2022-02-24 00:52:05 +03:00
|= =^duct
2022-06-04 02:22:55 +03:00
ke-core(listeners.keen (~(put in listeners.keen) duct))
2022-02-24 00:10:11 +03:00
:: scry is autocancelled in +ke-abet if no more listeners
::
++ ke-unsub
2022-02-24 00:52:05 +03:00
|= =^duct
2022-06-04 02:22:55 +03:00
ke-core(listeners.keen (~(del in listeners.keen) duct))
2022-02-23 21:31:56 +03:00
::
2022-06-04 02:22:55 +03:00
++ ke-send
2022-02-14 19:34:26 +03:00
|= =hoot
2022-06-04 02:22:55 +03:00
ke-core(event-core (send-blob for=| ship `@ux`hoot))
2022-02-12 04:30:40 +03:00
::
2022-06-04 06:58:50 +03:00
++ ke-sift-full
2022-02-12 04:30:40 +03:00
=, keen
~| %frag-mismatch
~| have/num-received
~| need/num-fragments
2022-02-24 01:00:20 +03:00
~| path/path
2022-02-12 04:30:40 +03:00
?> =(num-fragments num-received)
?> =((lent hav) num-received)
2022-06-04 06:58:50 +03:00
(sift-roar num-fragments hav)
2022-02-12 04:30:40 +03:00
::
++ ke-rcv
2022-06-04 06:58:50 +03:00
|= [[=full=^path num=@ud] =meow =lane:ames]
2022-02-12 04:30:40 +03:00
^+ ke-core
=/ og ke-core
2022-02-15 17:47:38 +03:00
=. pe-core (pe-update-qos %live last-contact=now)
2022-02-12 04:30:40 +03:00
:: handle empty
2022-05-29 04:23:37 +03:00
?: =(0 num.meow)
2022-05-26 01:30:35 +03:00
?> =(~ dat.meow)
(ke-done sig.meow ~)
2022-02-12 04:30:40 +03:00
:: update congestion, or fill details
::
=? ke-core =(0 num-fragments.keen)
2022-06-04 06:58:50 +03:00
?> =(num 1)
2022-05-26 01:30:35 +03:00
(ke-first-rcv meow)
2022-02-12 04:30:40 +03:00
::
2022-06-04 06:58:50 +03:00
?. ?=([@ @ @ *] full-path)
~| fine-path-too-short+full-path
!!
?. =(`ship (slaw %p i.full-path))
~| fine-path-bunk-ship+[full-path ship]
!!
2022-06-06 16:50:02 +03:00
?. =(`life.peer (slaw %ud i.t.t.full-path))
2022-06-04 06:58:50 +03:00
~| fine-path-bunk-life+[full-path life.peer]
!!
2022-06-06 16:50:02 +03:00
?. =(`rift.peer (slaw %ud i.t.full-path))
2022-06-04 06:58:50 +03:00
~| fine-path-bunk-rift+[full-path rift.peer]
!!
2022-06-01 02:31:38 +03:00
?. %- veri-fra:keys
2022-06-04 06:58:50 +03:00
[ship life.peer full-path num [dat sig]:meow]
~| fine-purr-fail-signature/num^`@ux`sig.meow
2022-06-01 02:31:38 +03:00
~| life.peer
!!
2022-02-17 00:35:59 +03:00
::
2022-06-04 06:58:50 +03:00
=^ found=? ke-core (ke-on-ack num)
2022-02-12 04:30:40 +03:00
?. found
2022-06-04 06:58:50 +03:00
(ke-fast-retransmit:og num)
=: hav.keen [[num meow] hav.keen]
num-received.keen +(num-received.keen)
==
?. =(num-fragments num-received):keen
ke-continue
(ke-done [sig dat]:ke-sift-full)
2022-02-12 04:30:40 +03:00
::
2022-02-23 21:58:44 +03:00
++ ke-fast-retransmit
|= fra=@ud
=; [cor=_ke-core wants=(pha want)]
cor(wan.keen wants)
%^ (dip-left:ke-deq ,cor=_ke-core) wan.keen
ke-core
|= [cor=_ke-core =want]
^- [(unit ^want) stop=? cor=_ke-core]
?. (lte fra.want fra)
[`want & cor]
?: (gth (next-expiry:ke-gauge:cor +>.want) now)
[`want & cor]
=. last-sent.want now
2022-06-04 02:22:55 +03:00
=. cor (ke-send:cor hoot.want)
2022-02-23 21:58:44 +03:00
[`want | cor]
::
2022-02-12 04:30:40 +03:00
++ ke-gauge
2022-02-15 17:47:38 +03:00
=* bug bug.ames-state
(make-pump-gauge now metrics.keen ship bug)
2022-02-12 04:30:40 +03:00
::
++ ke-timer-wire
`wire`(welp /fine/behn/wake/(scot %p ship) path)
::
++ ke-pass-timer
|= =note
2022-02-15 17:47:38 +03:00
ke-core(event-core (emit unix-duct.ames-state %pass ke-timer-wire note))
2022-02-12 04:30:40 +03:00
::
++ ke-wait |=(tim=@da (ke-pass-timer %b %wait tim))
++ ke-rest |=(tim=@da (ke-pass-timer %b %rest tim))
++ ke-set-wake
^+ ke-core
=/ next-wake=(unit @da)
2022-02-17 00:35:59 +03:00
=/ want=(unit want) (peek-left:ke-deq wan.keen)
?~ want ~
`(next-expiry:ke-gauge +>:u.want)
2022-02-12 04:30:40 +03:00
?: =(next-wake next-wake.keen)
ke-core
=? ke-core !=(~ next-wake.keen)
=/ old (need next-wake.keen)
=. next-wake.keen ~
(ke-rest old)
=? ke-core ?=(^ next-wake)
=. next-wake.keen next-wake
(ke-wait u.next-wake)
ke-core
2022-02-14 19:34:26 +03:00
:: +ke-take-wake: handle request packet timeout
::
2022-02-12 04:30:40 +03:00
++ ke-take-wake
^+ ke-core
2022-02-15 17:47:38 +03:00
=. next-wake.keen ~
2022-02-12 04:30:40 +03:00
=. pe-core %- pe-update-qos
=/ expiry=@da (add ~s30 last-contact.qos.peer)
=? -.qos.peer
(gte now expiry)
%dead
qos.peer
:: expire direct route
=? route.peer
?& ?=(%dead -.qos.peer)
?=(^ route.peer)
direct.u.route.peer
!=(%czar (clan:title ship))
==
route.peer(direct.u %.n)
2022-02-15 17:47:38 +03:00
=. metrics.keen on-timeout:ke-gauge
2022-02-17 00:35:59 +03:00
=^ want=(unit want) wan.keen
(pop-left:ke-deq wan.keen)
~| %took-wake-for-empty-want
?> ?=(^ want)
=: tries.u.want +(tries.u.want)
last-sent.u.want now
2022-02-14 19:34:26 +03:00
==
2022-02-17 00:35:59 +03:00
=. wan.keen (cons:ke-deq wan.keen u.want)
2022-06-04 02:22:55 +03:00
(ke-send hoot.u.want)
2022-02-12 04:30:40 +03:00
--
--
2022-03-15 00:04:14 +03:00
::
++ on-pine-plea
|= [=ship payload=*]
^+ event-core
=+ ;;(blk=balk payload)
?> =(%c van.blk)
=. car.blk %w
=. cas.blk da+now
2022-05-19 18:07:35 +03:00
=. spr.blk
2022-03-15 00:04:14 +03:00
?> ?=(^ spr.blk)
^- path
~[i.spr.blk]
=+ !<(=cass:clay q:(need (need (rof ~ (en-roof:balk blk)))))
=. event-core
(emit duct %give %boon ud.cass)
(emit duct %give %done ~)
::
++ on-pine-boon
|= [=ship =path payload=*]
=/ pe-core (need (pe-abed:fine-peer ship))
pe-abet:(pe-pine-boon:pe-core path payload)
::
++ on-pine
|= [=ship =path]
^+ event-core
?. =(our ship)
=/ peer-core
(pe-abed:fine-peer ship)
2022-03-15 19:40:34 +03:00
?^ peer-core
pe-abet:(pe-pine:u.peer-core path duct)
%+ enqueue-alien-todo ship
|= todos=alien-agenda
todos(pines (~(put ju keens.todos) path duct))
2022-03-15 00:04:14 +03:00
:: XX: crashing correct behaviour?
=+ blk=(need (de-part:balk our rift.ames-state life.ames-state path))
?> ?=(%c van.blk)
=+ nom=(en-roof:balk blk(car %w, cas [%da now]))
=+ cag=(rof ~ nom)
?- cag
~ !!
2022-03-15 19:40:34 +03:00
[~ ~] (emit duct %give %miss (en-path:balk blk))
2022-03-15 00:04:14 +03:00
::
[~ ~ *]
=+ !<(=cass:clay q.u.u.cag)
(emit duct %give %boon `*`ud.cass)
==
2022-05-26 01:30:35 +03:00
::
2022-01-29 01:54:01 +03:00
++ on-keen
2022-03-15 00:04:14 +03:00
|= [=ship =path]
2022-01-29 01:54:01 +03:00
^+ event-core
2022-05-26 01:30:35 +03:00
=+ ~:(spit path) :: assert length
2022-02-12 04:30:40 +03:00
=/ peer-core (pe-abed:fine-peer ship)
2022-02-24 00:52:05 +03:00
?^ peer-core pe-abet:(pe-keen:u.peer-core path duct)
2022-01-29 01:54:01 +03:00
%+ enqueue-alien-todo ship
|= todos=alien-agenda
2022-02-24 00:52:05 +03:00
todos(keens (~(put ju keens.todos) path duct))
2022-01-29 01:54:01 +03:00
::
++ on-yawn
2022-03-15 00:04:14 +03:00
|= [=ship =path]
2022-01-29 01:54:01 +03:00
^+ event-core
2022-05-27 23:54:38 +03:00
=/ peer-core (pe-abed:fine-peer ship)
?~ peer-core ~|(%no-ship-for-yawn !!)
2022-02-24 01:00:20 +03:00
pe-abet:(pe-yawn:u.peer-core path)
2022-01-29 01:54:01 +03:00
::
2022-02-12 04:30:40 +03:00
++ on-take-wake
|= [=wire error=(unit tang)]
^+ event-core
~| fine-on-take-wake/wire
2022-02-15 17:47:38 +03:00
?^ error
%- (slog leaf/"bad wake" u.error)
event-core
2022-02-12 04:30:40 +03:00
:: TODO: handle error case
?> ?=([@ *] wire)
=/ =ship (slav %p i.wire)
~| %no-ship-for-wake
=/ peer-core (need (pe-abed:fine-peer ship))
pe-abet:(pe-take-wake:peer-core t.wire)
::
2022-01-29 01:54:01 +03:00
++ on-hear-response
2022-06-04 06:58:50 +03:00
|= [=lane =shot dud=(unit goof)]
2022-01-29 01:54:01 +03:00
^+ event-core
?^ dud
::TODO handle
2022-02-01 14:42:13 +03:00
~& [%fine %done-goofed mote.u.dud]
%- (slog tang.u.dud)
2022-01-29 01:54:01 +03:00
event-core
2022-06-04 06:58:50 +03:00
:: TODO no longer true
2022-02-01 13:42:07 +03:00
::NOTE we only send requests to ships we know,
:: so we should only get responses from ships we know.
2022-06-30 17:27:02 +03:00
:: below we assume sndr.shot is a known peer.
2022-06-04 06:58:50 +03:00
=* from sndr.shot
2022-02-12 04:30:40 +03:00
=/ peer-core (need (pe-abed:fine-peer from))
2022-06-04 06:58:50 +03:00
pe-abet:(pe-hear:peer-core lane shot)
2022-01-29 01:54:01 +03:00
--
|%
::
2022-02-12 04:30:40 +03:00
++ orm ((on @ud keen-state) lte)
2022-05-26 01:30:35 +03:00
:: +gum: glue together a list of $byts into one
2022-05-27 05:23:09 +03:00
::
:: TODO: move to hoon.hoon
2022-05-26 01:30:35 +03:00
::
++ gum
2022-05-27 23:54:38 +03:00
::~/ %gum
2022-05-26 01:30:35 +03:00
|= biz=(list byts)
^- byts
2022-05-27 05:23:09 +03:00
:- (roll biz |=([[wid=@ *] acc=@] (add wid acc)))
(can 3 biz)
2022-01-29 01:54:01 +03:00
::
++ spit
|= =path
^- [pat=@t wid=@ud]
=+ pat=(spat path)
=+ wid=(met 3 pat)
2022-05-26 01:30:35 +03:00
?> (lte wid 384)
2022-01-29 01:54:01 +03:00
[pat wid]
::
2022-06-04 06:58:50 +03:00
++ etch-peep
2022-01-29 01:54:01 +03:00
|= [=path num=@ud]
^- byts
?> (lth num (bex 32))
=+ (spit path)
2022-05-26 01:30:35 +03:00
%- gum
2022-01-29 01:54:01 +03:00
:~ 4^num :: fragment number
2^wid :: path size
wid^`@`pat :: namespace path
==
2022-06-02 01:08:12 +03:00
:: +show-meow: prepare $meow for printing
::
++ show-meow
|= =meow
:* sig=`@q`(mug sig.meow)
num=num.meow
siz=siz.meow
dat=`@q`(mug dat.meow)
==
2022-01-29 01:54:01 +03:00
::
2022-06-01 02:31:38 +03:00
++ make-meow
|= [=path mes=@ num=@ud]
^- meow
2022-05-26 01:30:35 +03:00
=/ tot (met 13 mes)
2022-06-01 02:31:38 +03:00
=/ dat (cut 13 [(dec num) 1] mes)
=/ wid (met 3 dat)
:* sig=(sign-fra:keys path num dat) :: fragment signature
num=tot :: number of fragments
siz=?:(=(num tot) (met 3 dat) 1.024) :: fragment byte width
dat=dat :: response data fragment
==
::
2022-06-04 06:58:50 +03:00
++ etch-meow
2022-06-01 02:31:38 +03:00
|= =meow
^- @uxmeow
2022-05-26 01:30:35 +03:00
%+ can 3
2022-06-01 02:31:38 +03:00
:~ 64^sig.meow
4^num.meow
2^siz.meow
(met 3 dat.meow)^dat.meow
2022-05-26 01:30:35 +03:00
==
::
2022-06-04 06:58:50 +03:00
++ etch-keen
2022-01-29 01:54:01 +03:00
|= [=ship =path num=@ud]
^- hoot ^- @
2022-05-27 21:14:53 +03:00
=/ sic (mod life.ames-state 16)
=/ ric (mod (lyfe:keys ship) 16)
=/ syn
2022-06-04 06:58:50 +03:00
=/ bod (etch-peep path num)
2022-05-27 21:14:53 +03:00
=/ sig 64^(sign:keys dat.bod)
(can 3 sig bod ~)
2022-06-04 06:58:50 +03:00
(etch-shot [our ship] req=& sam=| sic ric ~ syn)
2022-01-29 01:54:01 +03:00
::
2022-06-04 06:58:50 +03:00
++ etch-hunk
2022-05-26 01:30:35 +03:00
|= [=path =hunk data=$@(~ (cask))]
^- (list @uxmeow)
=/ mes=@
2022-02-17 00:35:59 +03:00
=/ sig=@ (full:keys path data)
2022-05-26 01:30:35 +03:00
?~ data sig
2022-06-01 02:31:38 +03:00
(mix sig (lsh 9 (jam data)))
::(cat 9 sig (jam data))
2022-05-26 01:30:35 +03:00
::
2022-05-29 04:23:37 +03:00
=/ las (met 13 mes)
=/ tip (dec (add [lop len]:hunk))
=/ top (min las tip)
2022-05-26 01:30:35 +03:00
=/ num lop.hunk
2022-05-29 04:23:37 +03:00
?> (lte num top)
2022-05-26 01:30:35 +03:00
=| res=(list @uxmeow)
|- ^+ res
2022-05-29 04:23:37 +03:00
?: =(num top)
=- (flop - res)
2022-06-04 06:58:50 +03:00
(etch-meow (make-meow path mes num))
$(num +(num), res :_(res (etch-meow (make-meow path mes num))))
2022-01-29 01:54:01 +03:00
::
++ keys
|%
2022-02-01 13:42:07 +03:00
++ mess
2022-06-01 02:31:38 +03:00
|= [=ship life=@ud =path dat=$@(~ (cask))]
(jam +<)
2022-02-01 13:42:07 +03:00
::
2022-01-29 01:54:01 +03:00
++ full
2022-02-01 13:42:07 +03:00
|= [=path data=$@(~ (cask))]
2022-06-04 02:22:55 +03:00
=/ buf (mess our life.ames-state path data)
2022-06-04 06:58:50 +03:00
::=/ nam (crip "sign-full {<(met 3 buf)>}")
::~> %bout.[1 nam]
2022-06-04 02:22:55 +03:00
(sign buf)
2022-01-29 01:54:01 +03:00
::
2022-06-01 02:31:38 +03:00
++ frag
|= [=path fra=@ud dat=@ux]
(jam +<)
::
2022-02-17 00:35:59 +03:00
++ sign-fra
2022-06-01 02:31:38 +03:00
|= [=path fra=@ud dat=@ux]
2022-06-04 06:58:50 +03:00
::~> %bout.[1 %sign-fra]
2022-06-01 02:31:38 +03:00
(sign (frag path fra dat))
2022-02-17 00:35:59 +03:00
::
++ veri-fra
2022-06-01 02:31:38 +03:00
|= [who=ship lyf=life =path fra=@ud dat=@ux sig=@]
(veri who lyf sig (frag path fra dat))
2022-02-17 00:35:59 +03:00
::
2022-02-01 13:42:07 +03:00
++ sign
2022-02-02 23:52:48 +03:00
sigh:as:crypto-core.ames-state
2022-01-29 01:54:01 +03:00
::
++ lyfe
|= who=ship
2022-02-01 13:42:07 +03:00
^- life
2022-01-29 01:54:01 +03:00
~| [%fine %unknown-peer who]
=/ ship-state (~(got by peers.ames-state) who)
?> ?=([%known *] ship-state)
life.ship-state
::
++ pass
2022-02-01 13:42:07 +03:00
|= [who=ship lyf=life]
2022-01-29 01:54:01 +03:00
~| [%fine %unknown-peer who lyf]
=/ ship-state (~(got by peers.ames-state) who)
?> ?=([%known *] ship-state)
~| [%fine %life-mismatch who lyf]
?> =(lyf life.ship-state)
public-key.ship-state
2022-02-01 13:42:07 +03:00
::
++ veri
|= [who=ship lyf=life sig=@ dat=@]
2022-02-02 23:52:48 +03:00
^- ?
2022-02-17 00:35:59 +03:00
=/ =^pass (pass who lyf)
(safe:as:(com:nu:crub:crypto pass) sig dat)
2022-02-01 13:42:07 +03:00
::
++ meri
|= [who=ship lyf=life pax=path sig=@ dat=$@(~ (cask))]
(veri who lyf sig (mess who lyf pax dat))
2022-01-29 01:54:01 +03:00
--
--
2019-05-28 05:43:47 +03:00
--
2019-06-01 06:32:13 +03:00
:: +make-message-pump: constructor for |message-pump
2019-05-29 01:05:59 +03:00
::
++ make-message-pump
2019-06-02 01:16:41 +03:00
|= [state=message-pump-state =channel]
2019-12-11 21:55:16 +03:00
=* veb veb.bug.channel
2019-05-29 01:05:59 +03:00
=| gifts=(list message-pump-gift)
2019-05-29 05:56:05 +03:00
::
2019-05-29 01:05:59 +03:00
|%
2019-05-29 05:56:05 +03:00
++ message-pump .
++ give |=(gift=message-pump-gift message-pump(gifts [gift gifts]))
2019-06-19 02:33:53 +03:00
++ packet-pump (make-packet-pump packet-pump-state.state channel)
2019-12-11 21:55:16 +03:00
++ trace
|= [verb=? print=(trap tape)]
^+ same
(^trace verb her.channel ships.bug.channel print)
2019-05-29 05:56:05 +03:00
:: +work: handle a $message-pump-task
::
2019-05-29 01:05:59 +03:00
++ work
|= task=message-pump-task
2019-06-02 01:16:41 +03:00
^+ [gifts state]
2019-05-29 01:05:59 +03:00
::
2019-06-19 02:33:53 +03:00
=~ (dispatch-task task)
2019-05-29 05:56:05 +03:00
feed-packets
2019-06-20 10:21:37 +03:00
(run-packet-pump %halt ~)
2019-12-10 10:14:06 +03:00
assert
2019-06-02 01:16:41 +03:00
[(flop gifts) state]
2019-05-29 05:56:05 +03:00
==
2019-06-19 02:33:53 +03:00
:: +dispatch-task: perform task-specific processing
::
++ dispatch-task
|= task=message-pump-task
^+ message-pump
::
?- -.task
2021-08-28 22:39:57 +03:00
%prod (run-packet-pump %prod ~)
2019-07-28 10:50:32 +03:00
%memo (on-memo message-blob.task)
2019-12-10 10:14:06 +03:00
%wake (run-packet-pump %wake current.state)
2019-06-20 10:21:37 +03:00
%hear
2019-06-19 02:33:53 +03:00
?- -.ack-meat.task
2019-06-20 10:21:37 +03:00
%& (on-hear [message-num fragment-num=p.ack-meat]:task)
2019-12-02 23:20:57 +03:00
%| (on-done [message-num ?:(ok.p.ack-meat [%ok ~] [%nack ~])]:task)
==
%near (on-done [message-num %naxplanation error]:naxplanation.task)
==
2019-06-25 19:01:05 +03:00
:: +on-memo: handle request to send a message
2019-05-29 05:56:05 +03:00
::
2019-06-25 19:01:05 +03:00
++ on-memo
2019-07-28 10:50:32 +03:00
|= =message-blob
2019-05-29 05:56:05 +03:00
^+ message-pump
::
2019-07-28 10:50:32 +03:00
=. unsent-messages.state (~(put to unsent-messages.state) message-blob)
2019-05-29 05:56:05 +03:00
message-pump
2019-06-20 10:21:37 +03:00
:: +on-hear: handle packet acknowledgment
2019-06-02 01:16:41 +03:00
::
2019-06-20 10:21:37 +03:00
++ on-hear
2019-06-02 01:16:41 +03:00
|= [=message-num =fragment-num]
^+ message-pump
:: pass to |packet-pump unless duplicate or future ack
::
?. (is-message-num-in-range message-num)
2019-11-15 03:10:48 +03:00
%- (trace snd.veb |.("hear pump out of range"))
2019-06-02 01:16:41 +03:00
message-pump
2019-06-20 10:21:37 +03:00
(run-packet-pump %hear message-num fragment-num)
:: +on-done: handle message acknowledgment
2019-05-29 05:56:05 +03:00
::
2019-12-02 23:20:57 +03:00
:: A nack-trace message counts as a valid message nack on the
:: original failed message.
::
:: This prevents us from having to wait for a message nack packet,
:: which would mean we couldn't immediately ack the nack-trace
:: message, which would in turn violate the semantics of backward
:: flows.
::
2019-06-20 10:21:37 +03:00
++ on-done
2019-12-02 23:20:57 +03:00
|= [=message-num =ack]
2019-05-29 05:56:05 +03:00
^+ message-pump
2022-02-22 18:04:42 +03:00
~? (gte message-num next.state)
"unsent message from the future"^[message-num next.state current.state]
2019-06-21 04:36:16 +03:00
:: unsent messages from the future should never get acked
::
?> (lth message-num next.state)
:: ignore duplicate message acks
::
?: (lth message-num current.state)
2020-12-12 03:45:13 +03:00
%- %+ trace snd.veb
|.("duplicate done {<current=current.state message-num=message-num>}")
2019-06-21 04:36:16 +03:00
message-pump
2019-06-02 01:16:41 +03:00
:: ignore duplicate and future acks
2019-05-29 05:56:05 +03:00
::
2019-06-02 01:16:41 +03:00
?. (is-message-num-in-range message-num)
2019-05-29 05:56:05 +03:00
message-pump
:: clear and print .unsent-fragments if nonempty
::
2019-06-02 01:16:41 +03:00
=? unsent-fragments.state
2019-06-09 09:31:42 +03:00
&(=(current next) ?=(^ unsent-fragments)):state
2019-06-02 01:16:41 +03:00
::
2019-12-03 00:20:37 +03:00
~> %slog.0^leaf/"ames: early message ack {<her.channel>}"
2019-05-29 05:56:05 +03:00
~
:: clear all packets from this message from the packet pump
::
2019-12-02 23:20:57 +03:00
=. message-pump (run-packet-pump %done message-num lag=*@dr)
2019-06-02 01:16:41 +03:00
:: enqueue this ack to be sent back to local client vane
2019-05-29 05:56:05 +03:00
::
2019-12-02 23:20:57 +03:00
:: Don't clobber a naxplanation with just a nack packet.
::
=? queued-message-acks.state
=/ old (~(get by queued-message-acks.state) message-num)
!?=([~ %naxplanation *] old)
(~(put by queued-message-acks.state) message-num ack)
2019-06-02 01:16:41 +03:00
:: emit local acks from .queued-message-acks until incomplete
2019-05-29 05:56:05 +03:00
::
|- ^+ message-pump
2019-06-02 01:16:41 +03:00
:: if .current hasn't been fully acked, we're done
2019-05-29 05:56:05 +03:00
::
2019-12-02 23:20:57 +03:00
?~ cur=(~(get by queued-message-acks.state) current.state)
2019-05-29 05:56:05 +03:00
message-pump
2019-06-02 01:16:41 +03:00
:: .current is complete; pop, emit local ack, and try next message
2019-05-29 05:56:05 +03:00
::
2019-06-02 01:16:41 +03:00
=. queued-message-acks.state
(~(del by queued-message-acks.state) current.state)
2020-12-12 03:43:13 +03:00
:: clear all packets from this message from the packet pump
::
:: Note we did this when the original packet came in, a few lines
:: above. It's not clear why, but it doesn't always clear the
:: packets when it's not the current message. As a workaround,
:: we clear the packets again when we catch up to this packet.
::
:: This is slightly inefficient because we run this twice for
:: each packet and it may emit a few unnecessary packets, but
:: but it's not incorrect. pump-metrics are updated only once,
:: at the time when we actually delete the packet.
::
=. message-pump (run-packet-pump %done current.state lag=*@dr)
2019-12-02 23:20:57 +03:00
:: give %done to vane if we're ready
::
?- -.u.cur
%ok
=. message-pump (give %done current.state ~)
$(current.state +(current.state))
2019-05-29 05:56:05 +03:00
::
2019-12-02 23:20:57 +03:00
%nack
message-pump
2019-05-29 05:56:05 +03:00
::
2019-12-02 23:20:57 +03:00
%naxplanation
=. message-pump (give %done current.state `error.u.cur)
$(current.state +(current.state))
==
2019-06-02 01:16:41 +03:00
:: +is-message-num-in-range: %.y unless duplicate or future ack
::
++ is-message-num-in-range
|= =message-num
^- ?
::
?: (gte message-num next.state)
%.n
?: (lth message-num current.state)
%.n
!(~(has by queued-message-acks.state) message-num)
2019-06-01 06:32:13 +03:00
:: +feed-packets: give packets to |packet-pump until full
2019-05-29 05:56:05 +03:00
::
++ feed-packets
:: if nothing to send, no-op
::
2019-06-02 01:16:41 +03:00
?: &(=(~ unsent-messages) =(~ unsent-fragments)):state
2019-05-29 05:56:05 +03:00
message-pump
:: we have unsent fragments of the current message; feed them
::
2019-06-02 01:16:41 +03:00
?. =(~ unsent-fragments.state)
=/ res (feed:packet-pump unsent-fragments.state)
=+ [unsent packet-pump-gifts packet-pump-state]=res
2019-05-29 05:56:05 +03:00
::
2019-06-02 01:16:41 +03:00
=. unsent-fragments.state unsent
=. packet-pump-state.state packet-pump-state
2019-05-29 05:56:05 +03:00
::
=. message-pump (process-packet-pump-gifts packet-pump-gifts)
:: if it sent all of them, feed it more; otherwise, we're done
::
?~ unsent
feed-packets
message-pump
:: .unsent-messages is nonempty; pop a message off and feed it
::
2019-07-28 10:50:32 +03:00
=^ =message-blob unsent-messages.state ~(get to unsent-messages.state)
2019-06-01 06:32:13 +03:00
:: break .message into .chunks and set as .unsent-fragments
2019-05-29 05:56:05 +03:00
::
2019-07-28 10:50:32 +03:00
=. unsent-fragments.state (split-message next.state message-blob)
2019-06-01 06:32:13 +03:00
:: try to feed packets from the next message
2019-05-29 05:56:05 +03:00
::
2019-06-02 01:16:41 +03:00
=. next.state +(next.state)
2019-05-29 05:56:05 +03:00
feed-packets
2019-06-01 06:32:13 +03:00
:: +run-packet-pump: call +work:packet-pump and process results
2019-05-29 05:56:05 +03:00
::
++ run-packet-pump
|= =packet-pump-task
^+ message-pump
::
2019-06-02 01:16:41 +03:00
=^ packet-pump-gifts packet-pump-state.state
2019-05-29 05:56:05 +03:00
(work:packet-pump packet-pump-task)
::
(process-packet-pump-gifts packet-pump-gifts)
2019-06-01 06:32:13 +03:00
:: +process-packet-pump-gifts: pass |packet-pump effects up the chain
2019-05-29 05:56:05 +03:00
::
++ process-packet-pump-gifts
|= packet-pump-gifts=(list packet-pump-gift)
^+ message-pump
::
?~ packet-pump-gifts
message-pump
=. message-pump (give i.packet-pump-gifts)
::
$(packet-pump-gifts t.packet-pump-gifts)
2019-12-10 10:14:06 +03:00
:: +assert: sanity checks to isolate error cases
::
++ assert
^+ message-pump
=/ top-live
2021-04-29 00:12:46 +03:00
(pry:packet-queue:*make-packet-pump live.packet-pump-state.state)
2020-01-11 01:41:49 +03:00
?. |(?=(~ top-live) (lte current.state message-num.key.u.top-live))
2019-12-10 10:14:06 +03:00
~| [%strange-current current=current.state key.u.top-live]
!!
message-pump
2019-05-29 05:56:05 +03:00
--
2019-06-01 06:32:13 +03:00
:: +make-packet-pump: construct |packet-pump core
2019-05-29 05:56:05 +03:00
::
++ make-packet-pump
2019-06-01 05:03:09 +03:00
|= [state=packet-pump-state =channel]
2019-12-11 21:55:16 +03:00
=* veb veb.bug.channel
2019-05-29 05:56:05 +03:00
=| gifts=(list packet-pump-gift)
|%
++ packet-pump .
2019-06-01 03:50:22 +03:00
++ give |=(packet-pump-gift packet-pump(gifts [+< gifts]))
2019-12-11 21:55:16 +03:00
++ trace
|= [verb=? print=(trap tape)]
^+ same
(^trace verb her.channel ships.bug.channel print)
2019-06-01 06:32:13 +03:00
:: +packet-queue: type for all sent fragments, ordered by sequence number
2019-06-01 01:35:06 +03:00
::
++ packet-queue
%- (ordered-map live-packet-key live-packet-val)
2019-11-27 21:22:20 +03:00
lte-packets
2019-06-01 01:35:06 +03:00
:: +gauge: inflate a |pump-gauge to track congestion control
::
2019-12-11 21:55:16 +03:00
++ gauge (make-pump-gauge now.channel metrics.state [her bug]:channel)
2019-06-01 01:35:06 +03:00
:: +work: handle $packet-pump-task request
::
2019-05-29 05:56:05 +03:00
++ work
|= task=packet-pump-task
2019-06-01 05:03:09 +03:00
^+ [gifts state]
2019-05-29 05:56:05 +03:00
::
2019-06-01 05:03:09 +03:00
=- [(flop gifts) state]
2019-05-29 01:05:59 +03:00
::
?- -.task
2019-06-20 10:21:37 +03:00
%hear (on-hear [message-num fragment-num]:task)
%done (on-done message-num.task)
2019-12-10 10:14:06 +03:00
%wake (on-wake current.task)
2021-08-28 22:39:57 +03:00
%prod on-prod
2019-06-20 10:21:37 +03:00
%halt set-wake
2019-05-29 01:05:59 +03:00
==
2021-08-28 22:39:57 +03:00
:: +on-prod: reset congestion control, re-send packets
::
++ on-prod
^+ packet-pump
?: =(~ next-wake.state)
packet-pump
::
=. metrics.state %*(. *pump-metrics counter counter.metrics.state)
=. live.state
%+ run:packet-queue live.state
|=(p=live-packet-val p(- *packet-state))
::
=/ sot (max 1 num-slots:gauge)
=/ liv live.state
|- ^+ packet-pump
?: =(0 sot) packet-pump
?: =(~ liv) packet-pump
2021-08-28 23:01:15 +03:00
=^ hed liv (pop:packet-queue liv)
2021-08-28 22:39:57 +03:00
=. packet-pump (give %send (to-static-fragment hed))
$(sot (dec sot))
2019-09-27 14:45:22 +03:00
:: +on-wake: handle packet timeout
2019-05-29 01:05:59 +03:00
::
2019-09-27 14:45:22 +03:00
++ on-wake
2019-12-10 10:14:06 +03:00
|= current=message-num
2019-06-01 01:35:06 +03:00
^+ packet-pump
2019-09-27 14:45:22 +03:00
:: assert temporal coherence
2019-06-01 03:50:22 +03:00
::
2019-09-27 14:45:22 +03:00
?< =(~ next-wake.state)
=. next-wake.state ~
:: tell congestion control a packet timed out
2019-06-02 01:16:41 +03:00
::
2019-10-02 10:46:34 +03:00
=. metrics.state on-timeout:gauge
2019-09-27 14:45:22 +03:00
:: re-send first packet and update its state in-place
2019-06-02 01:16:41 +03:00
::
2019-11-15 03:10:48 +03:00
=- =* res -
=. live.state live.res
2019-12-10 10:14:06 +03:00
=? packet-pump ?=(^ static-fragment)
%- %+ trace snd.veb
=/ nums [message-num fragment-num]:u.static-fragment.res
|.("dead {<nums^show:gauge>}")
(give %send u.static-fragment.res)
2019-09-27 14:45:22 +03:00
packet-pump
2019-06-01 03:50:22 +03:00
::
2019-12-10 10:14:06 +03:00
=| acc=(unit static-fragment)
2019-09-27 14:45:22 +03:00
^+ [static-fragment=acc live=live.state]
2019-06-01 03:50:22 +03:00
::
2021-04-20 23:04:28 +03:00
%^ (dip:packet-queue _acc) live.state acc
2019-06-02 01:16:41 +03:00
|= $: acc=_acc
2019-06-01 03:50:22 +03:00
key=live-packet-key
val=live-packet-val
==
2019-06-02 01:16:41 +03:00
^- [new-val=(unit live-packet-val) stop=? _acc]
2019-12-10 10:14:06 +03:00
:: if already acked later message, don't resend
::
?: (lth message-num.key current)
%- %- slog :_ ~
leaf+"ames: strange wake queue, expected {<current>}, got {<key>}"
[~ stop=%.n ~]
2019-09-27 14:45:22 +03:00
:: packet has expired; update it in-place, stop, and produce it
2019-06-01 03:50:22 +03:00
::
2019-09-27 14:45:22 +03:00
=. last-sent.val now.channel
2022-02-12 04:30:40 +03:00
=. tries.val +(tries.val)
2019-06-01 03:50:22 +03:00
::
2019-12-10 10:14:06 +03:00
[`val stop=%.y `(to-static-fragment key val)]
2019-06-02 01:16:41 +03:00
:: +feed: try to send a list of packets, returning unsent and effects
2019-06-01 01:35:06 +03:00
::
2019-06-02 01:16:41 +03:00
++ feed
2019-05-29 05:56:05 +03:00
|= fragments=(list static-fragment)
2019-06-01 05:03:09 +03:00
^+ [fragments gifts state]
2019-06-02 01:16:41 +03:00
:: return unsent back to caller and reverse effects to finalize
::
=- [unsent (flop gifts) state]
::
^+ [unsent=fragments packet-pump]
2019-06-01 06:05:21 +03:00
:: bite off as many fragments as we can send
::
=/ num-slots num-slots:gauge
=/ sent (scag num-slots fragments)
=/ unsent (slag num-slots fragments)
::
2019-06-02 01:16:41 +03:00
:- unsent
^+ packet-pump
:: if nothing to send, we're done
::
?~ sent packet-pump
:: convert $static-fragment's into +ordered-set [key val] pairs
::
=/ send-list
2019-06-01 06:05:21 +03:00
%+ turn sent
|= static-fragment
2019-06-02 01:16:41 +03:00
^- [key=live-packet-key val=live-packet-val]
2019-06-01 06:05:21 +03:00
::
:- [message-num fragment-num]
2022-02-12 04:30:40 +03:00
:- [sent-date=now.channel tries=1 skips=0]
2019-06-01 06:05:21 +03:00
[num-fragments fragment]
2019-06-02 01:16:41 +03:00
:: update .live and .metrics
2019-05-29 01:05:59 +03:00
::
2019-06-02 01:16:41 +03:00
=. live.state (gas:packet-queue live.state send-list)
=. metrics.state (on-sent:gauge (lent send-list))
:: TMI
2019-06-01 06:05:21 +03:00
::
2019-06-02 01:16:41 +03:00
=> .(sent `(list static-fragment)`sent)
:: emit a $packet-pump-gift for each packet to send
::
2019-10-05 06:21:29 +03:00
%+ roll sent
|= [packet=static-fragment core=_packet-pump]
(give:core %send packet)
2019-11-27 21:22:20 +03:00
:: +fast-resend-after-ack: resend timed out packets
::
:: After we finally receive an ack, we want to resend all the live
:: packets that have been building up.
::
++ fast-resend-after-ack
|= [=message-num =fragment-num]
^+ packet-pump
=; res=[resends=(list static-fragment) live=_live.state]
=. live.state live.res
%+ reel resends.res
|= [packet=static-fragment core=_packet-pump]
(give:core %send packet)
::
=/ acc
resends=*(list static-fragment)
::
2021-04-20 23:04:28 +03:00
%^ (dip:packet-queue _acc) live.state acc
2019-11-27 21:22:20 +03:00
|= $: acc=_acc
key=live-packet-key
val=live-packet-val
==
^- [new-val=(unit live-packet-val) stop=? _acc]
?: (lte-packets key [message-num fragment-num])
[new-val=`val stop=%.n acc]
::
2022-02-12 04:30:40 +03:00
?: (gth (next-expiry:gauge -.val) now.channel)
2019-11-27 21:22:20 +03:00
[new-val=`val stop=%.y acc]
::
=. last-sent.val now.channel
=. resends.acc [(to-static-fragment key val) resends.acc]
[new-val=`val stop=%.n acc]
2019-06-20 10:21:37 +03:00
:: +on-hear: handle ack on a live packet
2019-05-29 01:05:59 +03:00
::
2019-09-27 14:45:22 +03:00
:: If the packet was in our queue, delete it and update our
2019-12-21 09:56:51 +03:00
:: metrics, possibly re-sending skipped packets. Otherwise, no-op.
2019-06-02 01:16:41 +03:00
::
2019-06-20 10:21:37 +03:00
++ on-hear
2019-06-01 01:35:06 +03:00
|= [=message-num =fragment-num]
^+ packet-pump
::
2019-06-02 01:16:41 +03:00
=- :: if no sent packet matches the ack, don't apply mutations or effects
::
?. found.-
2019-11-15 03:10:48 +03:00
%- (trace snd.veb |.("miss {<show:gauge>}"))
2019-06-02 01:16:41 +03:00
packet-pump
::
=. metrics.state metrics.-
2019-06-01 05:03:09 +03:00
=. live.state live.-
2019-12-03 02:46:40 +03:00
%- ?. ?| =(0 fragment-num)
=(0 (mod counter.metrics.state 20))
==
same
2020-12-12 03:45:13 +03:00
(trace snd.veb |.("send: {<[fragment=fragment-num show:gauge]>}"))
2019-10-05 06:21:29 +03:00
:: .resends is backward, so fold backward and emit
2019-06-02 01:16:41 +03:00
::
2019-11-27 21:22:20 +03:00
=. packet-pump
%+ reel resends.-
|= [packet=static-fragment core=_packet-pump]
(give:core %send packet)
(fast-resend-after-ack message-num fragment-num)
2019-10-05 06:21:29 +03:00
::
=/ acc
:* found=`?`%.n
resends=*(list static-fragment)
metrics=metrics.state
==
2019-06-01 01:35:06 +03:00
::
2019-10-05 06:21:29 +03:00
^+ [acc live=live.state]
2019-06-02 01:16:41 +03:00
::
2021-04-20 23:04:28 +03:00
%^ (dip:packet-queue _acc) live.state acc
2019-06-02 01:16:41 +03:00
|= $: acc=_acc
2019-06-01 01:35:06 +03:00
key=live-packet-key
val=live-packet-val
==
2019-06-02 01:16:41 +03:00
^- [new-val=(unit live-packet-val) stop=? _acc]
2019-06-01 01:35:06 +03:00
::
2019-12-11 21:55:16 +03:00
=/ gauge (make-pump-gauge now.channel metrics.acc [her bug]:channel)
2019-06-01 01:35:06 +03:00
:: is this the acked packet?
::
?: =(key [message-num fragment-num])
:: delete acked packet, update metrics, and stop traversal
::
2019-10-05 06:21:29 +03:00
=. found.acc %.y
=. metrics.acc (on-ack:gauge -.val)
[new-val=~ stop=%.y acc]
2019-12-02 11:25:30 +03:00
:: is this a duplicate ack?
::
?. (lte-packets key [message-num fragment-num])
:: stop, nothing more to do
::
[new-val=`val stop=%.y acc]
2019-10-05 06:21:29 +03:00
:: ack was on later packet; mark skipped, tell gauge, and continue
::
=. skips.val +(skips.val)
=^ resend metrics.acc (on-skipped-packet:gauge -.val)
?. resend
[new-val=`val stop=%.n acc]
2019-06-01 01:35:06 +03:00
::
2019-10-05 06:21:29 +03:00
=. last-sent.val now.channel
2022-02-12 04:30:40 +03:00
=. tries.val +(tries.val)
2019-10-05 06:21:29 +03:00
=. resends.acc [(to-static-fragment key val) resends.acc]
[new-val=`val stop=%.n acc]
2019-06-20 10:21:37 +03:00
:: +on-done: apply ack to all packets from .message-num
2019-05-29 01:05:59 +03:00
::
2019-06-20 10:21:37 +03:00
++ on-done
2019-05-29 05:56:05 +03:00
|= =message-num
^+ packet-pump
::
2019-06-02 01:16:41 +03:00
=- =. metrics.state metrics.-
=. live.state live.-
::
2020-12-12 03:45:13 +03:00
%- (trace snd.veb |.("done {<message-num=message-num^show:gauge>}"))
2019-11-27 21:22:20 +03:00
(fast-resend-after-ack message-num `fragment-num`0)
2019-05-29 01:05:59 +03:00
::
2019-10-05 06:21:29 +03:00
^+ [metrics=metrics.state live=live.state]
2019-06-02 01:16:41 +03:00
::
2021-04-20 23:04:28 +03:00
%^ (dip:packet-queue pump-metrics) live.state acc=metrics.state
2019-06-02 01:16:41 +03:00
|= $: metrics=pump-metrics
key=live-packet-key
val=live-packet-val
==
^- [new-val=(unit live-packet-val) stop=? pump-metrics]
::
2019-12-11 21:55:16 +03:00
=/ gauge (make-pump-gauge now.channel metrics [her bug]:channel)
2019-12-02 11:25:30 +03:00
:: if we get an out-of-order ack for a message, skip until it
2019-06-02 01:16:41 +03:00
::
?: (lth message-num.key message-num)
2019-12-02 11:25:30 +03:00
[new-val=`val stop=%.n metrics]
2019-06-02 01:16:41 +03:00
:: if packet was from acked message, delete it and continue
::
?: =(message-num.key message-num)
[new-val=~ stop=%.n metrics=(on-ack:gauge -.val)]
:: we've gone past the acked message; we're done
::
[new-val=`val stop=%.y metrics]
:: +set-wake: set, unset, or reset timer, emitting moves
2019-05-29 01:05:59 +03:00
::
2019-06-02 01:16:41 +03:00
++ set-wake
2019-05-29 05:56:05 +03:00
^+ packet-pump
2021-04-29 00:12:46 +03:00
:: if nonempty .live, pry at head to get next wake time
2019-05-29 01:05:59 +03:00
::
2019-06-02 01:16:41 +03:00
=/ new-wake=(unit @da)
2021-04-29 00:12:46 +03:00
?~ head=(pry:packet-queue live.state)
2019-06-02 01:16:41 +03:00
~
2022-02-12 04:30:40 +03:00
`(next-expiry:gauge -.val.u.head)
2019-06-02 01:16:41 +03:00
:: no-op if no change
::
?: =(new-wake next-wake.state) packet-pump
:: unset old timer if non-null
::
=? packet-pump !=(~ next-wake.state)
=/ old (need next-wake.state)
=. next-wake.state ~
(give %rest old)
:: set new timer if non-null
::
=? packet-pump ?=(^ new-wake)
=. next-wake.state new-wake
(give %wait u.new-wake)
::
packet-pump
2019-06-01 01:35:06 +03:00
--
2019-10-05 06:21:29 +03:00
:: +to-static-fragment: convenience function for |packet-pump
2019-06-01 01:35:06 +03:00
::
2019-10-05 06:21:29 +03:00
++ to-static-fragment
|= [live-packet-key live-packet-val]
^- static-fragment
[message-num num-fragments fragment-num fragment]
2019-06-01 03:50:22 +03:00
:: +make-pump-gauge: construct |pump-gauge congestion control core
2019-06-01 06:05:21 +03:00
::
2019-06-01 01:35:06 +03:00
++ make-pump-gauge
2019-12-11 21:55:16 +03:00
|= [now=@da pump-metrics =ship =bug]
=* veb veb.bug
2019-12-03 02:46:40 +03:00
=* metrics +<+<
2019-06-01 01:35:06 +03:00
|%
2019-12-11 21:55:16 +03:00
++ trace
|= [verb=? print=(trap tape)]
^+ same
(^trace verb ship ships.bug print)
2019-06-01 06:05:21 +03:00
:: +next-expiry: when should a newly sent fresh packet time out?
2019-06-01 03:50:22 +03:00
::
2019-09-27 14:45:22 +03:00
:: Use rtt + 4*sigma, where sigma is the mean deviation of rtt.
:: This should make it unlikely that a packet would time out from a
:: delay, as opposed to an actual packet loss.
2019-06-01 06:05:21 +03:00
::
2019-09-27 14:45:22 +03:00
++ next-expiry
2022-02-12 04:30:40 +03:00
|= packet-state
2019-06-01 06:05:21 +03:00
^- @da
2019-11-27 21:22:20 +03:00
(add last-sent rto)
2019-06-01 06:05:21 +03:00
:: +num-slots: how many packets can we send right now?
::
++ num-slots
^- @ud
2019-09-27 14:45:22 +03:00
(sub-safe cwnd num-live)
:: +on-sent: adjust metrics based on sending .num-sent fresh packets
2019-06-01 03:50:22 +03:00
::
2019-09-27 14:45:22 +03:00
++ on-sent
|= num-sent=@ud
2019-08-28 06:53:19 +03:00
^- pump-metrics
::
2019-09-27 14:45:22 +03:00
=. num-live (add num-live num-sent)
2019-06-01 05:03:09 +03:00
metrics
2019-06-01 03:50:22 +03:00
:: +on-ack: adjust metrics based on a packet getting acknowledged
::
2019-06-01 01:35:06 +03:00
++ on-ack
2019-09-27 14:45:22 +03:00
|= =packet-state
2019-06-01 05:03:09 +03:00
^- pump-metrics
2019-06-01 01:35:06 +03:00
::
2019-10-02 09:21:05 +03:00
=. counter +(counter)
2019-09-27 14:45:22 +03:00
=. num-live (dec num-live)
:: if below congestion threshold, add 1; else, add avg. 1 / cwnd
2019-08-29 03:28:31 +03:00
::
2019-09-27 14:45:22 +03:00
=. cwnd
?: in-slow-start
+(cwnd)
(add cwnd !=(0 (mod (mug now) cwnd)))
:: if this was a re-send, don't adjust rtt or downstream state
::
2022-02-12 04:30:40 +03:00
?: (gth tries.packet-state 1)
2019-09-27 14:45:22 +03:00
metrics
:: rtt-datum: new rtt measurement based on this packet roundtrip
::
=/ rtt-datum=@dr (sub-safe now last-sent.packet-state)
:: rtt-error: difference between this rtt measurement and expected
::
=/ rtt-error=@dr
?: (gte rtt-datum rtt)
(sub rtt-datum rtt)
(sub rtt rtt-datum)
:: exponential weighting ratio for .rtt and .rttvar
::
2019-11-28 03:43:09 +03:00
%- %+ trace ges.veb
|.("ack update {<show rtt-datum=rtt-datum rtt-error=rtt-error>}")
2019-09-27 14:45:22 +03:00
=. rtt (div (add rtt-datum (mul rtt 7)) 8)
=. rttvar (div (add rtt-error (mul rttvar 7)) 8)
=. rto (clamp-rto (add rtt (mul 4 rttvar)))
::
metrics
2019-10-05 06:21:29 +03:00
:: +on-skipped-packet: handle misordered ack
2019-06-01 03:50:22 +03:00
::
2019-09-27 14:45:22 +03:00
++ on-skipped-packet
|= packet-state
2019-10-05 06:21:29 +03:00
^- [resend=? pump-metrics]
2019-06-01 06:05:21 +03:00
::
2022-02-12 04:30:40 +03:00
=/ resend=? &((lte tries 1) |(in-recovery (gte skips 3)))
2019-10-05 06:21:29 +03:00
:- resend
::
=? cwnd !in-recovery (max 2 (div cwnd 2))
2019-11-15 03:10:48 +03:00
%- %+ trace snd.veb
|.("skip {<[resend=resend in-recovery=in-recovery show]>}")
2019-09-27 14:45:22 +03:00
metrics
:: +on-timeout: (re)enter slow-start mode on packet loss
2019-06-01 06:05:21 +03:00
::
2019-09-27 14:45:22 +03:00
++ on-timeout
2019-06-01 05:03:09 +03:00
^- pump-metrics
2019-08-28 06:53:19 +03:00
::
2019-12-03 02:46:40 +03:00
%- (trace ges.veb |.("timeout update {<show>}"))
2019-10-02 09:21:05 +03:00
=: ssthresh (max 1 (div cwnd 2))
2019-09-27 14:45:22 +03:00
cwnd 1
rto (clamp-rto (mul rto 2))
==
2019-06-04 15:38:08 +03:00
metrics
2019-09-27 14:45:22 +03:00
:: +clamp-rto: apply min and max to an .rto value
::
++ clamp-rto
|= rto=@dr
^+ rto
2022-06-01 02:31:38 +03:00
(min ~s5 (max ^~((div ~s1 5)) rto))
2019-10-05 06:21:29 +03:00
:: +in-slow-start: %.y iff we're in "slow-start" mode
2019-09-27 14:45:22 +03:00
::
++ in-slow-start
^- ?
(lth cwnd ssthresh)
2019-10-05 06:21:29 +03:00
:: +in-recovery: %.y iff we're recovering from a skipped packet
::
:: We finish recovering when .num-live finally dips back down to
:: .cwnd.
::
++ in-recovery
^- ?
(gth num-live cwnd)
2019-09-27 14:45:22 +03:00
:: +sub-safe: subtract with underflow protection
::
++ sub-safe
|= [a=@ b=@]
^- @
?:((lte a b) 0 (sub a b))
2019-10-05 06:21:29 +03:00
:: +show: produce a printable version of .metrics
2019-10-02 09:21:05 +03:00
::
++ show
=/ ms (div ~s1 1.000)
::
:* rto=(div rto ms)
rtt=(div rtt ms)
rttvar=(div rttvar ms)
ssthresh=ssthresh
cwnd=cwnd
num-live=num-live
counter=counter
==
2019-05-29 01:05:59 +03:00
--
2019-10-30 23:12:57 +03:00
:: +make-message-sink: construct |message-sink message receiver core
2019-05-29 01:05:59 +03:00
::
2019-10-30 23:12:57 +03:00
++ make-message-sink
|= [state=message-sink-state =channel]
2019-12-11 21:55:16 +03:00
=* veb veb.bug.channel
2019-10-30 23:12:57 +03:00
=| gifts=(list message-sink-gift)
2019-05-29 01:05:59 +03:00
|%
2019-10-30 23:12:57 +03:00
++ message-sink .
++ give |=(message-sink-gift message-sink(gifts [+< gifts]))
2019-12-11 21:55:16 +03:00
++ trace
|= [verb=? print=(trap tape)]
^+ same
(^trace verb her.channel ships.bug.channel print)
:: +work: handle a $message-sink-task
::
2019-05-29 01:05:59 +03:00
++ work
2019-10-30 23:12:57 +03:00
|= task=message-sink-task
2019-06-09 20:32:15 +03:00
^+ [gifts state]
2019-05-29 01:05:59 +03:00
::
2019-06-09 20:32:15 +03:00
=- [(flop gifts) state]
2019-05-29 01:05:59 +03:00
::
?- -.task
2019-06-20 10:21:37 +03:00
%done (on-done ok.task)
%drop (on-drop message-num.task)
2019-08-06 02:05:40 +03:00
%hear (on-hear [lane shut-packet ok]:task)
2019-05-29 01:05:59 +03:00
==
2019-06-11 23:22:24 +03:00
:: +on-hear: receive message fragment, possibly completing message
2019-05-29 01:05:59 +03:00
::
++ on-hear
2019-08-06 02:05:40 +03:00
|= [=lane =shut-packet ok=?]
2019-10-30 23:12:57 +03:00
^+ message-sink
2019-06-09 20:32:15 +03:00
:: we know this is a fragment, not an ack; expose into namespace
2019-05-29 01:05:59 +03:00
::
2019-06-09 20:32:15 +03:00
?> ?=(%& -.meat.shut-packet)
=+ [num-fragments fragment-num fragment]=+.meat.shut-packet
:: seq: message sequence number, for convenience
::
=/ seq message-num.shut-packet
:: ignore messages from far future; limit to 10 in progress
::
?: (gte seq (add 10 last-acked.state))
2020-12-12 03:45:13 +03:00
%- %+ trace odd.veb
|.("future %hear {<seq=seq^last-acked=last-acked.state>}")
2019-10-30 23:12:57 +03:00
message-sink
2019-06-09 20:32:15 +03:00
::
=/ is-last-fragment=? =(+(fragment-num) num-fragments)
:: always ack a dupe!
::
?: (lte seq last-acked.state)
?. is-last-fragment
:: single packet ack
::
2020-12-12 03:45:13 +03:00
%- %+ trace rcv.veb
|.("send dupe ack {<seq=seq^fragment-num=fragment-num>}")
2019-06-20 10:21:37 +03:00
(give %send seq %& fragment-num)
2019-06-19 03:38:25 +03:00
:: whole message (n)ack
2019-06-09 20:32:15 +03:00
::
2019-08-21 00:44:44 +03:00
=/ ok=? !(~(has in nax.state) seq)
2020-12-12 03:45:13 +03:00
%- (trace rcv.veb |.("send dupe message ack {<seq=seq>} ok={<ok>}"))
2019-06-20 10:21:37 +03:00
(give %send seq %| ok lag=`@dr`0)
2019-06-09 20:32:15 +03:00
:: last-acked<seq<=last-heard; heard message, unprocessed
::
2019-11-27 21:22:20 +03:00
:: Only true if we've heard some packets we haven't acked, which
:: doesn't happen for boons.
::
2019-06-09 20:32:15 +03:00
?: (lte seq last-heard.state)
?: is-last-fragment
:: drop last packet since we don't know whether to ack or nack
::
2019-11-28 03:58:26 +03:00
%- %+ trace rcv.veb
|. ^- tape
=/ data
2020-12-12 03:45:13 +03:00
:* her.channel seq=seq
fragment-num=fragment-num num-fragments=num-fragments
2019-11-28 03:58:26 +03:00
la=last-acked.state lh=last-heard.state
==
"hear last in-progress {<data>}"
2019-10-30 23:12:57 +03:00
message-sink
2019-06-09 20:32:15 +03:00
:: ack all other packets
::
2020-12-12 03:45:13 +03:00
%- %+ trace rcv.veb |.
=/ data
[seq=seq fragment-num=fragment-num num-fragments=num-fragments]
"send ack-1 {<data>}"
2019-06-20 10:21:37 +03:00
(give %send seq %& fragment-num)
2019-06-09 20:32:15 +03:00
:: last-heard<seq<10+last-heard; this is a packet in a live message
::
=/ =partial-rcv-message
:: create default if first fragment
::
?~ existing=(~(get by live-messages.state) seq)
[num-fragments num-received=0 fragments=~]
:: we have an existing partial message; check parameters match
::
?> (gth num-fragments.u.existing fragment-num)
?> =(num-fragments.u.existing num-fragments)
::
u.existing
::
2019-08-01 06:14:28 +03:00
=/ already-heard-fragment=?
2019-07-29 12:08:26 +03:00
(~(has by fragments.partial-rcv-message) fragment-num)
2019-06-09 20:32:15 +03:00
:: ack dupes except for the last fragment, in which case drop
::
2019-08-01 06:14:28 +03:00
?: already-heard-fragment
2019-06-09 20:32:15 +03:00
?: is-last-fragment
2019-12-18 02:40:51 +03:00
%- %+ trace rcv.veb |.
2020-12-12 03:45:13 +03:00
=/ data
[her.channel seq=seq lh=last-heard.state la=last-acked.state]
2019-12-18 02:40:51 +03:00
"hear last dupe {<data>}"
2019-10-30 23:12:57 +03:00
message-sink
2020-12-12 03:45:13 +03:00
%- %+ trace rcv.veb
|.("send dupe ack {<her.channel^seq=seq^fragment-num=fragment-num>}")
2019-06-20 10:21:37 +03:00
(give %send seq %& fragment-num)
2019-06-09 20:32:15 +03:00
:: new fragment; store in state and check if message is done
::
=. num-received.partial-rcv-message
+(num-received.partial-rcv-message)
::
=. fragments.partial-rcv-message
(~(put by fragments.partial-rcv-message) fragment-num fragment)
::
=. live-messages.state
(~(put by live-messages.state) seq partial-rcv-message)
:: ack any packet other than the last one, and continue either way
::
2019-10-30 23:12:57 +03:00
=? message-sink !is-last-fragment
2020-12-12 03:45:13 +03:00
%- %+ trace rcv.veb |.
=/ data
[seq=seq fragment-num=fragment-num num-fragments=num-fragments]
"send ack-2 {<data>}"
2019-06-20 10:21:37 +03:00
(give %send seq %& fragment-num)
2019-06-09 20:32:15 +03:00
:: enqueue all completed messages starting at +(last-heard.state)
::
2019-10-30 23:12:57 +03:00
|- ^+ message-sink
2019-06-09 20:32:15 +03:00
:: if this is not the next message to ack, we're done
::
?. =(seq +(last-heard.state))
2019-10-30 23:12:57 +03:00
message-sink
2019-06-09 20:32:15 +03:00
:: if we haven't heard anything from this message, we're done
::
?~ live=(~(get by live-messages.state) seq)
2019-10-30 23:12:57 +03:00
message-sink
2019-06-09 20:32:15 +03:00
:: if the message isn't done yet, we're done
::
?. =(num-received num-fragments):u.live
2019-10-30 23:12:57 +03:00
message-sink
2019-06-09 20:32:15 +03:00
:: we have whole message; update state, assemble, and send to vane
::
=. last-heard.state +(last-heard.state)
=. live-messages.state (~(del by live-messages.state) seq)
::
2019-12-03 02:46:40 +03:00
%- %+ trace msg.veb
2020-12-12 03:45:13 +03:00
|.("hear {<her.channel>} {<seq=seq>} {<num-fragments.u.live>}kb")
2019-07-28 10:50:32 +03:00
=/ message=* (assemble-fragments [num-fragments fragments]:u.live)
2019-10-30 23:12:57 +03:00
=. message-sink (enqueue-to-vane seq message)
2019-06-09 20:32:15 +03:00
::
$(seq +(seq))
2019-06-19 03:38:25 +03:00
:: +enqueue-to-vane: enqueue message to be sent to local vane
2019-06-09 20:32:15 +03:00
::
++ enqueue-to-vane
2019-07-28 10:50:32 +03:00
|= [seq=message-num message=*]
2019-10-30 23:12:57 +03:00
^+ message-sink
2019-06-09 20:32:15 +03:00
::
=/ empty=? =(~ pending-vane-ack.state)
=. pending-vane-ack.state (~(put to pending-vane-ack.state) seq message)
?. empty
2019-10-30 23:12:57 +03:00
message-sink
2019-06-20 10:21:37 +03:00
(give %memo seq message)
2019-06-11 03:31:50 +03:00
:: +on-done: handle confirmation of message processing from vane
2019-05-29 01:05:59 +03:00
::
++ on-done
2019-06-18 21:21:12 +03:00
|= ok=?
2019-10-30 23:12:57 +03:00
^+ message-sink
2019-05-29 01:05:59 +03:00
::
2019-06-11 03:31:50 +03:00
=^ pending pending-vane-ack.state ~(get to pending-vane-ack.state)
2019-06-19 03:38:25 +03:00
=/ =message-num message-num.p.pending
::
=. last-acked.state +(last-acked.state)
=? nax.state !ok (~(put in nax.state) message-num)
2019-06-11 03:31:50 +03:00
::
2019-11-27 21:22:20 +03:00
=. message-sink (give %send message-num %| ok lag=`@dr`0)
=/ next ~(top to pending-vane-ack.state)
?~ next
message-sink
(give %memo u.next)
2019-06-20 10:21:37 +03:00
:: +on-drop: drop .message-num from our .nax state
2019-06-19 03:38:25 +03:00
::
2019-06-20 10:21:37 +03:00
++ on-drop
2019-06-19 03:38:25 +03:00
|= =message-num
2019-10-30 23:12:57 +03:00
^+ message-sink
2019-06-19 03:38:25 +03:00
::
=. nax.state (~(del in nax.state) message-num)
::
2019-10-30 23:12:57 +03:00
message-sink
2019-05-29 01:05:59 +03:00
--
2019-05-25 05:03:33 +03:00
--