more work: allocator, input, shift responsibilities
This commit is contained in:
		
							parent
							
								
									79d38da497
								
							
						
					
					
						commit
						4f1b352b2a
					
				
							
								
								
									
										68
									
								
								docs/api.md
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								docs/api.md
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -176,46 +176,46 @@ for consistency.
 | 
			
		|||
 | 
			
		||||
The code-entry Helper object has the following API:
 | 
			
		||||
 | 
			
		||||
* `update_nameplates()`: requests an updated list of nameplates from the
 | 
			
		||||
* `refresh_nameplates()`: requests an updated list of nameplates from the
 | 
			
		||||
  Rendezvous Server. These form the first portion of the wormhole code (e.g.
 | 
			
		||||
  "4" in "4-purple-sausages"). Note that they are unicode strings (so "4",
 | 
			
		||||
  not 4). The Helper will get the response in the background, and calls to
 | 
			
		||||
  `complete_nameplate()` after the response will use the new list.
 | 
			
		||||
* `completions = h.complete_nameplate(prefix)`: returns (synchronously) a
 | 
			
		||||
  list of suffixes for the given nameplate prefix. For example, if the server
 | 
			
		||||
  reports nameplates 1, 12, 13, 24, and 170 are in use,
 | 
			
		||||
  `complete_nameplate("1")` will return `["", "2", "3", "70"]`. Raises
 | 
			
		||||
  `AlreadyClaimedNameplateError` if called after `h.claim_nameplate`.
 | 
			
		||||
* `d = h.claim_nameplate(nameplate)`: accepts a string with the chosen
 | 
			
		||||
  nameplate. May only be called once, after which `OnlyOneNameplateError` is
 | 
			
		||||
  raised. Returns a Deferred that fires (with None) when the nameplate's
 | 
			
		||||
  wordlist is known (which happens after the nameplate is claimed, requiring
 | 
			
		||||
  a roundtrip to the server).
 | 
			
		||||
* `completions = h.complete_words(prefix)`: return (synchronously) a list of
 | 
			
		||||
  suffixes for the given words prefix. The possible completions depend upon
 | 
			
		||||
  the wordlist in use for the previously-claimed nameplate, so calling this
 | 
			
		||||
  before `claim_nameplate` will raise `MustClaimNameplateFirstError`. Given a
 | 
			
		||||
  prefix like "su", this returns a list of strings which are appropriate to
 | 
			
		||||
  append to the prefix (e.g. `["pportive", "rrender", "spicious"]`, for
 | 
			
		||||
  expansion into "supportive", "surrender", and "suspicious". The prefix
 | 
			
		||||
  should not include the nameplate, but *should* include whatever words and
 | 
			
		||||
  hyphens have been typed so far (the default wordlist uses alternate lists,
 | 
			
		||||
  where even numbered words have three syllables, and odd numbered words have
 | 
			
		||||
  two, so the completions depend upon how many words are present, not just
 | 
			
		||||
  the partial last word). E.g. `complete_words("pr")` will return
 | 
			
		||||
  `["ocessor", "ovincial", "oximate"]`, while `complete_words("opulent-pr")`
 | 
			
		||||
  will return `["eclude", "efer", "eshrunk", "inter", "owler"]`.
 | 
			
		||||
  If the wordlist is not yet known (i.e. the Deferred from `claim_nameplate`
 | 
			
		||||
  has not yet fired), this returns an empty list. It will also return an
 | 
			
		||||
  empty list if the prefix is complete (the last word matches something in
 | 
			
		||||
  the completion list, and there are no longer extension words), although the
 | 
			
		||||
  code may not yet be complete if there are additional words. The completions
 | 
			
		||||
  will never include a hyphen: the UI frontend must supply these if desired.
 | 
			
		||||
* `h.submit_words(words)`: call this when the user is finished typing in the
 | 
			
		||||
  `get_nameplate_completions()` after the response will use the new list.
 | 
			
		||||
* `completions = h.get_nameplate_completions(prefix)`: returns
 | 
			
		||||
  (synchronously) a list of suffixes for the given nameplate prefix. For
 | 
			
		||||
  example, if the server reports nameplates 1, 12, 13, 24, and 170 are in
 | 
			
		||||
  use, `get_nameplate_completions("1")` will return `["", "2", "3", "70"]`.
 | 
			
		||||
  Raises `AlreadyClaimedNameplateError` if called after `h.choose_nameplate`.
 | 
			
		||||
* `h.choose_nameplate(nameplate)`: accepts a string with the chosen nameplate.
 | 
			
		||||
  May only be called once, after which `OnlyOneNameplateError` is raised. (in
 | 
			
		||||
  this future, this might return a Deferred that fires (with None) when the
 | 
			
		||||
  nameplate's wordlist is known (which happens after the nameplate is
 | 
			
		||||
  claimed, requiring a roundtrip to the server)).
 | 
			
		||||
* `completions = h.get_word_completions(prefix)`: return (synchronously) a
 | 
			
		||||
  list of suffixes for the given words prefix. The possible completions
 | 
			
		||||
  depend upon the wordlist in use for the previously-claimed nameplate, so
 | 
			
		||||
  calling this before `choose_nameplate` will raise
 | 
			
		||||
  `MustClaimNameplateFirstError`. Given a prefix like "su", this returns a
 | 
			
		||||
  list of strings which are appropriate to append to the prefix (e.g.
 | 
			
		||||
  `["pportive", "rrender", "spicious"]`, for expansion into "supportive",
 | 
			
		||||
  "surrender", and "suspicious". The prefix should not include the nameplate,
 | 
			
		||||
  but *should* include whatever words and hyphens have been typed so far (the
 | 
			
		||||
  default wordlist uses alternate lists, where even numbered words have three
 | 
			
		||||
  syllables, and odd numbered words have two, so the completions depend upon
 | 
			
		||||
  how many words are present, not just the partial last word). E.g.
 | 
			
		||||
  `get_word_completions("pr")` will return `["ocessor", "ovincial",
 | 
			
		||||
  "oximate"]`, while `get_word_completions("opulent-pr")` will return
 | 
			
		||||
  `["eclude", "efer", "eshrunk", "inter", "owler"]`. If the wordlist is not
 | 
			
		||||
  yet known, this returns an empty list. It will also return an empty list if
 | 
			
		||||
  the prefix is complete (the last word matches something in the completion
 | 
			
		||||
  list, and there are no longer extension words), although the code may not
 | 
			
		||||
  yet be complete if there are additional words. The completions will never
 | 
			
		||||
  include a hyphen: the UI frontend must supply these if desired.
 | 
			
		||||
* `h.choose_words(words)`: call this when the user is finished typing in the
 | 
			
		||||
  code. It does not return anything, but will cause the Wormhole's
 | 
			
		||||
  `w.when_code()` (or corresponding delegate) to fire, and triggers the
 | 
			
		||||
  wormhole connection process. This accepts a string like "purple-sausages",
 | 
			
		||||
  without the nameplate. It must be called after `h.claim_nameplate()` or
 | 
			
		||||
  without the nameplate. It must be called after `h.choose_nameplate()` or
 | 
			
		||||
  `MustClaimNameplateFirstError` will be raised.
 | 
			
		||||
 | 
			
		||||
The `rlcompleter` wrapper is a function that knows how to use the code-entry
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,8 +11,12 @@ digraph {
 | 
			
		|||
        S0B -> P_allocate [label="allocate"]
 | 
			
		||||
        P_allocate [shape="box" label="RC.tx_allocate" color="orange"]
 | 
			
		||||
        P_allocate -> S1B [color="orange"]
 | 
			
		||||
        S1B [label="S1B:\nallocating" color="orange"]
 | 
			
		||||
        S1B -> S1A [label="lost"]
 | 
			
		||||
        {rank=same; S1A P_allocate S1B}
 | 
			
		||||
        S0B -> S1B [style="invis"]
 | 
			
		||||
        S1B [label="S1B:\nallocating\nconnected" color="orange"]
 | 
			
		||||
        S1B -> foo [label="lost"]
 | 
			
		||||
        foo [style="dotted" label=""]
 | 
			
		||||
        foo -> S1A
 | 
			
		||||
        S1A [label="S1A:\nallocating\ndisconnected" color="orange"]
 | 
			
		||||
        S1A -> P_allocate [label="connected" color="orange"]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ digraph {
 | 
			
		|||
 | 
			
		||||
        {rank=same; P0_code S0}
 | 
			
		||||
        P0_code [shape="box" style="dashed"
 | 
			
		||||
                 label="input -> Code.input\n or allocate -> Code.allocate\n or set_code -> Code.set_code"]
 | 
			
		||||
                 label="C.input_code\n or C.allocate_code\n or C.set_code"]
 | 
			
		||||
        P0_code -> S0
 | 
			
		||||
        S0 [label="S0: empty"]
 | 
			
		||||
        S0 -> P0_build [label="set_code"]
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ digraph {
 | 
			
		|||
        P_close_error -> S_closing
 | 
			
		||||
        S0 -> P_close_lonely [label="close"]
 | 
			
		||||
 | 
			
		||||
        P0_build [shape="box" label="W.got_code\nN.set_nameplate\nK.got_code"]
 | 
			
		||||
        P0_build [shape="box" label="W.got_code"]
 | 
			
		||||
        P0_build -> S1
 | 
			
		||||
        S1 [label="S1: lonely" color="orange"]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ digraph {
 | 
			
		|||
 | 
			
		||||
        {rank=same; Other S_closed}
 | 
			
		||||
        Other [shape="box" style="dashed"
 | 
			
		||||
               label="rx_welcome -> process\nsend -> S.send\ngot_message -> got_version or got_phase\ngot_key -> W.got_key\ngot_verifier -> W.got_verifier\nallocate -> C.allocate\ninput -> C.input\nset_code -> C.set_code"
 | 
			
		||||
               label="rx_welcome -> process\nsend -> S.send\ngot_message -> got_version or got_phase\ngot_key -> W.got_key\ngot_verifier -> W.got_verifier\nallocate_Code -> C.allocate_code\ninput_code -> C.input_code\nset_code -> C.set_code"
 | 
			
		||||
               ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,27 +1,39 @@
 | 
			
		|||
digraph {
 | 
			
		||||
 | 
			
		||||
        start [label="C:\nCode\nManagement" style="dotted"]
 | 
			
		||||
        start [label="C:\nCode\n(management)" style="dotted"]
 | 
			
		||||
        {rank=same; start S0}
 | 
			
		||||
        start -> S0 [style="invis"]
 | 
			
		||||
        S0 [label="S0:\nidle"]
 | 
			
		||||
        S0 -> P0_got_code [label="set_code"]
 | 
			
		||||
        P0_got_code [shape="box" label="B.got_code"]
 | 
			
		||||
        P0_got_code -> S3
 | 
			
		||||
        S3 [label="S3: known" color="green"]
 | 
			
		||||
        P0_got_code [shape="box" label="N.set_nameplate"]
 | 
			
		||||
        P0_got_code -> P_done
 | 
			
		||||
        P_done [shape="box" label="K.got_code\nB.got_code"]
 | 
			
		||||
        P_done -> S5
 | 
			
		||||
        S5 [label="S5: known" color="green"]
 | 
			
		||||
 | 
			
		||||
        {rank=same; S1_inputting S2_allocating}
 | 
			
		||||
        {rank=same; S1_inputting_nameplate S3_allocating}
 | 
			
		||||
        {rank=same; P0_got_code P1_set_nameplate P3_got_nameplate}
 | 
			
		||||
        S0 -> P_input [label="input_code"]
 | 
			
		||||
        P_input [shape="box" label="I.start"]
 | 
			
		||||
        P_input -> S1_inputting
 | 
			
		||||
        S1_inputting [label="S1:\ninputting"]
 | 
			
		||||
        S1_inputting -> P0_got_code [label="finished_input"]
 | 
			
		||||
        P_input -> S1_inputting_nameplate
 | 
			
		||||
        S1_inputting_nameplate [label="S1:\ninputting\nnameplate"]
 | 
			
		||||
        S1_inputting_nameplate -> P1_set_nameplate [label="got_nameplate"]
 | 
			
		||||
        P1_set_nameplate [shape="box" label="N.set_nameplate"]
 | 
			
		||||
        P1_set_nameplate -> S2_inputting_words
 | 
			
		||||
        S2_inputting_words [label="S2:\ninputting\nwords"]
 | 
			
		||||
        S2_inputting_words -> P1_got_words [label="finished_input"]
 | 
			
		||||
        P1_got_words [shape="box" label="assemble\ncode"]
 | 
			
		||||
        P1_got_words -> P_done
 | 
			
		||||
        P_done
 | 
			
		||||
 | 
			
		||||
        S0 -> P_allocate [label="allocate_code"]
 | 
			
		||||
        P_allocate [shape="box" label="A.allocate"]
 | 
			
		||||
        P_allocate -> S2_allocating
 | 
			
		||||
        S2_allocating [label="S2:\nallocating"]
 | 
			
		||||
        S2_allocating -> P1_generate [label="allocated_nameplate"]
 | 
			
		||||
        P1_generate [shape="box" label="generate\nrandom words"]
 | 
			
		||||
        P1_generate -> P0_got_code
 | 
			
		||||
        P_allocate -> S3_allocating
 | 
			
		||||
        S3_allocating [label="S3:\nallocating"]
 | 
			
		||||
        S3_allocating -> P3_got_nameplate [label="allocated_nameplate"]
 | 
			
		||||
        P3_got_nameplate [shape="box" label="N.set_nameplate"]
 | 
			
		||||
        P3_got_nameplate -> P3_generate
 | 
			
		||||
        P3_generate [shape="box" label="append\nrandom words"]
 | 
			
		||||
        P3_generate -> P_done
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,28 +5,39 @@ digraph {
 | 
			
		|||
        start -> S0 [style="invis"]
 | 
			
		||||
        S0 [label="S0:\nidle"]
 | 
			
		||||
 | 
			
		||||
        S0 -> P0_list_nameplates [label="start" color="orange"]
 | 
			
		||||
        P0_list_nameplates [shape="box" label="L.refresh_nameplates" color="orange"]
 | 
			
		||||
        P0_list_nameplates -> S1 [color="orange"]
 | 
			
		||||
        S0 -> P0_list_nameplates [label="start"]
 | 
			
		||||
        P0_list_nameplates [shape="box" label="L.refresh"]
 | 
			
		||||
        P0_list_nameplates -> S1
 | 
			
		||||
        S1 [label="S1: typing\nnameplate" color="orange"]
 | 
			
		||||
 | 
			
		||||
        {rank=same; foo P0_list_nameplates}
 | 
			
		||||
        S1 -> foo [label="update_nameplates"]
 | 
			
		||||
        S1 -> foo [label="refresh_nameplates" color="orange" fontcolor="orange"]
 | 
			
		||||
        foo [style="dashed" label=""]
 | 
			
		||||
        foo -> P0_list_nameplates
 | 
			
		||||
 | 
			
		||||
        S1 -> P1_claim [label="claim_nameplate" color="orange" fontcolor="orange"]
 | 
			
		||||
        P1_claim [shape="box" label="N.set_nameplate" color="orange"]
 | 
			
		||||
        P1_claim -> S2 [color="orange"]
 | 
			
		||||
        S2 [label="S2: typing\ncode\n(no wordlist)" color="orange"]
 | 
			
		||||
        S2 -> P2_stash_wordlist [label="got_nameplates" color="orange"]
 | 
			
		||||
        P2_stash_wordlist [shape="box" label="stash\nwordlist" color="orange"]
 | 
			
		||||
        P2_stash_wordlist -> S3 [color="orange"]
 | 
			
		||||
        S2 -> P_done [label="submit_words"]
 | 
			
		||||
        S3 [label="S3: typing\ncode\n(yes wordlist)" color="orange"]
 | 
			
		||||
        S3 -> P_done [label="submit_words" color="orange" fontcolor="orange"]
 | 
			
		||||
        P_done [shape="box" label="C.finished_input" color="orange"]
 | 
			
		||||
        P_done -> S4 [color="orange"]
 | 
			
		||||
        S4 [label="S4: known" color="green"]
 | 
			
		||||
        S1 -> P1_record [label="got_nameplates"]
 | 
			
		||||
        P1_record [shape="box" label="record\nnameplates"]
 | 
			
		||||
        P1_record -> S1
 | 
			
		||||
 | 
			
		||||
        S1 -> P1_claim [label="choose_nameplate" color="orange" fontcolor="orange"]
 | 
			
		||||
        P1_claim [shape="box" label="stash nameplate\nC.got_nameplate"]
 | 
			
		||||
        P1_claim -> S2
 | 
			
		||||
        S2 [label="S2: typing\ncode\n(no wordlist)"]
 | 
			
		||||
        S2 -> S2 [label="got_nameplates"]
 | 
			
		||||
        S2 -> P2_stash_wordlist [label="got_wordlist"]
 | 
			
		||||
        P2_stash_wordlist [shape="box" label="stash wordlist"]
 | 
			
		||||
        P2_stash_wordlist -> S3
 | 
			
		||||
        S2 -> P_done [label="choose_words" color="orange" fontcolor="orange"]
 | 
			
		||||
        S3 [label="S3: typing\ncode\n(yes wordlist)"]
 | 
			
		||||
        S3 -> S3 [label="got_nameplates"]
 | 
			
		||||
        S3 -> P_done [label="choose_words" color="orange" fontcolor="orange"]
 | 
			
		||||
        P_done [shape="box" label="build code\nC.finished_input"]
 | 
			
		||||
        P_done -> S4
 | 
			
		||||
        S4 [label="S4: done" color="green"]
 | 
			
		||||
        S4 -> S4 [label="got_nameplates\ngot_wordlist"]
 | 
			
		||||
 | 
			
		||||
        other [shape="box" style="dotted"
 | 
			
		||||
               label="h.refresh_nameplates()\nh.get_nameplate_completions(prefix)\nh.choose_nameplate(nameplate)\nh.get_word_completions(prefix)\nh.choose_words(words)"
 | 
			
		||||
               ]
 | 
			
		||||
        {rank=same; S4 other}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,12 +31,9 @@ digraph {
 | 
			
		|||
        foo2 [label="" style="dashed"]
 | 
			
		||||
        foo2 -> P_tx
 | 
			
		||||
 | 
			
		||||
        S0B -> P_notify [label="rx"]
 | 
			
		||||
        S1B -> P_notify [label="rx" color="orange" fontcolor="orange"]
 | 
			
		||||
        P_notify [shape="box" label="C.got_nameplates()"]
 | 
			
		||||
        S0B -> P_notify [label="rx_nameplates"]
 | 
			
		||||
        S1B -> P_notify [label="rx_nameplates" color="orange" fontcolor="orange"]
 | 
			
		||||
        P_notify [shape="box" label="I.got_nameplates()"]
 | 
			
		||||
        P_notify -> S0B
 | 
			
		||||
 | 
			
		||||
        {rank=same; foo foo2 legend}
 | 
			
		||||
        legend [shape="box" style="dotted"
 | 
			
		||||
                label="refresh: L.refresh_nameplates()\nrx: L.rx_nameplates()"]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,8 +2,10 @@ digraph {
 | 
			
		|||
        Wormhole [shape="oval" color="blue" fontcolor="blue"]
 | 
			
		||||
        Boss [shape="box" label="Boss\n(manager)"
 | 
			
		||||
                  color="blue" fontcolor="blue"]
 | 
			
		||||
        Nameplate [shape="box" color="blue" fontcolor="blue"]
 | 
			
		||||
        Mailbox [shape="box" color="blue" fontcolor="blue"]
 | 
			
		||||
        Nameplate [label="Nameplate\n(claimer)"
 | 
			
		||||
                   shape="box" color="blue" fontcolor="blue"]
 | 
			
		||||
        Mailbox [label="Mailbox\n(opener)"
 | 
			
		||||
                 shape="box" color="blue" fontcolor="blue"]
 | 
			
		||||
        Connection [label="Rendezvous\nConnector"
 | 
			
		||||
                    shape="oval" color="blue" fontcolor="blue"]
 | 
			
		||||
        #websocket [color="blue" fontcolor="blue"]
 | 
			
		||||
| 
						 | 
				
			
			@ -16,9 +18,11 @@ digraph {
 | 
			
		|||
                color="blue" fontcolor="blue"]
 | 
			
		||||
        Allocator [shape="box" label="(nameplate)\nAllocator"
 | 
			
		||||
                   color="blue" fontcolor="blue"]
 | 
			
		||||
        Input [shape="box" label="(code)\nInput helper"
 | 
			
		||||
        Input [shape="box" label="(interactive\ncode)\nInput"
 | 
			
		||||
               color="blue" fontcolor="blue"]
 | 
			
		||||
        Terminator [shape="box" color="blue" fontcolor="blue"]
 | 
			
		||||
        InputHelperAPI [shape="oval" label="input\nhelper\nAPI"
 | 
			
		||||
                        color="blue" fontcolor="blue"]
 | 
			
		||||
 | 
			
		||||
        #Connection -> websocket [color="blue"]
 | 
			
		||||
        #Connection -> Order [color="blue"]
 | 
			
		||||
| 
						 | 
				
			
			@ -36,11 +40,8 @@ digraph {
 | 
			
		|||
 | 
			
		||||
        Boss -> Send [style="dashed" color="red" fontcolor="red" label="send"]
 | 
			
		||||
 | 
			
		||||
        Boss -> Nameplate [style="dashed" color="red" fontcolor="red"
 | 
			
		||||
                           label="set_nameplate"]
 | 
			
		||||
        #Boss -> Mailbox [color="blue"]
 | 
			
		||||
        Mailbox -> Order [style="dashed" label="got_message (once)"]
 | 
			
		||||
        Boss -> Key [style="dashed" label="got_code"]
 | 
			
		||||
        Key -> Boss [style="dashed" label="got_key\ngot_verifier\nscared"]
 | 
			
		||||
        Order -> Key [style="dashed" label="got_pake"]
 | 
			
		||||
        Order -> Receive [style="dashed" label="got_message"]
 | 
			
		||||
| 
						 | 
				
			
			@ -85,15 +86,18 @@ digraph {
 | 
			
		|||
                         ]
 | 
			
		||||
        #Code -> Lister [color="blue"]
 | 
			
		||||
        Input -> Lister [style="dashed" color="red" fontcolor="red"
 | 
			
		||||
                         label="refresh_nameplates"
 | 
			
		||||
                         label="refresh"
 | 
			
		||||
                         ]
 | 
			
		||||
        Boss -> Code [style="dashed" color="red" fontcolor="red"
 | 
			
		||||
                      label="allocate_code\ninput_code\nset_code"]
 | 
			
		||||
        Code -> Boss [style="dashed"
 | 
			
		||||
                      label="got_code"]
 | 
			
		||||
        Code -> Boss [style="dashed" label="got_code"]
 | 
			
		||||
        Code -> Key [style="dashed" label="got_code"]
 | 
			
		||||
        Code -> Nameplate [style="dashed" label="set_nameplate"]
 | 
			
		||||
 | 
			
		||||
        Code -> Input [style="dashed" color="red" fontcolor="red" label="start"]
 | 
			
		||||
        Input -> Code [style="dashed" label="finished_input"]
 | 
			
		||||
        Input -> Code [style="dashed" label="got_nameplate\nfinished_input"]
 | 
			
		||||
        InputHelperAPI -> Input [label="refresh_nameplates\nget_nameplate_completions\nchoose_nameplate\nget_word_completions\nchoose_words" color="orange" fontcolor="orange"]
 | 
			
		||||
 | 
			
		||||
        Code -> Allocator [style="dashed" color="red" fontcolor="red"
 | 
			
		||||
                           label="allocate"]
 | 
			
		||||
        Allocator -> Code [style="dashed" label="allocated"]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										65
									
								
								src/wormhole/_allocator.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/wormhole/_allocator.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,65 @@
 | 
			
		|||
from __future__ import print_function, absolute_import, unicode_literals
 | 
			
		||||
from zope.interface import implementer
 | 
			
		||||
from attr import attrs, attrib
 | 
			
		||||
from attr.validators import provides
 | 
			
		||||
from automat import MethodicalMachine
 | 
			
		||||
from . import _interfaces
 | 
			
		||||
 | 
			
		||||
@attrs
 | 
			
		||||
@implementer(_interfaces.IAllocator)
 | 
			
		||||
class Allocator(object):
 | 
			
		||||
    _timing = attrib(validator=provides(_interfaces.ITiming))
 | 
			
		||||
    m = MethodicalMachine()
 | 
			
		||||
    @m.setTrace()
 | 
			
		||||
    def set_trace(): pass # pragma: no cover
 | 
			
		||||
 | 
			
		||||
    def wire(self, rendezvous_connector, code):
 | 
			
		||||
        self._RC = _interfaces.IRendezvousConnector(rendezvous_connector)
 | 
			
		||||
        self._C = _interfaces.ICode(code)
 | 
			
		||||
 | 
			
		||||
    @m.state(initial=True)
 | 
			
		||||
    def S0A_idle(self): pass # pragma: no cover
 | 
			
		||||
    @m.state()
 | 
			
		||||
    def S0B_idle_connected(self): pass # pragma: no cover
 | 
			
		||||
    @m.state()
 | 
			
		||||
    def S1A_allocating(self): pass # pragma: no cover
 | 
			
		||||
    @m.state()
 | 
			
		||||
    def S1B_allocating_connected(self): pass # pragma: no cover
 | 
			
		||||
    @m.state()
 | 
			
		||||
    def S2_done(self): pass # pragma: no cover
 | 
			
		||||
 | 
			
		||||
    # from Code
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def allocate(self): pass
 | 
			
		||||
 | 
			
		||||
    # from RendezvousConnector
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def connected(self): pass
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def lost(self): pass
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def rx_allocated(self, nameplate): pass
 | 
			
		||||
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def RC_tx_allocate(self):
 | 
			
		||||
        self._RC.tx_allocate()
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def C_allocated(self, nameplate):
 | 
			
		||||
        self._C.allocated(nameplate)
 | 
			
		||||
 | 
			
		||||
    S0A_idle.upon(connected, enter=S0B_idle_connected, outputs=[])
 | 
			
		||||
    S0B_idle_connected.upon(lost, enter=S0A_idle, outputs=[])
 | 
			
		||||
 | 
			
		||||
    S0A_idle.upon(allocate, enter=S1A_allocating, outputs=[])
 | 
			
		||||
    S0B_idle_connected.upon(allocate, enter=S1B_allocating_connected,
 | 
			
		||||
                            outputs=[RC_tx_allocate])
 | 
			
		||||
 | 
			
		||||
    S1A_allocating.upon(connected, enter=S1B_allocating_connected,
 | 
			
		||||
                        outputs=[RC_tx_allocate])
 | 
			
		||||
    S1B_allocating_connected.upon(lost, enter=S1A_allocating, outputs=[])
 | 
			
		||||
 | 
			
		||||
    S1B_allocating_connected.upon(rx_allocated, enter=S2_done,
 | 
			
		||||
                                  outputs=[C_allocated])
 | 
			
		||||
 | 
			
		||||
    S2_done.upon(connected, enter=S2_done, outputs=[])
 | 
			
		||||
    S2_done.upon(lost, enter=S2_done, outputs=[])
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +15,8 @@ from ._key import Key
 | 
			
		|||
from ._receive import Receive
 | 
			
		||||
from ._rendezvous import RendezvousConnector
 | 
			
		||||
from ._lister import Lister
 | 
			
		||||
from ._allocator import Allocator
 | 
			
		||||
from ._input import Input
 | 
			
		||||
from ._code import Code
 | 
			
		||||
from ._terminator import Terminator
 | 
			
		||||
from .errors import (ServerError, LonelyError, WrongPasswordError,
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +51,8 @@ class Boss(object):
 | 
			
		|||
                                       self._reactor, self._journal,
 | 
			
		||||
                                       self._tor_manager, self._timing)
 | 
			
		||||
        self._L = Lister()
 | 
			
		||||
        self._A = Allocator(self._timing)
 | 
			
		||||
        self._I = Input(self._timing)
 | 
			
		||||
        self._C = Code(self._timing)
 | 
			
		||||
        self._T = Terminator()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +63,9 @@ class Boss(object):
 | 
			
		|||
        self._K.wire(self, self._M, self._R)
 | 
			
		||||
        self._R.wire(self, self._S)
 | 
			
		||||
        self._RC.wire(self, self._N, self._M, self._C, self._L, self._T)
 | 
			
		||||
        self._L.wire(self._RC, self._C)
 | 
			
		||||
        self._L.wire(self._RC, self._I)
 | 
			
		||||
        self._A.wire(self._RC, self._C)
 | 
			
		||||
        self._I.wire(self._C, self._L)
 | 
			
		||||
        self._C.wire(self, self._RC, self._L)
 | 
			
		||||
        self._T.wire(self, self._RC, self._N, self._M)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -189,8 +195,6 @@ class Boss(object):
 | 
			
		|||
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def do_got_code(self, code):
 | 
			
		||||
        nameplate = code.split("-")[0]
 | 
			
		||||
        self._N.set_nameplate(nameplate)
 | 
			
		||||
        self._K.got_code(code)
 | 
			
		||||
        self._W.got_code(code)
 | 
			
		||||
    @m.output()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,13 +74,11 @@ class Code(object):
 | 
			
		|||
    @m.input()
 | 
			
		||||
    def got_wordlist(self, wordlist): pass
 | 
			
		||||
 | 
			
		||||
    # from CodeInputHelper
 | 
			
		||||
    # from Input
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def update_nameplates(self): pass
 | 
			
		||||
    def got_nameplate(self, nameplate): pass
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def claim_nameplate(self, nameplate): pass
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def submit_words(self, words): pass
 | 
			
		||||
    def finished_input(self, code): pass
 | 
			
		||||
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def L_refresh_nameplates(self):
 | 
			
		||||
| 
						 | 
				
			
			@ -137,6 +135,7 @@ class Code(object):
 | 
			
		|||
        self._B_got_code()
 | 
			
		||||
 | 
			
		||||
    def _B_got_code(self):
 | 
			
		||||
        self._N.set_nameplate(nameplate) XXX
 | 
			
		||||
        self._B.got_code(self._code)
 | 
			
		||||
 | 
			
		||||
    S0A_unknown.upon(connected, enter=S0B_unknown_connected, outputs=[])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										106
									
								
								src/wormhole/_input.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/wormhole/_input.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,106 @@
 | 
			
		|||
from __future__ import print_function, absolute_import, unicode_literals
 | 
			
		||||
from zope.interface import implementer
 | 
			
		||||
from attr import attrs, attrib
 | 
			
		||||
from attr.validators import provides
 | 
			
		||||
from automat import MethodicalMachine
 | 
			
		||||
from . import _interfaces
 | 
			
		||||
 | 
			
		||||
@attrs
 | 
			
		||||
@implementer(_interfaces.IInput)
 | 
			
		||||
class Input(object):
 | 
			
		||||
    _timing = attrib(validator=provides(_interfaces.ITiming))
 | 
			
		||||
    m = MethodicalMachine()
 | 
			
		||||
    @m.setTrace()
 | 
			
		||||
    def set_trace(): pass # pragma: no cover
 | 
			
		||||
 | 
			
		||||
    def __attrs_post_init__(self):
 | 
			
		||||
        self._nameplate = None
 | 
			
		||||
        self._wordlist = None
 | 
			
		||||
        self._claimed_waiter = None
 | 
			
		||||
 | 
			
		||||
    def wire(self, code, lister):
 | 
			
		||||
        self._C = _interfaces.ICode(code)
 | 
			
		||||
        self._L = _interfaces.ILister(lister)
 | 
			
		||||
 | 
			
		||||
    @m.state(initial=True)
 | 
			
		||||
    def S0_idle(self): pass # pragma: no cover
 | 
			
		||||
    @m.state()
 | 
			
		||||
    def S1_nameplate(self): pass # pragma: no cover
 | 
			
		||||
    @m.state()
 | 
			
		||||
    def S2_code_no_wordlist(self): pass # pragma: no cover
 | 
			
		||||
    @m.state()
 | 
			
		||||
    def S3_code_yes_wordlist(self): pass # pragma: no cover
 | 
			
		||||
    @m.state(terminal=True)
 | 
			
		||||
    def S4_done(self): pass # pragma: no cover
 | 
			
		||||
 | 
			
		||||
    # from Code
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def start(self): pass
 | 
			
		||||
 | 
			
		||||
    # from Lister
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def got_nameplates(self, nameplates): pass
 | 
			
		||||
 | 
			
		||||
    # from Nameplate??
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def got_wordlist(self, wordlist): pass
 | 
			
		||||
 | 
			
		||||
    # from CodeInputHelper
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def refresh_nameplates(self): pass
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def _choose_nameplate(self, nameplate): pass
 | 
			
		||||
    @m.input()
 | 
			
		||||
    def choose_words(self, words): pass
 | 
			
		||||
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def L_refresh_nameplates(self):
 | 
			
		||||
        self._L.refresh_nameplates()
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def start_and_L_refresh_nameplates(self, input_helper):
 | 
			
		||||
        self._input_helper = input_helper
 | 
			
		||||
        self._L.refresh_nameplates()
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def stash_wordlist_and_notify(self, wordlist):
 | 
			
		||||
        self._wordlist = wordlist
 | 
			
		||||
        if self._claimed_waiter:
 | 
			
		||||
            self._claimed_waiter.callback(None)
 | 
			
		||||
            del self._claimed_waiter
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def stash_nameplate(self, nameplate):
 | 
			
		||||
        self._nameplate = nameplate
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def C_got_nameplate(self, nameplate):
 | 
			
		||||
        self._C.got_nameplate(nameplate)
 | 
			
		||||
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def finished(self, words):
 | 
			
		||||
        code = self._nameplate + "-" + words
 | 
			
		||||
        self._C.finished_input(code)
 | 
			
		||||
 | 
			
		||||
    S0_idle.upon(start, enter=S1_nameplate, outputs=[L_refresh_nameplates])
 | 
			
		||||
    S1_nameplate.upon(refresh_nameplates, enter=S1_nameplate,
 | 
			
		||||
                      outputs=[L_refresh_nameplates])
 | 
			
		||||
    S1_nameplate.upon(_choose_nameplate, enter=S2_code_no_wordlist,
 | 
			
		||||
                      outputs=[stash_nameplate, C_got_nameplate])
 | 
			
		||||
    S2_code_no_wordlist.upon(got_wordlist, enter=S3_code_yes_wordlist,
 | 
			
		||||
                             outputs=[stash_wordlist_and_notify])
 | 
			
		||||
    S2_code_no_wordlist.upon(choose_words, enter=S4_done, outputs=[finished])
 | 
			
		||||
    S3_code_yes_wordlist.upon(choose_words, enter=S4_done, outputs=[finished])
 | 
			
		||||
 | 
			
		||||
    # methods for the CodeInputHelper to use
 | 
			
		||||
    #refresh_nameplates/_choose_nameplate/choose_words: @m.input methods
 | 
			
		||||
 | 
			
		||||
    def get_nameplate_completions(self, prefix):
 | 
			
		||||
        completions = []
 | 
			
		||||
        for nameplate in self._nameplates
 | 
			
		||||
        pass
 | 
			
		||||
    def choose_nameplate(self, nameplate):
 | 
			
		||||
        if self._claimed_waiter is not None:
 | 
			
		||||
            raise X
 | 
			
		||||
        d = self._claimed_waiter = defer.Deferred()
 | 
			
		||||
        self._choose_nameplate(nameplate)
 | 
			
		||||
 | 
			
		||||
    def get_word_completions(self, prefix):
 | 
			
		||||
        pass
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +22,10 @@ class ILister(Interface):
 | 
			
		|||
    pass
 | 
			
		||||
class ICode(Interface):
 | 
			
		||||
    pass
 | 
			
		||||
class IInput(Interface):
 | 
			
		||||
    pass
 | 
			
		||||
class IAllocator(Interface):
 | 
			
		||||
    pass
 | 
			
		||||
class ITerminator(Interface):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,9 +9,9 @@ class Lister(object):
 | 
			
		|||
    @m.setTrace()
 | 
			
		||||
    def set_trace(): pass # pragma: no cover
 | 
			
		||||
 | 
			
		||||
    def wire(self, rendezvous_connector, code):
 | 
			
		||||
    def wire(self, rendezvous_connector, input):
 | 
			
		||||
        self._RC = _interfaces.IRendezvousConnector(rendezvous_connector)
 | 
			
		||||
        self._C = _interfaces.ICode(code)
 | 
			
		||||
        self._I = _interfaces.IInput(input)
 | 
			
		||||
 | 
			
		||||
    # Ideally, each API request would spawn a new "list_nameplates" message
 | 
			
		||||
    # to the server, so the response would be maximally fresh, but that would
 | 
			
		||||
| 
						 | 
				
			
			@ -44,8 +44,8 @@ class Lister(object):
 | 
			
		|||
    def RC_tx_list(self):
 | 
			
		||||
        self._RC.tx_list()
 | 
			
		||||
    @m.output()
 | 
			
		||||
    def C_got_nameplates(self, message):
 | 
			
		||||
        self._C.got_nameplates(message["nameplates"])
 | 
			
		||||
    def I_got_nameplates(self, message):
 | 
			
		||||
        self._I.got_nameplates(message["nameplates"])
 | 
			
		||||
 | 
			
		||||
    S0A_idle_disconnected.upon(connected, enter=S0B_idle_connected, outputs=[])
 | 
			
		||||
    S0B_idle_connected.upon(lost, enter=S0A_idle_disconnected, outputs=[])
 | 
			
		||||
| 
						 | 
				
			
			@ -59,9 +59,9 @@ class Lister(object):
 | 
			
		|||
    S0B_idle_connected.upon(refresh_nameplates, enter=S1B_wanting_connected,
 | 
			
		||||
                            outputs=[RC_tx_list])
 | 
			
		||||
    S0B_idle_connected.upon(rx_nameplates, enter=S0B_idle_connected,
 | 
			
		||||
                            outputs=[C_got_nameplates])
 | 
			
		||||
                            outputs=[I_got_nameplates])
 | 
			
		||||
    S1B_wanting_connected.upon(lost, enter=S1A_wanting_disconnected, outputs=[])
 | 
			
		||||
    S1B_wanting_connected.upon(refresh_nameplates, enter=S1B_wanting_connected,
 | 
			
		||||
                               outputs=[RC_tx_list])
 | 
			
		||||
    S1B_wanting_connected.upon(rx_nameplates, enter=S0B_idle_connected,
 | 
			
		||||
                               outputs=[C_got_nameplates])
 | 
			
		||||
                               outputs=[I_got_nameplates])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user