1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-11-14 08:15:55 -05:00
v2fly/app/tun/handler_udp.go
2023-10-22 22:44:28 +01:00

91 lines
2.7 KiB
Go

package tun
import (
"context"
"github.com/v2fly/v2ray-core/v5/common/buf"
"github.com/v2fly/v2ray-core/v5/common/net"
"github.com/v2fly/v2ray-core/v5/common/net/packetaddr"
udp_proto "github.com/v2fly/v2ray-core/v5/common/protocol/udp"
"github.com/v2fly/v2ray-core/v5/common/session"
"github.com/v2fly/v2ray-core/v5/features/policy"
"github.com/v2fly/v2ray-core/v5/features/routing"
"github.com/v2fly/v2ray-core/v5/transport/internet/udp"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/stack"
gvisor_udp "gvisor.dev/gvisor/pkg/tcpip/transport/udp"
"gvisor.dev/gvisor/pkg/waiter"
)
type UDPHandler struct {
ctx context.Context
dispatcher routing.Dispatcher
policyManager policy.Manager
config *Config
stack *stack.Stack
}
func SetUDPHandler(ctx context.Context, dispatcher routing.Dispatcher, policyManager policy.Manager, config *Config) StackOption {
return func(s *stack.Stack) error {
udpForwarder := gvisor_udp.NewForwarder(s, func(r *gvisor_udp.ForwarderRequest) {
wg := new(waiter.Queue)
linkedEndpoint, err := r.CreateEndpoint(wg)
if err != nil {
// TODO: log
return
}
udpConn := gonet.NewUDPConn(s, wg, linkedEndpoint)
udpHandler := &UDPHandler{
ctx: ctx,
dispatcher: dispatcher,
policyManager: policyManager,
config: config,
stack: s,
}
udpHandler.Handle(udpConn)
})
s.SetTransportProtocolHandler(gvisor_udp.ProtocolNumber, udpForwarder.HandlePacket)
return nil
}
}
func (h *UDPHandler) Handle(conn net.Conn) error {
ctx := session.ContextWithInbound(h.ctx, &session.Inbound{Tag: h.config.Tag})
packetConn := conn.(net.PacketConn)
udpDispatcherConstructor := udp.NewSplitDispatcher
switch h.config.PacketEncoding {
case packetaddr.PacketAddrType_None:
break
case packetaddr.PacketAddrType_Packet:
packetAddrDispatcherFactory := udp.NewPacketAddrDispatcherCreator(ctx)
udpDispatcherConstructor = packetAddrDispatcherFactory.NewPacketAddrDispatcher
}
udpServer := udpDispatcherConstructor(h.dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
if _, err := packetConn.WriteTo(packet.Payload.Bytes(), &net.UDPAddr{
IP: packet.Source.Address.IP(),
Port: int(packet.Source.Port),
}); err != nil {
newError("failed to write UDP packet").Base(err).WriteToLog()
}
})
for {
select {
case <-ctx.Done():
return nil
default:
var buffer [2048]byte
n, addr, err := packetConn.ReadFrom(buffer[:])
if err != nil {
return newError("failed to read UDP packet").Base(err)
}
currentPacketCtx := ctx
udpServer.Dispatch(currentPacketCtx, net.DestinationFromAddr(addr), buf.FromBytes(buffer[:n]))
}
}
}