mirror of
https://github.com/MengMengCode/VoCat.git
synced 2026-08-13 03:13:43 +08:00
56 lines
1.4 KiB
Go
56 lines
1.4 KiB
Go
package exportproxy
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
const proxyTimeout = 30 * time.Second
|
|
|
|
func dialTarget(ctx context.Context, address string, dialer *net.Dialer, resolver *net.Resolver) (net.Conn, error) {
|
|
host, port, err := net.SplitHostPort(address)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if ip := net.ParseIP(host); ip != nil {
|
|
return dialer.DialContext(ctx, "tcp", net.JoinHostPort(ip.String(), port))
|
|
}
|
|
ips, err := resolver.LookupIPAddr(ctx, host)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var lastErr error
|
|
for _, ip := range ips {
|
|
connection, err := dialer.DialContext(ctx, "tcp", net.JoinHostPort(ip.IP.String(), port))
|
|
if err == nil {
|
|
return connection, nil
|
|
}
|
|
lastErr = err
|
|
}
|
|
if lastErr == nil {
|
|
lastErr = fmt.Errorf("%w: no addresses for %s", errors.ErrUnsupported, host)
|
|
}
|
|
return nil, lastErr
|
|
}
|
|
|
|
func pipe(left, right net.Conn) {
|
|
done := make(chan struct{}, 2)
|
|
go func() { _, _ = copyConnection(right, left); done <- struct{}{} }()
|
|
go func() { _, _ = copyConnection(left, right); done <- struct{}{} }()
|
|
<-done
|
|
}
|
|
|
|
func copyConnection(destination net.Conn, source net.Conn) (int64, error) {
|
|
written, err := io.CopyBuffer(destination, source, make([]byte, 32*1024))
|
|
if err == nil && written > 0 {
|
|
if connection, ok := destination.(interface{ CloseWrite() error }); ok {
|
|
_ = connection.CloseWrite()
|
|
}
|
|
}
|
|
return written, err
|
|
}
|