func (cx *Connection) Wrap(conn net.Conn) *Connection {
	return &Connection{
		Conn:    conn,
		Context: cx.Context,
		buf:     cx.buf,
	}
}
Wrap wraps conn in a new Connection based on cx (reusing
cx's existing buffer and context). This is useful after
a connection is wrapped by a package that does not support
our Connection type (for example, `tls.Server()`).
package layer4
import (
	"bytes"
	"context"
	"io"
	"net"
	"sync"
	"github.com/caddyserver/caddy/v2"
)
func WrapConnection(underlying net.Conn, buf *bytes.Buffer) *Connection {
	repl := caddy.NewReplacer()
	repl.Set("l4.conn.remote_addr", underlying.RemoteAddr())
	repl.Set("l4.conn.local_addr", underlying.LocalAddr())
	ctx := context.Background()
	ctx = context.WithValue(ctx, VarsCtxKey, make(map[string]interface{}))
	ctx = context.WithValue(ctx, ReplacerCtxKey, repl)
	return &Connection{
		Conn:    underlying,
		Context: ctx,
		buf:     buf,
	}
}
type Connection struct {
	net.Conn
	Context context.Context
	buf       *bytes.Buffer  
	bufReader io.Reader      
	recording bool
	bytesRead, bytesWritten uint64
}
func (cx *Connection) Read(p []byte) (n int, err error) {
	if cx.bufReader != nil {
		n, err = cx.bufReader.Read(p)
		if err == io.EOF {
			cx.bufReader = nil
			err = nil
		}
		return
	}
	n, err = cx.Conn.Read(p)
	cx.bytesRead += uint64(n)
	if !cx.recording {
		return
	}
	if n > 0 {
		if nw, errw := cx.buf.Write(p[:n]); errw != nil {
			return nw, errw
		}
	}
	return
}
func (cx *Connection) Write(p []byte) (n int, err error) {
	n, err = cx.Conn.Write(p)
	cx.bytesWritten += uint64(n)
	return
}