tunnel: add write mutex for concurrent safety
WriteFrames and keepalive both write multi-part messages to the TLS connection. Without synchronization, their writes could interleave and corrupt the framing. Add writeMu to serialize all tunnel writes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6416159164
commit
b3f4c5f42b
1 changed files with 18 additions and 7 deletions
|
|
@ -28,6 +28,7 @@ const (
|
|||
// SoftEther VPN session. Each "block" is one Ethernet frame.
|
||||
type Tunnel struct {
|
||||
sess *Session
|
||||
writeMu sync.Mutex
|
||||
stopCh chan struct{}
|
||||
stopped sync.Once
|
||||
}
|
||||
|
|
@ -83,7 +84,11 @@ func (t *Tunnel) ReadFrames() ([][]byte, error) {
|
|||
}
|
||||
|
||||
// WriteFrames sends a batch of Ethernet frames to the server.
|
||||
// Safe for concurrent use from multiple goroutines.
|
||||
func (t *Tunnel) WriteFrames(frames [][]byte) error {
|
||||
t.writeMu.Lock()
|
||||
defer t.writeMu.Unlock()
|
||||
|
||||
if err := binary.Write(t.sess.Conn, binary.BigEndian, uint32(len(frames))); err != nil {
|
||||
return fmt.Errorf("write num blocks: %w", err)
|
||||
}
|
||||
|
|
@ -170,14 +175,20 @@ func (t *Tunnel) StartKeepalive() {
|
|||
return
|
||||
case <-ticker.C:
|
||||
size := uint32(rng.Intn(int(maxKeepaliveSize))) + 1
|
||||
if err := binary.Write(t.sess.Conn, binary.BigEndian, keepAliveMagic); err != nil {
|
||||
return
|
||||
}
|
||||
if err := binary.Write(t.sess.Conn, binary.BigEndian, size); err != nil {
|
||||
return
|
||||
}
|
||||
rng.Read(randBuf[:size])
|
||||
if _, err := t.sess.Conn.Write(randBuf[:size]); err != nil {
|
||||
|
||||
t.writeMu.Lock()
|
||||
err1 := binary.Write(t.sess.Conn, binary.BigEndian, keepAliveMagic)
|
||||
var err2, err3 error
|
||||
if err1 == nil {
|
||||
err2 = binary.Write(t.sess.Conn, binary.BigEndian, size)
|
||||
}
|
||||
if err2 == nil {
|
||||
_, err3 = t.sess.Conn.Write(randBuf[:size])
|
||||
}
|
||||
t.writeMu.Unlock()
|
||||
|
||||
if err1 != nil || err2 != nil || err3 != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue