GoPLS Viewer

Home|gopls/internal/fakenet/conn.go
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.
4
5package fakenet
6
7import (
8    "io"
9    "net"
10    "sync"
11    "time"
12)
13
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.
18func NewConn(name stringin io.ReadCloserout io.WriteClosernet.Conn {
19    c := &fakeConn{
20        name:   name,
21        readernewFeeder(in.Read),
22        writernewFeeder(out.Write),
23        in:     in,
24        out:    out,
25    }
26    go c.reader.run()
27    go c.writer.run()
28    return c
29}
30
31type fakeConn struct {
32    name   string
33    reader *connFeeder
34    writer *connFeeder
35    in     io.ReadCloser
36    out    io.WriteCloser
37}
38
39type fakeAddr string
40
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.
45type connFeeder struct {
46    source func([]byte) (interror)
47    input  chan []byte
48    result chan feedResult
49    mu     sync.Mutex
50    closed bool
51    done   chan struct{}
52}
53
54type feedResult struct {
55    n   int
56    err error
57}
58
59func (c *fakeConnClose() error {
60    c.reader.close()
61    c.writer.close()
62    c.in.Close()
63    c.out.Close()
64    return nil
65}
66
67func (c *fakeConnRead(b []byte) (n interr error)   { return c.reader.do(b) }
68func (c *fakeConnWrite(b []byte) (n interr error)  { return c.writer.do(b) }
69func (c *fakeConnLocalAddr() net.Addr                { return fakeAddr(c.name) }
70func (c *fakeConnRemoteAddr() net.Addr               { return fakeAddr(c.name) }
71func (c *fakeConnSetDeadline(t time.Timeerror      { return nil }
72func (c *fakeConnSetReadDeadline(t time.Timeerror  { return nil }
73func (c *fakeConnSetWriteDeadline(t time.Timeerror { return nil }
74func (a fakeAddrNetwork() string                     { return "fake" }
75func (a fakeAddrString() string                      { return string(a) }
76
77func newFeeder(source func([]byte) (interror)) *connFeeder {
78    return &connFeeder{
79        sourcesource,
80        input:  make(chan []byte),
81        resultmake(chan feedResult),
82        done:   make(chan struct{}),
83    }
84}
85
86func (f *connFeederclose() {
87    f.mu.Lock()
88    if !f.closed {
89        f.closed = true
90        close(f.done)
91    }
92    f.mu.Unlock()
93}
94
95func (f *connFeederdo(b []byte) (n interr error) {
96    // send the request to the worker
97    select {
98    case f.input <- b:
99    case <-f.done:
100        return 0io.EOF
101    }
102    // get the result from the worker
103    select {
104    case r := <-f.result:
105        return r.nr.err
106    case <-f.done:
107        return 0io.EOF
108    }
109}
110
111func (f *connFeederrun() {
112    var b []byte
113    for {
114        // wait for an input request
115        select {
116        case b = <-f.input:
117        case <-f.done:
118            return
119        }
120        // invoke the underlying method
121        nerr := f.source(b)
122        // send the result back to the requester
123        select {
124        case f.result <- feedResult{nnerrerr}:
125        case <-f.done:
126            return
127        }
128    }
129}
130
MembersX
newFeeder
connFeeder.close
connFeeder.run.BlockStmt.n
NewConn.name
feedResult
fakeConn.SetWriteDeadline
fakeAddr.String
connFeeder.source
connFeeder.mu
fakeConn.Close
fakeConn.Read.c
fakeConn.LocalAddr.c
net
fakeConn.name
fakeConn.out
fakeConn.Read.n
fakeAddr.Network
connFeeder.run.BlockStmt.err
sync
NewConn
connFeeder
fakeConn.RemoteAddr.c
fakeConn.SetDeadline.t
connFeeder.do
connFeeder.run.f
connFeeder.run
NewConn.c
fakeConn.reader
connFeeder.input
connFeeder.result
connFeeder.done
feedResult.n
fakeConn.SetDeadline.c
fakeConn.SetDeadline
fakeConn.SetReadDeadline
connFeeder.run.b
fakeConn.Write.n
fakeConn.SetReadDeadline.t
connFeeder.do.err
fakeConn
connFeeder.closed
fakeConn.Close.c
fakeConn.RemoteAddr
fakeConn.SetReadDeadline.c
connFeeder.do.n
NewConn.in
fakeConn.in
fakeConn.Write.err
fakeConn.LocalAddr
fakeConn.SetWriteDeadline.t
connFeeder.do.b
io
fakeConn.Read.err
fakeConn.Write.c
fakeConn.Write
fakeConn.Write.b
connFeeder.do.f
NewConn.out
fakeAddr
feedResult.err
fakeConn.SetWriteDeadline.c
newFeeder.source
fakeConn.Read
fakeConn.Read.b
fakeAddr.String.a
connFeeder.close.f
time
fakeConn.writer
fakeAddr.Network.a
Members
X