...
1
2
3
4
5 package fakenet
6
7 import (
8 "io"
9 "net"
10 "sync"
11 "time"
12 )
13
14
15
16
17
18 func NewConn(name string, in io.ReadCloser, out io.WriteCloser) net.Conn {
19 c := &fakeConn{
20 name: name,
21 reader: newFeeder(in.Read),
22 writer: newFeeder(out.Write),
23 in: in,
24 out: out,
25 }
26 go c.reader.run()
27 go c.writer.run()
28 return c
29 }
30
31 type fakeConn struct {
32 name string
33 reader *connFeeder
34 writer *connFeeder
35 in io.ReadCloser
36 out io.WriteCloser
37 }
38
39 type fakeAddr string
40
41
42
43
44
45 type connFeeder struct {
46 source func([]byte) (int, error)
47 input chan []byte
48 result chan feedResult
49 mu sync.Mutex
50 closed bool
51 done chan struct{}
52 }
53
54 type feedResult struct {
55 n int
56 err error
57 }
58
59 func (c *fakeConn) Close() error {
60 c.reader.close()
61 c.writer.close()
62 c.in.Close()
63 c.out.Close()
64 return nil
65 }
66
67 func (c *fakeConn) Read(b []byte) (n int, err error) { return c.reader.do(b) }
68 func (c *fakeConn) Write(b []byte) (n int, err error) { return c.writer.do(b) }
69 func (c *fakeConn) LocalAddr() net.Addr { return fakeAddr(c.name) }
70 func (c *fakeConn) RemoteAddr() net.Addr { return fakeAddr(c.name) }
71 func (c *fakeConn) SetDeadline(t time.Time) error { return nil }
72 func (c *fakeConn) SetReadDeadline(t time.Time) error { return nil }
73 func (c *fakeConn) SetWriteDeadline(t time.Time) error { return nil }
74 func (a fakeAddr) Network() string { return "fake" }
75 func (a fakeAddr) String() string { return string(a) }
76
77 func newFeeder(source func([]byte) (int, error)) *connFeeder {
78 return &connFeeder{
79 source: source,
80 input: make(chan []byte),
81 result: make(chan feedResult),
82 done: make(chan struct{}),
83 }
84 }
85
86 func (f *connFeeder) close() {
87 f.mu.Lock()
88 if !f.closed {
89 f.closed = true
90 close(f.done)
91 }
92 f.mu.Unlock()
93 }
94
95 func (f *connFeeder) do(b []byte) (n int, err error) {
96
97 select {
98 case f.input <- b:
99 case <-f.done:
100 return 0, io.EOF
101 }
102
103 select {
104 case r := <-f.result:
105 return r.n, r.err
106 case <-f.done:
107 return 0, io.EOF
108 }
109 }
110
111 func (f *connFeeder) run() {
112 var b []byte
113 for {
114
115 select {
116 case b = <-f.input:
117 case <-f.done:
118 return
119 }
120
121 n, err := f.source(b)
122
123 select {
124 case f.result <- feedResult{n: n, err: err}:
125 case <-f.done:
126 return
127 }
128 }
129 }
130
View as plain text