...
1
2
3
4
5 package jsonrpc2
6
7 import (
8 "context"
9 "io"
10 "net"
11 "os"
12 )
13
14
15
16
17
18 type NetListenOptions struct {
19 NetListenConfig net.ListenConfig
20 NetDialer net.Dialer
21 }
22
23
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
33 type netListener struct {
34 net net.Listener
35 }
36
37
38 func (l *netListener) Accept(context.Context) (io.ReadWriteCloser, error) {
39 return l.net.Accept()
40 }
41
42
43
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
57 func (l *netListener) Dialer() Dialer {
58 return NetDialer(l.net.Addr().Network(), l.net.Addr().String(), net.Dialer{})
59 }
60
61
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
81
82
83
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
92 type netPiper struct {
93 done chan struct{}
94 dialed chan io.ReadWriteCloser
95 }
96
97
98 func (l *netPiper) Accept(context.Context) (io.ReadWriteCloser, error) {
99
100
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
115
116 func (l *netPiper) Close() error {
117
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 }
139
View as plain text