@netkitty/codec 1.0.0
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.
- package/CHANGELOG.md +17 -0
- package/LICENSE +21 -0
- package/README.md +352 -0
- package/README.zh-CN.md +342 -0
- package/dist/Codec.d.ts +133 -0
- package/dist/Codec.js +632 -0
- package/dist/PacketHeaders.d.ts +189 -0
- package/dist/PacketHeaders.js +384 -0
- package/dist/abstracts/BaseHeader.d.ts +325 -0
- package/dist/abstracts/BaseHeader.js +734 -0
- package/dist/errors/CodecSchemaValidateError.d.ts +4 -0
- package/dist/errors/CodecSchemaValidateError.js +11 -0
- package/dist/headers/ADSAMS.d.ts +33 -0
- package/dist/headers/ADSAMS.js +208 -0
- package/dist/headers/AH.d.ts +28 -0
- package/dist/headers/AH.js +137 -0
- package/dist/headers/AMQP.d.ts +31 -0
- package/dist/headers/AMQP.js +316 -0
- package/dist/headers/ARP.d.ts +26 -0
- package/dist/headers/ARP.js +243 -0
- package/dist/headers/BACnetIP.d.ts +27 -0
- package/dist/headers/BACnetIP.js +97 -0
- package/dist/headers/BFD.d.ts +28 -0
- package/dist/headers/BFD.js +155 -0
- package/dist/headers/BGP.d.ts +27 -0
- package/dist/headers/BGP.js +111 -0
- package/dist/headers/BSAPIP.d.ts +33 -0
- package/dist/headers/BSAPIP.js +78 -0
- package/dist/headers/Babel.d.ts +32 -0
- package/dist/headers/Babel.js +224 -0
- package/dist/headers/BitTorrent.d.ts +28 -0
- package/dist/headers/BitTorrent.js +72 -0
- package/dist/headers/C37118.d.ts +26 -0
- package/dist/headers/C37118.js +147 -0
- package/dist/headers/CAPWAP.d.ts +38 -0
- package/dist/headers/CAPWAP.js +275 -0
- package/dist/headers/CDP.d.ts +25 -0
- package/dist/headers/CDP.js +117 -0
- package/dist/headers/CMS.d.ts +33 -0
- package/dist/headers/CMS.js +238 -0
- package/dist/headers/COTP.d.ts +30 -0
- package/dist/headers/COTP.js +193 -0
- package/dist/headers/CassandraCQL.d.ts +28 -0
- package/dist/headers/CassandraCQL.js +117 -0
- package/dist/headers/CoAP.d.ts +29 -0
- package/dist/headers/CoAP.js +140 -0
- package/dist/headers/Codesys.d.ts +32 -0
- package/dist/headers/Codesys.js +119 -0
- package/dist/headers/Collectd.d.ts +29 -0
- package/dist/headers/Collectd.js +154 -0
- package/dist/headers/DCCP.d.ts +30 -0
- package/dist/headers/DCCP.js +204 -0
- package/dist/headers/DHCP.d.ts +26 -0
- package/dist/headers/DHCP.js +148 -0
- package/dist/headers/DHCPFailover.d.ts +30 -0
- package/dist/headers/DHCPFailover.js +104 -0
- package/dist/headers/DHCPv6.d.ts +25 -0
- package/dist/headers/DHCPv6.js +145 -0
- package/dist/headers/DNP3.d.ts +27 -0
- package/dist/headers/DNP3.js +150 -0
- package/dist/headers/DNS.d.ts +55 -0
- package/dist/headers/DNS.js +309 -0
- package/dist/headers/DTLS.d.ts +33 -0
- package/dist/headers/DTLS.js +142 -0
- package/dist/headers/Diameter.d.ts +34 -0
- package/dist/headers/Diameter.js +229 -0
- package/dist/headers/EAPOL.d.ts +32 -0
- package/dist/headers/EAPOL.js +135 -0
- package/dist/headers/EIGRP.d.ts +28 -0
- package/dist/headers/EIGRP.js +165 -0
- package/dist/headers/ENIP.d.ts +31 -0
- package/dist/headers/ENIP.js +164 -0
- package/dist/headers/ESP.d.ts +27 -0
- package/dist/headers/ESP.js +140 -0
- package/dist/headers/Elasticsearch.d.ts +30 -0
- package/dist/headers/Elasticsearch.js +125 -0
- package/dist/headers/EtherCAT.d.ts +35 -0
- package/dist/headers/EtherCAT.js +150 -0
- package/dist/headers/EthernetII.d.ts +28 -0
- package/dist/headers/EthernetII.js +117 -0
- package/dist/headers/FCoE.d.ts +38 -0
- package/dist/headers/FCoE.js +210 -0
- package/dist/headers/FTP.d.ts +34 -0
- package/dist/headers/FTP.js +158 -0
- package/dist/headers/Finger.d.ts +41 -0
- package/dist/headers/Finger.js +135 -0
- package/dist/headers/FoundationFieldbusHSE.d.ts +43 -0
- package/dist/headers/FoundationFieldbusHSE.js +163 -0
- package/dist/headers/GELF.d.ts +35 -0
- package/dist/headers/GELF.js +261 -0
- package/dist/headers/GENEVE.d.ts +26 -0
- package/dist/headers/GENEVE.js +209 -0
- package/dist/headers/GESRTP.d.ts +32 -0
- package/dist/headers/GESRTP.js +141 -0
- package/dist/headers/GLBP.d.ts +29 -0
- package/dist/headers/GLBP.js +159 -0
- package/dist/headers/GRE.d.ts +27 -0
- package/dist/headers/GRE.js +181 -0
- package/dist/headers/GTPU.d.ts +25 -0
- package/dist/headers/GTPU.js +203 -0
- package/dist/headers/GTPv2C.d.ts +30 -0
- package/dist/headers/GTPv2C.js +281 -0
- package/dist/headers/GitProtocol.d.ts +34 -0
- package/dist/headers/GitProtocol.js +141 -0
- package/dist/headers/Goose.d.ts +115 -0
- package/dist/headers/Goose.js +1067 -0
- package/dist/headers/Gopher.d.ts +43 -0
- package/dist/headers/Gopher.js +182 -0
- package/dist/headers/HARTIP.d.ts +30 -0
- package/dist/headers/HARTIP.js +145 -0
- package/dist/headers/HSR.d.ts +27 -0
- package/dist/headers/HSR.js +105 -0
- package/dist/headers/HSRP.d.ts +26 -0
- package/dist/headers/HSRP.js +173 -0
- package/dist/headers/HTTP.d.ts +32 -0
- package/dist/headers/HTTP.js +153 -0
- package/dist/headers/HTTP2.d.ts +34 -0
- package/dist/headers/HTTP2.js +190 -0
- package/dist/headers/IAX2.d.ts +33 -0
- package/dist/headers/IAX2.js +274 -0
- package/dist/headers/ICMP.d.ts +15 -0
- package/dist/headers/ICMP.js +148 -0
- package/dist/headers/ICMPv6.d.ts +15 -0
- package/dist/headers/ICMPv6.js +129 -0
- package/dist/headers/IEC104_I_Frame.d.ts +23 -0
- package/dist/headers/IEC104_I_Frame.js +6489 -0
- package/dist/headers/IEC104_S_Frame.d.ts +26 -0
- package/dist/headers/IEC104_S_Frame.js +135 -0
- package/dist/headers/IEC104_U_Frame.d.ts +27 -0
- package/dist/headers/IEC104_U_Frame.js +176 -0
- package/dist/headers/IEC61850SampledValues.d.ts +20 -0
- package/dist/headers/IEC61850SampledValues.js +420 -0
- package/dist/headers/IGMP.d.ts +31 -0
- package/dist/headers/IGMP.js +274 -0
- package/dist/headers/IMAP.d.ts +32 -0
- package/dist/headers/IMAP.js +185 -0
- package/dist/headers/IPFIX.d.ts +29 -0
- package/dist/headers/IPFIX.js +156 -0
- package/dist/headers/IPv4.d.ts +20 -0
- package/dist/headers/IPv4.js +370 -0
- package/dist/headers/IPv6.d.ts +29 -0
- package/dist/headers/IPv6.js +209 -0
- package/dist/headers/IPv6HopByHopOptions.d.ts +81 -0
- package/dist/headers/IPv6HopByHopOptions.js +495 -0
- package/dist/headers/IRC.d.ts +34 -0
- package/dist/headers/IRC.js +175 -0
- package/dist/headers/ISAKMP.d.ts +29 -0
- package/dist/headers/ISAKMP.js +197 -0
- package/dist/headers/ISCSI.d.ts +39 -0
- package/dist/headers/ISCSI.js +289 -0
- package/dist/headers/ISIS.d.ts +25 -0
- package/dist/headers/ISIS.js +79 -0
- package/dist/headers/ISOSession.d.ts +27 -0
- package/dist/headers/ISOSession.js +343 -0
- package/dist/headers/Ident.d.ts +42 -0
- package/dist/headers/Ident.js +184 -0
- package/dist/headers/KNXnetIP.d.ts +30 -0
- package/dist/headers/KNXnetIP.js +135 -0
- package/dist/headers/Kafka.d.ts +35 -0
- package/dist/headers/Kafka.js +128 -0
- package/dist/headers/Kerberos.d.ts +30 -0
- package/dist/headers/Kerberos.js +217 -0
- package/dist/headers/L2TP.d.ts +26 -0
- package/dist/headers/L2TP.js +297 -0
- package/dist/headers/LACP.d.ts +31 -0
- package/dist/headers/LACP.js +151 -0
- package/dist/headers/LDAP.d.ts +31 -0
- package/dist/headers/LDAP.js +226 -0
- package/dist/headers/LDP.d.ts +31 -0
- package/dist/headers/LDP.js +138 -0
- package/dist/headers/LISP.d.ts +30 -0
- package/dist/headers/LISP.js +103 -0
- package/dist/headers/LLC.d.ts +27 -0
- package/dist/headers/LLC.js +81 -0
- package/dist/headers/LLDP.d.ts +26 -0
- package/dist/headers/LLDP.js +126 -0
- package/dist/headers/LLMNR.d.ts +23 -0
- package/dist/headers/LLMNR.js +40 -0
- package/dist/headers/LPD.d.ts +31 -0
- package/dist/headers/LPD.js +159 -0
- package/dist/headers/MACsec.d.ts +34 -0
- package/dist/headers/MACsec.js +178 -0
- package/dist/headers/MDNS.d.ts +26 -0
- package/dist/headers/MDNS.js +45 -0
- package/dist/headers/MGCP.d.ts +30 -0
- package/dist/headers/MGCP.js +155 -0
- package/dist/headers/MMS.d.ts +29 -0
- package/dist/headers/MMS.js +243 -0
- package/dist/headers/MPLS.d.ts +31 -0
- package/dist/headers/MPLS.js +145 -0
- package/dist/headers/MQTT.d.ts +30 -0
- package/dist/headers/MQTT.js +173 -0
- package/dist/headers/MQTTSN.d.ts +34 -0
- package/dist/headers/MQTTSN.js +177 -0
- package/dist/headers/MarkerProtocol.d.ts +32 -0
- package/dist/headers/MarkerProtocol.js +153 -0
- package/dist/headers/Megaco.d.ts +32 -0
- package/dist/headers/Megaco.js +144 -0
- package/dist/headers/Memcached.d.ts +44 -0
- package/dist/headers/Memcached.js +285 -0
- package/dist/headers/ModbusTCP.d.ts +25 -0
- package/dist/headers/ModbusTCP.js +99 -0
- package/dist/headers/ModbusUDP.d.ts +26 -0
- package/dist/headers/ModbusUDP.js +100 -0
- package/dist/headers/MongoDB.d.ts +33 -0
- package/dist/headers/MongoDB.js +143 -0
- package/dist/headers/MySQL.d.ts +30 -0
- package/dist/headers/MySQL.js +114 -0
- package/dist/headers/NATS.d.ts +29 -0
- package/dist/headers/NATS.js +135 -0
- package/dist/headers/NBDS.d.ts +34 -0
- package/dist/headers/NBDS.js +176 -0
- package/dist/headers/NBNS.d.ts +34 -0
- package/dist/headers/NBNS.js +78 -0
- package/dist/headers/NBSS.d.ts +36 -0
- package/dist/headers/NBSS.js +137 -0
- package/dist/headers/NFS.d.ts +36 -0
- package/dist/headers/NFS.js +273 -0
- package/dist/headers/NHRP.d.ts +32 -0
- package/dist/headers/NHRP.js +154 -0
- package/dist/headers/NNTP.d.ts +35 -0
- package/dist/headers/NNTP.js +162 -0
- package/dist/headers/NTP.d.ts +18 -0
- package/dist/headers/NTP.js +73 -0
- package/dist/headers/NetFlowV5.d.ts +28 -0
- package/dist/headers/NetFlowV5.js +205 -0
- package/dist/headers/OLSR.d.ts +31 -0
- package/dist/headers/OLSR.js +213 -0
- package/dist/headers/OPCUA.d.ts +33 -0
- package/dist/headers/OPCUA.js +165 -0
- package/dist/headers/OPCUAPubSub.d.ts +33 -0
- package/dist/headers/OPCUAPubSub.js +144 -0
- package/dist/headers/OSPF.d.ts +31 -0
- package/dist/headers/OSPF.js +365 -0
- package/dist/headers/OmronFINS.d.ts +31 -0
- package/dist/headers/OmronFINS.js +90 -0
- package/dist/headers/OpenFlow.d.ts +30 -0
- package/dist/headers/OpenFlow.js +113 -0
- package/dist/headers/OpenVPN.d.ts +35 -0
- package/dist/headers/OpenVPN.js +214 -0
- package/dist/headers/PCWorx.d.ts +35 -0
- package/dist/headers/PCWorx.js +115 -0
- package/dist/headers/PIM.d.ts +27 -0
- package/dist/headers/PIM.js +129 -0
- package/dist/headers/POP3.d.ts +31 -0
- package/dist/headers/POP3.js +152 -0
- package/dist/headers/POWERLINK.d.ts +28 -0
- package/dist/headers/POWERLINK.js +116 -0
- package/dist/headers/PPPoEDiscovery.d.ts +29 -0
- package/dist/headers/PPPoEDiscovery.js +198 -0
- package/dist/headers/PPPoESession.d.ts +28 -0
- package/dist/headers/PPPoESession.js +125 -0
- package/dist/headers/PPTP.d.ts +30 -0
- package/dist/headers/PPTP.js +122 -0
- package/dist/headers/PROFINETRT.d.ts +28 -0
- package/dist/headers/PROFINETRT.js +74 -0
- package/dist/headers/PTP.d.ts +34 -0
- package/dist/headers/PTP.js +213 -0
- package/dist/headers/PostgreSQL.d.ts +40 -0
- package/dist/headers/PostgreSQL.js +236 -0
- package/dist/headers/QUIC.d.ts +34 -0
- package/dist/headers/QUIC.js +308 -0
- package/dist/headers/RADIUS.d.ts +24 -0
- package/dist/headers/RADIUS.js +138 -0
- package/dist/headers/RDP.d.ts +27 -0
- package/dist/headers/RDP.js +93 -0
- package/dist/headers/RFB.d.ts +39 -0
- package/dist/headers/RFB.js +151 -0
- package/dist/headers/RGoose.d.ts +72 -0
- package/dist/headers/RGoose.js +340 -0
- package/dist/headers/RIP.d.ts +29 -0
- package/dist/headers/RIP.js +133 -0
- package/dist/headers/RIPng.d.ts +26 -0
- package/dist/headers/RIPng.js +140 -0
- package/dist/headers/RMCP.d.ts +26 -0
- package/dist/headers/RMCP.js +155 -0
- package/dist/headers/RSVP.d.ts +31 -0
- package/dist/headers/RSVP.js +263 -0
- package/dist/headers/RTCP.d.ts +34 -0
- package/dist/headers/RTCP.js +217 -0
- package/dist/headers/RTP.d.ts +33 -0
- package/dist/headers/RTP.js +291 -0
- package/dist/headers/RTPS.d.ts +33 -0
- package/dist/headers/RTPS.js +182 -0
- package/dist/headers/RTSP.d.ts +36 -0
- package/dist/headers/RTSP.js +184 -0
- package/dist/headers/RawData.d.ts +17 -0
- package/dist/headers/RawData.js +43 -0
- package/dist/headers/Redis.d.ts +32 -0
- package/dist/headers/Redis.js +202 -0
- package/dist/headers/Rlogin.d.ts +42 -0
- package/dist/headers/Rlogin.js +139 -0
- package/dist/headers/Rsync.d.ts +28 -0
- package/dist/headers/Rsync.js +117 -0
- package/dist/headers/S7comm.d.ts +36 -0
- package/dist/headers/S7comm.js +244 -0
- package/dist/headers/SCTP.d.ts +35 -0
- package/dist/headers/SCTP.js +174 -0
- package/dist/headers/SFlow.d.ts +29 -0
- package/dist/headers/SFlow.js +242 -0
- package/dist/headers/SIP.d.ts +27 -0
- package/dist/headers/SIP.js +146 -0
- package/dist/headers/SLMP.d.ts +36 -0
- package/dist/headers/SLMP.js +154 -0
- package/dist/headers/SLP.d.ts +30 -0
- package/dist/headers/SLP.js +207 -0
- package/dist/headers/SLPv1.d.ts +32 -0
- package/dist/headers/SLPv1.js +138 -0
- package/dist/headers/SMB1.d.ts +37 -0
- package/dist/headers/SMB1.js +200 -0
- package/dist/headers/SMB2.d.ts +36 -0
- package/dist/headers/SMB2.js +203 -0
- package/dist/headers/SMPP.d.ts +33 -0
- package/dist/headers/SMPP.js +119 -0
- package/dist/headers/SMTP.d.ts +33 -0
- package/dist/headers/SMTP.js +157 -0
- package/dist/headers/SNAP.d.ts +22 -0
- package/dist/headers/SNAP.js +68 -0
- package/dist/headers/SNMP.d.ts +28 -0
- package/dist/headers/SNMP.js +302 -0
- package/dist/headers/SOCKS4.d.ts +42 -0
- package/dist/headers/SOCKS4.js +302 -0
- package/dist/headers/SOCKS5.d.ts +45 -0
- package/dist/headers/SOCKS5.js +223 -0
- package/dist/headers/SSDP.d.ts +27 -0
- package/dist/headers/SSDP.js +161 -0
- package/dist/headers/SSH.d.ts +44 -0
- package/dist/headers/SSH.js +274 -0
- package/dist/headers/STOMP.d.ts +48 -0
- package/dist/headers/STOMP.js +177 -0
- package/dist/headers/STP.d.ts +26 -0
- package/dist/headers/STP.js +150 -0
- package/dist/headers/STUN.d.ts +25 -0
- package/dist/headers/STUN.js +183 -0
- package/dist/headers/SercosIII.d.ts +43 -0
- package/dist/headers/SercosIII.js +199 -0
- package/dist/headers/Skinny.d.ts +32 -0
- package/dist/headers/Skinny.js +139 -0
- package/dist/headers/StatsD.d.ts +27 -0
- package/dist/headers/StatsD.js +134 -0
- package/dist/headers/SunRPC.d.ts +34 -0
- package/dist/headers/SunRPC.js +268 -0
- package/dist/headers/Syslog.d.ts +21 -0
- package/dist/headers/Syslog.js +91 -0
- package/dist/headers/TCP.d.ts +19 -0
- package/dist/headers/TCP.js +905 -0
- package/dist/headers/TFTP.d.ts +28 -0
- package/dist/headers/TFTP.js +224 -0
- package/dist/headers/TLS_Alert.d.ts +24 -0
- package/dist/headers/TLS_Alert.js +639 -0
- package/dist/headers/TLS_ApplicationData.d.ts +24 -0
- package/dist/headers/TLS_ApplicationData.js +170 -0
- package/dist/headers/TLS_ChangeCipherSpec.d.ts +23 -0
- package/dist/headers/TLS_ChangeCipherSpec.js +168 -0
- package/dist/headers/TLS_Handshake.d.ts +65 -0
- package/dist/headers/TLS_Handshake.js +860 -0
- package/dist/headers/TLS_Heartbeat.d.ts +27 -0
- package/dist/headers/TLS_Heartbeat.js +247 -0
- package/dist/headers/TPKT.d.ts +26 -0
- package/dist/headers/TPKT.js +99 -0
- package/dist/headers/TacacsPlus.d.ts +27 -0
- package/dist/headers/TacacsPlus.js +133 -0
- package/dist/headers/Telnet.d.ts +40 -0
- package/dist/headers/Telnet.js +193 -0
- package/dist/headers/Teredo.d.ts +40 -0
- package/dist/headers/Teredo.js +251 -0
- package/dist/headers/TimeProtocol.d.ts +25 -0
- package/dist/headers/TimeProtocol.js +53 -0
- package/dist/headers/UDP.d.ts +19 -0
- package/dist/headers/UDP.js +171 -0
- package/dist/headers/VLAN_802dot1Q.d.ts +24 -0
- package/dist/headers/VLAN_802dot1Q.js +96 -0
- package/dist/headers/VRRP.d.ts +26 -0
- package/dist/headers/VRRP.js +309 -0
- package/dist/headers/VXLAN.d.ts +24 -0
- package/dist/headers/VXLAN.js +75 -0
- package/dist/headers/WCCP.d.ts +29 -0
- package/dist/headers/WCCP.js +117 -0
- package/dist/headers/WHOIS.d.ts +37 -0
- package/dist/headers/WHOIS.js +126 -0
- package/dist/headers/WSDiscovery.d.ts +29 -0
- package/dist/headers/WSDiscovery.js +118 -0
- package/dist/headers/WakeOnLAN.d.ts +30 -0
- package/dist/headers/WakeOnLAN.js +126 -0
- package/dist/headers/WebSocket.d.ts +26 -0
- package/dist/headers/WebSocket.js +173 -0
- package/dist/headers/WireGuard.d.ts +38 -0
- package/dist/headers/WireGuard.js +216 -0
- package/dist/headers/XMPP.d.ts +37 -0
- package/dist/headers/XMPP.js +149 -0
- package/dist/headers/Zabbix.d.ts +35 -0
- package/dist/headers/Zabbix.js +153 -0
- package/dist/headers/cms/AcsiPdu.d.ts +45 -0
- package/dist/headers/cms/AcsiPdu.js +112 -0
- package/dist/headers/cms/PerDecoder.d.ts +68 -0
- package/dist/headers/cms/PerDecoder.js +211 -0
- package/dist/headers/cms/PerReader.d.ts +64 -0
- package/dist/headers/cms/PerReader.js +155 -0
- package/dist/helper/BufferToHex.d.ts +5 -0
- package/dist/helper/BufferToHex.js +10 -0
- package/dist/helper/BufferToIP.d.ts +12 -0
- package/dist/helper/BufferToIP.js +23 -0
- package/dist/helper/BufferToNumber.d.ts +18 -0
- package/dist/helper/BufferToNumber.js +47 -0
- package/dist/helper/HexToBuffer.d.ts +7 -0
- package/dist/helper/HexToBuffer.js +27 -0
- package/dist/helper/HexToNumber.d.ts +18 -0
- package/dist/helper/HexToNumber.js +48 -0
- package/dist/helper/IPToBuffer.d.ts +12 -0
- package/dist/helper/IPToBuffer.js +34 -0
- package/dist/helper/NumberToBERBuffer.d.ts +18 -0
- package/dist/helper/NumberToBERBuffer.js +31 -0
- package/dist/helper/NumberToBERHex.d.ts +18 -0
- package/dist/helper/NumberToBERHex.js +52 -0
- package/dist/helper/NumberToBuffer.d.ts +18 -0
- package/dist/helper/NumberToBuffer.js +38 -0
- package/dist/helper/NumberToHex.d.ts +18 -0
- package/dist/helper/NumberToHex.js +35 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +113 -0
- package/dist/lib/FlexibleObject.d.ts +27 -0
- package/dist/lib/FlexibleObject.js +113 -0
- package/dist/lib/GetBERIntegerLengthFromBuffer.d.ts +6 -0
- package/dist/lib/GetBERIntegerLengthFromBuffer.js +16 -0
- package/dist/lib/ProcessPacketPostHandlers.d.ts +13 -0
- package/dist/lib/ProcessPacketPostHandlers.js +53 -0
- package/dist/lib/SortPostHandlers.d.ts +7 -0
- package/dist/lib/SortPostHandlers.js +11 -0
- package/dist/lib/StringContentEncodingEnum.d.ts +10 -0
- package/dist/lib/StringContentEncodingEnum.js +14 -0
- package/dist/schema/ProtocolFieldJSONSchema.d.ts +35 -0
- package/dist/schema/ProtocolFieldJSONSchema.js +2 -0
- package/dist/schema/ProtocolFieldJSONSchemaDefinition.d.ts +2 -0
- package/dist/schema/ProtocolFieldJSONSchemaDefinition.js +2 -0
- package/dist/schema/ProtocolJSONSchema.d.ts +32 -0
- package/dist/schema/ProtocolJSONSchema.js +2 -0
- package/dist/types/CodecData.d.ts +7 -0
- package/dist/types/CodecData.js +2 -0
- package/dist/types/CodecDecodeResult.d.ts +10 -0
- package/dist/types/CodecDecodeResult.js +2 -0
- package/dist/types/CodecEncodeInput.d.ts +2 -0
- package/dist/types/CodecEncodeInput.js +2 -0
- package/dist/types/CodecEncodeResult.d.ts +5 -0
- package/dist/types/CodecEncodeResult.js +2 -0
- package/dist/types/CodecErrorInfo.d.ts +5 -0
- package/dist/types/CodecErrorInfo.js +2 -0
- package/dist/types/CodecModule.d.ts +2 -0
- package/dist/types/CodecModule.js +2 -0
- package/dist/types/CodecModuleConstructor.d.ts +2 -0
- package/dist/types/CodecModuleConstructor.js +2 -0
- package/dist/types/CodecSchema.d.ts +6 -0
- package/dist/types/CodecSchema.js +2 -0
- package/dist/types/DemuxProducer.d.ts +23 -0
- package/dist/types/DemuxProducer.js +2 -0
- package/dist/types/Dissection.d.ts +23 -0
- package/dist/types/Dissection.js +2 -0
- package/dist/types/HeaderTreeNode.d.ts +4 -0
- package/dist/types/HeaderTreeNode.js +2 -0
- package/dist/types/LayerGraph.d.ts +32 -0
- package/dist/types/LayerGraph.js +2 -0
- package/dist/types/PostHandlerItem.d.ts +4 -0
- package/dist/types/PostHandlerItem.js +2 -0
- package/package.json +141 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { BaseHeader } from '../abstracts/BaseHeader';
|
|
2
|
+
import { ProtocolJSONSchema } from '../schema/ProtocolJSONSchema';
|
|
3
|
+
import { DemuxProducer } from '../types/DemuxProducer';
|
|
4
|
+
/**
|
|
5
|
+
* PostgreSQL frontend/backend protocol, version 3 (the wire protocol of libpq / the `psql` client and the
|
|
6
|
+
* server), carried over TCP well-known port 5432.
|
|
7
|
+
*
|
|
8
|
+
* Almost every message is framed uniformly: a 1-byte ASCII messageType (e.g. 'Q' Query, 'P' Parse, 'R'
|
|
9
|
+
* Authentication, 'C' CommandComplete, 'D' DataRow, 'Z' ReadyForQuery, 'T' RowDescription, 'S'
|
|
10
|
+
* ParameterStatus, 'E' ErrorResponse, 'K' BackendKeyData, 'X' Terminate), then a BIG-ENDIAN uint32 length,
|
|
11
|
+
* then (length − 4) body bytes. Crucially the length INCLUDES its own 4 bytes but NOT the type byte, so a
|
|
12
|
+
* typed message occupies 1 + length bytes on the wire and its body lives at offset 5.
|
|
13
|
+
*
|
|
14
|
+
* ⚠️ EXCEPTION — the very first message of a connection has NO type byte. The StartupMessage (and the
|
|
15
|
+
* SSLRequest / CancelRequest / GSSENCRequest handshakes) is length(4, BE) + protocol-version-or-code(4) +
|
|
16
|
+
* params: length still includes its own 4 bytes, so the body (version + params) lives at offset 4, and the
|
|
17
|
+
* message occupies exactly `length` bytes. The two shapes are told apart by the first byte: a typed
|
|
18
|
+
* message opens with a printable message-type letter; a startup message opens with the high octet of a
|
|
19
|
+
* small length (0x00 in practice) and carries a v3 version word (0x0003xxxx) or a special request code at
|
|
20
|
+
* offset 4. THIS OFFSET DIFFERENCE (typed length@1 body@5 vs startup length@0 body@4) is the crux of the
|
|
21
|
+
* codec — every field closure branches on it via #isStartupDecode()/#isStartupEncode().
|
|
22
|
+
*
|
|
23
|
+
* Per-message-type body structure (Parse's query text + parameter OIDs, DataRow's column array, an
|
|
24
|
+
* Authentication request's method, …) is message-type-specific and often cross-message (the backend's
|
|
25
|
+
* reply depends on the frontend's request), so this slice keeps the body verbatim as `body` hex
|
|
26
|
+
* (byte-perfect), bounded by the length field so a pipelined/trailing message is left to the codec's
|
|
27
|
+
* recursion / RawData. The length is honored when supplied (a crafted message may lie), else derived as
|
|
28
|
+
* 4 + body bytes. A well-formed message round-trips byte-for-byte. Structuring per-message-type bodies is
|
|
29
|
+
* a later slice.
|
|
30
|
+
*/
|
|
31
|
+
export declare class PostgreSQL extends BaseHeader {
|
|
32
|
+
#private;
|
|
33
|
+
get SCHEMA(): ProtocolJSONSchema;
|
|
34
|
+
readonly id: string;
|
|
35
|
+
readonly name: string;
|
|
36
|
+
readonly nickname: string;
|
|
37
|
+
readonly matchKeys: string[];
|
|
38
|
+
match(): boolean;
|
|
39
|
+
readonly demuxProducers: DemuxProducer[];
|
|
40
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.PostgreSQL = void 0;
|
|
5
|
+
const BaseHeader_1 = require("../abstracts/BaseHeader");
|
|
6
|
+
const BufferToHex_1 = require("../helper/BufferToHex");
|
|
7
|
+
const HexToBuffer_1 = require("../helper/HexToBuffer");
|
|
8
|
+
const BufferToNumber_1 = require("../helper/BufferToNumber");
|
|
9
|
+
const NumberToBuffer_1 = require("../helper/NumberToBuffer");
|
|
10
|
+
const StringContentEncodingEnum_1 = require("../lib/StringContentEncodingEnum");
|
|
11
|
+
/**
|
|
12
|
+
* The PostgreSQL v3 message-type bytes (a single ASCII byte that opens every TYPED message). Frontend and
|
|
13
|
+
* backend share the byte space: e.g. Q Query, P Parse, B Bind, E Execute/ErrorResponse, C Close/
|
|
14
|
+
* CommandComplete, D Describe/DataRow, R Authentication, Z ReadyForQuery, T RowDescription, S Sync/
|
|
15
|
+
* ParameterStatus, K BackendKeyData, X Terminate, plus the digit types 1/2/3 (Parse/Bind/CloseComplete).
|
|
16
|
+
* Used by match() and by decode's typed-vs-startup discriminator — a startup message has NO type byte (see
|
|
17
|
+
* the class doc), so its first byte is the high octet of a (small) length, never one of these letters.
|
|
18
|
+
*/
|
|
19
|
+
const PG_MESSAGE_TYPES = 'ABCDEFGHIKNPQRSTVWXZcdfnpstvw123';
|
|
20
|
+
/** PostgreSQL v3 protocol-version MAJOR number (the high 16 bits of the startup version word: 0x0003xxxx). */
|
|
21
|
+
const PG_PROTOCOL_MAJOR_V3 = 0x0003;
|
|
22
|
+
/**
|
|
23
|
+
* The special startup request codes that appear in place of a protocol version: SSLRequest (80877103 =
|
|
24
|
+
* 0x04d2162f), CancelRequest (80877102 = 0x04d2162e) and GSSENCRequest (80877104 = 0x04d21630). Like a v3
|
|
25
|
+
* StartupMessage, these have no type byte — length(4) + code(4) [ + payload ].
|
|
26
|
+
*/
|
|
27
|
+
const PG_SPECIAL_REQUEST_CODES = [0x04d2162f, 0x04d2162e, 0x04d21630];
|
|
28
|
+
/**
|
|
29
|
+
* PostgreSQL frontend/backend protocol, version 3 (the wire protocol of libpq / the `psql` client and the
|
|
30
|
+
* server), carried over TCP well-known port 5432.
|
|
31
|
+
*
|
|
32
|
+
* Almost every message is framed uniformly: a 1-byte ASCII messageType (e.g. 'Q' Query, 'P' Parse, 'R'
|
|
33
|
+
* Authentication, 'C' CommandComplete, 'D' DataRow, 'Z' ReadyForQuery, 'T' RowDescription, 'S'
|
|
34
|
+
* ParameterStatus, 'E' ErrorResponse, 'K' BackendKeyData, 'X' Terminate), then a BIG-ENDIAN uint32 length,
|
|
35
|
+
* then (length − 4) body bytes. Crucially the length INCLUDES its own 4 bytes but NOT the type byte, so a
|
|
36
|
+
* typed message occupies 1 + length bytes on the wire and its body lives at offset 5.
|
|
37
|
+
*
|
|
38
|
+
* ⚠️ EXCEPTION — the very first message of a connection has NO type byte. The StartupMessage (and the
|
|
39
|
+
* SSLRequest / CancelRequest / GSSENCRequest handshakes) is length(4, BE) + protocol-version-or-code(4) +
|
|
40
|
+
* params: length still includes its own 4 bytes, so the body (version + params) lives at offset 4, and the
|
|
41
|
+
* message occupies exactly `length` bytes. The two shapes are told apart by the first byte: a typed
|
|
42
|
+
* message opens with a printable message-type letter; a startup message opens with the high octet of a
|
|
43
|
+
* small length (0x00 in practice) and carries a v3 version word (0x0003xxxx) or a special request code at
|
|
44
|
+
* offset 4. THIS OFFSET DIFFERENCE (typed length@1 body@5 vs startup length@0 body@4) is the crux of the
|
|
45
|
+
* codec — every field closure branches on it via #isStartupDecode()/#isStartupEncode().
|
|
46
|
+
*
|
|
47
|
+
* Per-message-type body structure (Parse's query text + parameter OIDs, DataRow's column array, an
|
|
48
|
+
* Authentication request's method, …) is message-type-specific and often cross-message (the backend's
|
|
49
|
+
* reply depends on the frontend's request), so this slice keeps the body verbatim as `body` hex
|
|
50
|
+
* (byte-perfect), bounded by the length field so a pipelined/trailing message is left to the codec's
|
|
51
|
+
* recursion / RawData. The length is honored when supplied (a crafted message may lie), else derived as
|
|
52
|
+
* 4 + body bytes. A well-formed message round-trips byte-for-byte. Structuring per-message-type bodies is
|
|
53
|
+
* a later slice.
|
|
54
|
+
*/
|
|
55
|
+
class PostgreSQL extends BaseHeader_1.BaseHeader {
|
|
56
|
+
constructor() {
|
|
57
|
+
super(...arguments);
|
|
58
|
+
this.id = 'pgsql';
|
|
59
|
+
this.name = 'PostgreSQL Protocol';
|
|
60
|
+
this.nickname = 'PostgreSQL';
|
|
61
|
+
//PostgreSQL is recognized ONLY on its well-known port bucket 5432 — deliberately NOT via
|
|
62
|
+
//heuristicFallback. The v3 framing has NO strong global signature: a typed message is just a single
|
|
63
|
+
//ASCII letter followed by a 4-byte length, and a startup message is a small length followed by a
|
|
64
|
+
//version word — both are byte patterns that ordinary text or binary streams reproduce constantly, so
|
|
65
|
+
//(like POP3 and Redis, whose 1-byte/verb signatures are equally weak) joining the global heuristic
|
|
66
|
+
//chain would let PostgreSQL mis-claim countless non-PG layers on any port. Confining it to the
|
|
67
|
+
//tcp:5432 bucket makes that impossible off-port; alt-port PostgreSQL is rare and falls losslessly to
|
|
68
|
+
//raw.
|
|
69
|
+
this.matchKeys = ['tcpport:5432'];
|
|
70
|
+
//A leaf header — the per-message-type body requires message-dependent, cross-message parsing.
|
|
71
|
+
this.demuxProducers = [];
|
|
72
|
+
}
|
|
73
|
+
static #schemaCache;
|
|
74
|
+
get SCHEMA() {
|
|
75
|
+
return (_a.#schemaCache ??= _a.#buildSchema());
|
|
76
|
+
}
|
|
77
|
+
/** True when `byte` is a printable PostgreSQL v3 message-type byte (opens a TYPED message). */
|
|
78
|
+
static #isTypeByte(byte) {
|
|
79
|
+
return PG_MESSAGE_TYPES.includes(String.fromCharCode(byte));
|
|
80
|
+
}
|
|
81
|
+
/** Bytes of this header's payload available in the segment (never negative). */
|
|
82
|
+
#payloadLength() {
|
|
83
|
+
const available = this.packet.length - this.startPos;
|
|
84
|
+
return available < 0 ? 0 : available;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Decide, at DECODE time, whether the message at startPos is a startup message (no type byte) vs a
|
|
88
|
+
* typed message: a typed message opens with a printable message-type letter, so anything else (the
|
|
89
|
+
* high octet of a small length, 0x00 in practice) is a startup message. match() gates entry to exactly
|
|
90
|
+
* these two shapes, so this two-way split is reliable.
|
|
91
|
+
*/
|
|
92
|
+
#isStartupDecode() {
|
|
93
|
+
if (this.#payloadLength() < 1)
|
|
94
|
+
return false;
|
|
95
|
+
return !_a.#isTypeByte(this.readBytes(0, 1, true)[0]);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Decide, at ENCODE time, whether to emit a startup frame (no type byte). The messageType is the
|
|
99
|
+
* discriminator: a typed message always carries a non-empty type byte, a startup message carries none
|
|
100
|
+
* (messageType === '', the value decode stores for a startup). So an empty messageType means startup.
|
|
101
|
+
*/
|
|
102
|
+
#isStartupEncode() {
|
|
103
|
+
return this.instance.messageType.getValue('') === '';
|
|
104
|
+
}
|
|
105
|
+
static #buildSchema() {
|
|
106
|
+
return {
|
|
107
|
+
type: 'object',
|
|
108
|
+
summary: 'PostgreSQL ${messageType}',
|
|
109
|
+
properties: {
|
|
110
|
+
//Display-only flag: is this the type-byte-less startup/handshake message? Set on decode
|
|
111
|
+
//from the first byte; has no encode of its own (encode derives the framing from
|
|
112
|
+
//messageType emptiness — see #isStartupEncode), so it never affects the re-emitted bytes.
|
|
113
|
+
isStartup: {
|
|
114
|
+
type: 'boolean',
|
|
115
|
+
label: 'Is Startup',
|
|
116
|
+
decode: function () {
|
|
117
|
+
this.instance.isStartup.setValue(this.#isStartupDecode());
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
//The 1-byte ASCII message type ('' for a startup message, which has no type byte). Decode
|
|
121
|
+
//reads it only for a typed message; encode writes exactly 1 byte for a typed message and
|
|
122
|
+
//nothing for a startup message, so both shapes round-trip byte-for-byte.
|
|
123
|
+
messageType: {
|
|
124
|
+
type: 'string',
|
|
125
|
+
label: 'Message Type',
|
|
126
|
+
maxLength: 1,
|
|
127
|
+
contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.ASCII,
|
|
128
|
+
decode: function () {
|
|
129
|
+
this.instance.messageType.setValue(this.#isStartupDecode() ? '' : this.readBytes(0, 1).toString('latin1'));
|
|
130
|
+
},
|
|
131
|
+
encode: function () {
|
|
132
|
+
const value = this.instance.messageType.getValue('');
|
|
133
|
+
//Empty ⇒ startup message: no type byte is written (the length is the first field).
|
|
134
|
+
if (value === '')
|
|
135
|
+
return;
|
|
136
|
+
const buffer = Buffer.alloc(1);
|
|
137
|
+
Buffer.from(value, 'latin1').copy(buffer, 0, 0, 1);
|
|
138
|
+
this.writeBytes(0, buffer);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
//BIG-ENDIAN uint32 length. It INCLUDES its own 4 bytes but NOT the type byte, so it lives
|
|
142
|
+
//at offset 1 for a typed message and at offset 0 for a startup message. Honored when
|
|
143
|
+
//supplied (a crafted message may lie); else derived as 4 (the length word) + body bytes.
|
|
144
|
+
length: {
|
|
145
|
+
type: 'integer',
|
|
146
|
+
label: 'Length',
|
|
147
|
+
minimum: 0,
|
|
148
|
+
maximum: 4294967295,
|
|
149
|
+
decode: function () {
|
|
150
|
+
const offset = this.#isStartupDecode() ? 0 : 1;
|
|
151
|
+
this.instance.length.setValue((0, BufferToNumber_1.BufferToUInt32)(this.readBytes(offset, 4)));
|
|
152
|
+
},
|
|
153
|
+
encode: function () {
|
|
154
|
+
const startup = this.#isStartupEncode();
|
|
155
|
+
const provided = this.instance.length.getValue();
|
|
156
|
+
let value = (provided !== undefined && provided !== null)
|
|
157
|
+
? provided
|
|
158
|
+
: 4 + (0, HexToBuffer_1.HexToBuffer)(this.instance.body.getValue('')).length;
|
|
159
|
+
if (value > 4294967295) {
|
|
160
|
+
this.recordError(this.instance.length.getPath(), 'Maximum value is 4294967295');
|
|
161
|
+
value = 4294967295;
|
|
162
|
+
}
|
|
163
|
+
if (value < 0) {
|
|
164
|
+
this.recordError(this.instance.length.getPath(), 'Minimum value is 0');
|
|
165
|
+
value = 0;
|
|
166
|
+
}
|
|
167
|
+
this.instance.length.setValue(value);
|
|
168
|
+
this.writeBytes(startup ? 0 : 1, (0, NumberToBuffer_1.UInt32ToBuffer)(value));
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
//The message body after the length word, kept verbatim. For a TYPED message the body is at
|
|
172
|
+
//offset 5 (type byte + 4 length bytes) and the message ends at 1 + length; for a STARTUP
|
|
173
|
+
//message the body (version/code + params) is at offset 4 and the message ends at length.
|
|
174
|
+
//Bounded by the length field and the captured bytes, so trailing/pipelined data is left to
|
|
175
|
+
//the codec's recursion / RawData.
|
|
176
|
+
body: {
|
|
177
|
+
type: 'string',
|
|
178
|
+
label: 'Body',
|
|
179
|
+
contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX,
|
|
180
|
+
decode: function () {
|
|
181
|
+
const remaining = this.#payloadLength();
|
|
182
|
+
const startup = this.#isStartupDecode();
|
|
183
|
+
const headerLen = startup ? 4 : 5;
|
|
184
|
+
const length = this.instance.length.getValue(0);
|
|
185
|
+
//Wire span of the whole message: startup = length; typed = 1 (type) + length.
|
|
186
|
+
let end = startup ? length : 1 + length;
|
|
187
|
+
if (end > remaining)
|
|
188
|
+
end = remaining;
|
|
189
|
+
if (end < headerLen)
|
|
190
|
+
end = headerLen;
|
|
191
|
+
this.instance.body.setValue(end > headerLen ? (0, BufferToHex_1.BufferToHex)(this.readBytes(headerLen, end - headerLen)) : '');
|
|
192
|
+
},
|
|
193
|
+
encode: function () {
|
|
194
|
+
const headerLen = this.#isStartupEncode() ? 4 : 5;
|
|
195
|
+
const body = this.instance.body.getValue('');
|
|
196
|
+
if (body)
|
|
197
|
+
this.writeBytes(headerLen, (0, HexToBuffer_1.HexToBuffer)(body));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
match() {
|
|
204
|
+
//PostgreSQL rides on TCP port 5432. Within that bucket, confirm one of the two v3 shapes so
|
|
205
|
+
//non-PG traffic on 5432 falls through to raw:
|
|
206
|
+
// • a TYPED message — a known message-type letter followed by a plausible 4-byte length; or
|
|
207
|
+
// • a STARTUP message — a small length (8..296) whose next 4 bytes are a v3 version word
|
|
208
|
+
// (0x0003xxxx) or a special request code (SSLRequest / CancelRequest / GSSENCRequest).
|
|
209
|
+
if (!this.prevCodecModule || this.prevCodecModule.id !== 'tcp')
|
|
210
|
+
return false;
|
|
211
|
+
//Need at least a type byte + a 4-byte length (typed), which is also enough for a startup's
|
|
212
|
+
//length + the start of its version word.
|
|
213
|
+
if (this.#payloadLength() < 5)
|
|
214
|
+
return false;
|
|
215
|
+
const first = this.readBytes(0, 1, true)[0];
|
|
216
|
+
if (_a.#isTypeByte(first)) {
|
|
217
|
+
//Typed message: length includes its own 4 bytes, so a sane length is >= 4 and not absurd
|
|
218
|
+
//(PostgreSQL caps a message at ~1 GiB).
|
|
219
|
+
const length = (0, BufferToNumber_1.BufferToUInt32)(this.readBytes(1, 4, true));
|
|
220
|
+
return length >= 4 && length <= 0x3fffffff;
|
|
221
|
+
}
|
|
222
|
+
//Startup message: length(4) + version-or-code(4). Require the full 8 bytes and a plausible,
|
|
223
|
+
//bounded length, then a v3 version word or a recognized special request code.
|
|
224
|
+
if (this.#payloadLength() < 8)
|
|
225
|
+
return false;
|
|
226
|
+
const length = (0, BufferToNumber_1.BufferToUInt32)(this.readBytes(0, 4, true));
|
|
227
|
+
if (length < 8 || length > 296)
|
|
228
|
+
return false;
|
|
229
|
+
const code = (0, BufferToNumber_1.BufferToUInt32)(this.readBytes(4, 4, true));
|
|
230
|
+
if ((code >>> 16) === PG_PROTOCOL_MAJOR_V3)
|
|
231
|
+
return true;
|
|
232
|
+
return PG_SPECIAL_REQUEST_CODES.includes(code);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
exports.PostgreSQL = PostgreSQL;
|
|
236
|
+
_a = PostgreSQL;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BaseHeader } from '../abstracts/BaseHeader';
|
|
2
|
+
import { ProtocolJSONSchema } from '../schema/ProtocolJSONSchema';
|
|
3
|
+
import { DemuxProducer } from '../types/DemuxProducer';
|
|
4
|
+
/**
|
|
5
|
+
* QUIC — the UDP-based multiplexed and secure transport (RFC 9000), the substrate under HTTP/3. Every
|
|
6
|
+
* QUIC packet begins with a first byte whose most-significant bit is the Header Form: 1 = Long Header
|
|
7
|
+
* (used during connection setup — Initial / 0-RTT / Handshake / Retry / Version Negotiation), 0 = Short
|
|
8
|
+
* Header (1-RTT, used once the connection is established). This header structures the LONG header only:
|
|
9
|
+
*
|
|
10
|
+
* first byte = Header Form(1) | Fixed Bit(1) | Long Packet Type(2) | type-specific(4)
|
|
11
|
+
* Version(4) | DCID Len(1) | DCID(DCID Len) | SCID Len(1) | SCID(SCID Len) | ...rest
|
|
12
|
+
*
|
|
13
|
+
* Everything after the Source Connection ID (token / length / packet number / frames) is protected by
|
|
14
|
+
* QUIC header protection + AEAD encryption, so it is kept verbatim as an opaque `payload` hex (bounded
|
|
15
|
+
* by the UDP payload) — this is a best-effort structural slice, not a decryptor. The one exception is
|
|
16
|
+
* Version Negotiation (Version == 0, RFC 9000 §17.2.1): its body is an unencrypted list of 4-byte
|
|
17
|
+
* Supported Versions, decoded into `supportedVersions`.
|
|
18
|
+
*
|
|
19
|
+
* The Short Header (MSB clear) is deliberately NOT recognized by the content heuristic — its first byte
|
|
20
|
+
* is an almost signature-free value, so heuristic matching would over-claim ordinary UDP traffic; it is
|
|
21
|
+
* left to later enrichment / RawData. The connection-ID length fields are honored when supplied else
|
|
22
|
+
* derived from the ID bytes; the type-specific bits and all opaque bytes round-trip byte-for-byte.
|
|
23
|
+
*/
|
|
24
|
+
export declare class QUIC extends BaseHeader {
|
|
25
|
+
#private;
|
|
26
|
+
get SCHEMA(): ProtocolJSONSchema;
|
|
27
|
+
readonly id: string;
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly nickname: string;
|
|
30
|
+
readonly matchKeys: string[];
|
|
31
|
+
readonly heuristicFallback: boolean;
|
|
32
|
+
match(): boolean;
|
|
33
|
+
readonly demuxProducers: DemuxProducer[];
|
|
34
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QUIC = void 0;
|
|
4
|
+
const BaseHeader_1 = require("../abstracts/BaseHeader");
|
|
5
|
+
const BufferToHex_1 = require("../helper/BufferToHex");
|
|
6
|
+
const HexToBuffer_1 = require("../helper/HexToBuffer");
|
|
7
|
+
const BufferToNumber_1 = require("../helper/BufferToNumber");
|
|
8
|
+
const NumberToBuffer_1 = require("../helper/NumberToBuffer");
|
|
9
|
+
const StringContentEncodingEnum_1 = require("../lib/StringContentEncodingEnum");
|
|
10
|
+
/**
|
|
11
|
+
* QUIC — the UDP-based multiplexed and secure transport (RFC 9000), the substrate under HTTP/3. Every
|
|
12
|
+
* QUIC packet begins with a first byte whose most-significant bit is the Header Form: 1 = Long Header
|
|
13
|
+
* (used during connection setup — Initial / 0-RTT / Handshake / Retry / Version Negotiation), 0 = Short
|
|
14
|
+
* Header (1-RTT, used once the connection is established). This header structures the LONG header only:
|
|
15
|
+
*
|
|
16
|
+
* first byte = Header Form(1) | Fixed Bit(1) | Long Packet Type(2) | type-specific(4)
|
|
17
|
+
* Version(4) | DCID Len(1) | DCID(DCID Len) | SCID Len(1) | SCID(SCID Len) | ...rest
|
|
18
|
+
*
|
|
19
|
+
* Everything after the Source Connection ID (token / length / packet number / frames) is protected by
|
|
20
|
+
* QUIC header protection + AEAD encryption, so it is kept verbatim as an opaque `payload` hex (bounded
|
|
21
|
+
* by the UDP payload) — this is a best-effort structural slice, not a decryptor. The one exception is
|
|
22
|
+
* Version Negotiation (Version == 0, RFC 9000 §17.2.1): its body is an unencrypted list of 4-byte
|
|
23
|
+
* Supported Versions, decoded into `supportedVersions`.
|
|
24
|
+
*
|
|
25
|
+
* The Short Header (MSB clear) is deliberately NOT recognized by the content heuristic — its first byte
|
|
26
|
+
* is an almost signature-free value, so heuristic matching would over-claim ordinary UDP traffic; it is
|
|
27
|
+
* left to later enrichment / RawData. The connection-ID length fields are honored when supplied else
|
|
28
|
+
* derived from the ID bytes; the type-specific bits and all opaque bytes round-trip byte-for-byte.
|
|
29
|
+
*/
|
|
30
|
+
class QUIC extends BaseHeader_1.BaseHeader {
|
|
31
|
+
constructor() {
|
|
32
|
+
super(...arguments);
|
|
33
|
+
this.id = 'quic';
|
|
34
|
+
this.name = 'QUIC Transport';
|
|
35
|
+
this.nickname = 'QUIC';
|
|
36
|
+
//Bucketed on the common HTTP/3 port; heuristicFallback keeps it recognized on any other UDP port via
|
|
37
|
+
//its long-header + known-version signature (QUIC is used on many ports).
|
|
38
|
+
this.matchKeys = ['udpport:443'];
|
|
39
|
+
this.heuristicFallback = true;
|
|
40
|
+
//A leaf header — the payload is AEAD-encrypted and kept verbatim (no inner demux).
|
|
41
|
+
this.demuxProducers = [];
|
|
42
|
+
}
|
|
43
|
+
static #schemaCache;
|
|
44
|
+
get SCHEMA() {
|
|
45
|
+
return (QUIC.#schemaCache ??= QUIC.#buildSchema());
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Bytes available to this QUIC packet, bounded by the enclosing UDP payload (udp.length - 8) so a
|
|
49
|
+
* lying connection-ID length near the end of the datagram cannot read into trailing bytes, and so the
|
|
50
|
+
* opaque payload stops at the datagram boundary rather than swallowing the whole captured buffer.
|
|
51
|
+
*/
|
|
52
|
+
#available() {
|
|
53
|
+
let available = this.packet.length - this.startPos;
|
|
54
|
+
const prev = this.prevCodecModule;
|
|
55
|
+
if (prev && prev.id === 'udp') {
|
|
56
|
+
const udpPayload = prev.instance.length.getValue(0) - 8;
|
|
57
|
+
if (udpPayload >= 0 && udpPayload < available)
|
|
58
|
+
available = udpPayload;
|
|
59
|
+
}
|
|
60
|
+
return available < 0 ? 0 : available;
|
|
61
|
+
}
|
|
62
|
+
/** Absolute (header-relative) offset of the SCID Length octet = 6 + DCID Len. */
|
|
63
|
+
#scidLengthOffset() {
|
|
64
|
+
return 6 + this.instance.dcidLength.getValue(0);
|
|
65
|
+
}
|
|
66
|
+
/** Absolute (header-relative) offset of the bytes following the SCID = 7 + DCID Len + SCID Len. */
|
|
67
|
+
#tailOffset() {
|
|
68
|
+
return 7 + this.instance.dcidLength.getValue(0) + this.instance.scidLength.getValue(0);
|
|
69
|
+
}
|
|
70
|
+
/** A single flag bit within the first byte (bit 0 = MSB). */
|
|
71
|
+
static #flagBit(name, bitOffset, label) {
|
|
72
|
+
return {
|
|
73
|
+
type: 'boolean',
|
|
74
|
+
label: label,
|
|
75
|
+
decode: function () {
|
|
76
|
+
this.instance.firstByte[name].setValue(!!this.readBits(0, 1, bitOffset, 1));
|
|
77
|
+
},
|
|
78
|
+
encode: function () {
|
|
79
|
+
const value = !!this.instance.firstByte[name].getValue();
|
|
80
|
+
this.instance.firstByte[name].setValue(value);
|
|
81
|
+
this.writeBits(0, 1, bitOffset, 1, value ? 1 : 0);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** An unsigned integer packed into `bitLength` bits of the first byte at `bitOffset` (MSB-first). */
|
|
86
|
+
static #uintBits(name, bitOffset, bitLength, label) {
|
|
87
|
+
const maximum = (1 << bitLength) - 1;
|
|
88
|
+
return {
|
|
89
|
+
type: 'integer',
|
|
90
|
+
label: label,
|
|
91
|
+
minimum: 0,
|
|
92
|
+
maximum: maximum,
|
|
93
|
+
decode: function () {
|
|
94
|
+
this.instance.firstByte[name].setValue(this.readBits(0, 1, bitOffset, bitLength));
|
|
95
|
+
},
|
|
96
|
+
encode: function () {
|
|
97
|
+
const node = this.instance.firstByte[name];
|
|
98
|
+
let value = node.getValue(0);
|
|
99
|
+
if (value > maximum)
|
|
100
|
+
value = maximum;
|
|
101
|
+
if (value < 0)
|
|
102
|
+
value = 0;
|
|
103
|
+
node.setValue(value);
|
|
104
|
+
this.writeBits(0, 1, bitOffset, bitLength, value);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
static #buildSchema() {
|
|
109
|
+
return {
|
|
110
|
+
type: 'object',
|
|
111
|
+
summary: 'QUIC v=${version} type=${firstByte.longPacketType}',
|
|
112
|
+
properties: {
|
|
113
|
+
//First byte: Header Form(bit0) | Fixed Bit(bit1) | Long Packet Type(bits2-3) |
|
|
114
|
+
//type-specific(bits4-7). For Initial/0-RTT/Handshake the low 4 bits are Reserved(2) +
|
|
115
|
+
//Packet Number Length(2) but they are masked by header protection on the wire, so they are
|
|
116
|
+
//kept verbatim as a single opaque 4-bit field (Retry has no such split).
|
|
117
|
+
firstByte: {
|
|
118
|
+
type: 'object',
|
|
119
|
+
label: 'First Byte',
|
|
120
|
+
properties: {
|
|
121
|
+
headerForm: this.#flagBit('headerForm', 0, 'Header Form (1=Long)'),
|
|
122
|
+
fixedBit: this.#flagBit('fixedBit', 1, 'Fixed Bit'),
|
|
123
|
+
longPacketType: this.#uintBits('longPacketType', 2, 2, 'Long Packet Type'),
|
|
124
|
+
typeSpecificBits: this.#uintBits('typeSpecificBits', 4, 4, 'Type-Specific Bits')
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
//Version — 0x00000001 = QUIC v1 (RFC 9000), 0x6b3343cf = v2 (RFC 9369), 0xff0000xx = IETF
|
|
128
|
+
//drafts, 0x00000000 = Version Negotiation. Kept as a lower-case hex string so any value
|
|
129
|
+
//round-trips verbatim and the field is unbounded (the match gate restricts real selection).
|
|
130
|
+
version: this.fieldHex('version', 1, 4, 'Version'),
|
|
131
|
+
//Destination Connection ID length (0..20 per RFC 9000, but any 0..255 round-trips). Honored
|
|
132
|
+
//when supplied, else derived from the DCID bytes.
|
|
133
|
+
dcidLength: {
|
|
134
|
+
type: 'integer',
|
|
135
|
+
label: 'DCID Length',
|
|
136
|
+
minimum: 0,
|
|
137
|
+
maximum: 255,
|
|
138
|
+
decode: function () {
|
|
139
|
+
this.instance.dcidLength.setValue((0, BufferToNumber_1.BufferToUInt8)(this.readBytes(5, 1)));
|
|
140
|
+
},
|
|
141
|
+
encode: function () {
|
|
142
|
+
const provided = this.instance.dcidLength.getValue();
|
|
143
|
+
let value = (provided !== undefined && provided !== null)
|
|
144
|
+
? provided
|
|
145
|
+
: (0, HexToBuffer_1.HexToBuffer)(this.instance.dcid.getValue('')).length;
|
|
146
|
+
if (value > 255)
|
|
147
|
+
value = 255;
|
|
148
|
+
if (value < 0)
|
|
149
|
+
value = 0;
|
|
150
|
+
this.instance.dcidLength.setValue(value);
|
|
151
|
+
this.writeBytes(5, (0, NumberToBuffer_1.UInt8ToBuffer)(value));
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
//Destination Connection ID, kept verbatim. Bounded by DCID Len and the UDP payload.
|
|
155
|
+
dcid: {
|
|
156
|
+
type: 'string',
|
|
157
|
+
label: 'Destination Connection ID',
|
|
158
|
+
contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX,
|
|
159
|
+
decode: function () {
|
|
160
|
+
const dcidLength = this.instance.dcidLength.getValue(0);
|
|
161
|
+
this.instance.dcid.setValue(dcidLength > 0 ? (0, BufferToHex_1.BufferToHex)(this.readBytes(6, dcidLength)) : '');
|
|
162
|
+
},
|
|
163
|
+
encode: function () {
|
|
164
|
+
const dcid = this.instance.dcid.getValue('');
|
|
165
|
+
if (dcid)
|
|
166
|
+
this.writeBytes(6, (0, HexToBuffer_1.HexToBuffer)(dcid));
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
//Source Connection ID length. Offset is dynamic (after the DCID). Honored else derived.
|
|
170
|
+
scidLength: {
|
|
171
|
+
type: 'integer',
|
|
172
|
+
label: 'SCID Length',
|
|
173
|
+
minimum: 0,
|
|
174
|
+
maximum: 255,
|
|
175
|
+
decode: function () {
|
|
176
|
+
this.instance.scidLength.setValue((0, BufferToNumber_1.BufferToUInt8)(this.readBytes(this.#scidLengthOffset(), 1)));
|
|
177
|
+
},
|
|
178
|
+
encode: function () {
|
|
179
|
+
const provided = this.instance.scidLength.getValue();
|
|
180
|
+
let value = (provided !== undefined && provided !== null)
|
|
181
|
+
? provided
|
|
182
|
+
: (0, HexToBuffer_1.HexToBuffer)(this.instance.scid.getValue('')).length;
|
|
183
|
+
if (value > 255)
|
|
184
|
+
value = 255;
|
|
185
|
+
if (value < 0)
|
|
186
|
+
value = 0;
|
|
187
|
+
this.instance.scidLength.setValue(value);
|
|
188
|
+
this.writeBytes(this.#scidLengthOffset(), (0, NumberToBuffer_1.UInt8ToBuffer)(value));
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
//Source Connection ID, kept verbatim. Offset is dynamic (after the SCID Length octet).
|
|
192
|
+
scid: {
|
|
193
|
+
type: 'string',
|
|
194
|
+
label: 'Source Connection ID',
|
|
195
|
+
contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX,
|
|
196
|
+
decode: function () {
|
|
197
|
+
const scidLength = this.instance.scidLength.getValue(0);
|
|
198
|
+
const offset = this.#scidLengthOffset() + 1;
|
|
199
|
+
this.instance.scid.setValue(scidLength > 0 ? (0, BufferToHex_1.BufferToHex)(this.readBytes(offset, scidLength)) : '');
|
|
200
|
+
},
|
|
201
|
+
encode: function () {
|
|
202
|
+
const scid = this.instance.scid.getValue('');
|
|
203
|
+
if (scid)
|
|
204
|
+
this.writeBytes(this.#scidLengthOffset() + 1, (0, HexToBuffer_1.HexToBuffer)(scid));
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
//Version Negotiation only (Version == 0): an unencrypted list of 4-byte Supported Versions
|
|
208
|
+
//(RFC 9000 §17.2.1). Empty for every other packet type — mutually exclusive with `payload`.
|
|
209
|
+
supportedVersions: {
|
|
210
|
+
type: 'array',
|
|
211
|
+
label: 'Supported Versions',
|
|
212
|
+
items: {
|
|
213
|
+
type: 'string',
|
|
214
|
+
label: 'Version',
|
|
215
|
+
contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX
|
|
216
|
+
},
|
|
217
|
+
decode: function () {
|
|
218
|
+
const version = this.instance.version.getValue('');
|
|
219
|
+
if (version !== '00000000') {
|
|
220
|
+
this.instance.supportedVersions.setValue([]);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const available = this.#available();
|
|
224
|
+
const versions = [];
|
|
225
|
+
let offset = this.#tailOffset();
|
|
226
|
+
//Each Supported Version is exactly 4 bytes; stop at the datagram boundary. offset
|
|
227
|
+
//advances by 4 each turn so the loop always terminates.
|
|
228
|
+
while (offset + 4 <= available) {
|
|
229
|
+
versions.push((0, BufferToHex_1.BufferToHex)(this.readBytes(offset, 4)));
|
|
230
|
+
offset += 4;
|
|
231
|
+
}
|
|
232
|
+
this.instance.supportedVersions.setValue(versions);
|
|
233
|
+
},
|
|
234
|
+
encode: function () {
|
|
235
|
+
const version = this.instance.version.getValue('');
|
|
236
|
+
if (version !== '00000000')
|
|
237
|
+
return;
|
|
238
|
+
const versions = this.instance.supportedVersions.getValue();
|
|
239
|
+
if (!versions)
|
|
240
|
+
return;
|
|
241
|
+
let offset = this.#tailOffset();
|
|
242
|
+
versions.forEach((version) => {
|
|
243
|
+
//Each entry is sized to 4 bytes: extra dropped, short zero-padded — a
|
|
244
|
+
//Supported Version is a fixed 32-bit value.
|
|
245
|
+
this.writeBytes(offset, (0, HexToBuffer_1.HexToBuffer)(version ? version : '', 4));
|
|
246
|
+
offset += 4;
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
//Everything after the SCID for a normal (non-VN) packet: token / length / packet number /
|
|
251
|
+
//encrypted frames — kept verbatim (AEAD + header protection, not decryptable here).
|
|
252
|
+
//Bounded by the UDP payload so a trailing datagram is left to the codec's recursion.
|
|
253
|
+
payload: {
|
|
254
|
+
type: 'string',
|
|
255
|
+
label: 'Payload',
|
|
256
|
+
contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX,
|
|
257
|
+
decode: function () {
|
|
258
|
+
const version = this.instance.version.getValue('');
|
|
259
|
+
if (version === '00000000') {
|
|
260
|
+
this.instance.payload.setValue('');
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const available = this.#available();
|
|
264
|
+
const offset = this.#tailOffset();
|
|
265
|
+
this.instance.payload.setValue(offset < available ? (0, BufferToHex_1.BufferToHex)(this.readBytes(offset, available - offset)) : '');
|
|
266
|
+
},
|
|
267
|
+
encode: function () {
|
|
268
|
+
const version = this.instance.version.getValue('');
|
|
269
|
+
if (version === '00000000')
|
|
270
|
+
return;
|
|
271
|
+
const payload = this.instance.payload.getValue('');
|
|
272
|
+
if (payload)
|
|
273
|
+
this.writeBytes(this.#tailOffset(), (0, HexToBuffer_1.HexToBuffer)(payload));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
/** True when the enclosing UDP source or destination port is the well-known QUIC port. */
|
|
280
|
+
#onQuicPort() {
|
|
281
|
+
const prev = this.prevCodecModule;
|
|
282
|
+
return prev.instance.srcport.getValue(0) === 443 || prev.instance.dstport.getValue(0) === 443;
|
|
283
|
+
}
|
|
284
|
+
match() {
|
|
285
|
+
//QUIC rides UDP. Require the minimal long header (first byte + version + two length octets = 7
|
|
286
|
+
//bytes) within the UDP payload, the Long Header form bit set, and — the strong part — a KNOWN
|
|
287
|
+
//QUIC version. Short headers (MSB clear) and unknown versions are NOT heuristically claimed, so
|
|
288
|
+
//ordinary UDP traffic falls through to raw. Version Negotiation (version 0) is a weak signature,
|
|
289
|
+
//so it is only accepted on the well-known QUIC port bucket, never off-port via the heuristic.
|
|
290
|
+
if (!this.prevCodecModule || this.prevCodecModule.id !== 'udp')
|
|
291
|
+
return false;
|
|
292
|
+
if (this.#available() < 7)
|
|
293
|
+
return false;
|
|
294
|
+
if ((this.readBytes(0, 1, true)[0] & 0x80) === 0)
|
|
295
|
+
return false;
|
|
296
|
+
const version = (0, BufferToNumber_1.BufferToUInt32)(this.readBytes(1, 4, true));
|
|
297
|
+
if (version === 0x00000001)
|
|
298
|
+
return true;
|
|
299
|
+
if (version === 0x6b3343cf)
|
|
300
|
+
return true;
|
|
301
|
+
if ((version >>> 8) === 0xff0000)
|
|
302
|
+
return true;
|
|
303
|
+
if (version === 0)
|
|
304
|
+
return this.#onQuicPort();
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
exports.QUIC = QUIC;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BaseHeader } from '../abstracts/BaseHeader';
|
|
2
|
+
import { ProtocolJSONSchema } from '../schema/ProtocolJSONSchema';
|
|
3
|
+
import { DemuxProducer } from '../types/DemuxProducer';
|
|
4
|
+
/**
|
|
5
|
+
* RADIUS — Remote Authentication Dial-In User Service (RFC 2865 auth / RFC 2866 accounting), UDP ports
|
|
6
|
+
* 1812 (auth) and 1813 (accounting). A 20-byte fixed header — Code, Identifier, Length (the whole
|
|
7
|
+
* packet), and a 16-byte Authenticator — followed by attributes (AVPs) in Type-Length-Value form:
|
|
8
|
+
* type(1) + length(1, counts the type+length+value) + value(length-2).
|
|
9
|
+
*
|
|
10
|
+
* Attributes are carried generically (type + verbatim hex value) so every attribute — including
|
|
11
|
+
* Vendor-Specific (26) whose value nests sub-AVPs — round-trips byte-for-byte; per-attribute semantic
|
|
12
|
+
* decoding is a later enrichment. The AVP walk is bounded by the RADIUS Length (and the UDP payload),
|
|
13
|
+
* so any trailing padding/FCS spills to the raw layer.
|
|
14
|
+
*/
|
|
15
|
+
export declare class RADIUS extends BaseHeader {
|
|
16
|
+
#private;
|
|
17
|
+
get SCHEMA(): ProtocolJSONSchema;
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly nickname: string;
|
|
21
|
+
readonly matchKeys: string[];
|
|
22
|
+
match(): boolean;
|
|
23
|
+
readonly demuxProducers: DemuxProducer[];
|
|
24
|
+
}
|