refactor!: carry the Network Indicator as pointcode.NetworkIndicator

Merged
GO
15d ago
+322-26

The Network Indicator of Protocol Data was a plain uint8, so every application, and go-sccp, defined the four ITU-T Q.704 (07/96) §14.2.2 codes itself. gomaja/go-pointcode now provides that type: pointcode.NetworkIndicator, with NIInternational, NIInternationalSpare, NINational and NINationalReserved, plus Valid, String and text marshalling. go-m3ua now uses it:

  • ProtocolDataPayload.NetworkIndicator and DataQueueOverflowError.NetworkIndicator are pointcode.NetworkIndicator.
  • The ni parameter of params.NewProtocolDataPayload and params.NewProtocolData is pointcode.NetworkIndicator.

The octet on the wire is unchanged.

RFC 4666 §3.3.1 carries "the NI field from the original SS7 message justified to the least significant bit. Unused bits are coded 0'." The send paths (WriteData, WriteDataContext, WriteSignalfor DATA,MTPTransfer, MTPTransferContextand SGP distribution) now refuse a Network Indicator above 3 before anything reaches the transport. Each path reports it with the error andDataNotSentclassification it already uses for an unusable request. Received octets are delivered unchanged, because RFC 4666 defines no error for them;Valid()tells an application whether a value is one of the four codes. The codec still encodes any octet, andString()` still prints the number.

go-pointcode becomes a direct dependency of both modules. It imports only the standard library and is tracked at main, like go-sctp. The example ASP takes -network-indicator by name (international, national, ...).

Breaking changes: the field and parameter types above (convert uint8 values explicitly, or use the named constants), and the refusal to send values above 3.

Tests

  • TestNetworkIndicatorSendPaths: every send path refuses NI 4 and 255 with nothing written, and still sends 0 to 3. Against main's code, 4 and 255 reached every send path.
  • TestNetworkIndicatorReceivePreservesUnknownOctet: a received NI of 7 is delivered unchanged and reports Valid() false.
  • TestNetworkIndicatorDistribution and TestNetworkIndicatorDistributionPending cover SGP distribution, including traffic queued while an Application Server is pending.
  • TestNetworkIndicatorCodecAllOctets: all 256 octets round-trip through the codec.
  • FuzzPrepareDistributionDataKnownParameterLengths now expects ErrInvalidParameterValue for Protocol Data whose Network Indicator is above 3, with seeds for 4 and 128. Removing the distribution check makes those seeds fail; 300,000 fuzzing runs passed.
  • Twelve deliberate breakages were each caught by these tests: removing each send check, clamping or rejecting on receive, clamping on encode, refusing NI 3, zeroing the encoded octet, and changing the error classification.
  • A packet capture of DATA over SCTP, decoded with Wireshark's M3UA dissector, shows NI 2 and NI 4 on the wire from main, and only NI 2 from this branch.

Local validation: the full local suite passed on c1db0b4159ef (54 steps, including the Linux SCTP race suite in Docker and the cross-compiles); non-zero steps: none.


Summary by cubic

Carries the Network Indicator as pointcode.NetworkIndicator instead of a plain uint8, so applications can use the shared ITU-T Q.704 §14.2.2 codes from github.com/gomaja/go-pointcode. The octet on the wire is unchanged.

Breaking changes

  • ProtocolDataPayload.NetworkIndicator, DataQueueOverflowError.NetworkIndicator, and the ni parameters of params.NewProtocolDataPayload/params.NewProtocolData are now pointcode.NetworkIndicator; convert uint8 values explicitly or use the named constants.
  • DATA send paths (WriteData, WriteDataContext, WriteSignal, MTPTransfer, MTPTransferContext, SGP distribution) refuse NI values above 3 before transport submission, reported with the existing DataNotSent classification.
  • Received octets are delivered unchanged; applications can check them with Valid(). The codec still encodes any octet.