This repository has been archived by the owner on Feb 12, 2018. It is now read-only.
/
conn.go
103 lines (81 loc) · 1.82 KB
/
conn.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
package wire
import (
"net"
"sync"
"sync/atomic"
"time"
"github.com/erkl/xo"
)
const bufferSize = 8 * 1024
// Global buffer pool.
var buffers = &sync.Pool{
New: func() interface{} {
return make([]byte, 2*bufferSize)
},
}
type conn struct {
// Buffered I/O primitives.
xo.Reader
xo.Writer
// Buffer used for this conn's xo.Reader and xo.Writer instances.
buf []byte
// The actual connection.
raw net.Conn
// Owning Transport.
t *Transport
// Variable used for atomic operations when synchronizing
// connection shutdown.
state uint32
// Connection identifiers.
tls bool
addr string
// How long has this connection been idle?
idleSince time.Time
// Linked list pointer.
next *conn
}
func (c *conn) maybeClose(reuse bool) {
const halfReused = 1
const halfClosed = 2
// As far as the caller is concerned, can the connection be kept alive
// and reused for another round-trip?
var next uint32
if reuse {
next = halfReused
} else {
next = halfClosed
}
// Use an atomic swap to make sure we only close the connection once.
prev := atomic.SwapUint32(&c.state, next)
// Don't do anything unless we're the latter of the two "ends" (reading
// and writing) to finish with the connection.
if prev == 0 {
return
}
// Either reuse or close the connection.
if reuse && prev == halfReused {
c.raw.SetReadDeadline(time.Time{})
c.state = 0
c.t.putIdle(c)
} else {
c.Close()
}
}
func (c *conn) Close() error {
// Allow the connection's buffer to be reused.
buffers.Put(c.buf)
c.raw.Close()
return nil
}
func newConn(raw net.Conn, t *Transport, tls bool, addr string) *conn {
buf := buffers.Get().([]byte)
return &conn{
Reader: xo.NewReader(raw, buf[:bufferSize]),
Writer: xo.NewWriter(raw, buf[bufferSize:]),
raw: raw,
buf: buf,
t: t,
tls: tls,
addr: addr,
}
}