in pkg/hbone/io.go [90:176]
func (s Stream) CopyBuffered(ch chan int, close bool) {
buf1 := bufferPoolCopy.Get().([]byte)
defer bufferPoolCopy.Put(buf1)
bufCap := cap(buf1)
buf := buf1[0:bufCap:bufCap]
//st := Stream{}
// For netstack: src is a gonet.Conn, doesn't implement WriterTo. Dst is a net.TcpConn - and implements ReadFrom.
// CopyBuffered is the actual implementation of Copy and CopyBuffer.
// if buf is nil, one is allocated.
// Duplicated from io
// This will prevent stats from working.
// If the reader has a WriteTo method, use it to do the copy.
// Avoids an allocation and a copy.
//if wt, ok := src.(io.WriterTo); ok {
// return wt.WriteTo(dst)
//}
// Similarly, if the writer has a ReadFrom method, use it to do the copy.
//if rt, ok := dst.(io.ReaderFrom); ok {
// return rt.ReadFrom(src)
//}
if ch != nil {
defer func() {
ch <- int(0)
}()
}
if s.ID == "" {
s.ID = strconv.Itoa(int(atomic.AddInt64(&streamIDs, 1)))
}
if Debug {
log.Println(s.ID, "startCopy()")
}
for {
if srcc, ok := s.Src.(net.Conn); ok {
srcc.SetReadDeadline(time.Now().Add(15 * time.Minute))
}
nr, er := s.Src.Read(buf)
if Debug {
log.Println(s.ID, "read()", nr, er)
}
if nr > 0 { // before dealing with the read error
nw, ew := s.Dst.Write(buf[0:nr])
if Debug {
log.Println(s.ID, "write()", nw, ew)
}
if nw > 0 {
s.Written += int64(nw)
}
if f, ok := s.Dst.(http.Flusher); ok {
f.Flush()
}
if nr != nw { // Should not happen
ew = io.ErrShortWrite
if Debug {
log.Println(s.ID, "write error - short write", s.Err)
}
}
if ew != nil {
s.Err = ew
return
}
}
if er != nil {
if strings.Contains(er.Error(), "NetworkIdleTimeout") {
er = io.EOF
}
if er == io.EOF {
if Debug {
log.Println(s.ID, "done()")
}
} else {
s.Err = er
s.InError = true
if Debug {
log.Println(s.ID, "readError()", s.Err)
}
}
if close {
// read is already closed - we need to close out
closeWriter(s.Dst)
}
return
}
}
}