mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
56 lines
1.5 KiB
Go
56 lines
1.5 KiB
Go
package netconn
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// BiCopy закрывает оба conn, как только копирование в любую сторону завершится.
|
|
func BiCopy(ctx context.Context, c1, c2 net.Conn, errf func(format string, v ...any)) (int64, int64) {
|
|
ctx2, cancel := context.WithCancel(ctx)
|
|
setDeadline := func(t time.Time, what string) {
|
|
if err := c1.SetDeadline(t); err != nil && errf != nil {
|
|
errf("BiCopy: c1 %s: %v", what, err)
|
|
}
|
|
if err := c2.SetDeadline(t); err != nil && errf != nil {
|
|
errf("BiCopy: c2 %s: %v", what, err)
|
|
}
|
|
}
|
|
hookDone := make(chan struct{})
|
|
stopOnCancel := context.AfterFunc(ctx2, func() {
|
|
defer close(hookDone)
|
|
setDeadline(time.Now(), "SetDeadline")
|
|
})
|
|
|
|
var wg sync.WaitGroup
|
|
var c1FromC2, c2FromC1 int64
|
|
wg.Go(func() {
|
|
defer cancel()
|
|
n, err := io.Copy(c1, c2)
|
|
c1FromC2 = n
|
|
if err != nil && errf != nil {
|
|
errf("BiCopy: c1<-c2: %v", err)
|
|
}
|
|
})
|
|
wg.Go(func() {
|
|
defer cancel()
|
|
n, err := io.Copy(c2, c1)
|
|
c2FromC1 = n
|
|
if err != nil && errf != nil {
|
|
errf("BiCopy: c2<-c1: %v", err)
|
|
}
|
|
})
|
|
wg.Wait()
|
|
|
|
// Дедлайны сбрасываются только после того, как хук отменён или доработал - иначе
|
|
// он взвёлся бы следом и оставил conn'ы просроченными навсегда.
|
|
if !stopOnCancel() {
|
|
<-hookDone
|
|
}
|
|
setDeadline(time.Time{}, "clear deadline")
|
|
return c1FromC2, c2FromC1
|
|
}
|