github.com/apernet/sing-tun@v0.2.6-0.20240323130332-b9f6511036ad/internal/wintun/session_windows.go (about)

     1  /* SPDX-License-Identifier: MIT
     2   *
     3   * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
     4   */
     5  
     6  package wintun
     7  
     8  import (
     9  	"syscall"
    10  	"unsafe"
    11  
    12  	"golang.org/x/sys/windows"
    13  )
    14  
    15  type Session struct {
    16  	handle uintptr
    17  }
    18  
    19  const (
    20  	PacketSizeMax   = 0xffff    // Maximum packet size
    21  	RingCapacityMin = 0x20000   // Minimum ring capacity (128 kiB)
    22  	RingCapacityMax = 0x4000000 // Maximum ring capacity (64 MiB)
    23  )
    24  
    25  // Packet with data
    26  type Packet struct {
    27  	Next *Packet              // Pointer to next packet in queue
    28  	Size uint32               // Size of packet (max WINTUN_MAX_IP_PACKET_SIZE)
    29  	Data *[PacketSizeMax]byte // Pointer to layer 3 IPv4 or IPv6 packet
    30  }
    31  
    32  var (
    33  	procWintunAllocateSendPacket   = modwintun.NewProc("WintunAllocateSendPacket")
    34  	procWintunEndSession           = modwintun.NewProc("WintunEndSession")
    35  	procWintunGetReadWaitEvent     = modwintun.NewProc("WintunGetReadWaitEvent")
    36  	procWintunReceivePacket        = modwintun.NewProc("WintunReceivePacket")
    37  	procWintunReleaseReceivePacket = modwintun.NewProc("WintunReleaseReceivePacket")
    38  	procWintunSendPacket           = modwintun.NewProc("WintunSendPacket")
    39  	procWintunStartSession         = modwintun.NewProc("WintunStartSession")
    40  )
    41  
    42  func (wintun *Adapter) StartSession(capacity uint32) (session Session, err error) {
    43  	r0, _, e1 := syscall.Syscall(procWintunStartSession.Addr(), 2, uintptr(wintun.handle), uintptr(capacity), 0)
    44  	if r0 == 0 {
    45  		err = e1
    46  	} else {
    47  		session = Session{r0}
    48  	}
    49  	return
    50  }
    51  
    52  func (session Session) End() {
    53  	syscall.Syscall(procWintunEndSession.Addr(), 1, session.handle, 0, 0)
    54  	session.handle = 0
    55  }
    56  
    57  func (session Session) ReadWaitEvent() (handle windows.Handle) {
    58  	r0, _, _ := syscall.Syscall(procWintunGetReadWaitEvent.Addr(), 1, session.handle, 0, 0)
    59  	handle = windows.Handle(r0)
    60  	return
    61  }
    62  
    63  func (session Session) ReceivePacket() (packet []byte, err error) {
    64  	var packetSize uint32
    65  	r0, _, e1 := syscall.Syscall(procWintunReceivePacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packetSize)), 0)
    66  	if r0 == 0 {
    67  		err = e1
    68  		return
    69  	}
    70  	packet = unsafe.Slice((*byte)(unsafe.Pointer(r0)), packetSize)
    71  	return
    72  }
    73  
    74  func (session Session) ReleaseReceivePacket(packet []byte) {
    75  	syscall.Syscall(procWintunReleaseReceivePacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packet[0])), 0)
    76  }
    77  
    78  func (session Session) AllocateSendPacket(packetSize int) (packet []byte, err error) {
    79  	r0, _, e1 := syscall.Syscall(procWintunAllocateSendPacket.Addr(), 2, session.handle, uintptr(packetSize), 0)
    80  	if r0 == 0 {
    81  		err = e1
    82  		return
    83  	}
    84  	packet = unsafe.Slice((*byte)(unsafe.Pointer(r0)), packetSize)
    85  	return
    86  }
    87  
    88  func (session Session) SendPacket(packet []byte) {
    89  	syscall.Syscall(procWintunSendPacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packet[0])), 0)
    90  }