start on sample clients

This commit is contained in:
Brian Warner 2015-02-10 16:50:32 -08:00
parent 1b6668ff0a
commit 84852f26f5
5 changed files with 137 additions and 0 deletions

View File

@ -88,3 +88,48 @@ thousands of concurrent sessions.
The library uses a baked-in rendezvous server hostname. This must be the same
for both clients. To use a different hostname provide it as the `rendezvous=`
argument to the `Initiator`/`Receiver` constructor.
## Polling and Shutdown
The reactor-based (Twisted-style) forms of these objects need to establish
TCP connections, re-establish them if they are lost, and sometimes (for
transports that don't support long-running connections) poll for new
messages. They may also time out eventually. Longer delays mean less network
traffic, but higher latency.
These timers should be matched to the expectations, and expected behavior, of
your users. In a file-transfer application, where the users are sitting next
to each other, it is appropriate to poll very frequently (perhaps every
500ms) for a few minutes, then give up. In an email-like messaging program
where the introduction is establishing a long-term relationship, and the
program can store any outgoing messages until the connection is established,
it is probably better to poll once a minute for the first few minutes, then
back off to once an hour, and not give up for several days.
The `schedule=` constructor argument establishes the polling schedule. It
should contain a sorted list of (when, interval) tuples (both floats). At
`when` seconds after the first `start()` call, the polling interval will be
set to `interval`.
The `timeout=` argument provides a hard timeout. After this many seconds, the
sync will be abandoned, and all callbacks will errback with a TimeoutError.
Both have defaults suitable for face-to-face realtime setup environments.
## Serialization
You may not be able to hold the Initiator/Receiver object in memory for the
whole sync process: maybe you allow it to wait for several days, but the
program will be restarted during that time. To support this, you can persist
the state of the object by calling `data = i.serialize()`, which will return
a printable bytestring (the JSON-encoding of a small dictionary). To restore,
call `Initiator.from_serialized(data)`.
Note that callbacks are not serialized: they must be restored after
deserialization.
## Detailed Example
```python
```

View File

@ -0,0 +1,23 @@
import sys, json
from binascii import unhexlify
from nacl.secret import SecretBox
from nacl import utils
from . import api
APPID = "lothar.com/wormhole/file-xfer"
RELAY = "example.com"
# we're receiving
code = sys.argv[1]
blob = b""
r = api.Receiver(APPID, blob, code)
them_bytes = r.finish()
them_d = json.loads(them_bytes.decode("utf-8"))
print("them: %r" % (them_d,))
xfer_key = unhexlify(them_d["xfer_key"].encode("ascii"))
filename = them_d["filename"] # unicode
filesize = them_d["filesize"]
relay = them_d["relay"].encode("ascii")
# now receive the rest of the owl

View File

@ -0,0 +1,14 @@
import sys, json
from . import api
APPID = "lothar.com/wormhole/text-xfer"
RELAY = "example.com"
# we're receiving
code = sys.argv[1]
blob = b""
r = api.Receiver(APPID, blob, code)
them_bytes = r.finish()
them_d = json.loads(them_bytes.decode("utf-8"))
print(them_d["message"])

31
src/wormhole/send_file.py Normal file
View File

@ -0,0 +1,31 @@
import os, sys, json
from binascii import hexlify
from nacl.secret import SecretBox
from nacl import utils
from . import api
APPID = "lothar.com/wormhole/file-xfer"
RELAY = "example.com"
# we're sending
filename = sys.argv[1]
assert os.path.isfile(filename)
xfer_key = utils.random(SecretBox.KEY_SIZE)
blob = json.dumps({"xfer_key": hexlify(xfer_key),
"filename": os.path.basename(filename),
"filesize": os.stat(filename).st_size,
"relay": RELAY,
}).encode("utf-8")
i = api.Initiator(APPID, blob)
code = i.start()
print("Wormhole code is '%s'" % code)
print("On the other computer, please run:")
print()
print(" wormhole-receive-file %s" % code)
print()
them_bytes = i.finish()
them_d = json.loads(them_bytes.decode("utf-8"))
print("them: %r" % (them_d,))
# now draw the rest of the owl

24
src/wormhole/send_text.py Normal file
View File

@ -0,0 +1,24 @@
import sys, json
from nacl.secret import SecretBox
from nacl import utils
from . import api
APPID = "lothar.com/wormhole/text-xfer"
RELAY = "example.com"
# we're sending
message = sys.argv[1]
xfer_key = utils.random(SecretBox.KEY_SIZE)
blob = json.dumps({"message": message,
}).encode("utf-8")
i = api.Initiator(APPID, blob)
code = i.start()
print("Wormhole code is '%s'" % code)
print("On the other computer, please run:")
print()
print(" wormhole-receive-text %s" % code)
print()
them_bytes = i.finish()
them_d = json.loads(them_bytes.decode("utf-8"))
print("them: %r" % (them_d,))