heap: remove heap alloc in pcap of HTTP content type; more debugging logs

This commit is contained in:
Patricio Whittingslow
2026-02-28 17:46:08 -03:00
parent 4f7635b216
commit f6e7801d8c
5 changed files with 40 additions and 26 deletions
+4 -3
View File
@@ -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
View File
@@ -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)
} }
} }
+2 -1
View File
@@ -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 {
+9
View File
@@ -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)
}
}