mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-11-14 08:15:55 -05:00
91 lines
2.7 KiB
Go
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]))
|
|
}
|
|
}
|
|
}
|