...
1
18
19 package testutils
20
21 import (
22 "net"
23 "sync"
24 )
25
26 type tempError struct{}
27
28 func (*tempError) Error() string {
29 return "restartable listener temporary error"
30 }
31 func (*tempError) Temporary() bool {
32 return true
33 }
34
35
36
37 type RestartableListener struct {
38 lis net.Listener
39
40 mu sync.Mutex
41 stopped bool
42 conns []net.Conn
43 }
44
45
46 func NewRestartableListener(l net.Listener) *RestartableListener {
47 return &RestartableListener{lis: l}
48 }
49
50
51
52
53
54
55 func (l *RestartableListener) Accept() (net.Conn, error) {
56 conn, err := l.lis.Accept()
57 if err != nil {
58 return nil, err
59 }
60
61 l.mu.Lock()
62 defer l.mu.Unlock()
63 if l.stopped {
64 conn.Close()
65 return nil, &tempError{}
66 }
67 l.conns = append(l.conns, conn)
68 return conn, nil
69 }
70
71
72 func (l *RestartableListener) Close() error {
73 return l.lis.Close()
74 }
75
76
77 func (l *RestartableListener) Addr() net.Addr {
78 return l.lis.Addr()
79 }
80
81
82
83 func (l *RestartableListener) Stop() {
84 l.mu.Lock()
85 l.stopped = true
86 for _, conn := range l.conns {
87 conn.Close()
88 }
89 l.conns = nil
90 l.mu.Unlock()
91 }
92
93
94 func (l *RestartableListener) Restart() {
95 l.mu.Lock()
96 l.stopped = false
97 l.mu.Unlock()
98 }
99
View as plain text