mirror of
https://github.com/soypat/lneto.git
synced 2026-09-11 00:59:30 +00:00
heap: remove heap alloc in pcap of HTTP content type; more debugging logs
This commit is contained in:
@@ -3,7 +3,6 @@ package httpraw
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"log/slog"
|
|
||||||
"slices"
|
"slices"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -300,11 +299,13 @@ func (h *Header) appendHeader(key, value string) {
|
|||||||
if h.flags.hasAny(flagNoBufferGrow) {
|
if h.flags.hasAny(flagNoBufferGrow) {
|
||||||
panic(errSmallBuffer)
|
panic(errSmallBuffer)
|
||||||
}
|
}
|
||||||
|
debuglog("http:appendhdr:grow-buf")
|
||||||
hb.buf = slices.Grow(buf, len(key)+len(value))
|
hb.buf = slices.Grow(buf, len(key)+len(value))
|
||||||
}
|
}
|
||||||
h.flags |= flagMangledBuffer
|
h.flags |= flagMangledBuffer
|
||||||
k := hb.mustAppendSlice(key)
|
k := hb.mustAppendSlice(key)
|
||||||
v := hb.mustAppendSlice(value)
|
v := hb.mustAppendSlice(value)
|
||||||
|
debuglog("http:appendhdr:grow-hdrs")
|
||||||
hb.headers = append(hb.headers, argsKV{
|
hb.headers = append(hb.headers, argsKV{
|
||||||
key: k,
|
key: k,
|
||||||
value: v,
|
value: v,
|
||||||
@@ -426,10 +427,10 @@ func bytes2tok(buf, value []byte) headerSlice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const enableDebug = false
|
const enableDebug = internal.HeapAllocDebugging
|
||||||
|
|
||||||
func debuglog(msg string) {
|
func debuglog(msg string) {
|
||||||
if enableDebug {
|
if enableDebug {
|
||||||
internal.LogAttrs(nil, slog.LevelDebug, msg)
|
internal.LogAllocs(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-14
@@ -2,12 +2,12 @@ package pcap
|
|||||||
|
|
||||||
//go:generate stringer -type=FieldClass -linecomment -output stringers.go .
|
//go:generate stringer -type=FieldClass -linecomment -output stringers.go .
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
|
||||||
"math"
|
"math"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/soypat/lneto"
|
"github.com/soypat/lneto"
|
||||||
"github.com/soypat/lneto/arp"
|
"github.com/soypat/lneto/arp"
|
||||||
@@ -553,21 +553,21 @@ func (pc *PacketBreakdown) CaptureDHCPv4(dst []Frame, pkt []byte, bitOffset int)
|
|||||||
// based on the Content-Type header, falling back to byte inspection when Content-Type is absent.
|
// based on the Content-Type header, falling back to byte inspection when Content-Type is absent.
|
||||||
func httpBodyClass(contentType, body []byte) FieldClass {
|
func httpBodyClass(contentType, body []byte) FieldClass {
|
||||||
if len(contentType) > 0 {
|
if len(contentType) > 0 {
|
||||||
|
// Use unsafe string conversion to avoid []byte("literal") heap allocations in TinyGo.
|
||||||
|
ct := unsafe.String(&contentType[0], len(contentType))
|
||||||
// Strip parameters (e.g. "; charset=utf-8") for media type matching.
|
// Strip parameters (e.g. "; charset=utf-8") for media type matching.
|
||||||
mediaType := contentType
|
if i := strings.IndexByte(ct, ';'); i >= 0 {
|
||||||
if i := bytes.IndexByte(contentType, ';'); i >= 0 {
|
ct = strings.TrimSpace(ct[:i])
|
||||||
mediaType = contentType[:i]
|
|
||||||
}
|
}
|
||||||
mediaType = bytes.TrimSpace(mediaType)
|
|
||||||
switch {
|
switch {
|
||||||
case bytes.HasPrefix(mediaType, []byte("text/")):
|
case strings.HasPrefix(ct, "text/"):
|
||||||
return FieldClassText
|
return FieldClassText
|
||||||
case internal.BytesEqual(mediaType, []byte("application/json")),
|
case ct == "application/json",
|
||||||
internal.BytesEqual(mediaType, []byte("application/javascript")),
|
ct == "application/javascript",
|
||||||
internal.BytesEqual(mediaType, []byte("application/xml")):
|
ct == "application/xml":
|
||||||
return FieldClassText
|
return FieldClassText
|
||||||
case bytes.HasSuffix(mediaType, []byte("+json")),
|
case strings.HasSuffix(ct, "+json"),
|
||||||
bytes.HasSuffix(mediaType, []byte("+xml")):
|
strings.HasSuffix(ct, "+xml"):
|
||||||
return FieldClassText
|
return FieldClassText
|
||||||
}
|
}
|
||||||
return FieldClassPayload
|
return FieldClassPayload
|
||||||
@@ -603,8 +603,11 @@ func (pc *PacketBreakdown) CaptureHTTP(dst []Frame, pkt []byte, bitOffset int) (
|
|||||||
debuglog("pcap:http:parsed")
|
debuglog("pcap:http:parsed")
|
||||||
hdrLen := pc.hdr.BufferParsed()
|
hdrLen := pc.hdr.BufferParsed()
|
||||||
body, _ := pc.hdr.Body()
|
body, _ := pc.hdr.Body()
|
||||||
|
debuglog("pcap:http:body")
|
||||||
bodyClass := httpBodyClass(pc.hdr.Get("Content-Type"), body)
|
bodyClass := httpBodyClass(pc.hdr.Get("Content-Type"), body)
|
||||||
|
debuglog("pcap:http:bodyclass")
|
||||||
finfo := reclaimFrame(&dst, httpProtocol, bitOffset, nil)
|
finfo := reclaimFrame(&dst, httpProtocol, bitOffset, nil)
|
||||||
|
debuglog("pcap:http:reclaim")
|
||||||
finfo.Fields = append(finfo.Fields,
|
finfo.Fields = append(finfo.Fields,
|
||||||
FrameField{
|
FrameField{
|
||||||
Name: "HTTP Header",
|
Name: "HTTP Header",
|
||||||
@@ -1351,10 +1354,10 @@ func reclaimRemainingFrame(dst *[]Frame, proto string, class FieldClass, pktBitO
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const enableDebug = false
|
const enableDebug = internal.HeapAllocDebugging
|
||||||
|
|
||||||
func debuglog(msg string) {
|
func debuglog(msg string) {
|
||||||
if enableDebug {
|
if enableDebug {
|
||||||
internal.LogAttrs(nil, slog.LevelDebug, msg)
|
internal.LogAllocs(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ func (sb *StackIP) SetLogger(logger *slog.Logger) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sb *StackIP) Demux(carrierData []byte, offset int) error {
|
func (sb *StackIP) Demux(carrierData []byte, offset int) error {
|
||||||
|
debugLog("ip:demux")
|
||||||
sb.handlers.info("StackIP.Demux:start")
|
sb.handlers.info("StackIP.Demux:start")
|
||||||
frame := carrierData[offset:] // we don't care about carrier data in IP.
|
frame := carrierData[offset:] // we don't care about carrier data in IP.
|
||||||
ifrm, err := ipv4.NewFrame(frame)
|
ifrm, err := ipv4.NewFrame(frame)
|
||||||
@@ -232,7 +233,7 @@ func (l logger) trace(msg string, attrs ...slog.Attr) {
|
|||||||
internal.LogAttrs(l.log, internal.LevelTrace, msg, attrs...)
|
internal.LogAttrs(l.log, internal.LevelTrace, msg, attrs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
const enableAllocLog = false
|
const enableAllocLog = internal.HeapAllocDebugging
|
||||||
|
|
||||||
func debugLog(msg string) {
|
func debugLog(msg string) {
|
||||||
if enableAllocLog {
|
if enableAllocLog {
|
||||||
|
|||||||
@@ -411,10 +411,10 @@ func TestListener_RSTOnStalePacket(t *testing.T) {
|
|||||||
copy(rawBuf[12:16], clientIP[:])
|
copy(rawBuf[12:16], clientIP[:])
|
||||||
copy(rawBuf[16:20], serverIP[:])
|
copy(rawBuf[16:20], serverIP[:])
|
||||||
// TCP header at offset 20.
|
// TCP header at offset 20.
|
||||||
binary.BigEndian.PutUint16(rawBuf[20:], 1337) // src port
|
binary.BigEndian.PutUint16(rawBuf[20:], 1337) // src port
|
||||||
binary.BigEndian.PutUint16(rawBuf[22:], serverPort) // dst port
|
binary.BigEndian.PutUint16(rawBuf[22:], serverPort) // dst port
|
||||||
binary.BigEndian.PutUint32(rawBuf[24:], 500) // SEQ
|
binary.BigEndian.PutUint32(rawBuf[24:], 500) // SEQ
|
||||||
binary.BigEndian.PutUint32(rawBuf[28:], 200) // ACK
|
binary.BigEndian.PutUint32(rawBuf[28:], 200) // ACK
|
||||||
rawBuf[32] = 0x50 // offset=5
|
rawBuf[32] = 0x50 // offset=5
|
||||||
rawBuf[33] = 0x11 // flags = FIN|ACK (0x01|0x10)
|
rawBuf[33] = 0x11 // flags = FIN|ACK (0x01|0x10)
|
||||||
|
|
||||||
@@ -484,8 +484,8 @@ func TestStackPorts_RSTOnUnknownPort(t *testing.T) {
|
|||||||
binary.BigEndian.PutUint16(rawBuf[22:], 443) // dst port (no listener!)
|
binary.BigEndian.PutUint16(rawBuf[22:], 443) // dst port (no listener!)
|
||||||
binary.BigEndian.PutUint32(rawBuf[24:], 700) // SEQ = 700
|
binary.BigEndian.PutUint32(rawBuf[24:], 700) // SEQ = 700
|
||||||
binary.BigEndian.PutUint32(rawBuf[28:], 0) // ACK = 0
|
binary.BigEndian.PutUint32(rawBuf[28:], 0) // ACK = 0
|
||||||
rawBuf[32] = 0x50 // offset=5
|
rawBuf[32] = 0x50 // offset=5
|
||||||
rawBuf[33] = 0x02 // flags = SYN
|
rawBuf[33] = 0x02 // flags = SYN
|
||||||
|
|
||||||
err := sp.Demux(rawBuf[:40], 20)
|
err := sp.Demux(rawBuf[:40], 20)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -546,9 +546,9 @@ func TestListener_ECN_SYN(t *testing.T) {
|
|||||||
// TCP header at offset 20.
|
// TCP header at offset 20.
|
||||||
binary.BigEndian.PutUint16(rawBuf[20:], 5000) // src port
|
binary.BigEndian.PutUint16(rawBuf[20:], 5000) // src port
|
||||||
binary.BigEndian.PutUint16(rawBuf[22:], serverPort)
|
binary.BigEndian.PutUint16(rawBuf[22:], serverPort)
|
||||||
binary.BigEndian.PutUint32(rawBuf[24:], 300) // SEQ
|
binary.BigEndian.PutUint32(rawBuf[24:], 300) // SEQ
|
||||||
binary.BigEndian.PutUint32(rawBuf[28:], 0) // ACK
|
binary.BigEndian.PutUint32(rawBuf[28:], 0) // ACK
|
||||||
rawBuf[32] = 0x50 // offset=5
|
rawBuf[32] = 0x50 // offset=5
|
||||||
rawBuf[33] = byte(tcp.FlagSYN | tcp.FlagECE | tcp.FlagCWR) // SYN+ECE+CWR
|
rawBuf[33] = byte(tcp.FlagSYN | tcp.FlagECE | tcp.FlagCWR) // SYN+ECE+CWR
|
||||||
|
|
||||||
// Should be accepted (create connection), not dropped.
|
// Should be accepted (create connection), not dropped.
|
||||||
|
|||||||
@@ -241,6 +241,7 @@ func (listener *Listener) Demux(carrierData []byte, tcpFrameOffset int) error {
|
|||||||
listener.logerr("Listener:demux", slog.String("err", err.Error()))
|
listener.logerr("Listener:demux", slog.String("err", err.Error()))
|
||||||
return lneto.ErrPacketDrop
|
return lneto.ErrPacketDrop
|
||||||
}
|
}
|
||||||
|
debuglog("tcplistener:demux-append")
|
||||||
listener.incoming = append(listener.incoming, handler{
|
listener.incoming = append(listener.incoming, handler{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
id: *conn.ConnectionID(),
|
id: *conn.ConnectionID(),
|
||||||
@@ -316,3 +317,11 @@ func (listener *Listener) returnIncoming(idx int) {
|
|||||||
listener.poolReturn(listener.incoming[idx].conn)
|
listener.poolReturn(listener.incoming[idx].conn)
|
||||||
listener.incoming[idx] = handler{}
|
listener.incoming[idx] = handler{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const enableDebug = internal.HeapAllocDebugging
|
||||||
|
|
||||||
|
func debuglog(msg string) {
|
||||||
|
if enableDebug {
|
||||||
|
internal.LogAllocs(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user