Files
VoCat/internal/exportproxy/proxy_shared.go
T

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
}