This repository has been archived by the owner on Jun 12, 2022. It is now read-only.
/
net.go
134 lines (112 loc) · 3.27 KB
/
net.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
package net
import (
"io"
"net"
)
// DuplexConn is a net.Conn that allows for closing only the reader or writer end of
// it, supporting half-open state.
type DuplexConn interface {
net.Conn
// Closes the Read end of the connection, allowing for the release of resources.
// No more reads should happen.
CloseRead() error
// Closes the Write end of the connection. An EOF or FIN signal may be
// sent to the connection target.
CloseWrite() error
}
type duplexConnAdaptor struct {
DuplexConn
r io.Reader
w io.Writer
}
func (dc *duplexConnAdaptor) Read(b []byte) (int, error) {
return dc.r.Read(b)
}
func (dc *duplexConnAdaptor) WriteTo(w io.Writer) (int64, error) {
return io.Copy(w, dc.r)
}
func (dc *duplexConnAdaptor) CloseRead() error {
return dc.DuplexConn.CloseRead()
}
func (dc *duplexConnAdaptor) Write(b []byte) (int, error) {
return dc.w.Write(b)
}
func (dc *duplexConnAdaptor) ReadFrom(r io.Reader) (int64, error) {
return io.Copy(dc.w, r)
}
func (dc *duplexConnAdaptor) CloseWrite() error {
return dc.DuplexConn.CloseWrite()
}
// WrapDuplexConn wraps an existing DuplexConn with new Reader and Writer, but
// preserving the original CloseRead() and CloseWrite().
func WrapDuplexConn(c DuplexConn, r io.Reader, w io.Writer) DuplexConn {
conn := c
// We special-case duplexConnAdaptor to avoid multiple levels of nesting.
if a, ok := c.(*duplexConnAdaptor); ok {
conn = a.DuplexConn
}
return &duplexConnAdaptor{DuplexConn: conn, r: r, w: w}
}
func copyOneWay(leftConn, rightConn DuplexConn) (int64, error) {
n, err := io.Copy(leftConn, rightConn)
// Send FIN to indicate EOF
leftConn.CloseWrite()
// Release reader resources
rightConn.CloseRead()
return n, err
}
// Relay copies between left and right bidirectionally. Returns number of
// bytes copied from right to left, from left to right, and any error occurred.
// Relay allows for half-closed connections: if one side is done writing, it can
// still read all remaining data from its peer.
func Relay(leftConn, rightConn DuplexConn) (int64, int64, error) {
type res struct {
N int64
Err error
}
ch := make(chan res)
go func() {
n, err := copyOneWay(rightConn, leftConn)
ch <- res{n, err}
}()
n, err := copyOneWay(leftConn, rightConn)
rs := <-ch
if err == nil {
err = rs.Err
}
return n, rs.N, err
}
type UDPPacketConn interface {
net.PacketConn
ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error)
WriteToUDP(b []byte, addr *net.UDPAddr) (int, error)
ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error)
}
type ConnectionError struct {
// TODO: create status enums and move to metrics.go
Status string
Message string
Cause error
}
func NewConnectionError(status, message string, cause error) *ConnectionError {
return &ConnectionError{Status: status, Message: message, Cause: cause}
}
type addr struct {
address string
network string
}
func (a *addr) String() string {
return a.address
}
func (a *addr) Network() string {
return a.network
}
// NewAddr returns a net.Addr that holds an address of the form `host:port` with a domain name or IP as host.
// Used for SOCKS addressing.
func NewAddr(address, network string) net.Addr {
return &addr{
address: address,
network: network,
}
}