1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
14 // NewConn returns a net.Conn built on top of the supplied reader and writer.
15 // It decouples the read and write on the conn from the underlying stream
16 // to enable Close to abort ones that are in progress.
17 // It's primary use is to fake a network connection from stdin and stdout.
18 func NewConn(name string, in io.ReadCloser, out io.WriteCloser) net.Conn {
21 reader: newFeeder(in.Read),
22 writer: newFeeder(out.Write),
31 type fakeConn struct {
41 // connFeeder serializes calls to the source function (io.Reader.Read or
42 // io.Writer.Write) by delegating them to a channel. This also allows calls to
43 // be intercepted when the connection is closed, and cancelled early if the
44 // connection is closed while the calls are still outstanding.
45 type connFeeder struct {
46 source func([]byte) (int, error)
48 result chan feedResult
54 type feedResult struct {
59 func (c *fakeConn) Close() error {
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) }
77 func newFeeder(source func([]byte) (int, error)) *connFeeder {
80 input: make(chan []byte),
81 result: make(chan feedResult),
82 done: make(chan struct{}),
86 func (f *connFeeder) close() {
95 func (f *connFeeder) do(b []byte) (n int, err error) {
96 // send the request to the worker
102 // get the result from the worker
104 case r := <-f.result:
111 func (f *connFeeder) run() {
114 // wait for an input request
120 // invoke the underlying method
121 n, err := f.source(b)
122 // send the result back to the requester
124 case f.result <- feedResult{n: n, err: err}: