github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/requests/dialer.go (about) 1 /* 2 * Copyright (C) 2020 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package requests 19 20 import ( 21 "context" 22 "net" 23 "time" 24 25 "github.com/mysteriumnetwork/node/requests/resolver" 26 ) 27 28 // DialContext specifies the dial function for creating unencrypted TCP connections. 29 type DialContext func(ctx context.Context, network, addr string) (net.Conn, error) 30 31 // Dialer wraps default go dialer with extra features. 32 type Dialer struct { 33 // ResolveContext specifies the resolve function for doing custom DNS lookup. 34 // If ResolveContext is nil, then the transport dials using package net. 35 ResolveContext resolver.ResolveContext 36 37 // Dialer specifies the dial function for creating unencrypted TCP connections. 38 Dialer DialContext 39 } 40 41 // NewDialer creates dialer with default configuration. 42 func NewDialer(srcIP string) *Dialer { 43 return &Dialer{ 44 Dialer: (&net.Dialer{ 45 Timeout: 60 * time.Second, 46 KeepAlive: 30 * time.Second, 47 LocalAddr: &net.TCPAddr{IP: net.ParseIP(srcIP)}, 48 }).DialContext, 49 } 50 } 51 52 // DialContext connects to the address on the named network using the provided context. 53 func (d *Dialer) DialContext(ctx context.Context, network, addr string) (conn net.Conn, err error) { 54 if d.ResolveContext != nil { 55 addrs, err := d.ResolveContext(ctx, network, addr) 56 if err != nil { 57 return nil, &net.OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err} 58 } 59 60 conn, err := d.dialAddrs(ctx, network, addrs) 61 if err != nil { 62 return nil, &net.OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err} 63 } 64 65 return conn, nil 66 } 67 68 return d.Dialer(ctx, network, addr) 69 } 70 71 func (d *Dialer) dialAddrs(ctx context.Context, network string, addrs []string) (conn net.Conn, err error) { 72 for _, addr := range addrs { 73 conn, err = d.Dialer(ctx, network, addr) 74 if err == nil { 75 return conn, nil 76 } 77 } 78 79 return conn, err 80 }