add transport for bridge

pull/1/head
Pavol Rusnak 10 years ago
parent 58711df5d3
commit a527456db5

@ -12,7 +12,7 @@ from trezorlib.protobuf_json import pb2json
def parse_args(commands): def parse_args(commands):
parser = argparse.ArgumentParser(description='Commandline tool for Trezor devices.') 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('-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('-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('-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)") # 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': if transport_string == 'socket':
from trezorlib.transport_socket import SocketTransportClient from trezorlib.transport_socket import SocketTransportClient
return SocketTransportClient(path, **kwargs) return SocketTransportClient(path, **kwargs)
if transport_string == 'bridge':
from trezorlib.transport_bridge import BridgeTransport
return BridgeTransport(path, **kwargs)
if transport_string == 'fake': if transport_string == 'fake':
from trezorlib.transport_fake import FakeTransport from trezorlib.transport_fake import FakeTransport

@ -4,13 +4,14 @@ sys.path = ['../',] + sys.path
from trezorlib.transport_pipe import PipeTransport from trezorlib.transport_pipe import PipeTransport
from trezorlib.transport_hid import HidTransport from trezorlib.transport_hid import HidTransport
from trezorlib.transport_socket import SocketTransportClient from trezorlib.transport_socket import SocketTransportClient
from trezorlib.transport_bridge import BridgeTransport
devices = HidTransport.enumerate() devices = HidTransport.enumerate()
if len(devices) > 0: if len(devices) > 0:
if devices[0][1] != None: if devices[0][1] != None:
print 'Using TREZOR' print 'Using TREZOR'
TRANSPORT = HidTransport TRANSPORT = BridgeTransport
TRANSPORT_ARGS = (devices[0],) TRANSPORT_ARGS = (devices[0],)
TRANSPORT_KWARGS = {'debug_link': False} TRANSPORT_KWARGS = {'debug_link': False}
DEBUG_TRANSPORT = HidTransport DEBUG_TRANSPORT = HidTransport

@ -41,10 +41,10 @@ __version__='0.0.5'
__author__='Paul Dovbush <dpp@dpp.su>' __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 from google.protobuf.descriptor import FieldDescriptor as FD
import binascii import binascii
import types_pb2 as types
class ParseError(Exception): pass class ParseError(Exception): pass
@ -112,7 +112,7 @@ _ftype2js = {
#FD.TYPE_MESSAGE: pb2json, #handled specially #FD.TYPE_MESSAGE: pb2json, #handled specially
FD.TYPE_BYTES: lambda x: binascii.hexlify(x), FD.TYPE_BYTES: lambda x: binascii.hexlify(x),
FD.TYPE_UINT32: int, FD.TYPE_UINT32: int,
FD.TYPE_ENUM: int, FD.TYPE_ENUM: str,
FD.TYPE_SFIXED32: float, FD.TYPE_SFIXED32: float,
FD.TYPE_SFIXED64: float, FD.TYPE_SFIXED64: float,
FD.TYPE_SINT32: int, FD.TYPE_SINT32: int,
@ -132,7 +132,7 @@ _js2ftype = {
# FD.TYPE_MESSAGE: json2pb, #handled specially # FD.TYPE_MESSAGE: json2pb, #handled specially
FD.TYPE_BYTES: lambda x: binascii.unhexlify(x), FD.TYPE_BYTES: lambda x: binascii.unhexlify(x),
FD.TYPE_UINT32: int, FD.TYPE_UINT32: int,
FD.TYPE_ENUM: int, FD.TYPE_ENUM: lambda x: getattr(types, x),
FD.TYPE_SFIXED32: float, FD.TYPE_SFIXED32: float,
FD.TYPE_SFIXED64: float, FD.TYPE_SFIXED64: float,
FD.TYPE_SINT32: int, FD.TYPE_SINT32: int,

@ -19,7 +19,7 @@ class Transport(object):
def _close(self): def _close(self):
raise NotImplementedException("Not implemented") raise NotImplementedException("Not implemented")
def _write(self, msg): def _write(self, msg, protobuf_msg):
raise NotImplementedException("Not implemented") raise NotImplementedException("Not implemented")
def _read(self): def _read(self):
@ -51,7 +51,7 @@ class Transport(object):
def write(self, msg): def write(self, msg):
ser = msg.SerializeToString() ser = msg.SerializeToString()
header = struct.pack(">HL", mapping.get_type(msg), len(ser)) 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): def read(self):
if not self.ready_to_read(): if not self.ready_to_read():
@ -73,9 +73,12 @@ class Transport(object):
def _parse_message(self, data): def _parse_message(self, data):
(msg_type, data) = data (msg_type, data) = data
inst = mapping.get_class(msg_type)() if msg_type == 'protobuf':
inst.ParseFromString(data) return data
return inst else:
inst = mapping.get_class(msg_type)()
inst.ParseFromString(data)
return inst
def _read_headers(self, read_f): def _read_headers(self, read_f):
# Try to read headers until some sane value are detected # Try to read headers until some sane value are detected

@ -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): def ready_to_read(self):
return False return False
def _write(self, msg): def _write(self, msg, protobuf_msg):
pass pass
def _read(self): def _read(self):
raise NotImplementedException("Not implemented") raise NotImplementedException("Not implemented")

@ -96,7 +96,7 @@ class HidTransport(Transport):
def ready_to_read(self): def ready_to_read(self):
return False return False
def _write(self, msg): def _write(self, msg, protobuf_msg):
msg = bytearray(msg) msg = bytearray(msg)
while len(msg): while len(msg):
# Report ID, data padded to 63 bytes # 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.''' Use this transport for talking with trezor simulator.'''
import os import os
@ -42,7 +42,7 @@ class PipeTransport(Transport):
rlist, _, _ = select([self.read_f], [], [], 0) rlist, _, _ = select([self.read_f], [], [], 0)
return len(rlist) > 0 return len(rlist) > 0
def _write(self, msg): def _write(self, msg, protobuf_msg):
try: try:
self.write_f.write(msg) self.write_f.write(msg)
self.write_f.flush() self.write_f.flush()

@ -22,7 +22,7 @@ class SerialTransport(Transport):
rlist, _, _ = select([self.serial], [], [], 0) rlist, _, _ = select([self.serial], [], [], 0)
return len(rlist) > 0 return len(rlist) > 0
def _write(self, msg): def _write(self, msg, protobuf_msg):
try: try:
self.serial.write(msg) self.serial.write(msg)
self.serial.flush() self.serial.flush()
@ -36,4 +36,4 @@ class SerialTransport(Transport):
return (msg_type, self.serial.read(datalen)) return (msg_type, self.serial.read(datalen))
except serial.SerialException: except serial.SerialException:
print "Failed to read from device" print "Failed to read from device"
raise raise

@ -29,7 +29,7 @@ class SocketTransportClient(Transport):
rlist, _, _ = select([self.socket], [], [], 0) rlist, _, _ = select([self.socket], [], [], 0)
return len(rlist) > 0 return len(rlist) > 0
def _write(self, msg): def _write(self, msg, protobuf_msg):
self.socket.sendall(msg) self.socket.sendall(msg)
def _read(self): def _read(self):
@ -89,7 +89,7 @@ class SocketTransport(Transport):
return self.ready_to_read() return self.ready_to_read()
return False return False
def _write(self, msg): def _write(self, msg, protobuf_msg):
if self.filelike: if self.filelike:
# None on disconnected client # None on disconnected client
@ -107,4 +107,4 @@ class SocketTransport(Transport):
except Exception: except Exception:
print "Failed to read from device" print "Failed to read from device"
self._disconnect_client() self._disconnect_client()
return None return None

Loading…
Cancel
Save