mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 14:58:09 +00:00
add transport for bridge
This commit is contained in:
parent
58711df5d3
commit
a527456db5
6
cmdtr.py
6
cmdtr.py
@ -12,7 +12,7 @@ from trezorlib.protobuf_json import pb2json
|
||||
def parse_args(commands):
|
||||
parser = argparse.ArgumentParser(description='Commandline tool for Trezor devices.')
|
||||
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='Prints communication to device')
|
||||
parser.add_argument('-t', '--transport', dest='transport', choices=['usb', 'serial', 'pipe', 'socket'], default='usb', help="Transport used for talking with the device")
|
||||
parser.add_argument('-t', '--transport', dest='transport', choices=['usb', 'serial', 'pipe', 'socket', 'bridge'], default='usb', help="Transport used for talking with the device")
|
||||
parser.add_argument('-p', '--path', dest='path', default='', help="Path used by the transport (usually serial port)")
|
||||
# parser.add_argument('-dt', '--debuglink-transport', dest='debuglink_transport', choices=['usb', 'serial', 'pipe', 'socket'], default='usb', help="Debuglink transport")
|
||||
# parser.add_argument('-dp', '--debuglink-path', dest='debuglink_path', default='', help="Path used by the transport (usually serial port)")
|
||||
@ -66,6 +66,10 @@ def get_transport(transport_string, path, **kwargs):
|
||||
if transport_string == 'socket':
|
||||
from trezorlib.transport_socket import SocketTransportClient
|
||||
return SocketTransportClient(path, **kwargs)
|
||||
|
||||
if transport_string == 'bridge':
|
||||
from trezorlib.transport_bridge import BridgeTransport
|
||||
return BridgeTransport(path, **kwargs)
|
||||
|
||||
if transport_string == 'fake':
|
||||
from trezorlib.transport_fake import FakeTransport
|
||||
|
@ -4,13 +4,14 @@ sys.path = ['../',] + sys.path
|
||||
from trezorlib.transport_pipe import PipeTransport
|
||||
from trezorlib.transport_hid import HidTransport
|
||||
from trezorlib.transport_socket import SocketTransportClient
|
||||
from trezorlib.transport_bridge import BridgeTransport
|
||||
|
||||
devices = HidTransport.enumerate()
|
||||
|
||||
if len(devices) > 0:
|
||||
if devices[0][1] != None:
|
||||
print 'Using TREZOR'
|
||||
TRANSPORT = HidTransport
|
||||
TRANSPORT = BridgeTransport
|
||||
TRANSPORT_ARGS = (devices[0],)
|
||||
TRANSPORT_KWARGS = {'debug_link': False}
|
||||
DEBUG_TRANSPORT = HidTransport
|
||||
|
@ -41,10 +41,10 @@ __version__='0.0.5'
|
||||
__author__='Paul Dovbush <dpp@dpp.su>'
|
||||
|
||||
|
||||
import json # py2.6+ TODO: add support for other JSON serialization modules
|
||||
import json
|
||||
from google.protobuf.descriptor import FieldDescriptor as FD
|
||||
import binascii
|
||||
|
||||
import types_pb2 as types
|
||||
|
||||
class ParseError(Exception): pass
|
||||
|
||||
@ -112,7 +112,7 @@ _ftype2js = {
|
||||
#FD.TYPE_MESSAGE: pb2json, #handled specially
|
||||
FD.TYPE_BYTES: lambda x: binascii.hexlify(x),
|
||||
FD.TYPE_UINT32: int,
|
||||
FD.TYPE_ENUM: int,
|
||||
FD.TYPE_ENUM: str,
|
||||
FD.TYPE_SFIXED32: float,
|
||||
FD.TYPE_SFIXED64: float,
|
||||
FD.TYPE_SINT32: int,
|
||||
@ -132,7 +132,7 @@ _js2ftype = {
|
||||
# FD.TYPE_MESSAGE: json2pb, #handled specially
|
||||
FD.TYPE_BYTES: lambda x: binascii.unhexlify(x),
|
||||
FD.TYPE_UINT32: int,
|
||||
FD.TYPE_ENUM: int,
|
||||
FD.TYPE_ENUM: lambda x: getattr(types, x),
|
||||
FD.TYPE_SFIXED32: float,
|
||||
FD.TYPE_SFIXED64: float,
|
||||
FD.TYPE_SINT32: int,
|
||||
|
@ -19,7 +19,7 @@ class Transport(object):
|
||||
def _close(self):
|
||||
raise NotImplementedException("Not implemented")
|
||||
|
||||
def _write(self, msg):
|
||||
def _write(self, msg, protobuf_msg):
|
||||
raise NotImplementedException("Not implemented")
|
||||
|
||||
def _read(self):
|
||||
@ -51,7 +51,7 @@ class Transport(object):
|
||||
def write(self, msg):
|
||||
ser = msg.SerializeToString()
|
||||
header = struct.pack(">HL", mapping.get_type(msg), len(ser))
|
||||
self._write("##%s%s" % (header, ser))
|
||||
self._write("##%s%s" % (header, ser), msg)
|
||||
|
||||
def read(self):
|
||||
if not self.ready_to_read():
|
||||
@ -73,9 +73,12 @@ class Transport(object):
|
||||
|
||||
def _parse_message(self, data):
|
||||
(msg_type, data) = data
|
||||
inst = mapping.get_class(msg_type)()
|
||||
inst.ParseFromString(data)
|
||||
return inst
|
||||
if msg_type == 'protobuf':
|
||||
return data
|
||||
else:
|
||||
inst = mapping.get_class(msg_type)()
|
||||
inst.ParseFromString(data)
|
||||
return inst
|
||||
|
||||
def _read_headers(self, read_f):
|
||||
# Try to read headers until some sane value are detected
|
||||
|
74
trezorlib/transport_bridge.py
Normal file
74
trezorlib/transport_bridge.py
Normal file
@ -0,0 +1,74 @@
|
||||
'''BridgeTransport implements transport TREZOR Bridge (aka trezord).'''
|
||||
|
||||
import binascii
|
||||
import requests
|
||||
import protobuf_json
|
||||
import json
|
||||
import mapping
|
||||
from transport import Transport
|
||||
import messages_pb2 as proto
|
||||
|
||||
TREZORD_HOST = 'http://localhost:21324'
|
||||
CONFIG_URL = 'https://mytrezor.com/data/plugin/config_signed.bin'
|
||||
|
||||
class BridgeTransport(Transport):
|
||||
def __init__(self, device, *args, **kwargs):
|
||||
|
||||
r = requests.get(CONFIG_URL)
|
||||
if r.status_code != 200:
|
||||
raise Exception('Could not fetch config from %s' % CONFIG_URL)
|
||||
|
||||
config = binascii.unhexlify(r.text)
|
||||
|
||||
r = requests.post(TREZORD_HOST + '/configure', data=config)
|
||||
if r.status_code != 200:
|
||||
raise Exception('trezord: Could not configure')
|
||||
|
||||
r = requests.get(TREZORD_HOST + '/enumerate')
|
||||
if r.status_code != 200:
|
||||
raise Exception('trezord: Could not enumerate devices')
|
||||
enum = r.json()
|
||||
|
||||
if len(enum) < 1:
|
||||
raise Exception('trezord: No devices found')
|
||||
|
||||
self.path = enum[0]['path']
|
||||
self.session = None
|
||||
self.response = None
|
||||
|
||||
super(BridgeTransport, self).__init__(device, *args, **kwargs)
|
||||
|
||||
def _open(self):
|
||||
r = requests.post(TREZORD_HOST + '/acquire/%s' % self.path)
|
||||
if r.status_code != 200:
|
||||
raise Exception('trezord: Could not acquire session')
|
||||
resp = r.json()
|
||||
self.session = resp['session']
|
||||
|
||||
def _close(self):
|
||||
r = requests.post(TREZORD_HOST + '/release/%s' % self.session)
|
||||
if r.status_code != 200:
|
||||
raise Exception('trezord: Could not release session')
|
||||
else:
|
||||
self.session = None
|
||||
|
||||
def ready_to_read(self):
|
||||
return self.response != None
|
||||
|
||||
def _write(self, msg, protobuf_msg):
|
||||
cls = protobuf_msg.__class__.__name__
|
||||
msg = protobuf_json.pb2json(protobuf_msg)
|
||||
payload = '{"type": "%s","message": %s}' % (cls, json.dumps(msg))
|
||||
r = requests.post(TREZORD_HOST + '/call/%s' % self.session, data=payload)
|
||||
if r.status_code != 200:
|
||||
raise Exception('trezord: Could not write message')
|
||||
else:
|
||||
self.response = r.json()
|
||||
|
||||
def _read(self):
|
||||
if self.response == None:
|
||||
raise Exception('No response stored')
|
||||
cls = getattr(proto, self.response['type'])
|
||||
inst = cls()
|
||||
pb = protobuf_json.json2pb(inst, self.response['message'])
|
||||
return ('protobuf', pb)
|
@ -17,8 +17,8 @@ class FakeTransport(Transport):
|
||||
def ready_to_read(self):
|
||||
return False
|
||||
|
||||
def _write(self, msg):
|
||||
def _write(self, msg, protobuf_msg):
|
||||
pass
|
||||
|
||||
def _read(self):
|
||||
raise NotImplementedException("Not implemented")
|
||||
raise NotImplementedException("Not implemented")
|
||||
|
@ -96,7 +96,7 @@ class HidTransport(Transport):
|
||||
def ready_to_read(self):
|
||||
return False
|
||||
|
||||
def _write(self, msg):
|
||||
def _write(self, msg, protobuf_msg):
|
||||
msg = bytearray(msg)
|
||||
while len(msg):
|
||||
# Report ID, data padded to 63 bytes
|
||||
|
@ -1,4 +1,4 @@
|
||||
'''TransportFake implements fake wire transport over local named pipe.
|
||||
'''PipeTransport implements fake wire transport over local named pipe.
|
||||
Use this transport for talking with trezor simulator.'''
|
||||
|
||||
import os
|
||||
@ -42,7 +42,7 @@ class PipeTransport(Transport):
|
||||
rlist, _, _ = select([self.read_f], [], [], 0)
|
||||
return len(rlist) > 0
|
||||
|
||||
def _write(self, msg):
|
||||
def _write(self, msg, protobuf_msg):
|
||||
try:
|
||||
self.write_f.write(msg)
|
||||
self.write_f.flush()
|
||||
|
@ -22,7 +22,7 @@ class SerialTransport(Transport):
|
||||
rlist, _, _ = select([self.serial], [], [], 0)
|
||||
return len(rlist) > 0
|
||||
|
||||
def _write(self, msg):
|
||||
def _write(self, msg, protobuf_msg):
|
||||
try:
|
||||
self.serial.write(msg)
|
||||
self.serial.flush()
|
||||
@ -36,4 +36,4 @@ class SerialTransport(Transport):
|
||||
return (msg_type, self.serial.read(datalen))
|
||||
except serial.SerialException:
|
||||
print "Failed to read from device"
|
||||
raise
|
||||
raise
|
||||
|
@ -29,7 +29,7 @@ class SocketTransportClient(Transport):
|
||||
rlist, _, _ = select([self.socket], [], [], 0)
|
||||
return len(rlist) > 0
|
||||
|
||||
def _write(self, msg):
|
||||
def _write(self, msg, protobuf_msg):
|
||||
self.socket.sendall(msg)
|
||||
|
||||
def _read(self):
|
||||
@ -89,7 +89,7 @@ class SocketTransport(Transport):
|
||||
return self.ready_to_read()
|
||||
return False
|
||||
|
||||
def _write(self, msg):
|
||||
def _write(self, msg, protobuf_msg):
|
||||
if self.filelike:
|
||||
# None on disconnected client
|
||||
|
||||
@ -107,4 +107,4 @@ class SocketTransport(Transport):
|
||||
except Exception:
|
||||
print "Failed to read from device"
|
||||
self._disconnect_client()
|
||||
return None
|
||||
return None
|
||||
|
Loading…
Reference in New Issue
Block a user