The code in util.py can tolerate a missing os.statvfs, but the code which
tests that code's ability to tolerate a missing os.statvfs was itself unable
to tolerate a missing os.statvfs. Sigh.
Apparently there's an intermittent condition in tests that follows this path.
We used to ignore unrecognized states, but to improve test coverage I added a
clause to catch them, and now that clause is happening where I didn't expect
it.
This fixes the case where "wormhole send" would wait forever (upon network
error) instead of terminating with a useful error message.
Testing this will have to wait until we land the branch that abandons the
wormhole if the first connection fails, since that's the easiest way to
provoke a network error before when_code() has fired.
I think we're better off without this: the CLI commands propagate the Failure
up to their callers (rather than eating it silently), the callers are using
task.react (which reacts to Failures by exiting with rc!=0), so nothing
should get lost. And doing an extra log.err() just creates more cleanup work
for test cases to flush, and makes the CLI commands double-print the any
errors (maybe task.react also points logging at stderr?).
This completely rewrites the client, splitting everything into many (13!)
small-ish state machines, merging about 5 months of work. This will enable
the following new features (none of which are fully implemented yet):
* survive the rendezvous server connection being lost, if we can reconnect
* learn the wordlist from the server, after claiming the nameplate, to enable
i18n wordlists (sender chooses language, receiver tab-completes on the
matching wordlist)
* likewise we can learn the code-length (number of words) from the server,
although this needs more thought before we can make it safe
* new "Delegated Mode" API, with callbacks instead of Deferreds
* properly serializable Wormhole state
* "journaled mode": synchronzing outbound messages with application state
checkpoints to provide robust behavior in the face of frequent and
uncoordinated shutdown
* making progress even when neither side is connected at the same time
* code-completion with non-readline frontends (e.g. GUI wordlist-dropdown)
User-visible changes from this rewrite:
* wormhole receive: if you use tab-completion, you can only set the nameplate
once, after which we've claimed that channel and are stuck with it until
the process exits. This means you can't type "5-<TAB><DEL><DEL>3-", because
we've already committed to a nameplate of "5". So initial typos are more of
a problem now. The client will show you an exception, but then you must
Control-C the process to exit.
* the "you should upgrade to a newer version" message now overlaps with the
code-input prompt, which is annoying (I hope to fix this before a release)
* networking problems that prevent a connection to the rendezvous server will
cause silent hangs (until I fix this too)
New docs:
* the docs/ directory now contains descriptions of the various
client-to-server and client-to-client protocols we use (none of which
changed)
* docs/api.md now has a comprehensive description of the API (which is still
subject to change)
* docs/state-machines/ contains DOT-format descriptions of each new state
machine, although running "automat-visualize wormhole" will build
more-accurate (but less-informative) diagrams of the actual
implementations
refs #42
The Welcome class prints a message if the server recommends a CLI version
that's newer than what the client is currently using, but only if the client
is running a "release" version, not a "local" development one. "local"
versions have a "+" in them (at least when Versioneer creates it), but
Welcome was looking for "-" as an indicator. So it was printing the warning
when it shouldn't be.
re-enable the test, and add an extra one
The comments in cmd_send/cmd_receive now enumerate the four cases where we
might notice that things are taking too long, the three cases where we say
something about it, and the two cases where it might be appropriate to give
up automatically (although we don't do that anywhere yet).
Previously, w.when_verified() was documented to fire only after a valid
encrypted message was received, but in fact it fired as soon as the shared
key was derived (before any encrypted messages are seen, so no actual
"verification" could occur yet).
This fixes that, and also adds a new w.when_key() API call which fires at the
earlier point. Having something which fires early is useful for the CLI
commands that want to print a pacifier message when the peer is responding
slowly. In particular it helps detect the case where 'wormhole send' has quit
early (after depositing the PAKE message on the server, but before the
receiver has started). In this case, the receiver will compute the shared
key, but then wait forever hoping for a VERSION that will never come. By
starting a timer when w.when_key() fires, and cancelling it when
w.when_verified() fires, we have a good place to tell the user that something
is taking longer than it should have.
This shifts responsibility for notifying Boss.got_verifier, out of Key and
into Receive, since Receive is what notices the first valid encrypted
message. It also shifts the Boss's ordering expectations: it now receives
B.happy() before B.got_verifier(), and consequently got_verifier ought to
arrive in the S2_happy state rather than S1_lonely.