Compare commits

...

11 Commits

Author SHA1 Message Date
世界
2886aa61ef Remove dependency on comshim 2024-03-23 21:48:33 +08:00
世界
1181ab0d30 Update gVisor to 20240212.0-65-g71212d503 2024-03-23 21:48:33 +08:00
世界
bc7ba7447c Update gVisor to 20240206.0 2024-03-23 21:48:17 +08:00
世界
8bfb64cf04 Fix GSO batch size 2024-03-22 14:52:39 +08:00
世界
689e60891c Fix darwin monitor 2024-03-14 13:37:55 +08:00
世界
6ef2a6cdaa Fix deadlock on network update 2024-02-26 22:52:11 +08:00
世界
8d285f70fb Fix darwin monitor 2024-02-26 13:22:23 +08:00
世界
e8633c66d2 Update .gitignore 2024-02-26 13:22:15 +08:00
世界
951af3ca7a Update dependencies 2024-02-26 13:21:30 +08:00
世界
9b7c2a0a3c Fix unaligned panic on windows 2024-02-10 21:17:30 +08:00
世界
38c945fec5 Remove duplicated rules 2024-02-02 14:29:06 +08:00
14 changed files with 130 additions and 142 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
/.idea/
/vendor/
.DS_Store

9
go.mod
View File

@@ -5,13 +5,12 @@ go 1.18
require (
github.com/fsnotify/fsnotify v1.7.0
github.com/go-ole/go-ole v1.3.0
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e
github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
github.com/sagernet/sing v0.3.0
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9
github.com/sagernet/sing v0.3.6
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/net v0.19.0
golang.org/x/sys v0.16.0
golang.org/x/net v0.22.0
golang.org/x/sys v0.18.0
)
require (

20
go.sum
View File

@@ -6,25 +6,23 @@ github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e h1:DOkjByVeAR56dkszjnMZke4wr7yM/1xHaJF3G9olkEE=
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e/go.mod h1:fLxq/gtp0qzkaEwywlRRiGmjOK5ES/xUzyIKIFP2Asw=
github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311 h1:eUQ6kJZXK77xYZeeNrBb/7JMv0S0Wkk7EpmKUb3fsfc=
github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311/go.mod h1:mDrXZSv401qiaFiiIUC59Zp4VG5f4nqXFqDmp5o3hYI=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/sing v0.3.0 h1:PIDVFZHnQAAYRL1UYqNM+0k5s8f/tb1lUW6UDcQiOc8=
github.com/sagernet/sing v0.3.0/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/sagernet/sing v0.3.6 h1:dsEdYLKBQlrxUfw1a92x0VdPvR1/BOxQ+HIMyaoEJsQ=
github.com/sagernet/sing v0.3.6/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@@ -12,7 +12,6 @@ import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
"github.com/scjalliance/comshim"
)
// Firewall related API constants.
@@ -250,7 +249,10 @@ func FirewallRuleExistsByName(rules *ole.IDispatch, name string) (bool, error) {
// then:
// dispatch firewallAPIRelease(u, fwp)
func firewallAPIInit() (*ole.IUnknown, *ole.IDispatch, error) {
comshim.Add(1)
err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED)
if err != nil {
return nil, nil, fmt.Errorf("Failed to initialize COM: %s", err)
}
unknown, err := oleutil.CreateObject("HNetCfg.FwPolicy2")
if err != nil {
@@ -270,5 +272,5 @@ func firewallAPIInit() (*ole.IUnknown, *ole.IDispatch, error) {
func firewallAPIRelease(u *ole.IUnknown, fwp *ole.IDispatch) {
fwp.Release()
u.Release()
comshim.Done()
ole.CoUninitialize()
}

View File

@@ -42,7 +42,7 @@ func (m *networkUpdateMonitor) loopUpdate() {
select {
case <-m.done:
return
case <-time.After(time.Second):
default:
}
err := m.loopUpdate0()
if err != nil {
@@ -67,7 +67,16 @@ func (m *networkUpdateMonitor) loopUpdate1(routeSocketFile *os.File) {
defer routeSocketFile.Close()
buffer := buf.NewPacket()
defer buffer.Release()
done := make(chan struct{})
go func() {
select {
case <-m.done:
routeSocketFile.Close()
case <-done:
}
}()
n, err := routeSocketFile.Read(buffer.FreeBytes())
close(done)
if err != nil {
return
}
@@ -92,57 +101,59 @@ func (m *networkUpdateMonitor) Close() error {
}
func (m *defaultInterfaceMonitor) checkUpdate() error {
ribMessage, err := route.FetchRIB(unix.AF_UNSPEC, route.RIBTypeRoute, 0)
if err != nil {
return err
}
routeMessages, err := route.ParseRIB(route.RIBTypeRoute, ribMessage)
if err != nil {
return err
}
var defaultInterface *net.Interface
for _, rawRouteMessage := range routeMessages {
routeMessage := rawRouteMessage.(*route.RouteMessage)
if len(routeMessage.Addrs) <= unix.RTAX_NETMASK {
continue
}
destination, isIPv4Destination := routeMessage.Addrs[unix.RTAX_DST].(*route.Inet4Addr)
if !isIPv4Destination {
continue
}
if destination.IP != netip.IPv4Unspecified().As4() {
continue
}
mask, isIPv4Mask := routeMessage.Addrs[unix.RTAX_NETMASK].(*route.Inet4Addr)
if !isIPv4Mask {
continue
}
ones, _ := net.IPMask(mask.IP[:]).Size()
if ones != 0 {
continue
}
routeInterface, err := net.InterfaceByIndex(routeMessage.Index)
var (
defaultInterface *net.Interface
err error
)
if m.options.UnderNetworkExtension {
defaultInterface, err = getDefaultInterfaceBySocket()
if err != nil {
return err
}
if routeMessage.Flags&unix.RTF_UP == 0 {
continue
} else {
ribMessage, err := route.FetchRIB(unix.AF_UNSPEC, route.RIBTypeRoute, 0)
if err != nil {
return err
}
if routeMessage.Flags&unix.RTF_GATEWAY == 0 {
continue
routeMessages, err := route.ParseRIB(route.RIBTypeRoute, ribMessage)
if err != nil {
return err
}
if routeMessage.Flags&unix.RTF_IFSCOPE != 0 {
// continue
}
defaultInterface = routeInterface
break
}
if defaultInterface == nil {
if m.options.UnderNetworkExtension {
defaultInterface, err = getDefaultInterfaceBySocket()
for _, rawRouteMessage := range routeMessages {
routeMessage := rawRouteMessage.(*route.RouteMessage)
if len(routeMessage.Addrs) <= unix.RTAX_NETMASK {
continue
}
destination, isIPv4Destination := routeMessage.Addrs[unix.RTAX_DST].(*route.Inet4Addr)
if !isIPv4Destination {
continue
}
if destination.IP != netip.IPv4Unspecified().As4() {
continue
}
mask, isIPv4Mask := routeMessage.Addrs[unix.RTAX_NETMASK].(*route.Inet4Addr)
if !isIPv4Mask {
continue
}
ones, _ := net.IPMask(mask.IP[:]).Size()
if ones != 0 {
continue
}
routeInterface, err := net.InterfaceByIndex(routeMessage.Index)
if err != nil {
return err
}
if routeMessage.Flags&unix.RTF_UP == 0 {
continue
}
if routeMessage.Flags&unix.RTF_GATEWAY == 0 {
continue
}
if routeMessage.Flags&unix.RTF_IFSCOPE != 0 {
// continue
}
defaultInterface = routeInterface
break
}
}
if defaultInterface == nil {
@@ -170,6 +181,8 @@ func getDefaultInterfaceBySocket() (*net.Interface, error) {
Port: 80,
})
result := make(chan netip.Addr, 1)
done := make(chan struct{})
defer close(done)
go func() {
for {
sockname, sockErr := unix.Getsockname(socketFd)
@@ -182,8 +195,13 @@ func getDefaultInterfaceBySocket() (*net.Interface, error) {
}
addr := netip.AddrFrom4(sockaddr.Addr)
if addr.IsUnspecified() {
time.Sleep(time.Millisecond)
continue
select {
case <-done:
break
default:
time.Sleep(10 * time.Millisecond)
continue
}
}
result <- addr
break
@@ -193,7 +211,7 @@ func getDefaultInterfaceBySocket() (*net.Interface, error) {
select {
case selectedAddr = <-result:
case <-time.After(time.Second):
return nil, os.ErrDeadlineExceeded
return nil, nil
}
interfaces, err := net.Interfaces()
if err != nil {

View File

@@ -43,6 +43,7 @@ type defaultInterfaceMonitor struct {
defaultInterfaceIndex int
androidVPNEnabled bool
networkMonitor NetworkUpdateMonitor
checkUpdateTimer *time.Timer
element *list.Element[NetworkUpdateCallback]
access sync.Mutex
callbacks list.List[DefaultInterfaceUpdateCallback]
@@ -71,7 +72,13 @@ func (m *defaultInterfaceMonitor) Start() error {
}
func (m *defaultInterfaceMonitor) delayCheckUpdate() {
time.Sleep(time.Second)
if m.checkUpdateTimer != nil {
m.checkUpdateTimer.Stop()
}
m.checkUpdateTimer = time.AfterFunc(time.Second, m.postCheckUpdate)
}
func (m *defaultInterfaceMonitor) postCheckUpdate() {
err := m.updateInterfaces()
if err != nil {
m.logger.Error("update interfaces: ", err)
@@ -81,6 +88,8 @@ func (m *defaultInterfaceMonitor) delayCheckUpdate() {
m.defaultInterfaceName = ""
m.defaultInterfaceIndex = -1
m.emit(EventNoRoute)
} else if err != nil {
m.logger.Error("check interface: ", err)
}
}
@@ -127,9 +136,6 @@ func (m *defaultInterfaceMonitor) DefaultInterfaceName(destination netip.Addr) s
}
}
}
if m.defaultInterfaceIndex == -1 {
m.checkUpdate()
}
return m.defaultInterfaceName
}
@@ -141,9 +147,6 @@ func (m *defaultInterfaceMonitor) DefaultInterfaceIndex(destination netip.Addr)
}
}
}
if m.defaultInterfaceIndex == -1 {
m.checkUpdate()
}
return m.defaultInterfaceIndex
}
@@ -155,9 +158,6 @@ func (m *defaultInterfaceMonitor) DefaultInterface(destination netip.Addr) (stri
}
}
}
if m.defaultInterfaceIndex == -1 {
m.checkUpdate()
}
return m.defaultInterfaceName, m.defaultInterfaceIndex
}

View File

@@ -122,7 +122,7 @@ func (t *GVisor) Start() error {
if err != nil {
return
}
udpConn := gonet.NewUDPConn(ipStack, &wq, endpoint)
udpConn := gonet.NewUDPConn(&wq, endpoint)
lAddr := udpConn.RemoteAddr()
rAddr := udpConn.LocalAddr()
if lAddr == nil || rAddr == nil {

View File

@@ -32,7 +32,7 @@ type networkDispatcherFilter struct {
writer N.VectorisedWriter
}
func (w *networkDispatcherFilter) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr) {
func (w *networkDispatcherFilter) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
var network header.Network
if protocol == header.IPv4ProtocolNumber {
if headerPackets, loaded := pkt.Data().PullUp(header.IPv4MinimumSize); loaded {

View File

@@ -42,7 +42,7 @@ func NewUDPForwarder(ctx context.Context, stack *stack.Stack, handler Handler, u
}
}
func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt stack.PacketBufferPtr) bool {
func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.PacketBuffer) bool {
var upstreamMetadata M.Metadata
upstreamMetadata.Source = M.SocksaddrFrom(AddrFromAddress(id.RemoteAddress), id.RemotePort)
upstreamMetadata.Destination = M.SocksaddrFrom(AddrFromAddress(id.LocalAddress), id.LocalPort)
@@ -174,7 +174,7 @@ func (c *gUDPConn) Close() error {
return c.UDPConn.Close()
}
func gWriteUnreachable(gStack *stack.Stack, packet stack.PacketBufferPtr, err error) (retErr error) {
func gWriteUnreachable(gStack *stack.Stack, packet *stack.PacketBuffer, err error) (retErr error) {
if errors.Is(err, syscall.ENETUNREACH) {
if packet.NetworkProtocolNumber == header.IPv4ProtocolNumber {
return gWriteUnreachable4(gStack, packet, stack.RejectIPv4WithICMPNetUnreachable)
@@ -197,7 +197,7 @@ func gWriteUnreachable(gStack *stack.Stack, packet stack.PacketBufferPtr, err er
return nil
}
func gWriteUnreachable4(gStack *stack.Stack, packet stack.PacketBufferPtr, icmpCode stack.RejectIPv4WithICMPType) error {
func gWriteUnreachable4(gStack *stack.Stack, packet *stack.PacketBuffer, icmpCode stack.RejectIPv4WithICMPType) error {
err := gStack.NetworkProtocolInstance(header.IPv4ProtocolNumber).(stack.RejectIPv4WithHandler).SendRejectionError(packet, icmpCode, true)
if err != nil {
return wrapStackError(err)
@@ -205,7 +205,7 @@ func gWriteUnreachable4(gStack *stack.Stack, packet stack.PacketBufferPtr, icmpC
return nil
}
func gWriteUnreachable6(gStack *stack.Stack, packet stack.PacketBufferPtr, icmpCode stack.RejectIPv6WithICMPType) error {
func gWriteUnreachable6(gStack *stack.Stack, packet *stack.PacketBuffer, icmpCode stack.RejectIPv6WithICMPType) error {
err := gStack.NetworkProtocolInstance(header.IPv6ProtocolNumber).(stack.RejectIPv6WithHandler).SendRejectionError(packet, icmpCode, true)
if err != nil {
return wrapStackError(err)

View File

@@ -56,7 +56,7 @@ func (m *Mixed) Start() error {
if err != nil {
return
}
udpConn := gonet.NewUDPConn(ipStack, &wq, endpoint)
udpConn := gonet.NewUDPConn(&wq, endpoint)
lAddr := udpConn.RemoteAddr()
rAddr := udpConn.LocalAddr()
if lAddr == nil || rAddr == nil {

View File

@@ -102,10 +102,10 @@ func (e *DarwinEndpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareNone
}
func (e *DarwinEndpoint) AddHeader(buffer stack.PacketBufferPtr) {
func (e *DarwinEndpoint) AddHeader(buffer *stack.PacketBuffer) {
}
func (e *DarwinEndpoint) ParseHeader(ptr stack.PacketBufferPtr) bool {
func (e *DarwinEndpoint) ParseHeader(ptr *stack.PacketBuffer) bool {
return true
}

View File

@@ -136,11 +136,13 @@ func (t *NativeTun) BatchSize() int {
if !t.gsoEnabled {
return 1
}
/* // Not works on some devices: https://github.com/SagerNet/sing-box/issues/1605
batchSize := int(gsoMaxSize/t.options.MTU) * 2
if batchSize > idealBatchSize {
batchSize = idealBatchSize
}
return batchSize
return batchSize*/
return idealBatchSize
}
func (t *NativeTun) BatchRead(buffers [][]byte, offset int, readN []int) (n int, err error) {
@@ -450,14 +452,6 @@ func (t *NativeTun) rules() []*netlink.Rule {
it.Family = unix.AF_INET
rules = append(rules, it)
priority++
it = netlink.NewRule()
it.Priority = priority
it.OifName = includeInterface
it.Goto = matchPriority
it.Family = unix.AF_INET
rules = append(rules, it)
priority++
}
if p6 {
it = netlink.NewRule()
@@ -467,14 +461,6 @@ func (t *NativeTun) rules() []*netlink.Rule {
it.Family = unix.AF_INET6
rules = append(rules, it)
priority6++
it = netlink.NewRule()
it.Priority = priority6
it.OifName = includeInterface
it.Goto = matchPriority
it.Family = unix.AF_INET6
rules = append(rules, it)
priority6++
}
}
if p4 {
@@ -515,14 +501,6 @@ func (t *NativeTun) rules() []*netlink.Rule {
it.Family = unix.AF_INET
rules = append(rules, it)
priority++
it = netlink.NewRule()
it.Priority = priority
it.OifName = excludeInterface
it.Goto = nopPriority
it.Family = unix.AF_INET
rules = append(rules, it)
priority++
}
if p6 {
it = netlink.NewRule()
@@ -532,14 +510,6 @@ func (t *NativeTun) rules() []*netlink.Rule {
it.Family = unix.AF_INET6
rules = append(rules, it)
priority6++
it = netlink.NewRule()
it.Priority = priority6
it.OifName = excludeInterface
it.Goto = nopPriority
it.Family = unix.AF_INET6
rules = append(rules, it)
priority6++
}
}
}

View File

@@ -9,7 +9,6 @@ import (
"net/netip"
"os"
"sync"
"sync/atomic"
"time"
"unsafe"
@@ -17,6 +16,7 @@ import (
"github.com/sagernet/sing-tun/internal/winsys"
"github.com/sagernet/sing-tun/internal/wintun"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/atomic"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/windnsapi"
@@ -34,7 +34,7 @@ type NativeTun struct {
rate rateJuggler
running sync.WaitGroup
closeOnce sync.Once
close int32
close atomic.Int32
fwpmSession uintptr
}
@@ -334,13 +334,13 @@ func (t *NativeTun) ReadPacket() ([]byte, func(), error) {
t.running.Add(1)
defer t.running.Done()
retry:
if atomic.LoadInt32(&t.close) == 1 {
if t.close.Load() == 1 {
return nil, nil, os.ErrClosed
}
start := nanotime()
shouldSpin := atomic.LoadUint64(&t.rate.current) >= spinloopRateThreshold && uint64(start-atomic.LoadInt64(&t.rate.nextStartTime)) <= rateMeasurementGranularity*2
shouldSpin := t.rate.current.Load() >= spinloopRateThreshold && uint64(start-t.rate.nextStartTime.Load()) <= rateMeasurementGranularity*2
for {
if atomic.LoadInt32(&t.close) == 1 {
if t.close.Load() == 1 {
return nil, nil, os.ErrClosed
}
packet, err := t.session.ReceivePacket()
@@ -369,13 +369,13 @@ func (t *NativeTun) ReadFunc(block func(b []byte)) error {
t.running.Add(1)
defer t.running.Done()
retry:
if atomic.LoadInt32(&t.close) == 1 {
if t.close.Load() == 1 {
return os.ErrClosed
}
start := nanotime()
shouldSpin := atomic.LoadUint64(&t.rate.current) >= spinloopRateThreshold && uint64(start-atomic.LoadInt64(&t.rate.nextStartTime)) <= rateMeasurementGranularity*2
shouldSpin := t.rate.current.Load() >= spinloopRateThreshold && uint64(start-t.rate.nextStartTime.Load()) <= rateMeasurementGranularity*2
for {
if atomic.LoadInt32(&t.close) == 1 {
if t.close.Load() == 1 {
return os.ErrClosed
}
packet, err := t.session.ReceivePacket()
@@ -405,7 +405,7 @@ retry:
func (t *NativeTun) Write(p []byte) (n int, err error) {
t.running.Add(1)
defer t.running.Done()
if atomic.LoadInt32(&t.close) == 1 {
if t.close.Load() == 1 {
return 0, os.ErrClosed
}
t.rate.update(uint64(len(p)))
@@ -427,7 +427,7 @@ func (t *NativeTun) Write(p []byte) (n int, err error) {
func (t *NativeTun) write(packetElementList [][]byte) (n int, err error) {
t.running.Add(1)
defer t.running.Done()
if atomic.LoadInt32(&t.close) == 1 {
if t.close.Load() == 1 {
return 0, os.ErrClosed
}
var packetSize int
@@ -461,7 +461,7 @@ func (t *NativeTun) WriteVectorised(buffers []*buf.Buffer) error {
func (t *NativeTun) Close() error {
var err error
t.closeOnce.Do(func() {
atomic.StoreInt32(&t.close, 1)
t.close.Store(1)
windows.SetEvent(t.readWait)
t.running.Wait()
t.session.End()
@@ -491,24 +491,24 @@ func procyield(cycles uint32)
func nanotime() int64
type rateJuggler struct {
current uint64
nextByteCount uint64
nextStartTime int64
changing int32
current atomic.Uint64
nextByteCount atomic.Uint64
nextStartTime atomic.Int64
changing atomic.Int32
}
func (rate *rateJuggler) update(packetLen uint64) {
now := nanotime()
total := atomic.AddUint64(&rate.nextByteCount, packetLen)
period := uint64(now - atomic.LoadInt64(&rate.nextStartTime))
total := rate.nextByteCount.Add(packetLen)
period := uint64(now - rate.nextStartTime.Load())
if period >= rateMeasurementGranularity {
if !atomic.CompareAndSwapInt32(&rate.changing, 0, 1) {
if !rate.changing.CompareAndSwap(0, 1) {
return
}
atomic.StoreInt64(&rate.nextStartTime, now)
atomic.StoreUint64(&rate.current, total*uint64(time.Second/time.Nanosecond)/period)
atomic.StoreUint64(&rate.nextByteCount, 0)
atomic.StoreInt32(&rate.changing, 0)
rate.nextStartTime.Store(now)
rate.current.Store(total * uint64(time.Second/time.Nanosecond) / period)
rate.nextByteCount.Store(0)
rate.changing.Store(0)
}
}

View File

@@ -99,10 +99,10 @@ func (e *WintunEndpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareNone
}
func (e *WintunEndpoint) AddHeader(buffer stack.PacketBufferPtr) {
func (e *WintunEndpoint) AddHeader(buffer *stack.PacketBuffer) {
}
func (e *WintunEndpoint) ParseHeader(ptr stack.PacketBufferPtr) bool {
func (e *WintunEndpoint) ParseHeader(ptr *stack.PacketBuffer) bool {
return true
}