github.com/sagernet/sing-tun@v0.3.0-beta.5/tun_windows_gvisor.go (about) 1 //go:build with_gvisor && windows 2 3 package tun 4 5 import ( 6 "github.com/sagernet/gvisor/pkg/buffer" 7 "github.com/sagernet/gvisor/pkg/tcpip" 8 "github.com/sagernet/gvisor/pkg/tcpip/header" 9 "github.com/sagernet/gvisor/pkg/tcpip/stack" 10 ) 11 12 var _ GVisorTun = (*NativeTun)(nil) 13 14 func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) { 15 return &WintunEndpoint{tun: t}, nil 16 } 17 18 var _ stack.LinkEndpoint = (*WintunEndpoint)(nil) 19 20 type WintunEndpoint struct { 21 tun *NativeTun 22 dispatcher stack.NetworkDispatcher 23 } 24 25 func (e *WintunEndpoint) MTU() uint32 { 26 return e.tun.options.MTU 27 } 28 29 func (e *WintunEndpoint) MaxHeaderLength() uint16 { 30 return 0 31 } 32 33 func (e *WintunEndpoint) LinkAddress() tcpip.LinkAddress { 34 return "" 35 } 36 37 func (e *WintunEndpoint) Capabilities() stack.LinkEndpointCapabilities { 38 return stack.CapabilityRXChecksumOffload 39 } 40 41 func (e *WintunEndpoint) Attach(dispatcher stack.NetworkDispatcher) { 42 if dispatcher == nil && e.dispatcher != nil { 43 e.dispatcher = nil 44 return 45 } 46 if dispatcher != nil && e.dispatcher == nil { 47 e.dispatcher = dispatcher 48 go e.dispatchLoop() 49 } 50 } 51 52 func (e *WintunEndpoint) dispatchLoop() { 53 for { 54 var packetBuffer buffer.Buffer 55 err := e.tun.ReadFunc(func(b []byte) { 56 packetBuffer = buffer.MakeWithData(b) 57 }) 58 if err != nil { 59 break 60 } 61 ihl, ok := packetBuffer.PullUp(0, 1) 62 if !ok { 63 packetBuffer.Release() 64 continue 65 } 66 var networkProtocol tcpip.NetworkProtocolNumber 67 switch header.IPVersion(ihl.AsSlice()) { 68 case header.IPv4Version: 69 networkProtocol = header.IPv4ProtocolNumber 70 case header.IPv6Version: 71 networkProtocol = header.IPv6ProtocolNumber 72 default: 73 e.tun.Write(packetBuffer.Flatten()) 74 packetBuffer.Release() 75 continue 76 } 77 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 78 Payload: packetBuffer, 79 IsForwardedPacket: true, 80 }) 81 dispatcher := e.dispatcher 82 if dispatcher == nil { 83 pkt.DecRef() 84 return 85 } 86 dispatcher.DeliverNetworkPacket(networkProtocol, pkt) 87 pkt.DecRef() 88 } 89 } 90 91 func (e *WintunEndpoint) IsAttached() bool { 92 return e.dispatcher != nil 93 } 94 95 func (e *WintunEndpoint) Wait() { 96 } 97 98 func (e *WintunEndpoint) ARPHardwareType() header.ARPHardwareType { 99 return header.ARPHardwareNone 100 } 101 102 func (e *WintunEndpoint) AddHeader(buffer *stack.PacketBuffer) { 103 } 104 105 func (e *WintunEndpoint) ParseHeader(ptr *stack.PacketBuffer) bool { 106 return true 107 } 108 109 func (e *WintunEndpoint) WritePackets(packetBufferList stack.PacketBufferList) (int, tcpip.Error) { 110 var n int 111 for _, packet := range packetBufferList.AsSlice() { 112 _, err := e.tun.write(packet.AsSlices()) 113 if err != nil { 114 return n, &tcpip.ErrAborted{} 115 } 116 n++ 117 } 118 return n, nil 119 }