github.com/metacubex/sing-tun@v0.2.7-0.20240512075008-89e7c6208eec/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 }