pipe copies from src to dst using a manual read/write loop with a pooled buffer and returns the total bytes transferred. io.CopyBuffer is not used because it provides no opportunity to call SetReadDeadline/SetWriteDeadline between individual I/O operations.
(dst, src net.Conn, connCtx *ConnContext)
| 277 | // io.CopyBuffer is not used because it provides no opportunity |
| 278 | // to call SetReadDeadline/SetWriteDeadline between individual I/O operations. |
| 279 | func (p *TCPProxy) pipe(dst, src net.Conn, connCtx *ConnContext) int64 { |
| 280 | bp := p.bufPool.Get().(*[]byte) |
| 281 | defer p.bufPool.Put(bp) |
| 282 | buf := *bp |
| 283 | |
| 284 | var total int64 |
| 285 | for { |
| 286 | _ = src.SetReadDeadline(time.Now().Add(p.cfg.ReadTimeout)) |
| 287 | nr, readErr := src.Read(buf) |
| 288 | |
| 289 | if nr > 0 { |
| 290 | connCtx.touch() // session is active; reset idle tracking |
| 291 | _ = dst.SetWriteDeadline(time.Now().Add(p.cfg.WriteTimeout)) |
| 292 | nw, writeErr := dst.Write(buf[:nr]) |
| 293 | total += int64(nw) |
| 294 | if writeErr != nil { |
| 295 | if errors.Is(writeErr, os.ErrDeadlineExceeded) { |
| 296 | p.log.Debug(p.logPrefix+"session write timeout", "session", connCtx.id, "dest_ip", connCtx.destIP, "dest_port", connCtx.destPort, "timeout", p.cfg.WriteTimeout) |
| 297 | } else if !isClosedConnErr(writeErr) { |
| 298 | p.log.Debug(p.logPrefix+"session write error", "session", connCtx.id, "dest_ip", connCtx.destIP, "dest_port", connCtx.destPort, "err", writeErr) |
| 299 | } |
| 300 | break |
| 301 | } |
| 302 | } |
| 303 | if readErr != nil { |
| 304 | if errors.Is(readErr, os.ErrDeadlineExceeded) { |
| 305 | p.log.Debug(p.logPrefix+"session read timeout", "session", connCtx.id, "dest_ip", connCtx.destIP, "dest_port", connCtx.destPort, "timeout", p.cfg.ReadTimeout) |
| 306 | } else if !isClosedConnErr(readErr) { |
| 307 | p.log.Debug(p.logPrefix+"session read error", "session", connCtx.id, "dest_ip", connCtx.destIP, "dest_port", connCtx.destPort, "err", readErr) |
| 308 | } |
| 309 | break |
| 310 | } |
| 311 | } |
| 312 | return total |
| 313 | } |
| 314 | |
| 315 | // halfClose attempts a TCP write-shutdown so the peer receives EOF on its |
| 316 | // read side while the connection stays open for the other direction. |
no test coverage detected