88 lines
1.4 KiB
Go
88 lines
1.4 KiB
Go
package net
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
type Client struct {
|
|
Name string
|
|
|
|
Network string
|
|
Address string
|
|
TLSConfig *tls.Config
|
|
HandshakeTimeout time.Duration
|
|
KeepAlive time.Duration
|
|
LocalAddress net.Addr
|
|
|
|
MaxConnections int
|
|
}
|
|
|
|
func (c *Client) Dial() (net.Conn, error) {
|
|
if err := c.Validate(); nil != err {
|
|
return nil, err
|
|
}
|
|
|
|
var deadline time.Time
|
|
if 0 != c.HandshakeTimeout {
|
|
deadline = time.Now().Add(c.HandshakeTimeout)
|
|
}
|
|
|
|
d := &net.Dialer{
|
|
KeepAlive: c.KeepAlive,
|
|
Deadline: deadline,
|
|
LocalAddr: c.LocalAddress,
|
|
}
|
|
|
|
conn, err := d.Dial(c.Network, c.Address)
|
|
if nil != err {
|
|
return nil, err
|
|
}
|
|
|
|
if nil != c.TLSConfig {
|
|
cfg := c.TLSConfig.Clone()
|
|
tlsConn := tls.Client(conn, cfg)
|
|
if err := tlsConn.Handshake(); err != nil {
|
|
tlsConn.Close()
|
|
return nil, err
|
|
}
|
|
if !cfg.InsecureSkipVerify {
|
|
if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
conn = tlsConn
|
|
}
|
|
|
|
return conn, nil
|
|
}
|
|
|
|
func (c *Client) Validate() error {
|
|
if "" == c.Name {
|
|
c.Name = "Client"
|
|
}
|
|
|
|
if "" == c.Network {
|
|
return fmt.Errorf("Client: Network is not valid")
|
|
}
|
|
|
|
if "" == c.Address {
|
|
return fmt.Errorf("Client: Address is not valid")
|
|
}
|
|
|
|
if 0 >= c.MaxConnections {
|
|
c.MaxConnections = 1
|
|
}
|
|
|
|
if 0 >= c.KeepAlive {
|
|
c.KeepAlive = DefaultKeepAlive
|
|
}
|
|
if 0 >= c.HandshakeTimeout {
|
|
c.HandshakeTimeout = DefaultHandshakeTimeout
|
|
}
|
|
|
|
return nil
|
|
}
|