-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathclient.go
More file actions
108 lines (87 loc) · 1.93 KB
/
client.go
File metadata and controls
108 lines (87 loc) · 1.93 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
package tinytcp
import (
"crypto/tls"
"io"
"net"
"sync"
)
// Client represents a TCP/TLS client.
type Client struct {
connection net.Conn
closeSync sync.Once
onCloseHandler func()
}
// Dial connects to the TCP socket and creates new Client.
func Dial(address string) (*Client, error) {
connection, err := net.Dial("tcp", address)
if err != nil {
return nil, err
}
return &Client{
connection: connection,
}, nil
}
// DialTLS connects to the TCP socket and performs TLS handshake, and then creates new Client.
// Connection is TLS secured.
func DialTLS(address string, tlsConfig *tls.Config) (*Client, error) {
connection, err := tls.Dial("tcp", address, tlsConfig)
if err != nil {
return nil, err
}
return &Client{
connection: connection,
}, nil
}
// Close closes the socket.
func (c *Client) Close() error {
var err error
c.closeSync.Do(func() {
e := c.connection.Close()
if e != nil {
err = e
}
if c.onCloseHandler != nil {
c.onCloseHandler()
}
})
return err
}
// Read conforms to the io.Reader interface.
func (c *Client) Read(b []byte) (int, error) {
n, err := c.connection.Read(b)
if err != nil {
if isBrokenPipe(err) {
_ = c.Close()
return n, io.EOF
}
return n, err
}
return n, nil
}
// Write conforms to the io.Writer interface.
func (c *Client) Write(b []byte) (int, error) {
n, err := c.connection.Write(b)
if err != nil {
if isBrokenPipe(err) {
_ = c.Close()
return n, io.EOF
}
return n, err
}
return n, nil
}
// Unwrap returns underlying TCP connection.
func (c *Client) Unwrap() net.Conn {
return c.connection
}
// UnwrapTLS tries to return underlying tls.Conn instance.
func (c *Client) UnwrapTLS() (*tls.Conn, bool) {
if conn, ok := c.connection.(*tls.Conn); ok {
return conn, true
}
return nil, false
}
// OnClose sets a handler called on closing connection (either by client or server).
func (c *Client) OnClose(handler func()) {
c.onCloseHandler = handler
}