123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- package listener
- import (
- "net"
- "net/netip"
- "os"
- "github.com/sagernet/sing/common/buf"
- "github.com/sagernet/sing/common/control"
- E "github.com/sagernet/sing/common/exceptions"
- M "github.com/sagernet/sing/common/metadata"
- N "github.com/sagernet/sing/common/network"
- )
- func (l *Listener) ListenUDP() (net.PacketConn, error) {
- bindAddr := M.SocksaddrFrom(l.listenOptions.Listen.Build(netip.AddrFrom4([4]byte{127, 0, 0, 1})), l.listenOptions.ListenPort)
- var lc net.ListenConfig
- var udpFragment bool
- if l.listenOptions.UDPFragment != nil {
- udpFragment = *l.listenOptions.UDPFragment
- } else {
- udpFragment = l.listenOptions.UDPFragmentDefault
- }
- if !udpFragment {
- lc.Control = control.Append(lc.Control, control.DisableUDPFragment())
- }
- udpConn, err := lc.ListenPacket(l.ctx, M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.String())
- if err != nil {
- return nil, err
- }
- l.udpConn = udpConn.(*net.UDPConn)
- l.udpAddr = bindAddr
- l.logger.Info("udp server started at ", udpConn.LocalAddr())
- return udpConn, err
- }
- func (l *Listener) UDPAddr() M.Socksaddr {
- return l.udpAddr
- }
- func (l *Listener) PacketWriter() N.PacketWriter {
- return (*packetWriter)(l)
- }
- func (l *Listener) loopUDPIn() {
- defer close(l.packetOutboundClosed)
- var buffer *buf.Buffer
- if !l.threadUnsafePacketWriter {
- buffer = buf.NewPacket()
- defer buffer.Release()
- buffer.IncRef()
- defer buffer.DecRef()
- }
- if l.oobPacketHandler != nil {
- oob := make([]byte, 1024)
- for {
- if l.threadUnsafePacketWriter {
- buffer = buf.NewPacket()
- } else {
- buffer.Reset()
- }
- n, oobN, _, addr, err := l.udpConn.ReadMsgUDPAddrPort(buffer.FreeBytes(), oob)
- if err != nil {
- if l.threadUnsafePacketWriter {
- buffer.Release()
- }
- if l.shutdown.Load() && E.IsClosed(err) {
- return
- }
- l.udpConn.Close()
- l.logger.Error("udp listener closed: ", err)
- return
- }
- buffer.Truncate(n)
- l.oobPacketHandler.NewPacketEx(buffer, oob[:oobN], M.SocksaddrFromNetIP(addr).Unwrap())
- }
- } else {
- for {
- if l.threadUnsafePacketWriter {
- buffer = buf.NewPacket()
- } else {
- buffer.Reset()
- }
- n, addr, err := l.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes())
- if err != nil {
- if l.threadUnsafePacketWriter {
- buffer.Release()
- }
- if l.shutdown.Load() && E.IsClosed(err) {
- return
- }
- l.udpConn.Close()
- l.logger.Error("udp listener closed: ", err)
- return
- }
- buffer.Truncate(n)
- l.packetHandler.NewPacketEx(buffer, M.SocksaddrFromNetIP(addr).Unwrap())
- }
- }
- }
- func (l *Listener) loopUDPOut() {
- for {
- select {
- case packet := <-l.packetOutbound:
- destination := packet.Destination.AddrPort()
- _, err := l.udpConn.WriteToUDPAddrPort(packet.Buffer.Bytes(), destination)
- packet.Buffer.Release()
- N.PutPacketBuffer(packet)
- if err != nil {
- if l.shutdown.Load() && E.IsClosed(err) {
- return
- }
- l.udpConn.Close()
- l.logger.Error("udp listener write back: ", destination, ": ", err)
- return
- }
- continue
- case <-l.packetOutboundClosed:
- }
- for {
- select {
- case packet := <-l.packetOutbound:
- packet.Buffer.Release()
- N.PutPacketBuffer(packet)
- default:
- return
- }
- }
- }
- }
- type packetWriter Listener
- func (w *packetWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
- packet := N.NewPacketBuffer()
- packet.Buffer = buffer
- packet.Destination = destination
- select {
- case w.packetOutbound <- packet:
- return nil
- default:
- buffer.Release()
- N.PutPacketBuffer(packet)
- if w.shutdown.Load() {
- return os.ErrClosed
- }
- w.logger.Trace("dropped packet to ", destination)
- return nil
- }
- }
- func (w *packetWriter) WriteIsThreadUnsafe() {
- }
|