| package server |
|
|
| import ( |
| "errors" |
| "io" |
| "time" |
| ) |
|
|
| var errDisconnect = errors.New("traffic logger requested disconnect") |
|
|
| func copyBufferLog(dst io.Writer, src io.Reader, log func(n uint64) bool) error { |
| buf := make([]byte, 32*1024) |
| for { |
| nr, er := src.Read(buf) |
| if nr > 0 { |
| if !log(uint64(nr)) { |
| |
| return errDisconnect |
| } |
| _, ew := dst.Write(buf[0:nr]) |
| if ew != nil { |
| return ew |
| } |
| } |
| if er != nil { |
| if er == io.EOF { |
| |
| return nil |
| } |
| return er |
| } |
| } |
| } |
|
|
| func copyTwoWayEx(id string, serverRw, remoteRw io.ReadWriter, l TrafficLogger, stats *StreamStats) error { |
| errChan := make(chan error, 2) |
| go func() { |
| errChan <- copyBufferLog(serverRw, remoteRw, func(n uint64) bool { |
| stats.LastActiveTime.Store(time.Now()) |
| stats.Rx.Add(n) |
| return l.LogTraffic(id, 0, n) |
| }) |
| }() |
| go func() { |
| errChan <- copyBufferLog(remoteRw, serverRw, func(n uint64) bool { |
| stats.LastActiveTime.Store(time.Now()) |
| stats.Tx.Add(n) |
| return l.LogTraffic(id, n, 0) |
| }) |
| }() |
| |
| return <-errChan |
| } |
|
|
| |
| |
| func copyTwoWay(serverRw, remoteRw io.ReadWriter) error { |
| errChan := make(chan error, 2) |
| go func() { |
| _, err := io.Copy(serverRw, remoteRw) |
| errChan <- err |
| }() |
| go func() { |
| _, err := io.Copy(remoteRw, serverRw) |
| errChan <- err |
| }() |
| |
| return <-errChan |
| } |
|
|