github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/dns/proxy.go (about) 1 /* 2 * Copyright (C) 2019 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 dns 19 20 import ( 21 "net" 22 "strconv" 23 "sync" 24 25 "github.com/miekg/dns" 26 "github.com/pkg/errors" 27 "github.com/rs/zerolog/log" 28 ) 29 30 // Proxy defines DNS server with all handler attached to it. 31 type Proxy struct { 32 server *dns.Server 33 34 mu sync.Mutex 35 links int 36 } 37 38 // NewProxy returns new instance of API server. 39 func NewProxy(lhost string, lport int, handler dns.Handler) *Proxy { 40 return &Proxy{ 41 server: &dns.Server{ 42 Addr: net.JoinHostPort(lhost, strconv.Itoa(lport)), 43 Net: "udp", 44 ReadTimeout: dnsTimeout, 45 WriteTimeout: dnsTimeout, 46 ReusePort: true, 47 Handler: handler, 48 }, 49 } 50 } 51 52 // Run starts DNS proxy server and waits for the startup to complete. 53 func (p *Proxy) Run() (err error) { 54 p.mu.Lock() 55 defer p.mu.Unlock() 56 57 p.links++ 58 59 if p.links > 1 { 60 // Allow only one instance of the proxy to be running. 61 return nil 62 } 63 64 dnsProxyCh := make(chan error) 65 p.server.NotifyStartedFunc = func() { dnsProxyCh <- nil } 66 go func() { 67 log.Info().Msg("Starting DNS proxy on: " + p.server.Addr) 68 if err := p.server.ListenAndServe(); err != nil { 69 dnsProxyCh <- errors.Wrap(err, "failed to start DNS proxy") 70 } 71 }() 72 73 return <-dnsProxyCh 74 } 75 76 // Stop shutdowns DNS proxy server. 77 func (p *Proxy) Stop() error { 78 p.mu.Lock() 79 defer p.mu.Unlock() 80 81 p.links-- 82 83 if p.links > 0 { 84 // Do not stop until we have other instances running. 85 return nil 86 } 87 88 return p.server.Shutdown() 89 }