tailscale/tstest/natlab/vnet/pcap.go
Maisem Ali 31b5239a2f tstest/natlab/vnet: flush and sync pcap file after every packet
So that we can view the pcap as we debug interactively.

Updates #13038

Signed-off-by: Maisem Ali <maisem@tailscale.com>
2024-08-24 11:44:50 -07:00

70 lines
1.1 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package vnet
import (
"io"
"os"
"sync"
"github.com/google/gopacket"
"github.com/google/gopacket/pcapgo"
)
// pcapWriter is a pcapgo.NgWriter that writes to a file.
// It is safe for concurrent use. The nil value is a no-op.
type pcapWriter struct {
f *os.File
mu sync.Mutex
w *pcapgo.NgWriter
}
func do(fs ...func() error) error {
for _, f := range fs {
if err := f(); err != nil {
return err
}
}
return nil
}
func (p *pcapWriter) WritePacket(ci gopacket.CaptureInfo, data []byte) error {
if p == nil {
return nil
}
p.mu.Lock()
defer p.mu.Unlock()
if p.w == nil {
return io.ErrClosedPipe
}
return do(
func() error { return p.w.WritePacket(ci, data) },
p.w.Flush,
p.f.Sync,
)
}
func (p *pcapWriter) AddInterface(i pcapgo.NgInterface) (int, error) {
if p == nil {
return 0, nil
}
p.mu.Lock()
defer p.mu.Unlock()
return p.w.AddInterface(i)
}
func (p *pcapWriter) Close() error {
if p == nil {
return nil
}
p.mu.Lock()
defer p.mu.Unlock()
if p.w != nil {
p.w.Flush()
p.w = nil
}
return p.f.Close()
}