-
Notifications
You must be signed in to change notification settings - Fork 0
/
simulator.go
111 lines (93 loc) · 1.84 KB
/
simulator.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
package librmonitor
import (
"bufio"
"io"
"net"
"sync"
"time"
)
type Simulator struct {
sync.Mutex
clients map[string]chan []byte
source bufio.Reader
stopCh chan struct{}
listener *net.TCPListener
connErrors chan error
connNotifs chan string
}
func (s *Simulator) ConnErrors() chan error {
return s.connErrors
}
func (s *Simulator) ConnNotifs() chan string {
return s.connNotifs
}
func Simulate(addr *net.TCPAddr, source io.Reader, stopCh chan struct{}) (*Simulator, error) {
buf := bufio.NewReader(source)
listener, err := net.ListenTCP("tcp", addr)
if err != nil {
return nil, err
}
var svr = &Simulator{
clients: make(map[string]chan []byte),
source: *buf,
listener: listener,
connNotifs: make(chan string),
connErrors: make(chan error),
}
return svr, nil
}
func (s *Simulator) readAndServe() error {
for {
select {
case <-s.stopCh:
return nil
default:
if len(s.clients) > 0 {
line, _, err := s.source.ReadLine()
if err != nil {
return err
}
for _, l := range s.clients {
l <- line
}
time.Sleep(2 * time.Second)
}
}
}
}
func client(conn *net.TCPConn, stopCh chan struct{}, source chan []byte) error {
for {
select {
case <-stopCh:
return nil
case line := <-source:
line = append(line, '\n')
if _, err := conn.Write(line); err != nil {
return err
}
}
}
}
func (s *Simulator) Run() {
go s.readAndServe()
for {
c, err := s.listener.AcceptTCP()
if err != nil {
s.connErrors <- err
continue
}
s.Lock()
lch := make(chan []byte)
s.clients[c.RemoteAddr().String()] = lch
s.connNotifs <- c.RemoteAddr().String()
go func() {
if err := client(c, s.stopCh, lch); err != nil {
s.connErrors <- err
} else {
s.connNotifs <- "client disconnected"
}
delete(s.clients, c.RemoteAddr().String())
}()
s.Unlock()
}
}