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  }