@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,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NFS = 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
|
+
* Network File System (NFS, RFC 1813 v3 / RFC 7530 v4), TCP + UDP port 2049. NFS is carried inside an
|
|
12
|
+
* ONC RPC (RFC 5531) message, so on the wire an NFS packet is a plain RPC message: a 4-byte XID followed
|
|
13
|
+
* by a 4-byte Message Type (0 CALL, 1 REPLY). A CALL body continues with the RPC version (== 2), the
|
|
14
|
+
* program number (NFS = 100003), the program version, the procedure, then the credential + verifier auth
|
|
15
|
+
* structures and the NFS procedure arguments. NFS parses this RPC envelope itself at its 2049 port bucket
|
|
16
|
+
* (it does not depend on the SunRPC header, which is scoped to the portmapper's port 111).
|
|
17
|
+
*
|
|
18
|
+
* Transport framing differs by L4 (RFC 5531 §11): over UDP the RPC message is the whole datagram; over
|
|
19
|
+
* TCP a 4-byte Record Marking prefix precedes it — the high bit is the last-fragment flag and the low 31
|
|
20
|
+
* bits are the fragment length. This header detects the transport via prevCodecModule.id and structures
|
|
21
|
+
* accordingly: TCP → recordMark (lastFragment + fragmentLength) then the message at offset 4; UDP → the
|
|
22
|
+
* message directly at offset 0.
|
|
23
|
+
*
|
|
24
|
+
* Byte-perfect strategy (minimal slice): structure the XID and Message Type, and for a CALL the four
|
|
25
|
+
* fixed program-identity words (rpcVersion / program / programVersion / procedure); the remainder — the
|
|
26
|
+
* credential, verifier and NFS procedure arguments for a CALL, or the whole REPLY body — is kept verbatim
|
|
27
|
+
* as `body` hex, bounded by the transport payload (UDP length − 8, or the TCP Record Marking fragment
|
|
28
|
+
* length). The TCP fragmentLength is honored when supplied (a crafted frame may lie) else derived as the
|
|
29
|
+
* encoded message length; a well-formed message round-trips byte-for-byte. Trailing / pipelined bytes are
|
|
30
|
+
* left to the codec's recursion / RawData. Sub-decoding the per-procedure NFS argument/reply structures
|
|
31
|
+
* (GETATTR fh, LOOKUP dir+name, READ/WRITE, …) is a later enrichment.
|
|
32
|
+
*/
|
|
33
|
+
class NFS extends BaseHeader_1.BaseHeader {
|
|
34
|
+
constructor() {
|
|
35
|
+
super(...arguments);
|
|
36
|
+
this.id = 'nfs';
|
|
37
|
+
this.name = 'Network File System';
|
|
38
|
+
this.nickname = 'NFS';
|
|
39
|
+
//NFS ports 2049 on both TCP and UDP.
|
|
40
|
+
this.matchKeys = ['tcpport:2049', 'udpport:2049'];
|
|
41
|
+
//A leaf header — the credential / verifier / NFS arguments / REPLY body are kept verbatim for now.
|
|
42
|
+
this.demuxProducers = [];
|
|
43
|
+
}
|
|
44
|
+
static #schemaCache;
|
|
45
|
+
get SCHEMA() {
|
|
46
|
+
return (NFS.#schemaCache ??= NFS.#buildSchema());
|
|
47
|
+
}
|
|
48
|
+
/** True when this RPC message rides on TCP (a 4-byte Record Marking prefix precedes the message). */
|
|
49
|
+
#isTcp() {
|
|
50
|
+
return !!this.prevCodecModule && this.prevCodecModule.id === 'tcp';
|
|
51
|
+
}
|
|
52
|
+
/** Offset of the RPC message within this header: 4 bytes past startPos for TCP, 0 for UDP. */
|
|
53
|
+
#messageOffset() {
|
|
54
|
+
return this.#isTcp() ? 4 : 0;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Header-relative end offset of the bytes this NFS layer consumes, so a lying length never reads past
|
|
58
|
+
* the real transport payload and trailing / pipelined data is left to the codec. Over UDP the bound
|
|
59
|
+
* is (udp.length − 8); over TCP it is 4 (Record Marking) + the fragment length carried in that
|
|
60
|
+
* prefix; both clamped to the captured bytes.
|
|
61
|
+
*/
|
|
62
|
+
#payloadEnd() {
|
|
63
|
+
let end = this.packet.length - this.startPos;
|
|
64
|
+
const prev = this.prevCodecModule;
|
|
65
|
+
if (prev && prev.id === 'udp') {
|
|
66
|
+
const udpLength = prev.instance.length.getValue(0);
|
|
67
|
+
if (udpLength >= 8 && udpLength - 8 < end)
|
|
68
|
+
end = udpLength - 8;
|
|
69
|
+
}
|
|
70
|
+
else if (prev && prev.id === 'tcp') {
|
|
71
|
+
const word = (0, BufferToNumber_1.BufferToUInt32)(this.readBytes(0, 4, true));
|
|
72
|
+
const fragmentLength = (word & 0x7fffffff) >>> 0;
|
|
73
|
+
const total = 4 + fragmentLength;
|
|
74
|
+
if (total < end)
|
|
75
|
+
end = total;
|
|
76
|
+
}
|
|
77
|
+
return end < 0 ? 0 : end;
|
|
78
|
+
}
|
|
79
|
+
/** A 4-byte big-endian unsigned integer at the RPC-message offset + `wordOffset`, only for a CALL. */
|
|
80
|
+
static #callWord(name, wordOffset, label) {
|
|
81
|
+
return {
|
|
82
|
+
type: 'integer',
|
|
83
|
+
label: label,
|
|
84
|
+
minimum: 0,
|
|
85
|
+
maximum: 4294967295,
|
|
86
|
+
decode: function () {
|
|
87
|
+
if (this.instance.msgType.getValue(0) !== 0)
|
|
88
|
+
return;
|
|
89
|
+
const offset = this.#messageOffset() + wordOffset;
|
|
90
|
+
if (this.#payloadEnd() < offset + 4)
|
|
91
|
+
return;
|
|
92
|
+
this.instance[name].setValue((0, BufferToNumber_1.BufferToUInt32)(this.readBytes(offset, 4)));
|
|
93
|
+
},
|
|
94
|
+
encode: function () {
|
|
95
|
+
if (this.instance.msgType.getValue(0) !== 0)
|
|
96
|
+
return;
|
|
97
|
+
const node = this.instance[name];
|
|
98
|
+
let value = node.getValue(0, (nodePath) => this.recordError(nodePath, 'Not Found'));
|
|
99
|
+
if (value > 4294967295) {
|
|
100
|
+
this.recordError(node.getPath(), 'Maximum value is 4294967295');
|
|
101
|
+
value = 4294967295;
|
|
102
|
+
}
|
|
103
|
+
if (value < 0) {
|
|
104
|
+
this.recordError(node.getPath(), 'Minimum value is 0');
|
|
105
|
+
value = 0;
|
|
106
|
+
}
|
|
107
|
+
node.setValue(value);
|
|
108
|
+
this.writeBytes(this.#messageOffset() + wordOffset, (0, NumberToBuffer_1.UInt32ToBuffer)(value));
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
static #buildSchema() {
|
|
113
|
+
return {
|
|
114
|
+
type: 'object',
|
|
115
|
+
summary: 'NFS xid=${xid} type=${msgType}',
|
|
116
|
+
properties: {
|
|
117
|
+
//==== TCP-only Record Marking prefix (RFC 5531 §11) ====
|
|
118
|
+
//The 4-byte word's high bit is the last-fragment flag; the low 31 bits are the fragment
|
|
119
|
+
//length (message bytes that follow). Absent over UDP. The 4-byte word is written together
|
|
120
|
+
//by fragmentLength (colocated) so the flag and length stay a single field on the wire.
|
|
121
|
+
lastFragment: {
|
|
122
|
+
type: 'boolean',
|
|
123
|
+
label: 'Last Fragment',
|
|
124
|
+
decode: function () {
|
|
125
|
+
if (!this.#isTcp())
|
|
126
|
+
return;
|
|
127
|
+
this.instance.lastFragment.setValue(!!this.readBits(0, 1, 0, 1));
|
|
128
|
+
},
|
|
129
|
+
encode: function () {
|
|
130
|
+
//Display only; the combined 4-byte word is emitted by fragmentLength below.
|
|
131
|
+
if (!this.#isTcp())
|
|
132
|
+
return;
|
|
133
|
+
this.instance.lastFragment.setValue(!!this.instance.lastFragment.getValue(true));
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
fragmentLength: {
|
|
137
|
+
type: 'integer',
|
|
138
|
+
label: 'Fragment Length',
|
|
139
|
+
minimum: 0,
|
|
140
|
+
maximum: 2147483647,
|
|
141
|
+
decode: function () {
|
|
142
|
+
if (!this.#isTcp())
|
|
143
|
+
return;
|
|
144
|
+
const word = (0, BufferToNumber_1.BufferToUInt32)(this.readBytes(0, 4));
|
|
145
|
+
this.instance.fragmentLength.setValue((word & 0x7fffffff) >>> 0);
|
|
146
|
+
},
|
|
147
|
+
encode: function () {
|
|
148
|
+
if (!this.#isTcp())
|
|
149
|
+
return;
|
|
150
|
+
const last = !!this.instance.lastFragment.getValue(true);
|
|
151
|
+
const provided = this.instance.fragmentLength.getValue();
|
|
152
|
+
if (provided !== undefined && provided !== null) {
|
|
153
|
+
//Honored verbatim (a crafted frame may lie about the fragment length).
|
|
154
|
+
let value = provided;
|
|
155
|
+
if (value > 2147483647) {
|
|
156
|
+
this.recordError(this.instance.fragmentLength.getPath(), 'Maximum value is 2147483647');
|
|
157
|
+
value = 2147483647;
|
|
158
|
+
}
|
|
159
|
+
if (value < 0) {
|
|
160
|
+
this.recordError(this.instance.fragmentLength.getPath(), 'Minimum value is 0');
|
|
161
|
+
value = 0;
|
|
162
|
+
}
|
|
163
|
+
this.instance.fragmentLength.setValue(value);
|
|
164
|
+
this.writeBytes(0, (0, NumberToBuffer_1.UInt32ToBuffer)(((last ? 0x80000000 : 0) + value) >>> 0));
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
//Derive after the message bytes are written: the fragment length counts exactly
|
|
168
|
+
//the RPC message (everything after this 4-byte prefix).
|
|
169
|
+
this.writeBytes(0, (0, NumberToBuffer_1.UInt32ToBuffer)(last ? 0x80000000 : 0));
|
|
170
|
+
this.addPostSelfEncodeHandler(() => {
|
|
171
|
+
const messageLength = this.headerLength - 4;
|
|
172
|
+
const value = messageLength > 0 ? messageLength : 0;
|
|
173
|
+
this.instance.fragmentLength.setValue(value);
|
|
174
|
+
this.writeBytes(0, (0, NumberToBuffer_1.UInt32ToBuffer)(((last ? 0x80000000 : 0) + value) >>> 0));
|
|
175
|
+
}, 0);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
//==== RPC message (RFC 5531 §9) ====
|
|
180
|
+
//The transaction id — an opaque 4-byte value a caller matches its REPLY to, kept as hex.
|
|
181
|
+
xid: {
|
|
182
|
+
type: 'string',
|
|
183
|
+
label: 'XID',
|
|
184
|
+
contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX,
|
|
185
|
+
decode: function () {
|
|
186
|
+
const offset = this.#messageOffset();
|
|
187
|
+
if (this.#payloadEnd() < offset + 4)
|
|
188
|
+
return;
|
|
189
|
+
this.instance.xid.setValue((0, BufferToHex_1.BufferToHex)(this.readBytes(offset, 4)));
|
|
190
|
+
},
|
|
191
|
+
encode: function () {
|
|
192
|
+
this.writeBytes(this.#messageOffset(), (0, HexToBuffer_1.HexToBuffer)(this.instance.xid.getValue('00000000')));
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
//0 = CALL, 1 = REPLY. Drives whether the fixed CALL identity words are structured below.
|
|
196
|
+
msgType: {
|
|
197
|
+
type: 'integer',
|
|
198
|
+
label: 'Message Type',
|
|
199
|
+
minimum: 0,
|
|
200
|
+
maximum: 4294967295,
|
|
201
|
+
decode: function () {
|
|
202
|
+
const offset = this.#messageOffset() + 4;
|
|
203
|
+
if (this.#payloadEnd() < offset + 4)
|
|
204
|
+
return;
|
|
205
|
+
this.instance.msgType.setValue((0, BufferToNumber_1.BufferToUInt32)(this.readBytes(offset, 4)));
|
|
206
|
+
},
|
|
207
|
+
encode: function () {
|
|
208
|
+
const node = this.instance.msgType;
|
|
209
|
+
let value = node.getValue(0, (nodePath) => this.recordError(nodePath, 'Not Found'));
|
|
210
|
+
if (value > 4294967295) {
|
|
211
|
+
this.recordError(node.getPath(), 'Maximum value is 4294967295');
|
|
212
|
+
value = 4294967295;
|
|
213
|
+
}
|
|
214
|
+
if (value < 0) {
|
|
215
|
+
this.recordError(node.getPath(), 'Minimum value is 0');
|
|
216
|
+
value = 0;
|
|
217
|
+
}
|
|
218
|
+
node.setValue(value);
|
|
219
|
+
this.writeBytes(this.#messageOffset() + 4, (0, NumberToBuffer_1.UInt32ToBuffer)(value));
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
//==== CALL identity (RFC 5531 §9, decoded only for msgType == 0) ====
|
|
223
|
+
//For NFS the program word is 100003; kept as a plain unbounded-in-practice uint (honored
|
|
224
|
+
//verbatim) rather than a hard enum so any value round-trips (never-throws contract).
|
|
225
|
+
rpcVersion: this.#callWord('rpcVersion', 8, 'RPC Version'),
|
|
226
|
+
program: this.#callWord('program', 12, 'Program'),
|
|
227
|
+
programVersion: this.#callWord('programVersion', 16, 'Program Version'),
|
|
228
|
+
procedure: this.#callWord('procedure', 20, 'Procedure'),
|
|
229
|
+
//The remainder kept verbatim: for a CALL the credential + verifier + NFS procedure
|
|
230
|
+
//arguments (from message offset 24); for a REPLY / other the whole body (from message
|
|
231
|
+
//offset 8). Bounded by #payloadEnd so a lying length can't read past the transport payload.
|
|
232
|
+
body: {
|
|
233
|
+
type: 'string',
|
|
234
|
+
label: 'Body',
|
|
235
|
+
contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX,
|
|
236
|
+
decode: function () {
|
|
237
|
+
const isCall = this.instance.msgType.getValue(0) === 0;
|
|
238
|
+
const start = this.#messageOffset() + (isCall ? 24 : 8);
|
|
239
|
+
const end = this.#payloadEnd();
|
|
240
|
+
this.instance.body.setValue(end > start ? (0, BufferToHex_1.BufferToHex)(this.readBytes(start, end - start)) : '');
|
|
241
|
+
},
|
|
242
|
+
encode: function () {
|
|
243
|
+
const isCall = this.instance.msgType.getValue(0) === 0;
|
|
244
|
+
const start = this.#messageOffset() + (isCall ? 24 : 8);
|
|
245
|
+
const body = this.instance.body.getValue('');
|
|
246
|
+
if (body)
|
|
247
|
+
this.writeBytes(start, (0, HexToBuffer_1.HexToBuffer)(body));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
match() {
|
|
254
|
+
//NFS rides UDP/TCP port 2049 (selected via the udpport:2049 / tcpport:2049 buckets). This stays a
|
|
255
|
+
//port-bucket protocol: matchKeys only, NO heuristicFallback — the signature (XID + a Message Type
|
|
256
|
+
//of 0 or 1) is too weak to claim NFS/RPC off port 2049, and non-RPC traffic on 2049 must fall
|
|
257
|
+
//through to raw. Over TCP the message sits after the 4-byte Record Marking prefix; over UDP it is
|
|
258
|
+
//the first byte. Require the fixed XID + Message Type within the transport payload and a valid
|
|
259
|
+
//Message Type.
|
|
260
|
+
if (!this.prevCodecModule)
|
|
261
|
+
return false;
|
|
262
|
+
const isTcp = this.prevCodecModule.id === 'tcp';
|
|
263
|
+
const isUdp = this.prevCodecModule.id === 'udp';
|
|
264
|
+
if (!isTcp && !isUdp)
|
|
265
|
+
return false;
|
|
266
|
+
const offset = isTcp ? 4 : 0;
|
|
267
|
+
if (this.#payloadEnd() < offset + 8)
|
|
268
|
+
return false;
|
|
269
|
+
const msgType = (0, BufferToNumber_1.BufferToUInt32)(this.readBytes(offset + 4, 4, true));
|
|
270
|
+
return msgType === 0 || msgType === 1;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
exports.NFS = NFS;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BaseHeader } from '../abstracts/BaseHeader';
|
|
2
|
+
import { ProtocolJSONSchema } from '../schema/ProtocolJSONSchema';
|
|
3
|
+
import { DemuxProducer } from '../types/DemuxProducer';
|
|
4
|
+
/**
|
|
5
|
+
* NHRP — NBMA Next Hop Resolution Protocol (RFC 2332), carried directly over IP as protocol 54. Every
|
|
6
|
+
* NHRP packet opens with a 20-byte Fixed Header — ar$afn (Address Family Number of the NBMA network),
|
|
7
|
+
* ar$pro.type + ar$pro.snap (the protocol whose next hop is being resolved, an EtherType plus an
|
|
8
|
+
* optional SNAP), ar$hopcnt, ar$pktsz (the total NHRP packet length), ar$chksum (an IP-style
|
|
9
|
+
* ones-complement checksum over the whole NHRP packet), ar$extoff (offset to the first extension), the
|
|
10
|
+
* op.version / op.type opcode (1 Resolution Request, 2 Resolution Reply, 3 Registration Request,
|
|
11
|
+
* 4 Registration Reply, 5 Purge Request, 6 Purge Reply, 7 Error Indication), and ar$shtl / ar$sstl
|
|
12
|
+
* (the source NBMA address / subaddress type+length) — followed by the type-specific Mandatory Part and
|
|
13
|
+
* any Extensions.
|
|
14
|
+
*
|
|
15
|
+
* The Mandatory Part and Extensions are opcode-dependent, variable-length (their sub-address lengths are
|
|
16
|
+
* driven by ar$shtl and the per-entry CIE type/length octets) and carry cross-field context, so this
|
|
17
|
+
* codec keeps them verbatim as `body` hex (byte-perfect) and does not sub-decode them. Packet Length is
|
|
18
|
+
* auto-computed from the body on encode when not supplied, else honored verbatim (a crafted packet may
|
|
19
|
+
* lie); the checksum is honored verbatim, never recomputed (encode is a faithful executor). The body is
|
|
20
|
+
* bounded by both Packet Length and the enclosing IP payload, so trailing bytes are left to the codec's
|
|
21
|
+
* recursion / RawData. A well-formed packet round-trips byte-for-byte.
|
|
22
|
+
*/
|
|
23
|
+
export declare class NHRP extends BaseHeader {
|
|
24
|
+
#private;
|
|
25
|
+
get SCHEMA(): ProtocolJSONSchema;
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly nickname: string;
|
|
29
|
+
readonly matchKeys: string[];
|
|
30
|
+
match(): boolean;
|
|
31
|
+
readonly demuxProducers: DemuxProducer[];
|
|
32
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NHRP = 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
|
+
* NHRP — NBMA Next Hop Resolution Protocol (RFC 2332), carried directly over IP as protocol 54. Every
|
|
12
|
+
* NHRP packet opens with a 20-byte Fixed Header — ar$afn (Address Family Number of the NBMA network),
|
|
13
|
+
* ar$pro.type + ar$pro.snap (the protocol whose next hop is being resolved, an EtherType plus an
|
|
14
|
+
* optional SNAP), ar$hopcnt, ar$pktsz (the total NHRP packet length), ar$chksum (an IP-style
|
|
15
|
+
* ones-complement checksum over the whole NHRP packet), ar$extoff (offset to the first extension), the
|
|
16
|
+
* op.version / op.type opcode (1 Resolution Request, 2 Resolution Reply, 3 Registration Request,
|
|
17
|
+
* 4 Registration Reply, 5 Purge Request, 6 Purge Reply, 7 Error Indication), and ar$shtl / ar$sstl
|
|
18
|
+
* (the source NBMA address / subaddress type+length) — followed by the type-specific Mandatory Part and
|
|
19
|
+
* any Extensions.
|
|
20
|
+
*
|
|
21
|
+
* The Mandatory Part and Extensions are opcode-dependent, variable-length (their sub-address lengths are
|
|
22
|
+
* driven by ar$shtl and the per-entry CIE type/length octets) and carry cross-field context, so this
|
|
23
|
+
* codec keeps them verbatim as `body` hex (byte-perfect) and does not sub-decode them. Packet Length is
|
|
24
|
+
* auto-computed from the body on encode when not supplied, else honored verbatim (a crafted packet may
|
|
25
|
+
* lie); the checksum is honored verbatim, never recomputed (encode is a faithful executor). The body is
|
|
26
|
+
* bounded by both Packet Length and the enclosing IP payload, so trailing bytes are left to the codec's
|
|
27
|
+
* recursion / RawData. A well-formed packet round-trips byte-for-byte.
|
|
28
|
+
*/
|
|
29
|
+
class NHRP extends BaseHeader_1.BaseHeader {
|
|
30
|
+
constructor() {
|
|
31
|
+
super(...arguments);
|
|
32
|
+
this.id = 'nhrp';
|
|
33
|
+
this.name = 'NBMA Next Hop Resolution Protocol';
|
|
34
|
+
this.nickname = 'NHRP';
|
|
35
|
+
this.matchKeys = ['ipproto:54'];
|
|
36
|
+
//A leaf header — the Mandatory Part / Extensions require opcode-dependent, length-driven parsing.
|
|
37
|
+
this.demuxProducers = [];
|
|
38
|
+
}
|
|
39
|
+
static #schemaCache;
|
|
40
|
+
get SCHEMA() {
|
|
41
|
+
return (NHRP.#schemaCache ??= NHRP.#buildSchema());
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Bytes of NHRP the IP layer below says are available. IPv4 carries a total-length field, so the
|
|
45
|
+
* NHRP payload is (total length - IP header length); IPv6 carries the payload length directly (plen).
|
|
46
|
+
* Mirrors the OSPF/GRE pattern so the body decode and the match gate are bounded by the real on-wire
|
|
47
|
+
* length rather than trusting the NHRP Packet Length field alone (which a malformed packet may
|
|
48
|
+
* overstate). Returns 0 when neither is present.
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
#available() {
|
|
52
|
+
const prev = this.prevCodecModule;
|
|
53
|
+
if (!prev)
|
|
54
|
+
return 0;
|
|
55
|
+
const ipv4TotalLength = prev.instance.length.getValue(0);
|
|
56
|
+
if (ipv4TotalLength)
|
|
57
|
+
return ipv4TotalLength - prev.length;
|
|
58
|
+
const ipv6PayloadLength = prev.instance.plen.getValue(0);
|
|
59
|
+
if (ipv6PayloadLength)
|
|
60
|
+
return ipv6PayloadLength;
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Header-relative end offset of the NHRP body: the Packet Length field, clamped down to the bytes the
|
|
65
|
+
* IP layer actually made available (#available). Never less than the 20-byte Fixed Header. Bounds the
|
|
66
|
+
* verbatim body so a corrupt Packet Length can't read past the IP payload.
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
#bodyEnd() {
|
|
70
|
+
let end = this.instance.packetSize.getValue(0);
|
|
71
|
+
const available = this.#available();
|
|
72
|
+
if (available && available < end)
|
|
73
|
+
end = available;
|
|
74
|
+
if (end < 20)
|
|
75
|
+
end = 20;
|
|
76
|
+
return end;
|
|
77
|
+
}
|
|
78
|
+
static #buildSchema() {
|
|
79
|
+
return {
|
|
80
|
+
type: 'object',
|
|
81
|
+
summary: 'NHRP op=${opType} pktsz=${packetSize}',
|
|
82
|
+
properties: {
|
|
83
|
+
//==== Fixed Header (20 bytes, RFC 2332 §5.2.0.1) ====
|
|
84
|
+
afn: this.fieldUInt('afn', 0, 2, 'Address Family Number'),
|
|
85
|
+
//The protocol being resolved, an EtherType (e.g. 0x0800 IPv4) — kept as a hex string like
|
|
86
|
+
//eth.etherType, byte-perfect and editable.
|
|
87
|
+
protocolType: this.fieldHex('protocolType', 2, 2, 'Protocol Type'),
|
|
88
|
+
protocolSnap: this.fieldHex('protocolSnap', 4, 5, 'Protocol SNAP'),
|
|
89
|
+
hopCount: this.fieldUInt('hopCount', 9, 1, 'Hop Count'),
|
|
90
|
+
packetSize: {
|
|
91
|
+
type: 'integer',
|
|
92
|
+
label: 'Packet Length',
|
|
93
|
+
minimum: 0,
|
|
94
|
+
maximum: 65535,
|
|
95
|
+
decode: function () {
|
|
96
|
+
this.instance.packetSize.setValue((0, BufferToNumber_1.BufferToUInt16)(this.readBytes(10, 2)));
|
|
97
|
+
},
|
|
98
|
+
encode: function () {
|
|
99
|
+
//Packet Length counts the whole NHRP packet = 20-byte Fixed Header + body.
|
|
100
|
+
//Honored when supplied (a crafted packet may lie); else derived from the body.
|
|
101
|
+
const provided = this.instance.packetSize.getValue();
|
|
102
|
+
let value = (provided !== undefined && provided !== null)
|
|
103
|
+
? provided
|
|
104
|
+
: 20 + (0, HexToBuffer_1.HexToBuffer)(this.instance.body.getValue('')).length;
|
|
105
|
+
if (value > 65535) {
|
|
106
|
+
this.recordError(this.instance.packetSize.getPath(), 'Maximum value is 65535');
|
|
107
|
+
value = 65535;
|
|
108
|
+
}
|
|
109
|
+
this.instance.packetSize.setValue(value);
|
|
110
|
+
this.writeBytes(10, (0, NumberToBuffer_1.UInt16ToBuffer)(value));
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
//Honored verbatim: the NHRP checksum (ones-complement over the whole packet) is never
|
|
114
|
+
//recomputed, so a captured packet round-trips byte-for-byte.
|
|
115
|
+
checksum: this.fieldUInt('checksum', 12, 2, 'Checksum'),
|
|
116
|
+
extensionOffset: this.fieldUInt('extensionOffset', 14, 2, 'Extension Offset'),
|
|
117
|
+
opVersion: this.fieldUInt('opVersion', 16, 1, 'Version'),
|
|
118
|
+
opType: this.fieldUInt('opType', 17, 1, 'Operation Type'),
|
|
119
|
+
shtl: this.fieldUInt('shtl', 18, 1, 'Source NBMA Address Type/Length'),
|
|
120
|
+
sstl: this.fieldUInt('sstl', 19, 1, 'Source NBMA Subaddress Type/Length'),
|
|
121
|
+
//The type-specific Mandatory Part + Extensions after the 20-byte Fixed Header, kept
|
|
122
|
+
//verbatim. Bounded by both the Packet Length and the enclosing IP payload (#bodyEnd), so
|
|
123
|
+
//trailing / pipelined data is left to the codec's recursion / RawData.
|
|
124
|
+
body: {
|
|
125
|
+
type: 'string',
|
|
126
|
+
label: 'Body',
|
|
127
|
+
contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX,
|
|
128
|
+
decode: function () {
|
|
129
|
+
const end = this.#bodyEnd();
|
|
130
|
+
this.instance.body.setValue(end > 20 ? (0, BufferToHex_1.BufferToHex)(this.readBytes(20, end - 20)) : '');
|
|
131
|
+
},
|
|
132
|
+
encode: function () {
|
|
133
|
+
const body = this.instance.body.getValue('');
|
|
134
|
+
if (body)
|
|
135
|
+
this.writeBytes(20, (0, HexToBuffer_1.HexToBuffer)(body));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
match() {
|
|
142
|
+
if (!this.prevCodecModule)
|
|
143
|
+
return false;
|
|
144
|
+
//NHRP sits directly on IP (protocol 54). Accept the demux value from either the IPv4 protocol
|
|
145
|
+
//field or the IPv6 next-header field, and require at least a full 20-byte Fixed Header of IP
|
|
146
|
+
//payload to be present.
|
|
147
|
+
const protocol = this.prevCodecModule.instance.protocol.getValue(0);
|
|
148
|
+
const nextHeader = this.prevCodecModule.instance.nxt.getValue(0);
|
|
149
|
+
if (protocol !== 54 && nextHeader !== 54)
|
|
150
|
+
return false;
|
|
151
|
+
return this.#available() >= 20;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.NHRP = NHRP;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { BaseHeader } from '../abstracts/BaseHeader';
|
|
2
|
+
import { ProtocolJSONSchema } from '../schema/ProtocolJSONSchema';
|
|
3
|
+
import { DemuxProducer } from '../types/DemuxProducer';
|
|
4
|
+
/**
|
|
5
|
+
* NNTP — the Network News Transfer Protocol (RFC 3977), carried as US-ASCII text over TCP well-known
|
|
6
|
+
* port 119 (and 563 for NNTPS, the TLS-wrapped variant). The control channel is line-based and
|
|
7
|
+
* structurally identical to SMTP: a client sends commands (`ARTICLE 123\r\n`, `GROUP misc.test\r\n`,
|
|
8
|
+
* `POST\r\n`, `CAPABILITIES\r\n`, `QUIT\r\n`) and a server sends 3-digit-coded replies
|
|
9
|
+
* (`200 news.example.com ready\r\n`, `211 1234 3000234 3002322 misc.test\r\n`, `340 send article\r\n`);
|
|
10
|
+
* a multi-line reply repeats/marks the code with a '-' after the first line. The article/list data
|
|
11
|
+
* blocks that follow certain replies use the same line channel but their arbitrary content is out of
|
|
12
|
+
* scope — only the control channel is claimed here.
|
|
13
|
+
*
|
|
14
|
+
* Like SMTP, FTP, Syslog, SIP and HTTP, the message is text whose full internal structure (arbitrary
|
|
15
|
+
* arguments, significant whitespace, multi-line reply continuations) is richer than a form needs. So the
|
|
16
|
+
* ENTIRE raw message is kept verbatim as the authoritative `message` field (hex) and re-emitted
|
|
17
|
+
* untouched; only the first line is parsed on decode into display-only metadata (command/argument for a
|
|
18
|
+
* command, replyCode/replyText for a reply). Encode never reconstructs the message from the parsed
|
|
19
|
+
* fields — it writes `message` back byte-for-byte — so any conformant (or even malformed) NNTP line
|
|
20
|
+
* round-trips exactly.
|
|
21
|
+
*
|
|
22
|
+
* Note: a single TCP segment may carry more than one control line (pipelined commands) or only part of
|
|
23
|
+
* a multi-line reply/article block; reassembly across segments is out of scope. This single-segment
|
|
24
|
+
* codec keeps whatever bytes are present verbatim, which is byte-perfect for the single-packet case.
|
|
25
|
+
*/
|
|
26
|
+
export declare class NNTP extends BaseHeader {
|
|
27
|
+
#private;
|
|
28
|
+
get SCHEMA(): ProtocolJSONSchema;
|
|
29
|
+
readonly id: string;
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly nickname: string;
|
|
32
|
+
readonly matchKeys: string[];
|
|
33
|
+
match(): boolean;
|
|
34
|
+
readonly demuxProducers: DemuxProducer[];
|
|
35
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.NNTP = 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 StringContentEncodingEnum_1 = require("../lib/StringContentEncodingEnum");
|
|
9
|
+
/** NNTP command verbs (RFC 3977 + common extensions) used only to recognize a command line. */
|
|
10
|
+
const NNTP_COMMANDS = ['ARTICLE', 'BODY', 'HEAD', 'STAT', 'GROUP', 'LISTGROUP', 'LAST', 'NEXT', 'POST', 'IHAVE', 'QUIT', 'CAPABILITIES', 'MODE', 'LIST', 'NEWGROUPS', 'NEWNEWS', 'OVER', 'XOVER', 'HDR', 'XHDR', 'HELP', 'DATE', 'AUTHINFO', 'STARTTLS'];
|
|
11
|
+
/**
|
|
12
|
+
* NNTP — the Network News Transfer Protocol (RFC 3977), carried as US-ASCII text over TCP well-known
|
|
13
|
+
* port 119 (and 563 for NNTPS, the TLS-wrapped variant). The control channel is line-based and
|
|
14
|
+
* structurally identical to SMTP: a client sends commands (`ARTICLE 123\r\n`, `GROUP misc.test\r\n`,
|
|
15
|
+
* `POST\r\n`, `CAPABILITIES\r\n`, `QUIT\r\n`) and a server sends 3-digit-coded replies
|
|
16
|
+
* (`200 news.example.com ready\r\n`, `211 1234 3000234 3002322 misc.test\r\n`, `340 send article\r\n`);
|
|
17
|
+
* a multi-line reply repeats/marks the code with a '-' after the first line. The article/list data
|
|
18
|
+
* blocks that follow certain replies use the same line channel but their arbitrary content is out of
|
|
19
|
+
* scope — only the control channel is claimed here.
|
|
20
|
+
*
|
|
21
|
+
* Like SMTP, FTP, Syslog, SIP and HTTP, the message is text whose full internal structure (arbitrary
|
|
22
|
+
* arguments, significant whitespace, multi-line reply continuations) is richer than a form needs. So the
|
|
23
|
+
* ENTIRE raw message is kept verbatim as the authoritative `message` field (hex) and re-emitted
|
|
24
|
+
* untouched; only the first line is parsed on decode into display-only metadata (command/argument for a
|
|
25
|
+
* command, replyCode/replyText for a reply). Encode never reconstructs the message from the parsed
|
|
26
|
+
* fields — it writes `message` back byte-for-byte — so any conformant (or even malformed) NNTP line
|
|
27
|
+
* round-trips exactly.
|
|
28
|
+
*
|
|
29
|
+
* Note: a single TCP segment may carry more than one control line (pipelined commands) or only part of
|
|
30
|
+
* a multi-line reply/article block; reassembly across segments is out of scope. This single-segment
|
|
31
|
+
* codec keeps whatever bytes are present verbatim, which is byte-perfect for the single-packet case.
|
|
32
|
+
*/
|
|
33
|
+
class NNTP extends BaseHeader_1.BaseHeader {
|
|
34
|
+
constructor() {
|
|
35
|
+
super(...arguments);
|
|
36
|
+
this.id = 'nntp';
|
|
37
|
+
this.name = 'Network News Transfer Protocol';
|
|
38
|
+
this.nickname = 'NNTP';
|
|
39
|
+
//NNTP is recognized ONLY on its well-known port buckets 119 (news) and 563 (NNTPS/TLS) —
|
|
40
|
+
//deliberately NOT via heuristicFallback. Unlike HTTP/RTSP (whose method sets are distinctive),
|
|
41
|
+
//NNTP's line signature is a 3-digit reply code or a generic verb (QUIT/HELP/LIST/HEAD/BODY/STAT/…)
|
|
42
|
+
//that is SHARED with other US-ASCII line protocols this codec models — SMTP (HELP/QUIT), FTP (QUIT/
|
|
43
|
+
//HELP/LIST/STAT), POP3 (QUIT/STAT/LIST), IRC (QUIT), and any NNN-code greeting (FTP/SMTP). Joining
|
|
44
|
+
//the global heuristic chain would mislabel all of those as NNTP on their own ports. Confining NNTP to
|
|
45
|
+
//the tcp:119/tcp:563 buckets keeps that collision impossible (SMTP/FTP/POP3/IRC live on 25/21/110/
|
|
46
|
+
//6667, which never reach these buckets); alt-port NNTP is rare and falls losslessly to raw. (NNTPS on
|
|
47
|
+
//563 is normally TLS-wrapped, so the bucket rarely carries plain NNTP text, but is listed for
|
|
48
|
+
//completeness/STARTTLS-downgrade traffic.)
|
|
49
|
+
this.matchKeys = ['tcpport:119', 'tcpport:563'];
|
|
50
|
+
//A leaf header — the article/list data blocks and the news session they belong to are a higher-layer
|
|
51
|
+
//concern.
|
|
52
|
+
this.demuxProducers = [];
|
|
53
|
+
}
|
|
54
|
+
static #schemaCache;
|
|
55
|
+
get SCHEMA() {
|
|
56
|
+
return (_a.#schemaCache ??= _a.#buildSchema());
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Bytes of this header: NNTP rides on TCP, which has no per-message length, so take the rest of the
|
|
60
|
+
* segment. Reassembly across segments is out of scope (see class doc).
|
|
61
|
+
*/
|
|
62
|
+
#payloadLength() {
|
|
63
|
+
const available = this.packet.length - this.startPos;
|
|
64
|
+
return available < 0 ? 0 : available;
|
|
65
|
+
}
|
|
66
|
+
/** The first line of the message (up to the first CRLF, or the whole payload if none). */
|
|
67
|
+
static #firstLine(text) {
|
|
68
|
+
const idx = text.indexOf('\r\n');
|
|
69
|
+
return idx >= 0 ? text.slice(0, idx) : text;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Parse the first line into the display-only metadata fields. A line matching `^\d{3}[ -]` is a
|
|
73
|
+
* server reply (the code, whether it is multi-line, and the trailing text); anything else is a
|
|
74
|
+
* client command (the uppercased verb and its argument). Populated on decode only — these fields
|
|
75
|
+
* have no encode, so they never affect the re-emitted bytes and never mutate `message`. Never
|
|
76
|
+
* throws: missing/garbage tokens yield empty strings or 0.
|
|
77
|
+
*/
|
|
78
|
+
#parseFirstLine(text) {
|
|
79
|
+
const line = _a.#firstLine(text);
|
|
80
|
+
const reply = line.match(/^(\d{3})([ -])(.*)$/);
|
|
81
|
+
if (reply) {
|
|
82
|
+
//Reply: 3-digit code, then ' ' (final) or '-' (a multi-line continuation follows).
|
|
83
|
+
this.instance.isReply.setValue(true);
|
|
84
|
+
this.instance.replyCode.setValue(Number(reply[1]));
|
|
85
|
+
this.instance.isMultiline.setValue(reply[2] === '-');
|
|
86
|
+
this.instance.replyText.setValue(reply[3]);
|
|
87
|
+
this.instance.command.setValue('');
|
|
88
|
+
this.instance.argument.setValue('');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
//Command: VERB SP argument (the argument may itself contain spaces, e.g. a message-id or range).
|
|
92
|
+
const idx = line.indexOf(' ');
|
|
93
|
+
const verb = idx >= 0 ? line.slice(0, idx) : line;
|
|
94
|
+
this.instance.isReply.setValue(false);
|
|
95
|
+
this.instance.replyCode.setValue(0);
|
|
96
|
+
this.instance.isMultiline.setValue(false);
|
|
97
|
+
this.instance.replyText.setValue('');
|
|
98
|
+
this.instance.command.setValue(verb.toUpperCase());
|
|
99
|
+
this.instance.argument.setValue(idx >= 0 ? line.slice(idx + 1) : '');
|
|
100
|
+
}
|
|
101
|
+
static #buildSchema() {
|
|
102
|
+
return {
|
|
103
|
+
type: 'object',
|
|
104
|
+
summary: 'NNTP ${command}${replyCode}',
|
|
105
|
+
properties: {
|
|
106
|
+
//The whole raw message is the single source of truth: decoded verbatim to hex and
|
|
107
|
+
//re-emitted untouched (byte-perfect for any NNTP control text). The first line is parsed
|
|
108
|
+
//into the display-only metadata below, which carry no codec of their own.
|
|
109
|
+
message: {
|
|
110
|
+
type: 'string',
|
|
111
|
+
label: 'Message',
|
|
112
|
+
contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX,
|
|
113
|
+
decode: function () {
|
|
114
|
+
const available = this.#payloadLength();
|
|
115
|
+
if (available <= 0) {
|
|
116
|
+
this.instance.message.setValue('');
|
|
117
|
+
this.#parseFirstLine('');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const raw = this.readBytes(0, available);
|
|
121
|
+
this.instance.message.setValue((0, BufferToHex_1.BufferToHex)(raw));
|
|
122
|
+
this.#parseFirstLine(raw.toString('latin1'));
|
|
123
|
+
},
|
|
124
|
+
encode: function () {
|
|
125
|
+
//Re-emit the authoritative message verbatim — never reconstruct from metadata.
|
|
126
|
+
this.writeBytes(0, (0, HexToBuffer_1.HexToBuffer)(this.instance.message.getValue('')));
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
//Display-only metadata parsed from the first line on decode (no encode — populated by the
|
|
130
|
+
//message field above, never read back). isReply distinguishes a server reply from a
|
|
131
|
+
//client command; replyCode/isMultiline/replyText describe a reply, command/argument a
|
|
132
|
+
//command.
|
|
133
|
+
isReply: { type: 'boolean', label: 'Is Reply' },
|
|
134
|
+
replyCode: { type: 'integer', label: 'Reply Code', minimum: 0, maximum: 999 },
|
|
135
|
+
isMultiline: { type: 'boolean', label: 'Is Multiline' },
|
|
136
|
+
replyText: { type: 'string', label: 'Reply Text' },
|
|
137
|
+
command: { type: 'string', label: 'Command' },
|
|
138
|
+
argument: { type: 'string', label: 'Argument' }
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
match() {
|
|
143
|
+
//NNTP rides on TCP as US-ASCII text. Recognize it by the line signature: a 3-digit reply code
|
|
144
|
+
//followed by space or '-', or a known command verb as the leading token (up to the first space
|
|
145
|
+
//or CR) — so non-NNTP traffic on port 119/563 falls through to raw rather than claiming an
|
|
146
|
+
//un-decodable text layer.
|
|
147
|
+
if (!this.prevCodecModule)
|
|
148
|
+
return false;
|
|
149
|
+
if (this.prevCodecModule.id !== 'tcp')
|
|
150
|
+
return false;
|
|
151
|
+
if (this.#payloadLength() < 3)
|
|
152
|
+
return false;
|
|
153
|
+
const lead = this.readBytes(0, 16, true).toString('latin1');
|
|
154
|
+
if (/^\d{3}[ -]/.test(lead))
|
|
155
|
+
return true;
|
|
156
|
+
const line = _a.#firstLine(lead);
|
|
157
|
+
const token = (line.split(/[ \r]/)[0] || '').toUpperCase();
|
|
158
|
+
return NNTP_COMMANDS.includes(token);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
exports.NNTP = NNTP;
|
|
162
|
+
_a = NNTP;
|