pySim-smpp2sim: Implement handle_send-/receivedata

Change-Id: Icec9265520a6ab20cb4764e9cab5cdab31841862
This commit is contained in:
Daniel Willmann
2026-01-23 00:38:17 +01:00
parent 637276472d
commit 3506940448

View File

@@ -53,7 +53,7 @@ from pySim.cards import UiccCardBase
from pySim.exceptions import * from pySim.exceptions import *
from pySim.cat import ProactiveCommand, SendShortMessage, SMS_TPDU, SMSPPDownload, BearerDescription from pySim.cat import ProactiveCommand, SendShortMessage, SMS_TPDU, SMSPPDownload, BearerDescription
from pySim.cat import DeviceIdentities, Address, OtherAddress, UiccTransportLevel, BufferSize from pySim.cat import DeviceIdentities, Address, OtherAddress, UiccTransportLevel, BufferSize
from pySim.cat import ChannelStatus, ChannelData, ChannelDataLength from pySim.cat import ChannelStatus, ChannelData, ChannelDataLength, EventDownload, EventList
from pySim.utils import b2h, h2b from pySim.utils import b2h, h2b
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -71,24 +71,46 @@ class MyApduTracer(ApduTracer):
print("-> %s %s" % (cmd[:10], cmd[10:])) print("-> %s %s" % (cmd[:10], cmd[10:]))
print("<- %s: %s" % (sw, resp)) print("<- %s: %s" % (sw, resp))
class TcpProtocol(protocol.Protocol):
def dataReceived(self, data):
pass
def connectionLost(self, reason):
pass
def tcp_connected_callback(p: protocol.Protocol): def tcp_connected_callback(p: protocol.Protocol):
"""called by twisted TCP client.""" """called by twisted TCP client."""
logger.error("%s: connected!" % p) logger.error("%s: connected!" % p)
for data in p.pending_tx:
p.transport.write(data)
class ProactChannel: class ProactChannel(protocol.Protocol):
"""Representation of a single protective channel.""" """Representation of a single proective channel."""
def __init__(self, channels: 'ProactChannels', chan_nr: int): def __init__(self, channels: 'ProactChannels', chan_nr: int):
self.channels = channels self.channels = channels
self.chan_nr = chan_nr self.chan_nr = chan_nr
self.ep = None self.ep = None
self.pending_tx = []
self.pending_rx = bytearray()
def write(self, data: bytes):
if self.connected:
self.transport.write(data)
else:
self.pending_tx.append(data)
def dataReceived(self, data: bytes):
logger.error(f"Got data (len={len(data)}): {data}")
self.pending_rx.extend(data)
# Send ENVELOPE with EventDownload Data available
event_list_ie = EventList(decoded=[ EventList.Event.data_available])
channel_status_ie = ChannelStatus(decoded='8100')
channel_data_len_ie = ChannelDataLength(decoded=min(255,len(self.pending_rx)))
dev_ids = DeviceIdentities(decoded={'source_dev_id': 'network', 'dest_dev_id': 'uicc'})
event_dl = EventDownload(children=[event_list_ie, dev_ids, channel_status_ie, channel_data_len_ie])
# 3) send to the card
envelope_hex = b2h(event_dl.to_tlv())
logger.info("ENVELOPE Event: %s" % envelope_hex)
global g_ms
(data, sw) = g_ms.scc.envelope(envelope_hex)
logger.info("SW %s: %s" % (sw, data))
# FIXME: Handle result?!
def connectionLost(self, reason):
logger.error("connection lost: %s" % reason)
def close(self): def close(self):
"""Close the channel.""" """Close the channel."""
@@ -174,14 +196,13 @@ class Proact(ProactiveHandler):
raise ValueError('Unsupported protocol_type') raise ValueError('Unsupported protocol_type')
if other_addr_ie.decoded.get('type_of_address', None) != 'ipv4': if other_addr_ie.decoded.get('type_of_address', None) != 'ipv4':
raise ValueError('Unsupported type_of_address') raise ValueError('Unsupported type_of_address')
ipv4_bytes = h2b(other_addr_ie.decoded['address']) ipv4_bytes = other_addr_ie.decoded['address']
ipv4_str = '%u.%u.%u.%u' % (ipv4_bytes[0], ipv4_bytes[1], ipv4_bytes[2], ipv4_bytes[3]) ipv4_str = '%u.%u.%u.%u' % (ipv4_bytes[0], ipv4_bytes[1], ipv4_bytes[2], ipv4_bytes[3])
port_nr = transp_lvl_ie.decoded['port_number'] port_nr = transp_lvl_ie.decoded['port_number']
print("%s:%u" % (ipv4_str, port_nr)) logger.error("OpenChannel opening with %s:%u" % (ipv4_str, port_nr))
channel = self.channels.channel_create() channel = self.channels.channel_create()
channel.ep = endpoints.TCP4ClientEndpoint(reactor, ipv4_str, port_nr) channel.ep = endpoints.TCP4ClientEndpoint(reactor, ipv4_str, port_nr)
channel.prot = TcpProtocol() d = endpoints.connectProtocol(channel.ep, channel)
d = endpoints.connectProtocol(channel.ep, channel.prot)
# FIXME: why is this never called despite the client showing the inbound connection? # FIXME: why is this never called despite the client showing the inbound connection?
d.addCallback(tcp_connected_callback) d.addCallback(tcp_connected_callback)
@@ -213,6 +234,17 @@ class Proact(ProactiveHandler):
# ]} # ]}
logger.info("ReceiveData") logger.info("ReceiveData")
logger.info(pcmd) logger.info(pcmd)
dev_id_ie = Proact._find_first_element_of_type(pcmd.children, DeviceIdentities)
chan_data_len_ie = Proact._find_first_element_of_type(pcmd.children, ChannelDataLength)
len_requested = chan_data_len_ie.decoded
chan_str = dev_id_ie.decoded['dest_dev_id']
chan_nr = 1 # FIXME
chan = self.channels.channels.get(chan_nr, None)
requested = chan.pending_rx[:len_requested]
chan.pending_rx = chan.pending_rx[len_requested:]
resp = self.prepare_response(pcmd) + [ChannelData(decoded=requested), ChannelDataLength(decoded=min(255, len(chan.pending_rx)))]
# Terminal Response example: [ # Terminal Response example: [
# {'command_details': {'command_number': 1, # {'command_details': {'command_number': 1,
# 'type_of_command': 'receive_data', # 'type_of_command': 'receive_data',
@@ -222,7 +254,8 @@ class Proact(ProactiveHandler):
# {'channel_data': '16030100040e000000'}, # {'channel_data': '16030100040e000000'},
# {'channel_data_length': 0} # {'channel_data_length': 0}
# ] # ]
return self.prepare_response(pcmd) + [] resp = self.prepare_response(pcmd) + [ChannelData(decoded=requested), ChannelDataLength(decoded=min(255, len(chan.pending_rx)))]
return resp
def handle_SendData(self, pcmd: ProactiveCommand): def handle_SendData(self, pcmd: ProactiveCommand):
"""Send/write data received from the SIM to the socket.""" """Send/write data received from the SIM to the socket."""
@@ -240,7 +273,10 @@ class Proact(ProactiveHandler):
chan_str = dev_id_ie.decoded['dest_dev_id'] chan_str = dev_id_ie.decoded['dest_dev_id']
chan_nr = 1 # FIXME chan_nr = 1 # FIXME
chan = self.channels.channels.get(chan_nr, None) chan = self.channels.channels.get(chan_nr, None)
# FIXME chan.prot.transport.write(h2b(chan_data_ie.decoded)) # FIXME
logger.error(f"Chan data received: {chan_data_ie.decoded}")
chan.write(chan_data_ie.decoded)
#chan.write(h2b(chan_data_ie.decoded))
# Terminal Response example: [ # Terminal Response example: [
# {'command_details': {'command_number': 1, # {'command_details': {'command_number': 1,
# 'type_of_command': 'send_data', # 'type_of_command': 'send_data',
@@ -425,4 +461,3 @@ if __name__ == '__main__':
g_ms = MyServer(opts.smpp_bind_port, opts.smpp_bind_ip, opts.smpp_system_id, opts.smpp_password) g_ms = MyServer(opts.smpp_bind_port, opts.smpp_bind_ip, opts.smpp_system_id, opts.smpp_password)
g_ms.connect_to_card(tp) g_ms.connect_to_card(tp)
reactor.run() reactor.run()