start on sample clients
This commit is contained in:
parent
1b6668ff0a
commit
84852f26f5
45
docs/api.md
45
docs/api.md
|
@ -88,3 +88,48 @@ thousands of concurrent sessions.
|
||||||
The library uses a baked-in rendezvous server hostname. This must be the same
|
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=`
|
for both clients. To use a different hostname provide it as the `rendezvous=`
|
||||||
argument to the `Initiator`/`Receiver` constructor.
|
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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
23
src/wormhole/receive_file.py
Normal file
23
src/wormhole/receive_file.py
Normal 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
|
14
src/wormhole/receive_text.py
Normal file
14
src/wormhole/receive_text.py
Normal 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
31
src/wormhole/send_file.py
Normal 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
24
src/wormhole/send_text.py
Normal 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,))
|
Loading…
Reference in New Issue
Block a user