123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- package inbound
- import (
- "context"
- "net"
- "github.com/sagernet/sing-box/adapter"
- "github.com/sagernet/sing-box/common/settings"
- C "github.com/sagernet/sing-box/constant"
- "github.com/sagernet/sing-box/log"
- "github.com/sagernet/sing-box/option"
- "github.com/sagernet/sing/common"
- "github.com/sagernet/sing/common/atomic"
- E "github.com/sagernet/sing/common/exceptions"
- M "github.com/sagernet/sing/common/metadata"
- N "github.com/sagernet/sing/common/network"
- )
- var _ adapter.Inbound = (*myInboundAdapter)(nil)
- type myInboundAdapter struct {
- protocol string
- network []string
- ctx context.Context
- router adapter.ConnectionRouter
- logger log.ContextLogger
- tag string
- listenOptions option.ListenOptions
- connHandler adapter.ConnectionHandler
- packetHandler adapter.PacketHandler
- oobPacketHandler adapter.OOBPacketHandler
- packetUpstream any
- // http mixed
- setSystemProxy bool
- systemProxy settings.SystemProxy
- // internal
- tcpListener net.Listener
- udpConn *net.UDPConn
- udpAddr M.Socksaddr
- packetOutboundClosed chan struct{}
- packetOutbound chan *myInboundPacket
- inShutdown atomic.Bool
- }
- func (a *myInboundAdapter) Type() string {
- return a.protocol
- }
- func (a *myInboundAdapter) Tag() string {
- return a.tag
- }
- func (a *myInboundAdapter) Network() []string {
- return a.network
- }
- func (a *myInboundAdapter) Start() error {
- var err error
- if common.Contains(a.network, N.NetworkTCP) {
- _, err = a.ListenTCP()
- if err != nil {
- return err
- }
- go a.loopTCPIn()
- }
- if common.Contains(a.network, N.NetworkUDP) {
- _, err = a.ListenUDP()
- if err != nil {
- return err
- }
- a.packetOutboundClosed = make(chan struct{})
- a.packetOutbound = make(chan *myInboundPacket)
- if a.oobPacketHandler != nil {
- if _, threadUnsafeHandler := common.Cast[N.ThreadUnsafeWriter](a.packetUpstream); !threadUnsafeHandler {
- go a.loopUDPOOBIn()
- } else {
- go a.loopUDPOOBInThreadSafe()
- }
- } else {
- if _, threadUnsafeHandler := common.Cast[N.ThreadUnsafeWriter](a.packetUpstream); !threadUnsafeHandler {
- go a.loopUDPIn()
- } else {
- go a.loopUDPInThreadSafe()
- }
- go a.loopUDPOut()
- }
- }
- if a.setSystemProxy {
- listenPort := M.SocksaddrFromNet(a.tcpListener.Addr()).Port
- var listenAddrString string
- listenAddr := a.listenOptions.Listen.Build()
- if listenAddr.IsUnspecified() {
- listenAddrString = "127.0.0.1"
- } else {
- listenAddrString = listenAddr.String()
- }
- var systemProxy settings.SystemProxy
- systemProxy, err = settings.NewSystemProxy(a.ctx, M.ParseSocksaddrHostPort(listenAddrString, listenPort), a.protocol == C.TypeMixed)
- if err != nil {
- return E.Cause(err, "initialize system proxy")
- }
- err = systemProxy.Enable()
- if err != nil {
- return E.Cause(err, "set system proxy")
- }
- a.systemProxy = systemProxy
- }
- return nil
- }
- func (a *myInboundAdapter) Close() error {
- a.inShutdown.Store(true)
- var err error
- if a.systemProxy != nil && a.systemProxy.IsEnabled() {
- err = a.systemProxy.Disable()
- }
- return E.Errors(err, common.Close(
- a.tcpListener,
- common.PtrOrNil(a.udpConn),
- ))
- }
- func (a *myInboundAdapter) upstreamHandler(metadata adapter.InboundContext) adapter.UpstreamHandlerAdapter {
- return adapter.NewUpstreamHandler(metadata, a.newConnection, a.streamPacketConnection, a)
- }
- func (a *myInboundAdapter) upstreamContextHandler() adapter.UpstreamHandlerAdapter {
- return adapter.NewUpstreamContextHandler(a.newConnection, a.newPacketConnection, a)
- }
- func (a *myInboundAdapter) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
- a.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
- return a.router.RouteConnection(ctx, conn, metadata)
- }
- func (a *myInboundAdapter) streamPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
- a.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
- return a.router.RoutePacketConnection(ctx, conn, metadata)
- }
- func (a *myInboundAdapter) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
- ctx = log.ContextWithNewID(ctx)
- a.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
- a.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
- return a.router.RoutePacketConnection(ctx, conn, metadata)
- }
- func (a *myInboundAdapter) createMetadata(conn net.Conn, metadata adapter.InboundContext) adapter.InboundContext {
- metadata.Inbound = a.tag
- metadata.InboundType = a.protocol
- metadata.InboundDetour = a.listenOptions.Detour
- metadata.InboundOptions = a.listenOptions.InboundOptions
- if !metadata.Source.IsValid() {
- metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr()).Unwrap()
- }
- if !metadata.Destination.IsValid() {
- metadata.Destination = M.SocksaddrFromNet(conn.LocalAddr()).Unwrap()
- }
- if tcpConn, isTCP := common.Cast[*net.TCPConn](conn); isTCP {
- metadata.OriginDestination = M.SocksaddrFromNet(tcpConn.LocalAddr()).Unwrap()
- }
- return metadata
- }
- func (a *myInboundAdapter) createPacketMetadata(conn N.PacketConn, metadata adapter.InboundContext) adapter.InboundContext {
- metadata.Inbound = a.tag
- metadata.InboundType = a.protocol
- metadata.InboundDetour = a.listenOptions.Detour
- metadata.InboundOptions = a.listenOptions.InboundOptions
- if !metadata.Destination.IsValid() {
- metadata.Destination = M.SocksaddrFromNet(conn.LocalAddr()).Unwrap()
- }
- return metadata
- }
- func (a *myInboundAdapter) newError(err error) {
- a.logger.Error(err)
- }
- func (a *myInboundAdapter) NewError(ctx context.Context, err error) {
- NewError(a.logger, ctx, err)
- }
- func NewError(logger log.ContextLogger, ctx context.Context, err error) {
- common.Close(err)
- if E.IsClosedOrCanceled(err) {
- logger.DebugContext(ctx, "connection closed: ", err)
- return
- }
- logger.ErrorContext(ctx, err)
- }
|