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