mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
48 lines
1.2 KiB
Go
48 lines
1.2 KiB
Go
package mobile
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"sync/atomic"
|
|
"syscall"
|
|
|
|
"github.com/samosvalishe/free-turn-proxy/internal/netctl"
|
|
)
|
|
|
|
// Protector реализуется хостом для исключения сокетов клиента из VPN-туннеля (VpnService.protect).
|
|
// Без этого TURN / VK API / DNS трафик заворачивается обратно в туннель.
|
|
type Protector interface {
|
|
Protect(fd int) bool
|
|
}
|
|
|
|
var ErrProtect = errors.New("mobile: socket protect failed") //nolint:gochecknoglobals // sentinel для errors.Is
|
|
|
|
var protector atomic.Pointer[Protector]
|
|
|
|
// SetProtect устанавливает обработчик защиты сокетов хоста (nil - no-op).
|
|
func SetProtect(p Protector) {
|
|
if p == nil {
|
|
protector.Store(nil)
|
|
netctl.SetControl(nil)
|
|
return
|
|
}
|
|
protector.Store(&p)
|
|
netctl.SetControl(func(_, _ string, c syscall.RawConn) error {
|
|
ok := false
|
|
if err := c.Control(func(fd uintptr) { ok = p.Protect(int(fd)) }); err != nil {
|
|
return fmt.Errorf("socket control: %w", err)
|
|
}
|
|
if !ok {
|
|
return ErrProtect
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func protectFD(fd int) bool {
|
|
if p := protector.Load(); p != nil {
|
|
return (*p).Protect(fd)
|
|
}
|
|
return false
|
|
}
|