SEDbgMuxApp: employ DbgMuxFrameDisp, implement basic handlers

This commit is contained in:
Vadim Yanitskiy 2022-06-26 00:02:02 +07:00
parent 91abeb7220
commit c81e0e2ad8
2 changed files with 85 additions and 54 deletions

View File

@ -112,12 +112,12 @@ class DbgMuxPeer:
# Init frame dispatcher
self.disp = DbgMuxFrameDisp(self._rx_queue,
self._tx_queue)
# TODO: self.disp.start()
def start(self) -> None:
self._shutdown.clear()
self._rx_thread.start()
self._tx_thread.start()
self.disp.start()
def stop(self) -> None:
# Set the shutdown event
@ -125,6 +125,7 @@ class DbgMuxPeer:
# Wait for both threads to terminate
self._tx_thread.join()
self._rx_thread.join()
self.disp.stop()
def _rx_worker(self) -> None:
while not self._shutdown.is_set():

View File

@ -23,11 +23,74 @@ import argparse
import cmd2
import enum
import sys
import time
from transport import TransportModem
from proto import DbgMuxFrame
from peer import DbgMuxPeer
from construct import Container
from handlers import DbgMuxFrameHandler
from handlers import DbgMuxConnUdpBridge
from handlers import DbgMuxConnInteractiveTerminal
class CommonFrameHandler(DbgMuxFrameHandler):
''' Handles some common messages '''
def __init__(self, cmd2):
self.cmd2 = cmd2
def _handle_frame(self, frame: Container) -> None:
if frame['MsgType'] == DbgMuxFrame.MsgType.Ident:
log.info("Identified target: '%s', IMEI=%s",
frame['Msg']['Ident'][:-15],
frame['Msg']['Ident'][-15:])
elif frame['MsgType'] == DbgMuxFrame.MsgType.DPAnnounce:
log.info("Data Provider available (DPRef=0x%04x): '%s'",
frame['Msg']['DPRef'], frame['Msg']['Name'])
elif frame['MsgType'] == DbgMuxFrame.MsgType.FlowControl:
log.warning("Rx FlowControl message, which is not yet supported")
elif frame['MsgType'] == DbgMuxFrame.MsgType.ConnEstablished \
and frame['Msg']['ConnRef'] == 0xffff:
log.warning("Connection establishment failed, "
"no such DPRef=0x%04x?", frame['Msg']['DPRef'])
elif frame['MsgType'] == DbgMuxFrame.MsgType.ConnTerminated \
and frame['Msg']['ConnRef'] == 0xffff:
log.warning("Connection termination failed, "
"no such DPRef=0x%04x?", frame['Msg']['DPRef'])
elif frame['MsgType'] == DbgMuxFrame.MsgType.Ack:
raise StopIteration
else: # To be consumed by other handlers
return
self.send(DbgMuxFrame.MsgType.Ack)
raise StopIteration
class PingPongHandler(DbgMuxFrameHandler):
''' Handles DbgMuxFrame.MsgType.Pong '''
def __init__(self):
self.expect_pong: bool = False
def ping(self, payload: str):
log.info('Tx Ping with payload \'%s\'', payload)
self.send(DbgMuxFrame.MsgType.Ping, payload)
self.expect_pong = True
# TODO: start a timer?
def handle_pong(self, payload: str):
if not self.expect_pong:
log.warning('Rx unexpected Pong, sending ACK anyway')
return
log.info('Rx Pong with payload \'%s\'', payload)
self.expect_pong = False
def _handle_frame(self, frame: Container) -> None:
if frame['MsgType'] == DbgMuxFrame.MsgType.Pong:
self.handle_pong(frame['Msg'])
self.send(DbgMuxFrame.MsgType.Ack)
raise StopIteration
class SEDbgMuxApp(cmd2.Cmd):
DESC = 'DebugMux client for [Sony] Ericsson phones and modems'
@ -48,6 +111,10 @@ class SEDbgMuxApp(cmd2.Cmd):
self.transport = TransportModem(self.argv)
self.peer = DbgMuxPeer(self.transport)
# Register DebugMux frame handlers
self.peer.disp.register(CommonFrameHandler(self), 'Common')
self.peer.disp.register(PingPongHandler(), 'PingPong')
# Modem connection state
self.set_connected(False)
@ -88,23 +155,8 @@ class SEDbgMuxApp(cmd2.Cmd):
def do_enquiry(self, opts) -> None:
''' Enquiry target identifier and available Data Providers '''
self.peer.send(DbgMuxFrame.MsgType.Enquiry)
while True:
f = self.peer.recv()
if f['MsgType'] == DbgMuxFrame.MsgType.Ident:
log.info("Identified target: '%s', IMEI=%s",
f['Msg']['Ident'][:-15],
f['Msg']['Ident'][-15:])
elif f['MsgType'] == DbgMuxFrame.MsgType.DPAnnounce:
log.info("Data Provider available (DPRef=0x%04x): '%s'",
f['Msg']['DPRef'], f['Msg']['Name'])
# No more data in the buffer
# FIXME: layer violation!
if self.transport._sl.in_waiting == 0:
break
# ACKnowledge reception of the info
self.peer.send(DbgMuxFrame.MsgType.Ack)
# The responce to be handled by CommonFrameHandler
time.sleep(0.5)
ping_parser = cmd2.Cmd2ArgumentParser()
ping_parser.add_argument('-p', '--payload',
@ -115,52 +167,30 @@ class SEDbgMuxApp(cmd2.Cmd):
@cmd2.with_category(CATEGORY_DBGMUX)
def do_ping(self, opts) -> None:
''' Send a Ping to the target, expect Pong '''
log.info('Tx Ping with payload \'%s\'', opts.payload)
self.peer.send(DbgMuxFrame.MsgType.Ping, opts.payload)
f = self.peer.recv()
assert f['MsgType'] == DbgMuxFrame.MsgType.Pong
log.info('Rx Pong with payload \'%s\'', f['Msg'])
self.peer.send(DbgMuxFrame.MsgType.Ack)
hinst = self.peer.disp.find_by_name('PingPong')
hinst.ping(opts.payload)
establish_parser = cmd2.Cmd2ArgumentParser()
establish_parser.add_argument('DPRef',
type=lambda v: int(v, 16),
help='DPRef of a Data Provider in hex')
establish_parser.add_argument('mode',
choices=['interactive', 'udp-bridge'],
help='Connection mode')
@cmd2.with_argparser(establish_parser)
@cmd2.with_category(CATEGORY_DBGMUX)
def do_establish(self, opts) -> None:
''' Establish connection with a Data Provider '''
log.info("Establishing connection with DPRef=0x%04x", opts.DPRef)
self.peer.send(DbgMuxFrame.MsgType.ConnEstablish,
dict(DPRef=opts.DPRef))
f = self.peer.recv()
assert f['MsgType'] == DbgMuxFrame.MsgType.ConnEstablished
if f['Msg']['ConnRef'] == 0xffff:
log.warning("Connection failed: unknown DPRef=0x%04x?", opts.DPRef)
self.peer.send(DbgMuxFrame.MsgType.Ack)
return
log.info("Connection established (ConnRef=0x%04x)",
f['Msg']['ConnRef'])
# Read the messages
while True:
f = self.peer.recv()
if f['MsgType'] != DbgMuxFrame.MsgType.ConnData:
log.warning('Unexpected frame: %s', f)
self.peer.send(DbgMuxFrame.MsgType.Ack)
continue
try: # FIXME: there can be binary data
self.stdout.write(f['Msg']['Data'].decode())
except: # ... ignore it for now
continue
# ACKnowledge reception of a frame
self.peer.send(DbgMuxFrame.MsgType.Ack)
if opts.mode == 'interactive':
ch = DbgMuxConnInteractiveTerminal()
self.peer.disp.register(ch)
ch.establish(opts.DPRef)
ch.attach()
elif opts.mode == 'udp-bridge':
ch = DbgMuxConnUdpBridge()
self.peer.disp.register(ch)
ch.establish(opts.DPRef)
ap = argparse.ArgumentParser(prog='sedbgmux', description=SEDbgMuxApp.DESC,