golang.org/x/tools@v0.21.1-0.20240520172518-788d39e776b1/internal/jsonrpc2_v2/net.go (about) 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 5 package jsonrpc2 6 7 import ( 8 "context" 9 "io" 10 "net" 11 "os" 12 ) 13 14 // This file contains implementations of the transport primitives that use the standard network 15 // package. 16 17 // NetListenOptions is the optional arguments to the NetListen function. 18 type NetListenOptions struct { 19 NetListenConfig net.ListenConfig 20 NetDialer net.Dialer 21 } 22 23 // NetListener returns a new Listener that listens on a socket using the net package. 24 func NetListener(ctx context.Context, network, address string, options NetListenOptions) (Listener, error) { 25 ln, err := options.NetListenConfig.Listen(ctx, network, address) 26 if err != nil { 27 return nil, err 28 } 29 return &netListener{net: ln}, nil 30 } 31 32 // netListener is the implementation of Listener for connections made using the net package. 33 type netListener struct { 34 net net.Listener 35 } 36 37 // Accept blocks waiting for an incoming connection to the listener. 38 func (l *netListener) Accept(context.Context) (io.ReadWriteCloser, error) { 39 return l.net.Accept() 40 } 41 42 // Close will cause the listener to stop listening. It will not close any connections that have 43 // already been accepted. 44 func (l *netListener) Close() error { 45 addr := l.net.Addr() 46 err := l.net.Close() 47 if addr.Network() == "unix" { 48 rerr := os.Remove(addr.String()) 49 if rerr != nil && err == nil { 50 err = rerr 51 } 52 } 53 return err 54 } 55 56 // Dialer returns a dialer that can be used to connect to the listener. 57 func (l *netListener) Dialer() Dialer { 58 return NetDialer(l.net.Addr().Network(), l.net.Addr().String(), net.Dialer{}) 59 } 60 61 // NetDialer returns a Dialer using the supplied standard network dialer. 62 func NetDialer(network, address string, nd net.Dialer) Dialer { 63 return &netDialer{ 64 network: network, 65 address: address, 66 dialer: nd, 67 } 68 } 69 70 type netDialer struct { 71 network string 72 address string 73 dialer net.Dialer 74 } 75 76 func (n *netDialer) Dial(ctx context.Context) (io.ReadWriteCloser, error) { 77 return n.dialer.DialContext(ctx, n.network, n.address) 78 } 79 80 // NetPipeListener returns a new Listener that listens using net.Pipe. 81 // It is only possibly to connect to it using the Dialer returned by the 82 // Dialer method, each call to that method will generate a new pipe the other 83 // side of which will be returned from the Accept call. 84 func NetPipeListener(ctx context.Context) (Listener, error) { 85 return &netPiper{ 86 done: make(chan struct{}), 87 dialed: make(chan io.ReadWriteCloser), 88 }, nil 89 } 90 91 // netPiper is the implementation of Listener build on top of net.Pipes. 92 type netPiper struct { 93 done chan struct{} 94 dialed chan io.ReadWriteCloser 95 } 96 97 // Accept blocks waiting for an incoming connection to the listener. 98 func (l *netPiper) Accept(context.Context) (io.ReadWriteCloser, error) { 99 // Block until the pipe is dialed or the listener is closed, 100 // preferring the latter if already closed at the start of Accept. 101 select { 102 case <-l.done: 103 return nil, errClosed 104 default: 105 } 106 select { 107 case rwc := <-l.dialed: 108 return rwc, nil 109 case <-l.done: 110 return nil, errClosed 111 } 112 } 113 114 // Close will cause the listener to stop listening. It will not close any connections that have 115 // already been accepted. 116 func (l *netPiper) Close() error { 117 // unblock any accept calls that are pending 118 close(l.done) 119 return nil 120 } 121 122 func (l *netPiper) Dialer() Dialer { 123 return l 124 } 125 126 func (l *netPiper) Dial(ctx context.Context) (io.ReadWriteCloser, error) { 127 client, server := net.Pipe() 128 129 select { 130 case l.dialed <- server: 131 return client, nil 132 133 case <-l.done: 134 client.Close() 135 server.Close() 136 return nil, errClosed 137 } 138 }