Patch tunggal: digsub-level-up.patch — apply dengan git apply digsub-level-up.patch dari root repo (base: main, commit terkini per 2026-07-06).
GoldenFrames.cs: pabrik frame byte-perfect (Ethernet + session header 61850 + BER builder dengan panjang TLV yang dihitung, short/long form) untuk SV, GOOSE, dan varian VLAN-tagged.BerReaderTests.cs: TLV short/long form, truncated, high-tag-number,ReadUnsignedInteger1–4 byte,ReadChildren, plus regression test overflow (panjang hostile mendekatiint.MaxValue).ProcessBusDecodeTests.cs: parse header sesi (APPID/Length), VLAN TCI (PCP 4 / VID 100), runt frame, declared-length bohong → APDU dipotong ke available, decode SV end-to-end (svID/smpCnt/confRev/smpSynch/payload), garbage APDU → frame parse OK tapiHasDecodedApdu == false, decode GOOSE end-to-end (goCbRef/datSet/goID/stNum/sqNum/TAL/confRev/test).- Ter-wire ke
ProcessBusSuite.sln(4 konfigurasi). Step CI "Run tests when present" yang sudah ada akan otomatis mendeteksi dan menjalankannya — badge hijau kini bermakna.
RawAnalyzerDataSource: semuaawaitdiStopAsync/PumpAsynckiniConfigureAwait(false)(5 titik).MainWindowViewModel:SwitchToRaw()sync-over-async →SwitchToRawAsync()async penuh;SwitchToRawCommandpindah dariRelayCommandkeAsyncRelayCommand.AsyncRelayCommand.Execute(async void) kini menangkap exception yang lolos dan melapor viaTrace.TraceError— exception command tidak lagi bisa menjatuhkan proses.
- Semua P/Invoke yang men-dereference
_handle(pcap_next_ex, copy buffer pcap,pcap_close) kini di bawah satu_handleGate. pcap_breakloopsengaja di luar gate untuk membangunkanPcapNextExyang sedang blocking (read timeout 100 ms → Dispose menunggu gate maksimal ~100 ms).- Hanya satu pemenang
DisposeviaInterlocked.Exchange;_disposedjadivolatile. EnsureOpenmengonfigurasi handle lokal (DLT check, BPF filter) sebelum dipublikasikan, sehingga handle yang belum published tidak pernah bisa balapan denganDispose.- Salinan managed dari buffer pcap dilakukan di dalam gate (buffer milik pcap hanya valid sampai call/close berikutnya).
- Validasi
offset + length > source.Length→length > source.Length - offsetsupaya panjang 4-byte hostile tidak bisa overflow penjumlahan dan lolos keSlice(). Try-method kini benar-benar tidak bisa throw pada traffic mentah. (Dibuktikan test regresi N1.)
RawProcessBusAnalyzer.ObserveOwnedFrame(byte[]): jalur zero-copy untuk caller yang mentransfer kepemilikan array segar (pump Npcap).ObserveFrame(ReadOnlyMemory<byte>)tetap ada dengan defensive copy untuk caller arbitrer — identifier lama tidak diganggu.- Pump memakai
MemoryMarshal.TryGetArray+ verifikasi full-array sebelum transfer ownership. Efek: alokasi per-frame turun 50% (~9.600 → ~4.800 alokasi/detik pada dua stream SV 80 sps/siklus).
- Terbukti:
publish-windows-portable.ps1memakai$Versionhanya untuk penamaan artefak, sehingga binary rilis v1.2.7 membawaAssemblyVersion 1.2.0.0. Directory.Build.props: versi tunggal1.2.7, semua properti turunan (AssemblyVersion=$(VersionPrefix).0, dst.) dan bisa dioverride.- Script publish kini meneruskan
/p:VersionPrefix,/p:VersionSuffix,/p:AssemblyVersion,/p:FileVersion,/p:InformationalVersion— drift tag-vs-binary tidak bisa terjadi lagi.
- Lingkungan patch ini TIDAK memiliki .NET SDK — belum ada kompilasi. Semua API yang disentuh/di-assert dibaca dari sumber sebelum diedit (signature
ProcessBusFrame,SampledValueAsdu,GoosePacket,VlanTagrecord struct, urutan tag parser SV/GOOSE,ResolveApduLength). - Gate verifikasi: CI
windows-latestyang sudah ada (dotnet buildsln → auto-detect & runProcessBus.Tests). - Perubahan Npcap/threading butuh satu sesi smoke test manual dengan adapter riil: start → switch mode saat running → stop → stop dengan timeout paksa → close app saat capture jalan.
- Pecah
MainWindowViewModel(4.564 baris) per workspace; shell VM tipis. - Lock per-protokol di
RawProcessBusAnalyzer(SV/GOOSE/PTP state independen). - Golden pcap fixtures dari capture FAT riil (anonimkan MAC) sebagai test korpus kedua.