oscura 0.0.1__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oscura/__init__.py +813 -8
- oscura/__main__.py +392 -0
- oscura/analyzers/__init__.py +37 -0
- oscura/analyzers/digital/__init__.py +177 -0
- oscura/analyzers/digital/bus.py +691 -0
- oscura/analyzers/digital/clock.py +805 -0
- oscura/analyzers/digital/correlation.py +720 -0
- oscura/analyzers/digital/edges.py +632 -0
- oscura/analyzers/digital/extraction.py +413 -0
- oscura/analyzers/digital/quality.py +878 -0
- oscura/analyzers/digital/signal_quality.py +877 -0
- oscura/analyzers/digital/thresholds.py +708 -0
- oscura/analyzers/digital/timing.py +1104 -0
- oscura/analyzers/eye/__init__.py +46 -0
- oscura/analyzers/eye/diagram.py +434 -0
- oscura/analyzers/eye/metrics.py +555 -0
- oscura/analyzers/jitter/__init__.py +83 -0
- oscura/analyzers/jitter/ber.py +333 -0
- oscura/analyzers/jitter/decomposition.py +759 -0
- oscura/analyzers/jitter/measurements.py +413 -0
- oscura/analyzers/jitter/spectrum.py +220 -0
- oscura/analyzers/measurements.py +40 -0
- oscura/analyzers/packet/__init__.py +171 -0
- oscura/analyzers/packet/daq.py +1077 -0
- oscura/analyzers/packet/metrics.py +437 -0
- oscura/analyzers/packet/parser.py +327 -0
- oscura/analyzers/packet/payload.py +2156 -0
- oscura/analyzers/packet/payload_analysis.py +1312 -0
- oscura/analyzers/packet/payload_extraction.py +236 -0
- oscura/analyzers/packet/payload_patterns.py +670 -0
- oscura/analyzers/packet/stream.py +359 -0
- oscura/analyzers/patterns/__init__.py +266 -0
- oscura/analyzers/patterns/clustering.py +1036 -0
- oscura/analyzers/patterns/discovery.py +539 -0
- oscura/analyzers/patterns/learning.py +797 -0
- oscura/analyzers/patterns/matching.py +1091 -0
- oscura/analyzers/patterns/periodic.py +650 -0
- oscura/analyzers/patterns/sequences.py +767 -0
- oscura/analyzers/power/__init__.py +116 -0
- oscura/analyzers/power/ac_power.py +391 -0
- oscura/analyzers/power/basic.py +383 -0
- oscura/analyzers/power/conduction.py +314 -0
- oscura/analyzers/power/efficiency.py +297 -0
- oscura/analyzers/power/ripple.py +356 -0
- oscura/analyzers/power/soa.py +372 -0
- oscura/analyzers/power/switching.py +479 -0
- oscura/analyzers/protocol/__init__.py +150 -0
- oscura/analyzers/protocols/__init__.py +150 -0
- oscura/analyzers/protocols/base.py +500 -0
- oscura/analyzers/protocols/can.py +620 -0
- oscura/analyzers/protocols/can_fd.py +448 -0
- oscura/analyzers/protocols/flexray.py +405 -0
- oscura/analyzers/protocols/hdlc.py +399 -0
- oscura/analyzers/protocols/i2c.py +368 -0
- oscura/analyzers/protocols/i2s.py +296 -0
- oscura/analyzers/protocols/jtag.py +393 -0
- oscura/analyzers/protocols/lin.py +445 -0
- oscura/analyzers/protocols/manchester.py +333 -0
- oscura/analyzers/protocols/onewire.py +501 -0
- oscura/analyzers/protocols/spi.py +334 -0
- oscura/analyzers/protocols/swd.py +325 -0
- oscura/analyzers/protocols/uart.py +393 -0
- oscura/analyzers/protocols/usb.py +495 -0
- oscura/analyzers/signal_integrity/__init__.py +63 -0
- oscura/analyzers/signal_integrity/embedding.py +294 -0
- oscura/analyzers/signal_integrity/equalization.py +370 -0
- oscura/analyzers/signal_integrity/sparams.py +484 -0
- oscura/analyzers/spectral/__init__.py +53 -0
- oscura/analyzers/spectral/chunked.py +273 -0
- oscura/analyzers/spectral/chunked_fft.py +571 -0
- oscura/analyzers/spectral/chunked_wavelet.py +391 -0
- oscura/analyzers/spectral/fft.py +92 -0
- oscura/analyzers/statistical/__init__.py +250 -0
- oscura/analyzers/statistical/checksum.py +923 -0
- oscura/analyzers/statistical/chunked_corr.py +228 -0
- oscura/analyzers/statistical/classification.py +778 -0
- oscura/analyzers/statistical/entropy.py +1113 -0
- oscura/analyzers/statistical/ngrams.py +614 -0
- oscura/analyzers/statistics/__init__.py +119 -0
- oscura/analyzers/statistics/advanced.py +885 -0
- oscura/analyzers/statistics/basic.py +263 -0
- oscura/analyzers/statistics/correlation.py +630 -0
- oscura/analyzers/statistics/distribution.py +298 -0
- oscura/analyzers/statistics/outliers.py +463 -0
- oscura/analyzers/statistics/streaming.py +93 -0
- oscura/analyzers/statistics/trend.py +520 -0
- oscura/analyzers/validation.py +598 -0
- oscura/analyzers/waveform/__init__.py +36 -0
- oscura/analyzers/waveform/measurements.py +943 -0
- oscura/analyzers/waveform/measurements_with_uncertainty.py +371 -0
- oscura/analyzers/waveform/spectral.py +1689 -0
- oscura/analyzers/waveform/wavelets.py +298 -0
- oscura/api/__init__.py +62 -0
- oscura/api/dsl.py +538 -0
- oscura/api/fluent.py +571 -0
- oscura/api/operators.py +498 -0
- oscura/api/optimization.py +392 -0
- oscura/api/profiling.py +396 -0
- oscura/automotive/__init__.py +73 -0
- oscura/automotive/can/__init__.py +52 -0
- oscura/automotive/can/analysis.py +356 -0
- oscura/automotive/can/checksum.py +250 -0
- oscura/automotive/can/correlation.py +212 -0
- oscura/automotive/can/discovery.py +355 -0
- oscura/automotive/can/message_wrapper.py +375 -0
- oscura/automotive/can/models.py +385 -0
- oscura/automotive/can/patterns.py +381 -0
- oscura/automotive/can/session.py +452 -0
- oscura/automotive/can/state_machine.py +300 -0
- oscura/automotive/can/stimulus_response.py +461 -0
- oscura/automotive/dbc/__init__.py +15 -0
- oscura/automotive/dbc/generator.py +156 -0
- oscura/automotive/dbc/parser.py +146 -0
- oscura/automotive/dtc/__init__.py +30 -0
- oscura/automotive/dtc/database.py +3036 -0
- oscura/automotive/j1939/__init__.py +14 -0
- oscura/automotive/j1939/decoder.py +745 -0
- oscura/automotive/loaders/__init__.py +35 -0
- oscura/automotive/loaders/asc.py +98 -0
- oscura/automotive/loaders/blf.py +77 -0
- oscura/automotive/loaders/csv_can.py +136 -0
- oscura/automotive/loaders/dispatcher.py +136 -0
- oscura/automotive/loaders/mdf.py +331 -0
- oscura/automotive/loaders/pcap.py +132 -0
- oscura/automotive/obd/__init__.py +14 -0
- oscura/automotive/obd/decoder.py +707 -0
- oscura/automotive/uds/__init__.py +48 -0
- oscura/automotive/uds/decoder.py +265 -0
- oscura/automotive/uds/models.py +64 -0
- oscura/automotive/visualization.py +369 -0
- oscura/batch/__init__.py +55 -0
- oscura/batch/advanced.py +627 -0
- oscura/batch/aggregate.py +300 -0
- oscura/batch/analyze.py +139 -0
- oscura/batch/logging.py +487 -0
- oscura/batch/metrics.py +556 -0
- oscura/builders/__init__.py +41 -0
- oscura/builders/signal_builder.py +1131 -0
- oscura/cli/__init__.py +14 -0
- oscura/cli/batch.py +339 -0
- oscura/cli/characterize.py +273 -0
- oscura/cli/compare.py +775 -0
- oscura/cli/decode.py +551 -0
- oscura/cli/main.py +247 -0
- oscura/cli/shell.py +350 -0
- oscura/comparison/__init__.py +66 -0
- oscura/comparison/compare.py +397 -0
- oscura/comparison/golden.py +487 -0
- oscura/comparison/limits.py +391 -0
- oscura/comparison/mask.py +434 -0
- oscura/comparison/trace_diff.py +30 -0
- oscura/comparison/visualization.py +481 -0
- oscura/compliance/__init__.py +70 -0
- oscura/compliance/advanced.py +756 -0
- oscura/compliance/masks.py +363 -0
- oscura/compliance/reporting.py +483 -0
- oscura/compliance/testing.py +298 -0
- oscura/component/__init__.py +38 -0
- oscura/component/impedance.py +365 -0
- oscura/component/reactive.py +598 -0
- oscura/component/transmission_line.py +312 -0
- oscura/config/__init__.py +191 -0
- oscura/config/defaults.py +254 -0
- oscura/config/loader.py +348 -0
- oscura/config/memory.py +271 -0
- oscura/config/migration.py +458 -0
- oscura/config/pipeline.py +1077 -0
- oscura/config/preferences.py +530 -0
- oscura/config/protocol.py +875 -0
- oscura/config/schema.py +713 -0
- oscura/config/settings.py +420 -0
- oscura/config/thresholds.py +599 -0
- oscura/convenience.py +457 -0
- oscura/core/__init__.py +299 -0
- oscura/core/audit.py +457 -0
- oscura/core/backend_selector.py +405 -0
- oscura/core/cache.py +590 -0
- oscura/core/cancellation.py +439 -0
- oscura/core/confidence.py +225 -0
- oscura/core/config.py +506 -0
- oscura/core/correlation.py +216 -0
- oscura/core/cross_domain.py +422 -0
- oscura/core/debug.py +301 -0
- oscura/core/edge_cases.py +541 -0
- oscura/core/exceptions.py +535 -0
- oscura/core/gpu_backend.py +523 -0
- oscura/core/lazy.py +832 -0
- oscura/core/log_query.py +540 -0
- oscura/core/logging.py +931 -0
- oscura/core/logging_advanced.py +952 -0
- oscura/core/memoize.py +171 -0
- oscura/core/memory_check.py +274 -0
- oscura/core/memory_guard.py +290 -0
- oscura/core/memory_limits.py +336 -0
- oscura/core/memory_monitor.py +453 -0
- oscura/core/memory_progress.py +465 -0
- oscura/core/memory_warnings.py +315 -0
- oscura/core/numba_backend.py +362 -0
- oscura/core/performance.py +352 -0
- oscura/core/progress.py +524 -0
- oscura/core/provenance.py +358 -0
- oscura/core/results.py +331 -0
- oscura/core/types.py +504 -0
- oscura/core/uncertainty.py +383 -0
- oscura/discovery/__init__.py +52 -0
- oscura/discovery/anomaly_detector.py +672 -0
- oscura/discovery/auto_decoder.py +415 -0
- oscura/discovery/comparison.py +497 -0
- oscura/discovery/quality_validator.py +528 -0
- oscura/discovery/signal_detector.py +769 -0
- oscura/dsl/__init__.py +73 -0
- oscura/dsl/commands.py +246 -0
- oscura/dsl/interpreter.py +455 -0
- oscura/dsl/parser.py +689 -0
- oscura/dsl/repl.py +172 -0
- oscura/exceptions.py +59 -0
- oscura/exploratory/__init__.py +111 -0
- oscura/exploratory/error_recovery.py +642 -0
- oscura/exploratory/fuzzy.py +513 -0
- oscura/exploratory/fuzzy_advanced.py +786 -0
- oscura/exploratory/legacy.py +831 -0
- oscura/exploratory/parse.py +358 -0
- oscura/exploratory/recovery.py +275 -0
- oscura/exploratory/sync.py +382 -0
- oscura/exploratory/unknown.py +707 -0
- oscura/export/__init__.py +25 -0
- oscura/export/wireshark/README.md +265 -0
- oscura/export/wireshark/__init__.py +47 -0
- oscura/export/wireshark/generator.py +312 -0
- oscura/export/wireshark/lua_builder.py +159 -0
- oscura/export/wireshark/templates/dissector.lua.j2 +92 -0
- oscura/export/wireshark/type_mapping.py +165 -0
- oscura/export/wireshark/validator.py +105 -0
- oscura/exporters/__init__.py +94 -0
- oscura/exporters/csv.py +303 -0
- oscura/exporters/exporters.py +44 -0
- oscura/exporters/hdf5.py +219 -0
- oscura/exporters/html_export.py +701 -0
- oscura/exporters/json_export.py +291 -0
- oscura/exporters/markdown_export.py +367 -0
- oscura/exporters/matlab_export.py +354 -0
- oscura/exporters/npz_export.py +219 -0
- oscura/exporters/spice_export.py +210 -0
- oscura/extensibility/__init__.py +131 -0
- oscura/extensibility/docs.py +752 -0
- oscura/extensibility/extensions.py +1125 -0
- oscura/extensibility/logging.py +259 -0
- oscura/extensibility/measurements.py +485 -0
- oscura/extensibility/plugins.py +414 -0
- oscura/extensibility/registry.py +346 -0
- oscura/extensibility/templates.py +913 -0
- oscura/extensibility/validation.py +651 -0
- oscura/filtering/__init__.py +89 -0
- oscura/filtering/base.py +563 -0
- oscura/filtering/convenience.py +564 -0
- oscura/filtering/design.py +725 -0
- oscura/filtering/filters.py +32 -0
- oscura/filtering/introspection.py +605 -0
- oscura/guidance/__init__.py +24 -0
- oscura/guidance/recommender.py +429 -0
- oscura/guidance/wizard.py +518 -0
- oscura/inference/__init__.py +251 -0
- oscura/inference/active_learning/README.md +153 -0
- oscura/inference/active_learning/__init__.py +38 -0
- oscura/inference/active_learning/lstar.py +257 -0
- oscura/inference/active_learning/observation_table.py +230 -0
- oscura/inference/active_learning/oracle.py +78 -0
- oscura/inference/active_learning/teachers/__init__.py +15 -0
- oscura/inference/active_learning/teachers/simulator.py +192 -0
- oscura/inference/adaptive_tuning.py +453 -0
- oscura/inference/alignment.py +653 -0
- oscura/inference/bayesian.py +943 -0
- oscura/inference/binary.py +1016 -0
- oscura/inference/crc_reverse.py +711 -0
- oscura/inference/logic.py +288 -0
- oscura/inference/message_format.py +1305 -0
- oscura/inference/protocol.py +417 -0
- oscura/inference/protocol_dsl.py +1084 -0
- oscura/inference/protocol_library.py +1230 -0
- oscura/inference/sequences.py +809 -0
- oscura/inference/signal_intelligence.py +1509 -0
- oscura/inference/spectral.py +215 -0
- oscura/inference/state_machine.py +634 -0
- oscura/inference/stream.py +918 -0
- oscura/integrations/__init__.py +59 -0
- oscura/integrations/llm.py +1827 -0
- oscura/jupyter/__init__.py +32 -0
- oscura/jupyter/display.py +268 -0
- oscura/jupyter/magic.py +334 -0
- oscura/loaders/__init__.py +526 -0
- oscura/loaders/binary.py +69 -0
- oscura/loaders/configurable.py +1255 -0
- oscura/loaders/csv.py +26 -0
- oscura/loaders/csv_loader.py +473 -0
- oscura/loaders/hdf5.py +9 -0
- oscura/loaders/hdf5_loader.py +510 -0
- oscura/loaders/lazy.py +370 -0
- oscura/loaders/mmap_loader.py +583 -0
- oscura/loaders/numpy_loader.py +436 -0
- oscura/loaders/pcap.py +432 -0
- oscura/loaders/preprocessing.py +368 -0
- oscura/loaders/rigol.py +287 -0
- oscura/loaders/sigrok.py +321 -0
- oscura/loaders/tdms.py +367 -0
- oscura/loaders/tektronix.py +711 -0
- oscura/loaders/validation.py +584 -0
- oscura/loaders/vcd.py +464 -0
- oscura/loaders/wav.py +233 -0
- oscura/math/__init__.py +45 -0
- oscura/math/arithmetic.py +824 -0
- oscura/math/interpolation.py +413 -0
- oscura/onboarding/__init__.py +39 -0
- oscura/onboarding/help.py +498 -0
- oscura/onboarding/tutorials.py +405 -0
- oscura/onboarding/wizard.py +466 -0
- oscura/optimization/__init__.py +19 -0
- oscura/optimization/parallel.py +440 -0
- oscura/optimization/search.py +532 -0
- oscura/pipeline/__init__.py +43 -0
- oscura/pipeline/base.py +338 -0
- oscura/pipeline/composition.py +242 -0
- oscura/pipeline/parallel.py +448 -0
- oscura/pipeline/pipeline.py +375 -0
- oscura/pipeline/reverse_engineering.py +1119 -0
- oscura/plugins/__init__.py +122 -0
- oscura/plugins/base.py +272 -0
- oscura/plugins/cli.py +497 -0
- oscura/plugins/discovery.py +411 -0
- oscura/plugins/isolation.py +418 -0
- oscura/plugins/lifecycle.py +959 -0
- oscura/plugins/manager.py +493 -0
- oscura/plugins/registry.py +421 -0
- oscura/plugins/versioning.py +372 -0
- oscura/py.typed +0 -0
- oscura/quality/__init__.py +65 -0
- oscura/quality/ensemble.py +740 -0
- oscura/quality/explainer.py +338 -0
- oscura/quality/scoring.py +616 -0
- oscura/quality/warnings.py +456 -0
- oscura/reporting/__init__.py +248 -0
- oscura/reporting/advanced.py +1234 -0
- oscura/reporting/analyze.py +448 -0
- oscura/reporting/argument_preparer.py +596 -0
- oscura/reporting/auto_report.py +507 -0
- oscura/reporting/batch.py +615 -0
- oscura/reporting/chart_selection.py +223 -0
- oscura/reporting/comparison.py +330 -0
- oscura/reporting/config.py +615 -0
- oscura/reporting/content/__init__.py +39 -0
- oscura/reporting/content/executive.py +127 -0
- oscura/reporting/content/filtering.py +191 -0
- oscura/reporting/content/minimal.py +257 -0
- oscura/reporting/content/verbosity.py +162 -0
- oscura/reporting/core.py +508 -0
- oscura/reporting/core_formats/__init__.py +17 -0
- oscura/reporting/core_formats/multi_format.py +210 -0
- oscura/reporting/engine.py +836 -0
- oscura/reporting/export.py +366 -0
- oscura/reporting/formatting/__init__.py +129 -0
- oscura/reporting/formatting/emphasis.py +81 -0
- oscura/reporting/formatting/numbers.py +403 -0
- oscura/reporting/formatting/standards.py +55 -0
- oscura/reporting/formatting.py +466 -0
- oscura/reporting/html.py +578 -0
- oscura/reporting/index.py +590 -0
- oscura/reporting/multichannel.py +296 -0
- oscura/reporting/output.py +379 -0
- oscura/reporting/pdf.py +373 -0
- oscura/reporting/plots.py +731 -0
- oscura/reporting/pptx_export.py +360 -0
- oscura/reporting/renderers/__init__.py +11 -0
- oscura/reporting/renderers/pdf.py +94 -0
- oscura/reporting/sections.py +471 -0
- oscura/reporting/standards.py +680 -0
- oscura/reporting/summary_generator.py +368 -0
- oscura/reporting/tables.py +397 -0
- oscura/reporting/template_system.py +724 -0
- oscura/reporting/templates/__init__.py +15 -0
- oscura/reporting/templates/definition.py +205 -0
- oscura/reporting/templates/index.html +649 -0
- oscura/reporting/templates/index.md +173 -0
- oscura/schemas/__init__.py +158 -0
- oscura/schemas/bus_configuration.json +322 -0
- oscura/schemas/device_mapping.json +182 -0
- oscura/schemas/packet_format.json +418 -0
- oscura/schemas/protocol_definition.json +363 -0
- oscura/search/__init__.py +16 -0
- oscura/search/anomaly.py +292 -0
- oscura/search/context.py +149 -0
- oscura/search/pattern.py +160 -0
- oscura/session/__init__.py +34 -0
- oscura/session/annotations.py +289 -0
- oscura/session/history.py +313 -0
- oscura/session/session.py +445 -0
- oscura/streaming/__init__.py +43 -0
- oscura/streaming/chunked.py +611 -0
- oscura/streaming/progressive.py +393 -0
- oscura/streaming/realtime.py +622 -0
- oscura/testing/__init__.py +54 -0
- oscura/testing/synthetic.py +808 -0
- oscura/triggering/__init__.py +68 -0
- oscura/triggering/base.py +229 -0
- oscura/triggering/edge.py +353 -0
- oscura/triggering/pattern.py +344 -0
- oscura/triggering/pulse.py +581 -0
- oscura/triggering/window.py +453 -0
- oscura/ui/__init__.py +48 -0
- oscura/ui/formatters.py +526 -0
- oscura/ui/progressive_display.py +340 -0
- oscura/utils/__init__.py +99 -0
- oscura/utils/autodetect.py +338 -0
- oscura/utils/buffer.py +389 -0
- oscura/utils/lazy.py +407 -0
- oscura/utils/lazy_imports.py +147 -0
- oscura/utils/memory.py +836 -0
- oscura/utils/memory_advanced.py +1326 -0
- oscura/utils/memory_extensions.py +465 -0
- oscura/utils/progressive.py +352 -0
- oscura/utils/windowing.py +362 -0
- oscura/visualization/__init__.py +321 -0
- oscura/visualization/accessibility.py +526 -0
- oscura/visualization/annotations.py +374 -0
- oscura/visualization/axis_scaling.py +305 -0
- oscura/visualization/colors.py +453 -0
- oscura/visualization/digital.py +337 -0
- oscura/visualization/eye.py +420 -0
- oscura/visualization/histogram.py +281 -0
- oscura/visualization/interactive.py +858 -0
- oscura/visualization/jitter.py +702 -0
- oscura/visualization/keyboard.py +394 -0
- oscura/visualization/layout.py +365 -0
- oscura/visualization/optimization.py +1028 -0
- oscura/visualization/palettes.py +446 -0
- oscura/visualization/plot.py +92 -0
- oscura/visualization/power.py +290 -0
- oscura/visualization/power_extended.py +626 -0
- oscura/visualization/presets.py +467 -0
- oscura/visualization/protocols.py +932 -0
- oscura/visualization/render.py +207 -0
- oscura/visualization/rendering.py +444 -0
- oscura/visualization/reverse_engineering.py +791 -0
- oscura/visualization/signal_integrity.py +808 -0
- oscura/visualization/specialized.py +553 -0
- oscura/visualization/spectral.py +811 -0
- oscura/visualization/styles.py +381 -0
- oscura/visualization/thumbnails.py +311 -0
- oscura/visualization/time_axis.py +351 -0
- oscura/visualization/waveform.py +367 -0
- oscura/workflow/__init__.py +13 -0
- oscura/workflow/dag.py +377 -0
- oscura/workflows/__init__.py +58 -0
- oscura/workflows/compliance.py +280 -0
- oscura/workflows/digital.py +272 -0
- oscura/workflows/multi_trace.py +502 -0
- oscura/workflows/power.py +178 -0
- oscura/workflows/protocol.py +492 -0
- oscura/workflows/reverse_engineering.py +639 -0
- oscura/workflows/signal_integrity.py +227 -0
- oscura-0.1.0.dist-info/METADATA +300 -0
- oscura-0.1.0.dist-info/RECORD +463 -0
- oscura-0.1.0.dist-info/entry_points.txt +2 -0
- {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/licenses/LICENSE +1 -1
- oscura-0.0.1.dist-info/METADATA +0 -63
- oscura-0.0.1.dist-info/RECORD +0 -5
- {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Export module for TraceKit protocol definitions.
|
|
2
|
+
|
|
3
|
+
This module provides functionality to export TraceKit protocol definitions
|
|
4
|
+
to various formats for integration with other tools and workflows.
|
|
5
|
+
|
|
6
|
+
Supported export formats:
|
|
7
|
+
- Wireshark Lua dissectors
|
|
8
|
+
- (Future) Scapy packet definitions
|
|
9
|
+
- (Future) Kaitai Struct definitions
|
|
10
|
+
- (Future) C/C++ parser code
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
>>> from oscura.export.wireshark import WiresharkDissectorGenerator
|
|
14
|
+
>>> from oscura.inference.protocol_dsl import ProtocolDefinition
|
|
15
|
+
>>> protocol = ProtocolDefinition(name="myproto", description="My Protocol")
|
|
16
|
+
>>> generator = WiresharkDissectorGenerator()
|
|
17
|
+
>>> generator.generate(protocol, Path("myproto.lua"))
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
# Import main exports
|
|
21
|
+
from . import wireshark
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"wireshark",
|
|
25
|
+
]
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# Wireshark Lua Dissector Export
|
|
2
|
+
|
|
3
|
+
This module generates Wireshark Lua dissectors from Oscura protocol definitions, enabling seamless integration with Wireshark for interactive protocol analysis.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Complete Protocol Support**: Handles all Oscura field types (uint8, uint16, uint32, int8, etc.)
|
|
8
|
+
- **Variable-Length Fields**: Supports fields with dynamic lengths based on other fields
|
|
9
|
+
- **Endianness Support**: Generates correct big-endian and little-endian field readers
|
|
10
|
+
- **Enum Values**: Creates value_string tables for human-readable enum display
|
|
11
|
+
- **Transport Registration**: Automatic TCP/UDP port registration
|
|
12
|
+
- **Syntax Validation**: Optional Lua syntax validation using `luac`
|
|
13
|
+
- **Error Handling**: Generates robust dissectors with malformed packet detection
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from oscura.export.wireshark import WiresharkDissectorGenerator
|
|
20
|
+
from oscura.inference.protocol_dsl import ProtocolDefinition, FieldDefinition
|
|
21
|
+
|
|
22
|
+
# Define your protocol
|
|
23
|
+
protocol = ProtocolDefinition(
|
|
24
|
+
name="myproto",
|
|
25
|
+
description="My Custom Protocol",
|
|
26
|
+
settings={"transport": "tcp", "port": 8000},
|
|
27
|
+
fields=[
|
|
28
|
+
FieldDefinition(name="type", field_type="uint8", size=1),
|
|
29
|
+
FieldDefinition(name="length", field_type="uint16", size=2),
|
|
30
|
+
FieldDefinition(name="data", field_type="bytes", size="length"),
|
|
31
|
+
],
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Generate dissector
|
|
35
|
+
generator = WiresharkDissectorGenerator()
|
|
36
|
+
generator.generate(protocol, Path("myproto.lua"))
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Installation in Wireshark
|
|
40
|
+
|
|
41
|
+
Copy the generated `.lua` file to your Wireshark plugins directory:
|
|
42
|
+
|
|
43
|
+
**Linux:**
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
mkdir -p ~/.local/lib/wireshark/plugins/
|
|
47
|
+
cp myproto.lua ~/.local/lib/wireshark/plugins/
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**macOS:**
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
mkdir -p ~/.config/wireshark/plugins/
|
|
54
|
+
cp myproto.lua ~/.config/wireshark/plugins/
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Windows:**
|
|
58
|
+
|
|
59
|
+
```powershell
|
|
60
|
+
Copy-Item myproto.lua $env:APPDATA\Wireshark\plugins\
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then reload Lua plugins in Wireshark: **Analyze > Reload Lua Plugins** (Ctrl+Shift+L)
|
|
64
|
+
|
|
65
|
+
## Supported Field Types
|
|
66
|
+
|
|
67
|
+
|Oscura Type|Wireshark Type|Size|Notes|
|
|
68
|
+
|---|---|---|---|
|
|
69
|
+
|`uint8`|`ProtoField.uint8`|1 byte|Unsigned 8-bit integer|
|
|
70
|
+
|`uint16`|`ProtoField.uint16`|2 bytes|Unsigned 16-bit integer|
|
|
71
|
+
|`uint32`|`ProtoField.uint32`|4 bytes|Unsigned 32-bit integer|
|
|
72
|
+
|`uint64`|`ProtoField.uint64`|8 bytes|Unsigned 64-bit integer|
|
|
73
|
+
|`int8`|`ProtoField.int8`|1 byte|Signed 8-bit integer|
|
|
74
|
+
|`int16`|`ProtoField.int16`|2 bytes|Signed 16-bit integer|
|
|
75
|
+
|`int32`|`ProtoField.int32`|4 bytes|Signed 32-bit integer|
|
|
76
|
+
|`int64`|`ProtoField.int64`|8 bytes|Signed 64-bit integer|
|
|
77
|
+
|`float32`|`ProtoField.float`|4 bytes|IEEE 754 single precision|
|
|
78
|
+
|`float64`|`ProtoField.double`|8 bytes|IEEE 754 double precision|
|
|
79
|
+
|`bool`|`ProtoField.bool`|1 byte|Boolean value|
|
|
80
|
+
|`bytes`|`ProtoField.bytes`|Variable|Raw byte array|
|
|
81
|
+
|`string`|`ProtoField.string`|Variable|Text string|
|
|
82
|
+
|
|
83
|
+
## Display Bases
|
|
84
|
+
|
|
85
|
+
The generator automatically selects appropriate display bases:
|
|
86
|
+
|
|
87
|
+
- **Unsigned integers** (uint\*): Displayed in hexadecimal (`base.HEX`)
|
|
88
|
+
- **Signed integers** (int\*): Displayed in decimal (`base.DEC`)
|
|
89
|
+
- **Floating point**: No base (`base.NONE`)
|
|
90
|
+
- **Strings/bytes**: No base (`base.NONE`)
|
|
91
|
+
|
|
92
|
+
You can override the display base using the `display_base` parameter.
|
|
93
|
+
|
|
94
|
+
## Variable-Length Fields
|
|
95
|
+
|
|
96
|
+
For fields with variable lengths, reference another field's value:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
fields=[
|
|
100
|
+
FieldDefinition(name="length", field_type="uint16", size=2),
|
|
101
|
+
FieldDefinition(name="payload", field_type="bytes", size="length"),
|
|
102
|
+
]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The generator automatically:
|
|
106
|
+
|
|
107
|
+
1. Reads the `length` field value
|
|
108
|
+
2. Uses it to determine `payload` size
|
|
109
|
+
3. Validates that enough data is available
|
|
110
|
+
|
|
111
|
+
## Enum Fields
|
|
112
|
+
|
|
113
|
+
Create human-readable enum displays:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
FieldDefinition(
|
|
117
|
+
name="msg_type",
|
|
118
|
+
field_type="uint8",
|
|
119
|
+
size=1,
|
|
120
|
+
enum={
|
|
121
|
+
0x01: "REQUEST",
|
|
122
|
+
0x02: "RESPONSE",
|
|
123
|
+
0x03: "ERROR",
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Wireshark will display "REQUEST" instead of "0x01" in the packet tree.
|
|
129
|
+
|
|
130
|
+
## Transport Registration
|
|
131
|
+
|
|
132
|
+
### TCP Registration
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
settings={"transport": "tcp", "port": 8000}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### UDP Registration
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
settings={"transport": "udp", "port": 5000}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The dissector automatically registers on the specified port. Packets on that port will be decoded automatically.
|
|
145
|
+
|
|
146
|
+
## Endianness
|
|
147
|
+
|
|
148
|
+
### Protocol-Level
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
protocol = ProtocolDefinition(
|
|
152
|
+
name="myproto",
|
|
153
|
+
endian="little", # All fields default to little-endian
|
|
154
|
+
...
|
|
155
|
+
)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Field-Level
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
FieldDefinition(
|
|
162
|
+
name="value",
|
|
163
|
+
field_type="uint32",
|
|
164
|
+
size=4,
|
|
165
|
+
endian="little", # Override protocol endianness
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Conditional Fields
|
|
170
|
+
|
|
171
|
+
Fields with conditions are documented in comments (evaluation not yet implemented):
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
FieldDefinition(
|
|
175
|
+
name="optional_field",
|
|
176
|
+
field_type="uint32",
|
|
177
|
+
size=4,
|
|
178
|
+
condition="flags == 1", # Only present when flags field equals 1
|
|
179
|
+
)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Syntax Validation
|
|
183
|
+
|
|
184
|
+
Enable automatic Lua syntax validation:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
generator = WiresharkDissectorGenerator(validate=True)
|
|
188
|
+
generator.generate(protocol, Path("myproto.lua"))
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Requires `luac` (Lua compiler) to be installed:
|
|
192
|
+
|
|
193
|
+
- **Linux**: `sudo apt install lua5.3` or `sudo yum install lua`
|
|
194
|
+
- **macOS**: `brew install lua`
|
|
195
|
+
- **Windows**: Download from [lua.org](https://www.lua.org/download.html)
|
|
196
|
+
|
|
197
|
+
## Examples
|
|
198
|
+
|
|
199
|
+
See `examples/05_export/wireshark_dissector_example.py` for complete examples:
|
|
200
|
+
|
|
201
|
+
- Simple protocol with enum fields
|
|
202
|
+
- Modbus-like protocol
|
|
203
|
+
- Custom protocol with multiple field types
|
|
204
|
+
|
|
205
|
+
Run the example:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
python examples/05_export/wireshark_dissector_example.py
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## API Reference
|
|
212
|
+
|
|
213
|
+
### WiresharkDissectorGenerator
|
|
214
|
+
|
|
215
|
+
Main class for generating dissectors.
|
|
216
|
+
|
|
217
|
+
**Methods:**
|
|
218
|
+
|
|
219
|
+
- `generate(protocol, output_path)`: Generate dissector to file
|
|
220
|
+
- `generate_to_string(protocol)`: Generate dissector as string
|
|
221
|
+
|
|
222
|
+
### Helper Functions
|
|
223
|
+
|
|
224
|
+
- `get_protofield_type(field_type, display_base)`: Map field type to ProtoField
|
|
225
|
+
- `get_field_size(field_type)`: Get fixed size for field type
|
|
226
|
+
- `is_variable_length(field_type)`: Check if field is variable length
|
|
227
|
+
- `get_lua_reader_function(field_type, endian)`: Get Lua buffer reader function
|
|
228
|
+
- `validate_lua_syntax(lua_code)`: Validate Lua code syntax
|
|
229
|
+
- `check_luac_available()`: Check if luac is available
|
|
230
|
+
|
|
231
|
+
## Limitations
|
|
232
|
+
|
|
233
|
+
- **Conditional fields**: Comment generated but evaluation not implemented
|
|
234
|
+
- **Nested structures**: Not yet supported
|
|
235
|
+
- **Arrays**: Not yet supported
|
|
236
|
+
- **Heuristic dissectors**: Pattern-based registration not implemented
|
|
237
|
+
- **TCP reassembly**: Not yet supported for stream protocols
|
|
238
|
+
|
|
239
|
+
## Troubleshooting
|
|
240
|
+
|
|
241
|
+
### Dissector not loading in Wireshark
|
|
242
|
+
|
|
243
|
+
1. Check Wireshark's Lua console: **Tools > Lua > Evaluate**
|
|
244
|
+
2. Verify file is in correct plugins directory
|
|
245
|
+
3. Check for syntax errors: `luac -p myproto.lua`
|
|
246
|
+
4. Ensure Lua support is enabled in Wireshark build
|
|
247
|
+
|
|
248
|
+
### Protocol not decoding automatically
|
|
249
|
+
|
|
250
|
+
1. Verify port registration matches capture
|
|
251
|
+
2. Try manual decode: Right-click packet > Decode As > select protocol
|
|
252
|
+
3. Check minimum length requirements
|
|
253
|
+
|
|
254
|
+
### Malformed packet errors
|
|
255
|
+
|
|
256
|
+
1. Verify field sizes match actual protocol
|
|
257
|
+
2. Check variable-length field references are correct
|
|
258
|
+
3. Ensure endianness is set correctly
|
|
259
|
+
|
|
260
|
+
## References
|
|
261
|
+
|
|
262
|
+
- [Wireshark Lua API](https://wiki.wireshark.org/LuaAPI)
|
|
263
|
+
- [Writing Lua Dissectors](https://wiki.wireshark.org/lua/dissectors)
|
|
264
|
+
- [ProtoField Reference](https://wiki.wireshark.org/LuaAPI/Proto)
|
|
265
|
+
- [DissectorTable Reference](https://wiki.wireshark.org/LuaAPI/DissectorTable)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Wireshark dissector export module.
|
|
2
|
+
|
|
3
|
+
This module provides functionality to export TraceKit protocol definitions
|
|
4
|
+
as Wireshark Lua dissectors for integration with Wireshark's protocol
|
|
5
|
+
analysis tools.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
>>> from oscura.inference.protocol_dsl import ProtocolDefinition
|
|
9
|
+
>>> from oscura.export.wireshark import WiresharkDissectorGenerator
|
|
10
|
+
>>> protocol = ProtocolDefinition(name="myproto", description="My Protocol")
|
|
11
|
+
>>> generator = WiresharkDissectorGenerator()
|
|
12
|
+
>>> generator.generate(protocol, Path("myproto.lua"))
|
|
13
|
+
|
|
14
|
+
Installation:
|
|
15
|
+
Copy the generated .lua file to your Wireshark plugins directory:
|
|
16
|
+
- Linux: ~/.local/lib/wireshark/plugins/
|
|
17
|
+
- macOS: ~/.config/wireshark/plugins/
|
|
18
|
+
- Windows: %APPDATA%\\Wireshark\\plugins\\
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from .generator import WiresharkDissectorGenerator
|
|
22
|
+
from .lua_builder import LuaCodeBuilder
|
|
23
|
+
from .type_mapping import (
|
|
24
|
+
BASE_MAPPING,
|
|
25
|
+
DEFAULT_BASE,
|
|
26
|
+
FIELD_TYPE_MAPPING,
|
|
27
|
+
get_field_size,
|
|
28
|
+
get_lua_reader_function,
|
|
29
|
+
get_protofield_type,
|
|
30
|
+
is_variable_length,
|
|
31
|
+
)
|
|
32
|
+
from .validator import check_luac_available, validate_lua_file, validate_lua_syntax
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"BASE_MAPPING",
|
|
36
|
+
"DEFAULT_BASE",
|
|
37
|
+
"FIELD_TYPE_MAPPING",
|
|
38
|
+
"LuaCodeBuilder",
|
|
39
|
+
"WiresharkDissectorGenerator",
|
|
40
|
+
"check_luac_available",
|
|
41
|
+
"get_field_size",
|
|
42
|
+
"get_lua_reader_function",
|
|
43
|
+
"get_protofield_type",
|
|
44
|
+
"is_variable_length",
|
|
45
|
+
"validate_lua_file",
|
|
46
|
+
"validate_lua_syntax",
|
|
47
|
+
]
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
"""Wireshark Lua dissector generator.
|
|
2
|
+
|
|
3
|
+
This module generates Wireshark Lua dissectors from TraceKit protocol definitions.
|
|
4
|
+
The generated dissectors can be loaded into Wireshark for interactive protocol analysis.
|
|
5
|
+
|
|
6
|
+
Features:
|
|
7
|
+
- Generate ProtoField declarations for all field types
|
|
8
|
+
- Handle fixed and variable-length fields
|
|
9
|
+
- Support TCP/UDP port registration
|
|
10
|
+
- Checksum validation support
|
|
11
|
+
- Proper error handling for malformed packets
|
|
12
|
+
|
|
13
|
+
References:
|
|
14
|
+
https://wiki.wireshark.org/lua/dissectors
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from datetime import UTC, datetime
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
from jinja2 import Environment, PackageLoader, select_autoescape
|
|
22
|
+
|
|
23
|
+
from oscura.inference.protocol_dsl import FieldDefinition, ProtocolDefinition
|
|
24
|
+
|
|
25
|
+
from .type_mapping import get_field_size, get_lua_reader_function, get_protofield_type
|
|
26
|
+
from .validator import validate_lua_syntax
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class WiresharkDissectorGenerator:
|
|
30
|
+
"""Generate Wireshark Lua dissectors from protocol definitions.
|
|
31
|
+
|
|
32
|
+
This class converts TraceKit protocol definitions into Wireshark Lua
|
|
33
|
+
dissectors that can be loaded into Wireshark for protocol analysis.
|
|
34
|
+
|
|
35
|
+
Features:
|
|
36
|
+
- Generate ProtoField declarations
|
|
37
|
+
- Handle fixed and variable-length fields
|
|
38
|
+
- Support nested protocols (dissector stacking)
|
|
39
|
+
- TCP/UDP registration
|
|
40
|
+
- Checksum validation
|
|
41
|
+
- Registration on port/pattern
|
|
42
|
+
|
|
43
|
+
Example:
|
|
44
|
+
>>> from oscura.inference.protocol_dsl import ProtocolDefinition
|
|
45
|
+
>>> protocol = ProtocolDefinition(name="simple", description="Simple Protocol")
|
|
46
|
+
>>> generator = WiresharkDissectorGenerator()
|
|
47
|
+
>>> generator.generate(protocol, Path("simple.lua"))
|
|
48
|
+
|
|
49
|
+
References:
|
|
50
|
+
https://wiki.wireshark.org/lua/dissectors
|
|
51
|
+
https://wiki.wireshark.org/LuaAPI/Proto
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(self, validate: bool = True) -> None:
|
|
55
|
+
"""Initialize the generator.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
validate: Run luac syntax validation if available
|
|
59
|
+
"""
|
|
60
|
+
self.validate = validate
|
|
61
|
+
self.env = Environment(
|
|
62
|
+
loader=PackageLoader("oscura.export.wireshark"),
|
|
63
|
+
autoescape=select_autoescape(),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def generate(self, protocol: ProtocolDefinition, output_path: Path) -> None:
|
|
67
|
+
"""Generate Lua dissector file.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
protocol: Protocol definition to export
|
|
71
|
+
output_path: Where to write .lua file
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
RuntimeError: If Lua syntax validation fails
|
|
75
|
+
"""
|
|
76
|
+
lua_code = self.generate_to_string(protocol)
|
|
77
|
+
|
|
78
|
+
# Validate if requested
|
|
79
|
+
if self.validate:
|
|
80
|
+
is_valid, error_msg = validate_lua_syntax(lua_code)
|
|
81
|
+
if not is_valid:
|
|
82
|
+
raise RuntimeError(f"Generated Lua code has syntax errors:\n{error_msg}")
|
|
83
|
+
|
|
84
|
+
# Write to file
|
|
85
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
86
|
+
output_path.write_text(lua_code)
|
|
87
|
+
|
|
88
|
+
def generate_to_string(self, protocol: ProtocolDefinition) -> str:
|
|
89
|
+
"""Generate Lua dissector as string.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
protocol: Protocol definition to export
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Generated Lua code
|
|
96
|
+
|
|
97
|
+
Raises:
|
|
98
|
+
ValueError: If protocol definition is invalid
|
|
99
|
+
"""
|
|
100
|
+
# Validate protocol
|
|
101
|
+
if not protocol.name:
|
|
102
|
+
raise ValueError("Protocol name is required")
|
|
103
|
+
|
|
104
|
+
# Prepare template context
|
|
105
|
+
context = self._build_template_context(protocol)
|
|
106
|
+
|
|
107
|
+
# Render template
|
|
108
|
+
template = self.env.get_template("dissector.lua.j2")
|
|
109
|
+
return template.render(**context)
|
|
110
|
+
|
|
111
|
+
def _build_template_context(self, protocol: ProtocolDefinition) -> dict[str, Any]:
|
|
112
|
+
"""Build context dictionary for template rendering.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
protocol: Protocol definition
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Template context dictionary
|
|
119
|
+
"""
|
|
120
|
+
# Generate proto variable name (lowercase, no spaces)
|
|
121
|
+
proto_var = protocol.name.lower().replace(" ", "_").replace("-", "_") + "_proto"
|
|
122
|
+
|
|
123
|
+
# Process fields and calculate offsets
|
|
124
|
+
field_data = []
|
|
125
|
+
field_offsets = {} # Track offset of each field by name
|
|
126
|
+
current_offset = 0
|
|
127
|
+
min_length = 0
|
|
128
|
+
|
|
129
|
+
for field_def in protocol.fields:
|
|
130
|
+
# Store offset for this field
|
|
131
|
+
field_offsets[field_def.name] = current_offset
|
|
132
|
+
|
|
133
|
+
field_info = self._process_field(field_def, protocol, field_offsets)
|
|
134
|
+
field_data.append(field_info)
|
|
135
|
+
|
|
136
|
+
# Update offset for next field (if fixed size)
|
|
137
|
+
if field_info["size"] is not None and not field_info["is_variable_length"]:
|
|
138
|
+
current_offset += field_info["size"]
|
|
139
|
+
|
|
140
|
+
# Calculate minimum length (sum of fixed-size fields)
|
|
141
|
+
if not field_info["is_variable_length"]:
|
|
142
|
+
min_length += field_info["size"]
|
|
143
|
+
|
|
144
|
+
# Extract transport settings
|
|
145
|
+
transport = None
|
|
146
|
+
port = None
|
|
147
|
+
|
|
148
|
+
if "transport" in protocol.settings:
|
|
149
|
+
transport = protocol.settings["transport"]
|
|
150
|
+
if "port" in protocol.settings:
|
|
151
|
+
port = protocol.settings["port"]
|
|
152
|
+
|
|
153
|
+
# Check framing for transport/port
|
|
154
|
+
if transport is None and "transport" in protocol.framing:
|
|
155
|
+
transport = protocol.framing["transport"]
|
|
156
|
+
if port is None and "port" in protocol.framing:
|
|
157
|
+
port = protocol.framing["port"]
|
|
158
|
+
|
|
159
|
+
context = {
|
|
160
|
+
"protocol": protocol,
|
|
161
|
+
"proto_var": proto_var,
|
|
162
|
+
"fields": field_data,
|
|
163
|
+
"min_length": max(min_length, 1), # At least 1 byte
|
|
164
|
+
"timestamp": datetime.now(UTC).isoformat(),
|
|
165
|
+
"transport": transport,
|
|
166
|
+
"port": port,
|
|
167
|
+
"pattern": protocol.framing.get("sync_pattern"),
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return context
|
|
171
|
+
|
|
172
|
+
def _process_field(
|
|
173
|
+
self,
|
|
174
|
+
field_def: FieldDefinition,
|
|
175
|
+
protocol: ProtocolDefinition,
|
|
176
|
+
field_offsets: dict[str, int],
|
|
177
|
+
) -> dict[str, Any]:
|
|
178
|
+
"""Process a field definition for template rendering.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
field_def: Field definition
|
|
182
|
+
protocol: Parent protocol definition
|
|
183
|
+
field_offsets: Dictionary mapping field names to byte offsets
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
Dictionary with field information for template
|
|
187
|
+
"""
|
|
188
|
+
# Get ProtoField type and display base
|
|
189
|
+
protofield_type, display_base = get_protofield_type(field_def.field_type)
|
|
190
|
+
|
|
191
|
+
# Get field size
|
|
192
|
+
size = get_field_size(field_def.field_type)
|
|
193
|
+
is_variable = size is None
|
|
194
|
+
|
|
195
|
+
# Handle explicit size specification
|
|
196
|
+
if field_def.size is not None:
|
|
197
|
+
if isinstance(field_def.size, int):
|
|
198
|
+
size = field_def.size
|
|
199
|
+
is_variable = False
|
|
200
|
+
elif isinstance(field_def.size, str):
|
|
201
|
+
# Size is a reference to another field
|
|
202
|
+
is_variable = True
|
|
203
|
+
|
|
204
|
+
# Generate display name
|
|
205
|
+
display_name = field_def.description or field_def.name.replace("_", " ").title()
|
|
206
|
+
|
|
207
|
+
# Get Lua reader function
|
|
208
|
+
reader_func = get_lua_reader_function(field_def.field_type, field_def.endian)
|
|
209
|
+
|
|
210
|
+
field_info = {
|
|
211
|
+
"name": field_def.name,
|
|
212
|
+
"display_name": display_name,
|
|
213
|
+
"protofield_type": protofield_type,
|
|
214
|
+
"display_base": display_base,
|
|
215
|
+
"size": size,
|
|
216
|
+
"is_variable_length": is_variable,
|
|
217
|
+
"condition": field_def.condition,
|
|
218
|
+
"reader_function": reader_func,
|
|
219
|
+
"endian": field_def.endian,
|
|
220
|
+
"value_string": self._generate_value_string(field_def),
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
# Handle variable-length fields with size reference
|
|
224
|
+
if is_variable and isinstance(field_def.size, str):
|
|
225
|
+
# Find the size field
|
|
226
|
+
size_field_def = self._find_field(protocol, field_def.size)
|
|
227
|
+
if size_field_def:
|
|
228
|
+
size_field_size = get_field_size(size_field_def.field_type)
|
|
229
|
+
size_reader = get_lua_reader_function(
|
|
230
|
+
size_field_def.field_type, size_field_def.endian
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Get the offset of the size field
|
|
234
|
+
size_field_offset = field_offsets.get(field_def.size, 0)
|
|
235
|
+
|
|
236
|
+
field_info.update(
|
|
237
|
+
{
|
|
238
|
+
"size_field": field_def.size,
|
|
239
|
+
"size_offset": size_field_offset,
|
|
240
|
+
"size_field_size": size_field_size,
|
|
241
|
+
"size_reader": size_reader,
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
return field_info
|
|
246
|
+
|
|
247
|
+
def _find_field(self, protocol: ProtocolDefinition, field_name: str) -> FieldDefinition | None:
|
|
248
|
+
"""Find a field definition by name.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
protocol: Protocol definition
|
|
252
|
+
field_name: Field name to find
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
Field definition or None if not found
|
|
256
|
+
"""
|
|
257
|
+
for field_def in protocol.fields:
|
|
258
|
+
if field_def.name == field_name:
|
|
259
|
+
return field_def
|
|
260
|
+
return None
|
|
261
|
+
|
|
262
|
+
def _generate_value_string(self, field_def: FieldDefinition) -> str | None:
|
|
263
|
+
"""Generate Wireshark value_string table for enum fields.
|
|
264
|
+
|
|
265
|
+
Args:
|
|
266
|
+
field_def: Field definition
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
Lua table definition or None if field has no enum
|
|
270
|
+
"""
|
|
271
|
+
if not field_def.enum:
|
|
272
|
+
return None
|
|
273
|
+
|
|
274
|
+
# Generate Lua table for enum
|
|
275
|
+
entries = []
|
|
276
|
+
for key, value in field_def.enum.items():
|
|
277
|
+
if isinstance(key, int):
|
|
278
|
+
entries.append(f'[{key}] = "{value}"')
|
|
279
|
+
else:
|
|
280
|
+
# String key - try to get value
|
|
281
|
+
entries.append(f'["{key}"] = "{value}"')
|
|
282
|
+
|
|
283
|
+
return "{" + ", ".join(entries) + "}"
|
|
284
|
+
|
|
285
|
+
def _calculate_min_length(self, protocol: ProtocolDefinition) -> int:
|
|
286
|
+
"""Calculate the minimum packet length for the protocol.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
protocol: Protocol definition
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
Minimum length in bytes
|
|
293
|
+
"""
|
|
294
|
+
min_length = 0
|
|
295
|
+
|
|
296
|
+
for field_def in protocol.fields:
|
|
297
|
+
# Skip conditional fields (they might not be present)
|
|
298
|
+
if field_def.condition:
|
|
299
|
+
continue
|
|
300
|
+
|
|
301
|
+
# Get field size
|
|
302
|
+
size = get_field_size(field_def.field_type)
|
|
303
|
+
|
|
304
|
+
# Handle explicit size
|
|
305
|
+
if field_def.size is not None and isinstance(field_def.size, int):
|
|
306
|
+
size = field_def.size
|
|
307
|
+
|
|
308
|
+
# Add to minimum length if fixed size
|
|
309
|
+
if size is not None:
|
|
310
|
+
min_length += size
|
|
311
|
+
|
|
312
|
+
return max(min_length, 1) # At least 1 byte
|