From 511acfa34c363f425fcdc8147c26cb9c6be2065f Mon Sep 17 00:00:00 2001 From: Chen Yufei Date: Wed, 12 Dec 2012 23:43:07 +0800 Subject: [PATCH] Fix a potential problem in Pipe and add comment. --- shadowsocks/pipe.go | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/shadowsocks/pipe.go b/shadowsocks/pipe.go index 3355ff4..e78abd1 100644 --- a/shadowsocks/pipe.go +++ b/shadowsocks/pipe.go @@ -5,25 +5,30 @@ import ( "net" ) -func Pipe(src net.Conn, dst net.Conn, end chan int) { +func Pipe(src, dst net.Conn, end chan int) { + // Should not use io.Copy here. + // io.Copy will try to use the ReadFrom interface of TCPConn, but the src + // here is not a regular file, so sendfile is not applicable. + // io.Copy will fallback to the normal copy after discovering this, + // introducing unnecessary overhead. buf := make([]byte, 4096) for { num, err := src.Read(buf) - if err == nil { - _, err := dst.Write(buf[0:num]) - if err != nil { + // read may return EOF with num > 0 + // should always process num > 0 bytes before handling error + if num > 0 { + if _, err = dst.Write(buf[0:num]); err != nil { log.Println("write:", err) - end <- 1 - return + break } - } else { - log.Println("read:", err) - end <- 1 - return } - if num == 0 { - end <- 1 - return + if num == 0 { // num == 0 should associate with EOF + break + } + if err != nil { + log.Println("read:", err) + break } } + end <- 1 }