pycrate-org / pycrate

A Python library to ease the development of encoders and decoders for various protocols and file formats, especially telecom ones. Provides an ASN.1 compiler and a CSN.1 runtime.
https://github.com/pycrate-org/pycrate
GNU Lesser General Public License v2.1
45 stars 9 forks source link

iterating ASN.1 objects #22

Open abouillot-stl opened 1 week ago

abouillot-stl commented 1 week ago

Hello,

I'm trying get an object iterating an ASN.1 object.

I have a rrcReconfigurationmessage. I can iterate through it and get objects from most of the hierarchy, but when looking into the reportConfigToAddModList, it always return the last item of the sequence.

I can access the values of the different items reportConfigToAddModList if I iterate the serialization of the object.

I guess I miss something about the usage of the get_obj_at function in this particular case of SEQ OF SQUENCE

Here is the code snippet to show it:

import binascii
import re
from pycrate_asn1dir import RRCNR
from pycrate_asn1rt.utils import get_val_at, get_obj_at

payload = """
00 29 56 04 07 80 01 04  49 c1 00 40 00 1c 01 40
30 02 f0 00 20 67 28 20  08 00 03 80 28 06 00 80
20 06 a2 90 03 80 24 04  c0 02 00 70 08 81 12 00
80 0f c0 02 00 28 c6 51  01 80 50 28 05 c1 00 48
24 12 c0 01 00 47 40 01  00 80 89 01 b0 48 ca 82
80 31 00 00 00 e0 fc 04  c7 3e c3 50 04 fc 00 84
02 12 ee 00 17 e4 05 f0  21 00 02 03 47 50 72 80
a8 0e 00 05 f0 20 00 00  02 2a 2c 02 02 08 02 00
00 04 08 02 00 00 0c 08  02 00 00 0e 08 02 00 00
02 22 0a 82 02 00 00 14  62 36 02 02 08 02 00 00
14 08 02 00 00 02 08 02  00 00 04 08 02 00 00 0c
08 02 00 00 0e 42 04 06  00 bc 03 7c 68 10 06 3e
33 e2 06 3e 23 e4                               
"""

msg = binascii.a2b_hex(re.sub(r"\s+", "", payload))

dl_dcch = RRCNR.NR_RRC_Definitions.DL_DCCH_Message
dl_dcch.from_uper(msg)
meas = get_obj_at(dl_dcch, ["message", "c1", "rrcReconfiguration", "criticalExtensions", "rrcReconfiguration", "measConfig"])
# reports is ReportConfigToAddModList ::=        SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigToAddMod
reports = get_obj_at(meas, ["reportConfigToAddModList"])
# will only return the last item of the Seq of Sequence
for i in range(len(reports())):
    # report is expected to be ReportConfigToAddMod ::=            SEQUENCE {
    # at the given index
    report = get_obj_at(reports, [i])
    print(f"--- {i} ---")
    # But only 3rd and last item presented
    print(report.to_json())

# will present the 3 differents report to add
for i in range(len(reports())):
    report = reports()[i]
    print(f"--- {i} ---")
    print(report)

Any hints on get_obj_at usage would be welcome.

Thanks

mitshell commented 6 days ago

get_obj() and get_obj_at() methods are only to work on objects, and not values. This is to keep in mind especially when working with SEQUENCE OF and SET OF. If you want to access values, you need to use get_val() and get_val_at() all the way.

abouillot-stl commented 5 days ago

I fully understand get_obj_at, and get_obj() are not meant to access values. I was looking at getting the objects corresponding to each of the reportConfigToAddMod present in reportConfigToAddModList and manipulate them as objects.

mitshell commented 4 days ago

To access reportConfigToAddMod, your can use:

report = get_obj_at(meas, ["reportConfigToAddModList", None])

There is no such each of the reportConfigToAddMod. There is only a single object reportConfigToAddMod, and a list of values that were encoded / decoded through it.

abouillot-stl commented 4 days ago

Ok, so this is why, after going through, only the last set of values are stored into the object.

report = get_obj_at(meas, ["reportConfigToAddModList", None])
print(get_val_at(report, ["reportConfigId"]))    
print(report())

output

3
{'reportConfigId': 3, 'reportConfig': ('reportConfigNR', {'reportType': ('eventTriggered', {'eventId': ('eventA3', {'a3-Offset': ('rsrp', 6), 'reportOnLeave': False, 'hysteresis': 0, 'timeToTrigger': 'ms100', 'useAllowedCellList': False}), 'rsType': 'ssb', 'reportInterval': 'ms120', 'reportAmount': 'r1', 'reportQuantityCell': {'rsrp': True, 'rsrq': True, 'sinr': True}, 'maxReportCells': 8, 'includeBeamMeasurements': False})})}  

I'll have to revise my strategy then.

Thanks for your time.