-
Notifications
You must be signed in to change notification settings - Fork 0
/
do.go
58 lines (51 loc) · 1.32 KB
/
do.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
package listeners
import (
"net"
"sync"
"time"
)
// DoListener is a net.TCPListener with keep-alive timeouts and
// ability to execute the given func on first accept being called.
type DoListener struct {
*net.TCPListener
once sync.Once
do func()
fn func() (net.Conn, error)
}
// NewDoListener instance.
func NewDoListener(l *net.TCPListener) *DoListener {
ln := &DoListener{TCPListener: l}
ln.fn = ln.firstAccept
return ln
}
// Accept implements net.Listener interface.
func (ln *DoListener) Accept() (net.Conn, error) {
return ln.fn()
}
// OnFirstAcceptDo sets func that will be fired on the first Accept execution.
// Use it like:
// l, err := net.ListenTCP("tcp", addr)
// // catch err
// dl := NewDoListener(l).OnFirstAcceptDo(func() {fmt.Println("i'm ready to accept")})
func (ln *DoListener) OnFirstAcceptDo(fn func()) *DoListener {
ln.do = fn
return ln
}
// firstAccept atomically changes accept method and executes Do func.
func (ln *DoListener) firstAccept() (net.Conn, error) {
ln.once.Do(func() {
ln.fn = ln.accept
ln.do()
})
return ln.fn()
}
// accept internal method that implements net.Listener interface.
func (ln *DoListener) accept() (net.Conn, error) {
tc, err := ln.AcceptTCP()
if err != nil {
return nil, err
}
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(3 * time.Minute)
return tc, nil
}