google.golang.org/grpc@v1.72.2/test/bufconn/bufconn.go (about) 1 /* 2 * 3 * Copyright 2017 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 // Package bufconn provides a net.Conn implemented by a buffer and related 20 // dialing and listening functionality. 21 package bufconn 22 23 import ( 24 "context" 25 "fmt" 26 "io" 27 "net" 28 "sync" 29 "time" 30 ) 31 32 // Listener implements a net.Listener that creates local, buffered net.Conns 33 // via its Accept and Dial method. 34 type Listener struct { 35 mu sync.Mutex 36 sz int 37 ch chan net.Conn 38 done chan struct{} 39 } 40 41 // Implementation of net.Error providing timeout 42 type netErrorTimeout struct { 43 error 44 } 45 46 func (e netErrorTimeout) Timeout() bool { return true } 47 func (e netErrorTimeout) Temporary() bool { return false } 48 49 var errClosed = fmt.Errorf("closed") 50 var errTimeout net.Error = netErrorTimeout{error: fmt.Errorf("i/o timeout")} 51 52 // Listen returns a Listener that can only be contacted by its own Dialers and 53 // creates buffered connections between the two. 54 func Listen(sz int) *Listener { 55 return &Listener{sz: sz, ch: make(chan net.Conn), done: make(chan struct{})} 56 } 57 58 // Accept blocks until Dial is called, then returns a net.Conn for the server 59 // half of the connection. 60 func (l *Listener) Accept() (net.Conn, error) { 61 select { 62 case <-l.done: 63 return nil, errClosed 64 case c := <-l.ch: 65 return c, nil 66 } 67 } 68 69 // Close stops the listener. 70 func (l *Listener) Close() error { 71 l.mu.Lock() 72 defer l.mu.Unlock() 73 select { 74 case <-l.done: 75 // Already closed. 76 default: 77 close(l.done) 78 } 79 return nil 80 } 81 82 // Addr reports the address of the listener. 83 func (l *Listener) Addr() net.Addr { return addr{} } 84 85 // Dial creates an in-memory full-duplex network connection, unblocks Accept by 86 // providing it the server half of the connection, and returns the client half 87 // of the connection. 88 func (l *Listener) Dial() (net.Conn, error) { 89 return l.DialContext(context.Background()) 90 } 91 92 // DialContext creates an in-memory full-duplex network connection, unblocks Accept by 93 // providing it the server half of the connection, and returns the client half 94 // of the connection. If ctx is Done, returns ctx.Err() 95 func (l *Listener) DialContext(ctx context.Context) (net.Conn, error) { 96 p1, p2 := newPipe(l.sz), newPipe(l.sz) 97 select { 98 case <-ctx.Done(): 99 return nil, ctx.Err() 100 case <-l.done: 101 return nil, errClosed 102 case l.ch <- &conn{p1, p2}: 103 return &conn{p2, p1}, nil 104 } 105 } 106 107 type pipe struct { 108 mu sync.Mutex 109 110 // buf contains the data in the pipe. It is a ring buffer of fixed capacity, 111 // with r and w pointing to the offset to read and write, respectively. 112 // 113 // Data is read between [r, w) and written to [w, r), wrapping around the end 114 // of the slice if necessary. 115 // 116 // The buffer is empty if r == len(buf), otherwise if r == w, it is full. 117 // 118 // w and r are always in the range [0, cap(buf)) and [0, len(buf)]. 119 buf []byte 120 w, r int 121 122 wwait sync.Cond 123 rwait sync.Cond 124 125 // Indicate that a write/read timeout has occurred 126 wtimedout bool 127 rtimedout bool 128 129 wtimer *time.Timer 130 rtimer *time.Timer 131 132 closed bool 133 writeClosed bool 134 } 135 136 func newPipe(sz int) *pipe { 137 p := &pipe{buf: make([]byte, 0, sz)} 138 p.wwait.L = &p.mu 139 p.rwait.L = &p.mu 140 141 p.wtimer = time.AfterFunc(0, func() {}) 142 p.rtimer = time.AfterFunc(0, func() {}) 143 return p 144 } 145 146 func (p *pipe) empty() bool { 147 return p.r == len(p.buf) 148 } 149 150 func (p *pipe) full() bool { 151 return p.r < len(p.buf) && p.r == p.w 152 } 153 154 func (p *pipe) Read(b []byte) (n int, err error) { 155 p.mu.Lock() 156 defer p.mu.Unlock() 157 // Block until p has data. 158 for { 159 if p.closed { 160 return 0, io.ErrClosedPipe 161 } 162 if !p.empty() { 163 break 164 } 165 if p.writeClosed { 166 return 0, io.EOF 167 } 168 if p.rtimedout { 169 return 0, errTimeout 170 } 171 172 p.rwait.Wait() 173 } 174 wasFull := p.full() 175 176 n = copy(b, p.buf[p.r:len(p.buf)]) 177 p.r += n 178 if p.r == cap(p.buf) { 179 p.r = 0 180 p.buf = p.buf[:p.w] 181 } 182 183 // Signal a blocked writer, if any 184 if wasFull { 185 p.wwait.Signal() 186 } 187 188 return n, nil 189 } 190 191 func (p *pipe) Write(b []byte) (n int, err error) { 192 p.mu.Lock() 193 defer p.mu.Unlock() 194 if p.closed { 195 return 0, io.ErrClosedPipe 196 } 197 for len(b) > 0 { 198 // Block until p is not full. 199 for { 200 if p.closed || p.writeClosed { 201 return 0, io.ErrClosedPipe 202 } 203 if !p.full() { 204 break 205 } 206 if p.wtimedout { 207 return 0, errTimeout 208 } 209 210 p.wwait.Wait() 211 } 212 wasEmpty := p.empty() 213 214 end := cap(p.buf) 215 if p.w < p.r { 216 end = p.r 217 } 218 x := copy(p.buf[p.w:end], b) 219 b = b[x:] 220 n += x 221 p.w += x 222 if p.w > len(p.buf) { 223 p.buf = p.buf[:p.w] 224 } 225 if p.w == cap(p.buf) { 226 p.w = 0 227 } 228 229 // Signal a blocked reader, if any. 230 if wasEmpty { 231 p.rwait.Signal() 232 } 233 } 234 return n, nil 235 } 236 237 func (p *pipe) Close() error { 238 p.mu.Lock() 239 defer p.mu.Unlock() 240 p.closed = true 241 // Signal all blocked readers and writers to return an error. 242 p.rwait.Broadcast() 243 p.wwait.Broadcast() 244 return nil 245 } 246 247 func (p *pipe) closeWrite() error { 248 p.mu.Lock() 249 defer p.mu.Unlock() 250 p.writeClosed = true 251 // Signal all blocked readers and writers to return an error. 252 p.rwait.Broadcast() 253 p.wwait.Broadcast() 254 return nil 255 } 256 257 type conn struct { 258 io.Reader 259 io.Writer 260 } 261 262 func (c *conn) Close() error { 263 err1 := c.Reader.(*pipe).Close() 264 err2 := c.Writer.(*pipe).closeWrite() 265 if err1 != nil { 266 return err1 267 } 268 return err2 269 } 270 271 func (c *conn) SetDeadline(t time.Time) error { 272 c.SetReadDeadline(t) 273 c.SetWriteDeadline(t) 274 return nil 275 } 276 277 func (c *conn) SetReadDeadline(t time.Time) error { 278 p := c.Reader.(*pipe) 279 p.mu.Lock() 280 defer p.mu.Unlock() 281 p.rtimer.Stop() 282 p.rtimedout = false 283 if !t.IsZero() { 284 p.rtimer = time.AfterFunc(time.Until(t), func() { 285 p.mu.Lock() 286 defer p.mu.Unlock() 287 p.rtimedout = true 288 p.rwait.Broadcast() 289 }) 290 } 291 return nil 292 } 293 294 func (c *conn) SetWriteDeadline(t time.Time) error { 295 p := c.Writer.(*pipe) 296 p.mu.Lock() 297 defer p.mu.Unlock() 298 p.wtimer.Stop() 299 p.wtimedout = false 300 if !t.IsZero() { 301 p.wtimer = time.AfterFunc(time.Until(t), func() { 302 p.mu.Lock() 303 defer p.mu.Unlock() 304 p.wtimedout = true 305 p.wwait.Broadcast() 306 }) 307 } 308 return nil 309 } 310 311 func (*conn) LocalAddr() net.Addr { return addr{} } 312 func (*conn) RemoteAddr() net.Addr { return addr{} } 313 314 type addr struct{} 315 316 func (addr) Network() string { return "bufconn" } 317 func (addr) String() string { return "bufconn" }