github.com/volts-dev/volts@v0.0.0-20240120094013-5e9c65924106/transport/tcp.go (about)

     1  package transport
     2  
     3  import (
     4  	"crypto/tls"
     5  	"net"
     6  
     7  	vaddr "github.com/volts-dev/volts/internal/addr"
     8  	vnet "github.com/volts-dev/volts/internal/net"
     9  	mls "github.com/volts-dev/volts/internal/tls"
    10  )
    11  
    12  type tcpTransport struct {
    13  	config *Config
    14  }
    15  
    16  func NewTCPTransport(opts ...Option) ITransport {
    17  	return &tcpTransport{
    18  		config: newConfig(opts...),
    19  	}
    20  }
    21  
    22  func (self *tcpTransport) Dial(addr string, opts ...DialOption) (IClient, error) {
    23  	dialCfg := DialConfig{
    24  		DialTimeout:  self.config.DialTimeout,
    25  		ReadTimeout:  self.config.ReadTimeout,
    26  		WriteTimeout: self.config.WriteTimeout,
    27  	}
    28  	dialCfg.Init(opts...)
    29  
    30  	var conn net.Conn
    31  	var err error
    32  
    33  	// TODO: support dial option here rather than using internal config
    34  	if self.config.Secure || self.config.TlsConfig != nil {
    35  		config := self.config.TlsConfig
    36  		if config == nil {
    37  			config = &tls.Config{
    38  				InsecureSkipVerify: true,
    39  			}
    40  		}
    41  		conn, err = tls.DialWithDialer(&net.Dialer{Timeout: dialCfg.DialTimeout}, "tcp", addr, config)
    42  	} else {
    43  		conn, err = net.DialTimeout("tcp", addr, dialCfg.DialTimeout)
    44  	}
    45  
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	//encBuf := bufio.NewWriter(conn)
    51  	return &tcpTransportClient{
    52  		tcpTransportSocket: *NewTcpTransportSocket(conn, dialCfg.ReadTimeout, dialCfg.WriteTimeout),
    53  		transport:          self,
    54  		config:             dialCfg,
    55  		conn:               conn,
    56  	}, nil
    57  }
    58  
    59  func (self *tcpTransport) Listen(addr string, opts ...ListenOption) (IListener, error) {
    60  	var options ListenConfig
    61  	for _, o := range opts {
    62  		o(&options)
    63  	}
    64  
    65  	var l net.Listener
    66  	var err error
    67  
    68  	// TODO: support use of listen options
    69  	if self.config.Secure || self.config.TlsConfig != nil {
    70  		config := self.config.TlsConfig
    71  
    72  		fn := func(addr string) (net.Listener, error) {
    73  			if config == nil {
    74  				hosts := []string{addr}
    75  
    76  				// check if its a valid host:port
    77  				if host, _, err := net.SplitHostPort(addr); err == nil {
    78  					if len(host) == 0 {
    79  						hosts = vaddr.IPs()
    80  					} else {
    81  						hosts = []string{host}
    82  					}
    83  				}
    84  
    85  				// generate a certificate
    86  				cert, err := mls.Certificate(hosts...)
    87  				if err != nil {
    88  					return nil, err
    89  				}
    90  				config = &tls.Config{Certificates: []tls.Certificate{cert}}
    91  			}
    92  			return tls.Listen("tcp", addr, config)
    93  		}
    94  
    95  		l, err = vnet.Listen(addr, fn)
    96  	} else {
    97  		fn := func(addr string) (net.Listener, error) {
    98  			return net.Listen("tcp", addr)
    99  		}
   100  
   101  		l, err = vnet.Listen(addr, fn)
   102  	}
   103  
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	self.config.Listener = &tcpTransportListener{
   109  		transport: self,
   110  		listener:  l,
   111  	}
   112  
   113  	return self.config.Listener, nil
   114  }
   115  
   116  func (t *tcpTransport) Init(opts ...Option) error {
   117  	for _, o := range opts {
   118  		o(t.config)
   119  	}
   120  	return nil
   121  }
   122  
   123  func (t *tcpTransport) Config() *Config {
   124  	return t.config
   125  }
   126  
   127  func (*tcpTransport) String() string {
   128  	return "TcpTransport"
   129  }
   130  
   131  func (*tcpTransport) Protocol() string {
   132  	return "TCP"
   133  }