github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/transport/internet/request/assembly/dialer.go (about)

     1  package assembly
     2  
     3  import (
     4  	"context"
     5  	gonet "net"
     6  	"time"
     7  
     8  	"github.com/v2fly/v2ray-core/v5/transport/internet/transportcommon"
     9  
    10  	"github.com/v2fly/v2ray-core/v5/common"
    11  	"github.com/v2fly/v2ray-core/v5/common/net"
    12  	"github.com/v2fly/v2ray-core/v5/common/serial"
    13  	"github.com/v2fly/v2ray-core/v5/common/session"
    14  	"github.com/v2fly/v2ray-core/v5/transport/internet"
    15  	"github.com/v2fly/v2ray-core/v5/transport/internet/request"
    16  )
    17  
    18  type client struct {
    19  	tripper   request.RoundTripperClient
    20  	assembler request.SessionAssemblerClient
    21  
    22  	streamSettings *internet.MemoryStreamConfig
    23  	dest           net.Destination
    24  }
    25  
    26  func (c client) Dial(ctx context.Context) (net.Conn, error) {
    27  	return transportcommon.DialWithSecuritySettings(ctx, c.dest, c.streamSettings)
    28  }
    29  
    30  func (c client) AutoImplDialer() request.Dialer {
    31  	return c
    32  }
    33  
    34  func (c client) Tripper() request.Tripper {
    35  	return c.tripper
    36  }
    37  
    38  func (c client) dialRequestSession(ctx context.Context) (net.Conn, error) {
    39  	session, err := c.assembler.NewSession(ctx)
    40  	if err != nil {
    41  		return nil, newError("failed to create new session").Base(err)
    42  	}
    43  	return clientConnection{session}, nil
    44  }
    45  
    46  type clientConnection struct {
    47  	request.Session
    48  }
    49  
    50  func (c clientConnection) LocalAddr() gonet.Addr {
    51  	return &net.UnixAddr{Name: "unimplemented"}
    52  }
    53  
    54  func (c clientConnection) RemoteAddr() gonet.Addr {
    55  	return &net.UnixAddr{Name: "unimplemented"}
    56  }
    57  
    58  func (c clientConnection) SetDeadline(t time.Time) error {
    59  	// Unimplemented
    60  	return nil
    61  }
    62  
    63  func (c clientConnection) SetReadDeadline(t time.Time) error {
    64  	// Unimplemented
    65  	return nil
    66  }
    67  
    68  func (c clientConnection) SetWriteDeadline(t time.Time) error {
    69  	// Unimplemented
    70  	return nil
    71  }
    72  
    73  func dialRequest(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (net.Conn, error) {
    74  	clientAssembly := &client{}
    75  	transportConfiguration := streamSettings.ProtocolSettings.(*Config)
    76  
    77  	assemblerConfigInstance, err := serial.GetInstanceOf(transportConfiguration.Assembler)
    78  	if err != nil {
    79  		return nil, newError("failed to get config instance of assembler").Base(err)
    80  	}
    81  	assembler, err := common.CreateObject(ctx, assemblerConfigInstance)
    82  	if err != nil {
    83  		return nil, newError("failed to create assembler").Base(err)
    84  	}
    85  	if typedAssembler, ok := assembler.(request.SessionAssemblerClient); !ok {
    86  		return nil, newError("failed to type assert assembler to SessionAssemblerClient")
    87  	} else {
    88  		clientAssembly.assembler = typedAssembler
    89  	}
    90  
    91  	roundtripperConfigInstance, err := serial.GetInstanceOf(transportConfiguration.Roundtripper)
    92  	if err != nil {
    93  		return nil, newError("failed to get config instance of roundtripper").Base(err)
    94  	}
    95  	roundtripper, err := common.CreateObject(ctx, roundtripperConfigInstance)
    96  	if err != nil {
    97  		return nil, newError("failed to create roundtripper").Base(err)
    98  	}
    99  	if typedRoundtripper, ok := roundtripper.(request.RoundTripperClient); !ok {
   100  		return nil, newError("failed to type assert roundtripper to RoundTripperClient")
   101  	} else {
   102  		clientAssembly.tripper = typedRoundtripper
   103  	}
   104  
   105  	clientAssembly.streamSettings = streamSettings
   106  	clientAssembly.dest = dest
   107  
   108  	clientAssembly.assembler.OnTransportClientAssemblyReady(clientAssembly)
   109  	clientAssembly.tripper.OnTransportClientAssemblyReady(clientAssembly)
   110  	return clientAssembly.dialRequestSession(ctx)
   111  }
   112  
   113  func dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
   114  	newError("creating connection to ", dest).WriteToLog(session.ExportIDToError(ctx))
   115  
   116  	conn, err := dialRequest(ctx, dest, streamSettings)
   117  	if err != nil {
   118  		return nil, newError("failed to dial request to ", dest).Base(err)
   119  	}
   120  	return internet.Connection(conn), nil
   121  }
   122  
   123  func init() {
   124  	common.Must(internet.RegisterTransportDialer(protocolName, dial))
   125  }