github.com/imannamdari/v2ray-core/v5@v5.0.5/transport/internet/udp/dispatcher_split.go (about)

     1  package udp
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/imannamdari/v2ray-core/v5/common"
    10  	"github.com/imannamdari/v2ray-core/v5/common/buf"
    11  	"github.com/imannamdari/v2ray-core/v5/common/net"
    12  	"github.com/imannamdari/v2ray-core/v5/common/protocol/udp"
    13  	"github.com/imannamdari/v2ray-core/v5/common/session"
    14  	"github.com/imannamdari/v2ray-core/v5/common/signal"
    15  	"github.com/imannamdari/v2ray-core/v5/common/signal/done"
    16  	"github.com/imannamdari/v2ray-core/v5/features/routing"
    17  	"github.com/imannamdari/v2ray-core/v5/transport"
    18  )
    19  
    20  type ResponseCallback func(ctx context.Context, packet *udp.Packet)
    21  
    22  type connEntry struct {
    23  	link   *transport.Link
    24  	timer  signal.ActivityUpdater
    25  	cancel context.CancelFunc
    26  }
    27  
    28  type Dispatcher struct {
    29  	sync.RWMutex
    30  	conns      map[net.Destination]*connEntry
    31  	dispatcher routing.Dispatcher
    32  	callback   ResponseCallback
    33  }
    34  
    35  func (v *Dispatcher) Close() error {
    36  	return nil
    37  }
    38  
    39  func NewSplitDispatcher(dispatcher routing.Dispatcher, callback ResponseCallback) DispatcherI {
    40  	return &Dispatcher{
    41  		conns:      make(map[net.Destination]*connEntry),
    42  		dispatcher: dispatcher,
    43  		callback:   callback,
    44  	}
    45  }
    46  
    47  func (v *Dispatcher) RemoveRay(dest net.Destination) {
    48  	v.Lock()
    49  	defer v.Unlock()
    50  	if conn, found := v.conns[dest]; found {
    51  		common.Close(conn.link.Reader)
    52  		common.Close(conn.link.Writer)
    53  		delete(v.conns, dest)
    54  	}
    55  }
    56  
    57  func (v *Dispatcher) getInboundRay(ctx context.Context, dest net.Destination) *connEntry {
    58  	v.Lock()
    59  	defer v.Unlock()
    60  
    61  	if entry, found := v.conns[dest]; found {
    62  		return entry
    63  	}
    64  
    65  	newError("establishing new connection for ", dest).WriteToLog()
    66  
    67  	ctx, cancel := context.WithCancel(ctx)
    68  	removeRay := func() {
    69  		cancel()
    70  		v.RemoveRay(dest)
    71  	}
    72  	timer := signal.CancelAfterInactivity(ctx, removeRay, time.Second*300)
    73  	link, _ := v.dispatcher.Dispatch(ctx, dest)
    74  	entry := &connEntry{
    75  		link:   link,
    76  		timer:  timer,
    77  		cancel: removeRay,
    78  	}
    79  	v.conns[dest] = entry
    80  	go handleInput(ctx, entry, dest, v.callback)
    81  	return entry
    82  }
    83  
    84  func (v *Dispatcher) Dispatch(ctx context.Context, destination net.Destination, payload *buf.Buffer) {
    85  	// TODO: Add user to destString
    86  	newError("dispatch request to: ", destination).AtDebug().WriteToLog(session.ExportIDToError(ctx))
    87  
    88  	conn := v.getInboundRay(ctx, destination)
    89  	outputStream := conn.link.Writer
    90  	if outputStream != nil {
    91  		if err := outputStream.WriteMultiBuffer(buf.MultiBuffer{payload}); err != nil {
    92  			newError("failed to write first UDP payload").Base(err).WriteToLog(session.ExportIDToError(ctx))
    93  			conn.cancel()
    94  			return
    95  		}
    96  	}
    97  }
    98  
    99  func handleInput(ctx context.Context, conn *connEntry, dest net.Destination, callback ResponseCallback) {
   100  	defer conn.cancel()
   101  
   102  	input := conn.link.Reader
   103  	timer := conn.timer
   104  
   105  	for {
   106  		select {
   107  		case <-ctx.Done():
   108  			return
   109  		default:
   110  		}
   111  
   112  		mb, err := input.ReadMultiBuffer()
   113  		if err != nil {
   114  			newError("failed to handle UDP input").Base(err).WriteToLog(session.ExportIDToError(ctx))
   115  			return
   116  		}
   117  		timer.Update()
   118  		for _, b := range mb {
   119  			callback(ctx, &udp.Packet{
   120  				Payload: b,
   121  				Source:  dest,
   122  			})
   123  		}
   124  	}
   125  }
   126  
   127  type dispatcherConn struct {
   128  	dispatcher *Dispatcher
   129  	cache      chan *udp.Packet
   130  	done       *done.Instance
   131  }
   132  
   133  func DialDispatcher(ctx context.Context, dispatcher routing.Dispatcher) (net.PacketConn, error) {
   134  	c := &dispatcherConn{
   135  		cache: make(chan *udp.Packet, 16),
   136  		done:  done.New(),
   137  	}
   138  
   139  	d := NewSplitDispatcher(dispatcher, c.callback)
   140  	c.dispatcher = d.(*Dispatcher)
   141  	return c, nil
   142  }
   143  
   144  func (c *dispatcherConn) callback(ctx context.Context, packet *udp.Packet) {
   145  	select {
   146  	case <-c.done.Wait():
   147  		packet.Payload.Release()
   148  		return
   149  	case c.cache <- packet:
   150  	default:
   151  		packet.Payload.Release()
   152  		return
   153  	}
   154  }
   155  
   156  func (c *dispatcherConn) ReadFrom(p []byte) (int, net.Addr, error) {
   157  	select {
   158  	case <-c.done.Wait():
   159  		return 0, nil, io.EOF
   160  	case packet := <-c.cache:
   161  		n := copy(p, packet.Payload.Bytes())
   162  		return n, &net.UDPAddr{
   163  			IP:   packet.Source.Address.IP(),
   164  			Port: int(packet.Source.Port),
   165  		}, nil
   166  	}
   167  }
   168  
   169  func (c *dispatcherConn) WriteTo(p []byte, addr net.Addr) (int, error) {
   170  	buffer := buf.New()
   171  	raw := buffer.Extend(buf.Size)
   172  	n := copy(raw, p)
   173  	buffer.Resize(0, int32(n))
   174  
   175  	ctx := context.Background()
   176  	c.dispatcher.Dispatch(ctx, net.DestinationFromAddr(addr), buffer)
   177  	return n, nil
   178  }
   179  
   180  func (c *dispatcherConn) Close() error {
   181  	return c.done.Close()
   182  }
   183  
   184  func (c *dispatcherConn) LocalAddr() net.Addr {
   185  	return &net.UDPAddr{
   186  		IP:   []byte{0, 0, 0, 0},
   187  		Port: 0,
   188  	}
   189  }
   190  
   191  func (c *dispatcherConn) SetDeadline(t time.Time) error {
   192  	return nil
   193  }
   194  
   195  func (c *dispatcherConn) SetReadDeadline(t time.Time) error {
   196  	return nil
   197  }
   198  
   199  func (c *dispatcherConn) SetWriteDeadline(t time.Time) error {
   200  	return nil
   201  }