github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/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 break 77 default: 78 close(l.done) 79 } 80 return nil 81 } 82 83 // Addr reports the address of the listener. 84 func (l *Listener) Addr() net.Addr { return addr{} } 85 86 // Dial creates an in-memory full-duplex network connection, unblocks Accept by 87 // providing it the server half of the connection, and returns the client half 88 // of the connection. 89 func (l *Listener) Dial() (net.Conn, error) { 90 return l.DialContext(context.Background()) 91 } 92 93 // DialContext creates an in-memory full-duplex network connection, unblocks Accept by 94 // providing it the server half of the connection, and returns the client half 95 // of the connection. If ctx is Done, returns ctx.Err() 96 func (l *Listener) DialContext(ctx context.Context) (net.Conn, error) { 97 p1, p2 := newPipe(l.sz), newPipe(l.sz) 98 select { 99 case <-ctx.Done(): 100 return nil, ctx.Err() 101 case <-l.done: 102 return nil, errClosed 103 case l.ch <- &conn{p1, p2}: 104 return &conn{p2, p1}, nil 105 } 106 } 107 108 type pipe struct { 109 mu sync.Mutex 110 111 // buf contains the data in the pipe. It is a ring buffer of fixed capacity, 112 // with r and w pointing to the offset to read and write, respsectively. 113 // 114 // Data is read between [r, w) and written to [w, r), wrapping around the end 115 // of the slice if necessary. 116 // 117 // The buffer is empty if r == len(buf), otherwise if r == w, it is full. 118 // 119 // w and r are always in the range [0, cap(buf)) and [0, len(buf)]. 120 buf []byte 121 w, r int 122 123 wwait sync.Cond 124 rwait sync.Cond 125 126 // Indicate that a write/read timeout has occurred 127 wtimedout bool 128 rtimedout bool 129 130 wtimer *time.Timer 131 rtimer *time.Timer 132 133 closed bool 134 writeClosed bool 135 } 136 137 func newPipe(sz int) *pipe { 138 p := &pipe{buf: make([]byte, 0, sz)} 139 p.wwait.L = &p.mu 140 p.rwait.L = &p.mu 141 142 p.wtimer = time.AfterFunc(0, func() {}) 143 p.rtimer = time.AfterFunc(0, func() {}) 144 return p 145 } 146 147 func (p *pipe) empty() bool { 148 return p.r == len(p.buf) 149 } 150 151 func (p *pipe) full() bool { 152 return p.r < len(p.buf) && p.r == p.w 153 } 154 155 func (p *pipe) Read(b []byte) (n int, err error) { 156 p.mu.Lock() 157 defer p.mu.Unlock() 158 // Block until p has data. 159 for { 160 if p.closed { 161 return 0, io.ErrClosedPipe 162 } 163 if !p.empty() { 164 break 165 } 166 if p.writeClosed { 167 return 0, io.EOF 168 } 169 if p.rtimedout { 170 return 0, errTimeout 171 } 172 173 p.rwait.Wait() 174 } 175 wasFull := p.full() 176 177 n = copy(b, p.buf[p.r:len(p.buf)]) 178 p.r += n 179 if p.r == cap(p.buf) { 180 p.r = 0 181 p.buf = p.buf[:p.w] 182 } 183 184 // Signal a blocked writer, if any 185 if wasFull { 186 p.wwait.Signal() 187 } 188 189 return n, nil 190 } 191 192 func (p *pipe) Write(b []byte) (n int, err error) { 193 p.mu.Lock() 194 defer p.mu.Unlock() 195 if p.closed { 196 return 0, io.ErrClosedPipe 197 } 198 for len(b) > 0 { 199 // Block until p is not full. 200 for { 201 if p.closed || p.writeClosed { 202 return 0, io.ErrClosedPipe 203 } 204 if !p.full() { 205 break 206 } 207 if p.wtimedout { 208 return 0, errTimeout 209 } 210 211 p.wwait.Wait() 212 } 213 wasEmpty := p.empty() 214 215 end := cap(p.buf) 216 if p.w < p.r { 217 end = p.r 218 } 219 x := copy(p.buf[p.w:end], b) 220 b = b[x:] 221 n += x 222 p.w += x 223 if p.w > len(p.buf) { 224 p.buf = p.buf[:p.w] 225 } 226 if p.w == cap(p.buf) { 227 p.w = 0 228 } 229 230 // Signal a blocked reader, if any. 231 if wasEmpty { 232 p.rwait.Signal() 233 } 234 } 235 return n, nil 236 } 237 238 func (p *pipe) Close() error { 239 p.mu.Lock() 240 defer p.mu.Unlock() 241 p.closed = true 242 // Signal all blocked readers and writers to return an error. 243 p.rwait.Broadcast() 244 p.wwait.Broadcast() 245 return nil 246 } 247 248 func (p *pipe) closeWrite() error { 249 p.mu.Lock() 250 defer p.mu.Unlock() 251 p.writeClosed = true 252 // Signal all blocked readers and writers to return an error. 253 p.rwait.Broadcast() 254 p.wwait.Broadcast() 255 return nil 256 } 257 258 type conn struct { 259 io.Reader 260 io.Writer 261 } 262 263 func (c *conn) Close() error { 264 err1 := c.Reader.(*pipe).Close() 265 err2 := c.Writer.(*pipe).closeWrite() 266 if err1 != nil { 267 return err1 268 } 269 return err2 270 } 271 272 func (c *conn) SetDeadline(t time.Time) error { 273 c.SetReadDeadline(t) 274 c.SetWriteDeadline(t) 275 return nil 276 } 277 278 func (c *conn) SetReadDeadline(t time.Time) error { 279 p := c.Reader.(*pipe) 280 p.mu.Lock() 281 defer p.mu.Unlock() 282 p.rtimer.Stop() 283 p.rtimedout = false 284 if !t.IsZero() { 285 p.rtimer = time.AfterFunc(time.Until(t), func() { 286 p.mu.Lock() 287 defer p.mu.Unlock() 288 p.rtimedout = true 289 p.rwait.Broadcast() 290 }) 291 } 292 return nil 293 } 294 295 func (c *conn) SetWriteDeadline(t time.Time) error { 296 p := c.Writer.(*pipe) 297 p.mu.Lock() 298 defer p.mu.Unlock() 299 p.wtimer.Stop() 300 p.wtimedout = false 301 if !t.IsZero() { 302 p.wtimer = time.AfterFunc(time.Until(t), func() { 303 p.mu.Lock() 304 defer p.mu.Unlock() 305 p.wtimedout = true 306 p.wwait.Broadcast() 307 }) 308 } 309 return nil 310 } 311 312 func (*conn) LocalAddr() net.Addr { return addr{} } 313 func (*conn) RemoteAddr() net.Addr { return addr{} } 314 315 type addr struct{} 316 317 func (addr) Network() string { return "bufconn" } 318 func (addr) String() string { return "bufconn" }