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
|
||||
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
|
||||
|
||||
```
|
||||
|
|
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