magic-wormhole/bin/send_file.py

69 lines
2.0 KiB
Python
Raw Normal View History

2015-02-11 09:18:31 +00:00
from __future__ import print_function
2015-02-11 00:50:32 +00:00
import os, sys, json
from nacl.secret import SecretBox
2015-02-20 08:32:48 +00:00
from wormhole.blocking.transcribe import Initiator, WrongPasswordError
2015-02-15 17:53:59 +00:00
from wormhole.blocking.transit import TransitSender
2015-02-11 00:50:32 +00:00
APPID = "lothar.com/wormhole/file-xfer"
# we're sending
filename = sys.argv[1]
assert os.path.isfile(filename)
2015-02-15 17:53:59 +00:00
transit_sender = TransitSender()
filesize = os.stat(filename).st_size
2015-02-15 22:42:59 +00:00
data = json.dumps({
"file": {
"filename": os.path.basename(filename),
"filesize": filesize,
2015-02-15 22:42:59 +00:00
},
"transit": {
2015-02-20 03:09:08 +00:00
"direct_connection_hints": transit_sender.get_direct_hints(),
"relay_connection_hints": transit_sender.get_relay_hints(),
2015-02-15 22:42:59 +00:00
},
}).encode("utf-8")
2015-02-15 17:53:59 +00:00
i = Initiator(APPID, data)
code = i.get_code()
2015-02-15 17:53:59 +00:00
print("On the other computer, please run: receive_file")
2015-02-11 00:50:32 +00:00
print("Wormhole code is '%s'" % code)
2015-02-15 17:53:59 +00:00
print("")
2015-02-20 08:32:48 +00:00
try:
them_bytes = i.get_data()
except WrongPasswordError as e:
print("ERROR: " + e.explain(), file=sys.stderr)
sys.exit(1)
2015-02-11 00:50:32 +00:00
them_d = json.loads(them_bytes.decode("utf-8"))
#print("them: %r" % (them_d,))
xfer_key = i.derive_key(APPID+"/xfer-key", SecretBox.KEY_SIZE)
2015-02-11 00:50:32 +00:00
2015-02-11 01:04:28 +00:00
box = SecretBox(xfer_key)
with open(filename, "rb") as f:
plaintext = f.read()
nonce = os.urandom(SecretBox.NONCE_SIZE)
2015-02-11 01:04:28 +00:00
encrypted = box.encrypt(plaintext, nonce)
tdata = them_d["transit"]
transit_key = i.derive_key(APPID+"/transit-key")
transit_sender.set_transit_key(transit_key)
2015-02-20 03:09:08 +00:00
transit_sender.add_their_direct_hints(tdata["direct_connection_hints"])
transit_sender.add_their_relay_hints(tdata["relay_connection_hints"])
skt = transit_sender.establish_connection()
print("Sending %d bytes.." % filesize)
sent = 0
while sent < len(encrypted):
more = skt.send(encrypted[sent:])
sent += more
2015-02-15 17:53:59 +00:00
print("File sent.. waiting for confirmation")
# ack is a short newline-terminated string, followed by socket close. A long
# read is probably good enough.
ack = skt.recv(300)
if ack == "ok\n":
print("Confirmation received. Transfer complete.")
sys.exit(0)
else:
print("Transfer failed (remote says: %r)" % ack)
sys.exit(1)