-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathdialer.go
More file actions
144 lines (132 loc) · 3.99 KB
/
Copy pathdialer.go
File metadata and controls
144 lines (132 loc) · 3.99 KB
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
//
//
// Tencent is pleased to support the open source community by making tRPC available.
//
// Copyright (C) 2023 Tencent.
// All rights reserved.
//
// If you have downloaded a copy of the tRPC source code from Tencent,
// please note that tRPC source code is licensed under the Apache 2.0 License,
// A copy of the Apache 2.0 License is included in this file.
//
//
package tnet
import (
"context"
"fmt"
"net"
"sync"
"time"
"trpc.group/trpc-go/tnet/internal/iovec"
"trpc.group/trpc-go/tnet/internal/netutil"
"trpc.group/trpc-go/tnet/internal/stat"
"trpc.group/trpc-go/tnet/metrics"
)
// DialTCP connects to the address on the named network within the timeout.
// Valid networks for DialTCP are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only).
func DialTCP(network, address string, timeout time.Duration) (Conn, error) {
return dialTCP(context.Background(), network, address, timeout)
}
// DialContextTCP connects to the address on the named network using the provided context.
// Valid networks for DialTCP are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only).
func DialContextTCP(ctx context.Context, network, address string) (Conn, error) {
return dialTCP(ctx, network, address, 0)
}
func dialTCP(ctx context.Context, network, address string, timeout time.Duration) (Conn, error) {
reportDialTCP()
switch network {
case "tcp", "tcp4", "tcp6":
default:
return nil, fmt.Errorf("DialTCP: unknown network %s", network)
}
d := net.Dialer{Timeout: timeout}
c, err := d.DialContext(ctx, network, address)
if err != nil {
return nil, fmt.Errorf("dial network %s, address %s with timeout %+v error: %w", network, address, timeout, err)
}
return newTCPConn(c, network)
}
// DialUDP connects to the address on the named network within the timeout.
// Valid networks for DialUDP are "udp", "udp4" (IPv4-only), "udp6" (IPv6-only).
func DialUDP(network, address string, timeout time.Duration) (PacketConn, error) {
reportDialUDP()
switch network {
case "udp", "udp4", "udp6":
default:
return nil, fmt.Errorf("DialUDP: unknown network %s", network)
}
return dialUDP(network, address, timeout)
}
func newTCPConn(c net.Conn, network string) (Conn, error) {
fd, err := netutil.GetFD(c)
if err != nil {
c.Close()
return nil, fmt.Errorf("dial tcp get fd error: %w", err)
}
conn := &tcpconn{
nfd: netFD{
fd: fd,
fdtype: fdTCP,
sock: c,
laddr: c.LocalAddr(),
raddr: c.RemoteAddr(),
network: network,
},
readTrigger: make(chan struct{}, 1),
closedFinished: make(chan struct{}, 1),
writevData: iovec.NewIOData(),
}
conn.inBuffer.Initialize()
conn.outBuffer.Initialize()
conn.closedReadBuf.Initialize(nil, ErrConnClosed)
if err := conn.nfd.Schedule(tcpOnRead, tcpOnWrite, tcpOnHup, conn); err != nil {
conn.Close()
return nil, fmt.Errorf("dial tcp net fd schedule error: %w", err)
}
metrics.Add(metrics.TCPConnsCreate, 1)
return conn, nil
}
func dialUDP(network, address string, timeout time.Duration) (PacketConn, error) {
c, err := net.DialTimeout(network, address, timeout)
if err != nil {
return nil, fmt.Errorf("dial network %s, address %s with timeout %+v error: %w", network, address, timeout, err)
}
fd, err := netutil.GetFD(c)
if err != nil {
c.Close()
return nil, fmt.Errorf("dial udp get fd error: %w", err)
}
conn := &udpconn{
nfd: netFD{
fd: fd,
fdtype: fdUDP,
sock: c,
laddr: c.LocalAddr(),
raddr: c.RemoteAddr(),
network: network,
udpBufferSize: defaultUDPBufferSize,
},
readTrigger: make(chan struct{}, 1),
}
conn.inBuffer.Initialize()
conn.outBuffer.Initialize()
if err := conn.schedule(); err != nil {
conn.Close()
return nil, fmt.Errorf("dial udp net fd schedule error: %w", err)
}
return conn, nil
}
var (
dialTCPReportOnce sync.Once
dialUDPReportOnce sync.Once
)
func reportDialTCP() {
dialTCPReportOnce.Do(func() {
stat.Report(stat.ClientAttr, stat.TCPAttr)
})
}
func reportDialUDP() {
dialUDPReportOnce.Do(func() {
stat.Report(stat.ClientAttr, stat.UDPAttr)
})
}