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  }