-
Notifications
You must be signed in to change notification settings - Fork 33
/
dialer.go
146 lines (130 loc) · 3.72 KB
/
dialer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package drpc
import (
"context"
"crypto/tls"
"github.com/gogf/gf/v2/container/gtype"
"github.com/osgochina/dmicro/drpc/internal"
"github.com/osgochina/dmicro/drpc/netproto/kcp"
"github.com/osgochina/dmicro/drpc/netproto/quic"
"github.com/osgochina/dmicro/utils"
"net"
"time"
)
// Dialer 拨号器
type Dialer struct {
//网络类型
network string
//本地使用的地址端口
localAddr net.Addr
//tls配置信息
tlsConfig *tls.Config
//拨号器拨号超时时间
dialTimeout time.Duration
//拨号器重复拨号的时间间隔
redialInterval time.Duration
//拨号器重复拨号的最大次数
redialTimes int
}
// NewDialer 创建一个拨号器
func NewDialer(localAddr net.Addr, tlsConfig *tls.Config, dialTimeout, redialInterval time.Duration, redialTimes int) *Dialer {
return &Dialer{
network: localAddr.Network(),
localAddr: localAddr,
tlsConfig: tlsConfig,
dialTimeout: dialTimeout,
redialTimes: redialTimes,
redialInterval: redialInterval,
}
}
// Network 获取拨号器的网络类型
func (that *Dialer) Network() string {
return that.network
}
// LocalAddr 获取拨号器本地使用的端口地址
func (that *Dialer) LocalAddr() net.Addr {
return that.localAddr
}
// TLSConfig 获取tls配置信息
func (that *Dialer) TLSConfig() *tls.Config {
return that.tlsConfig
}
// DialTimeout 获取拨号器拨号时候的超时时间
func (that *Dialer) DialTimeout() time.Duration {
return that.dialTimeout
}
// RedialInterval 返回拨号器重试拨号时候的间隔
func (that *Dialer) RedialInterval() time.Duration {
return that.redialInterval
}
// RedialTimes 拨号器重复拨号的最大次数
func (that *Dialer) RedialTimes() int {
return that.redialTimes
}
// Dial 拨号链接地址 addr
func (that *Dialer) Dial(addr string) (net.Conn, error) {
return that.dialWithRetry(addr, "", nil)
}
// 拨号,如果拨号失败,则重试 redialTimes 次
func (that *Dialer) dialWithRetry(addr, sessID string, fn func(conn net.Conn) error) (net.Conn, error) {
conn, err := that.dialOne(addr)
if err == nil {
if fn == nil {
return conn, nil
} else {
err = fn(conn)
if err == nil {
return conn, nil
}
}
}
redialTimes := that.newRedialCounter()
for redialTimes.Add(-1) > 0 {
time.Sleep(that.redialInterval)
if sessID == "" {
internal.Debugf(context.TODO(), "trying to redial... (network:%s, addr:%s)", that.network, addr)
} else {
internal.Debugf(context.TODO(), "trying to redial... (network:%s, addr:%s, id:%s)", that.network, addr, sessID)
}
conn, err = that.dialOne(addr)
if err == nil {
if fn == nil {
return conn, nil
} else {
err = fn(conn)
if err == nil {
return conn, nil
}
}
}
}
return nil, err
}
//拨号一次
func (that *Dialer) dialOne(addr string) (net.Conn, error) {
if network := asQUIC(that.network); network != "" {
ctx := context.Background()
if that.dialTimeout > 0 {
ctx, _ = context.WithTimeout(ctx, that.dialTimeout)
}
var tlsConf = that.tlsConfig
if tlsConf == nil {
tlsConf = utils.GenerateTLSConfigForClient()
}
return quic.DialAddrContext(ctx, network, that.localAddr.(*utils.FakeAddr).UdpAddr(), addr, tlsConf, nil)
}
if network := asKCP(that.network); network != "" {
return kcp.DialAddrContext(network, that.localAddr.(*utils.FakeAddr).UdpAddr(), addr, that.tlsConfig, kcp.DefaultDataShards, kcp.DefaultParityShards)
}
dialer := &net.Dialer{
LocalAddr: that.localAddr,
Timeout: that.dialTimeout,
}
//使用tls加密拨号
if that.tlsConfig != nil {
return tls.DialWithDialer(dialer, that.network, addr, that.tlsConfig)
}
return dialer.Dial(that.network, addr)
}
func (that *Dialer) newRedialCounter() *gtype.Int {
return gtype.NewInt(that.redialTimes)
}