tunnel: buffer WriteFrames into single TLS write

Assemble numBlocks + frame sizes + frame data into one buffer before
writing. Reduces TLS records and syscalls from 3 per frame to 1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Git Sagar 2026-06-06 23:07:55 +05:30
parent fc07ac507d
commit 14ec4a02dd

View file

@ -85,20 +85,31 @@ func (t *Tunnel) ReadFrames() ([][]byte, error) {
// WriteFrames sends a batch of Ethernet frames to the server. // WriteFrames sends a batch of Ethernet frames to the server.
// Safe for concurrent use from multiple goroutines. // Safe for concurrent use from multiple goroutines.
// Assembles the entire message into one buffer for a single TLS write.
func (t *Tunnel) WriteFrames(frames [][]byte) error { func (t *Tunnel) WriteFrames(frames [][]byte) error {
t.writeMu.Lock() // Calculate total size: 4 (numBlocks) + per frame: 4 (size) + len(data)
defer t.writeMu.Unlock() total := 4
for _, f := range frames {
if err := binary.Write(t.sess.Conn, binary.BigEndian, uint32(len(frames))); err != nil { total += 4 + len(f)
return fmt.Errorf("write num blocks: %w", err)
} }
for _, frame := range frames {
if err := binary.Write(t.sess.Conn, binary.BigEndian, uint32(len(frame))); err != nil { buf := make([]byte, total)
return fmt.Errorf("write block size: %w", err) off := 0
} binary.BigEndian.PutUint32(buf[off:], uint32(len(frames)))
if _, err := t.sess.Conn.Write(frame); err != nil { off += 4
return fmt.Errorf("write block data: %w", err) for _, f := range frames {
} binary.BigEndian.PutUint32(buf[off:], uint32(len(f)))
off += 4
copy(buf[off:], f)
off += len(f)
}
t.writeMu.Lock()
_, err := t.sess.Conn.Write(buf)
t.writeMu.Unlock()
if err != nil {
return fmt.Errorf("write frames: %w", err)
} }
return nil return nil
} }