go.etcd.io/etcd@v3.3.27+incompatible/pkg/proxy/server.go (about)

     1  // Copyright 2018 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package proxy
    16  
    17  import (
    18  	"fmt"
    19  	"io"
    20  	mrand "math/rand"
    21  	"net"
    22  	"net/http"
    23  	"net/url"
    24  	"strings"
    25  	"sync"
    26  	"time"
    27  
    28  	"github.com/coreos/etcd/pkg/transport"
    29  
    30  	humanize "github.com/dustin/go-humanize"
    31  	"go.uber.org/zap"
    32  )
    33  
    34  // Server defines proxy server layer that simulates common network faults,
    35  // such as latency spikes, packet drop/corruption, etc..
    36  type Server interface {
    37  	// From returns proxy source address in "scheme://host:port" format.
    38  	From() string
    39  	// To returns proxy destination address in "scheme://host:port" format.
    40  	To() string
    41  
    42  	// Ready returns when proxy is ready to serve.
    43  	Ready() <-chan struct{}
    44  	// Done returns when proxy has been closed.
    45  	Done() <-chan struct{}
    46  	// Error sends errors while serving proxy.
    47  	Error() <-chan error
    48  	// Close closes listener and transport.
    49  	Close() error
    50  
    51  	// DelayAccept adds latency ± random variable to accepting new incoming connections.
    52  	DelayAccept(latency, rv time.Duration)
    53  	// UndelayAccept removes sending latencies.
    54  	UndelayAccept()
    55  	// LatencyAccept returns current latency on accepting new incoming connections.
    56  	LatencyAccept() time.Duration
    57  	// DelayTx adds latency ± random variable to "sending" layer.
    58  	DelayTx(latency, rv time.Duration)
    59  	// UndelayTx removes sending latencies.
    60  	UndelayTx()
    61  	// LatencyTx returns current send latency.
    62  	LatencyTx() time.Duration
    63  	// DelayRx adds latency ± random variable to "receiving" layer.
    64  	DelayRx(latency, rv time.Duration)
    65  	// UndelayRx removes "receiving" latencies.
    66  	UndelayRx()
    67  	// LatencyRx returns current receive latency.
    68  	LatencyRx() time.Duration
    69  
    70  	// PauseAccept stops accepting new connections.
    71  	PauseAccept()
    72  	// UnpauseAccept removes pause operation on accepting new connections.
    73  	UnpauseAccept()
    74  	// PauseTx stops "forwarding" packets.
    75  	PauseTx()
    76  	// UnpauseTx removes "forwarding" pause operation.
    77  	UnpauseTx()
    78  	// PauseRx stops "receiving" packets to client.
    79  	PauseRx()
    80  	// UnpauseRx removes "receiving" pause operation.
    81  	UnpauseRx()
    82  
    83  	// BlackholeTx drops all incoming packets before "forwarding".
    84  	BlackholeTx()
    85  	// UnblackholeTx removes blackhole operation on "sending".
    86  	UnblackholeTx()
    87  	// BlackholeRx drops all incoming packets to client.
    88  	BlackholeRx()
    89  	// UnblackholeRx removes blackhole operation on "receiving".
    90  	UnblackholeRx()
    91  
    92  	// CorruptTx corrupts incoming packets from the listener.
    93  	CorruptTx(f func(data []byte) []byte)
    94  	// UncorruptTx removes corrupt operation on "forwarding".
    95  	UncorruptTx()
    96  	// CorruptRx corrupts incoming packets to client.
    97  	CorruptRx(f func(data []byte) []byte)
    98  	// UncorruptRx removes corrupt operation on "receiving".
    99  	UncorruptRx()
   100  
   101  	// ResetListener closes and restarts listener.
   102  	ResetListener() error
   103  }
   104  
   105  type proxyServer struct {
   106  	lg *zap.Logger
   107  
   108  	from, to      url.URL
   109  	tlsInfo       transport.TLSInfo
   110  	dialTimeout   time.Duration
   111  	bufferSize    int
   112  	retryInterval time.Duration
   113  
   114  	readyc chan struct{}
   115  	donec  chan struct{}
   116  	errc   chan error
   117  
   118  	closeOnce sync.Once
   119  	closeWg   sync.WaitGroup
   120  
   121  	listenerMu sync.RWMutex
   122  	listener   net.Listener
   123  
   124  	latencyAcceptMu sync.RWMutex
   125  	latencyAccept   time.Duration
   126  	latencyTxMu     sync.RWMutex
   127  	latencyTx       time.Duration
   128  	latencyRxMu     sync.RWMutex
   129  	latencyRx       time.Duration
   130  
   131  	corruptTxMu sync.RWMutex
   132  	corruptTx   func(data []byte) []byte
   133  	corruptRxMu sync.RWMutex
   134  	corruptRx   func(data []byte) []byte
   135  
   136  	acceptMu     sync.Mutex
   137  	pauseAcceptc chan struct{}
   138  	txMu         sync.Mutex
   139  	pauseTxc     chan struct{}
   140  	blackholeTxc chan struct{}
   141  	rxMu         sync.Mutex
   142  	pauseRxc     chan struct{}
   143  	blackholeRxc chan struct{}
   144  }
   145  
   146  // ServerConfig defines proxy server configuration.
   147  type ServerConfig struct {
   148  	Logger        *zap.Logger
   149  	From          url.URL
   150  	To            url.URL
   151  	TLSInfo       transport.TLSInfo
   152  	DialTimeout   time.Duration
   153  	BufferSize    int
   154  	RetryInterval time.Duration
   155  }
   156  
   157  var (
   158  	defaultDialTimeout   = 3 * time.Second
   159  	defaultBufferSize    = 48 * 1024
   160  	defaultRetryInterval = 10 * time.Millisecond
   161  	defaultLogger        *zap.Logger
   162  )
   163  
   164  func init() {
   165  	var err error
   166  	defaultLogger, err = zap.NewProduction()
   167  	if err != nil {
   168  		panic(err)
   169  	}
   170  }
   171  
   172  // NewServer returns a proxy implementation with no iptables/tc dependencies.
   173  // The proxy layer overhead is <1ms.
   174  func NewServer(cfg ServerConfig) Server {
   175  	p := &proxyServer{
   176  		lg: cfg.Logger,
   177  
   178  		from:          cfg.From,
   179  		to:            cfg.To,
   180  		tlsInfo:       cfg.TLSInfo,
   181  		dialTimeout:   cfg.DialTimeout,
   182  		bufferSize:    cfg.BufferSize,
   183  		retryInterval: cfg.RetryInterval,
   184  
   185  		readyc: make(chan struct{}),
   186  		donec:  make(chan struct{}),
   187  		errc:   make(chan error, 16),
   188  
   189  		pauseAcceptc: make(chan struct{}),
   190  		pauseTxc:     make(chan struct{}),
   191  		blackholeTxc: make(chan struct{}),
   192  		pauseRxc:     make(chan struct{}),
   193  		blackholeRxc: make(chan struct{}),
   194  	}
   195  	if p.dialTimeout == 0 {
   196  		p.dialTimeout = defaultDialTimeout
   197  	}
   198  	if p.bufferSize == 0 {
   199  		p.bufferSize = defaultBufferSize
   200  	}
   201  	if p.retryInterval == 0 {
   202  		p.retryInterval = defaultRetryInterval
   203  	}
   204  	if p.lg == nil {
   205  		p.lg = defaultLogger
   206  	}
   207  	close(p.pauseAcceptc)
   208  	close(p.pauseTxc)
   209  	close(p.pauseRxc)
   210  
   211  	if strings.HasPrefix(p.from.Scheme, "http") {
   212  		p.from.Scheme = "tcp"
   213  	}
   214  	if strings.HasPrefix(p.to.Scheme, "http") {
   215  		p.to.Scheme = "tcp"
   216  	}
   217  
   218  	var ln net.Listener
   219  	var err error
   220  	if !p.tlsInfo.Empty() {
   221  		ln, err = transport.NewListener(p.from.Host, p.from.Scheme, &p.tlsInfo)
   222  	} else {
   223  		ln, err = net.Listen(p.from.Scheme, p.from.Host)
   224  	}
   225  	if err != nil {
   226  		p.errc <- err
   227  		p.Close()
   228  		return p
   229  	}
   230  	p.listener = ln
   231  
   232  	p.closeWg.Add(1)
   233  	go p.listenAndServe()
   234  
   235  	p.lg.Info("started proxying", zap.String("from", p.From()), zap.String("to", p.To()))
   236  	return p
   237  }
   238  
   239  func (p *proxyServer) From() string {
   240  	return fmt.Sprintf("%s://%s", p.from.Scheme, p.from.Host)
   241  }
   242  
   243  func (p *proxyServer) To() string {
   244  	return fmt.Sprintf("%s://%s", p.to.Scheme, p.to.Host)
   245  }
   246  
   247  // TODO: implement packet reordering from multiple TCP connections
   248  // buffer packets per connection for awhile, reorder before transmit
   249  // - https://github.com/coreos/etcd/issues/5614
   250  // - https://github.com/coreos/etcd/pull/6918#issuecomment-264093034
   251  
   252  func (p *proxyServer) listenAndServe() {
   253  	defer p.closeWg.Done()
   254  
   255  	p.lg.Info("proxy is listening on", zap.String("from", p.From()))
   256  	close(p.readyc)
   257  
   258  	for {
   259  		p.acceptMu.Lock()
   260  		pausec := p.pauseAcceptc
   261  		p.acceptMu.Unlock()
   262  		select {
   263  		case <-pausec:
   264  		case <-p.donec:
   265  			return
   266  		}
   267  
   268  		p.latencyAcceptMu.RLock()
   269  		lat := p.latencyAccept
   270  		p.latencyAcceptMu.RUnlock()
   271  		if lat > 0 {
   272  			select {
   273  			case <-time.After(lat):
   274  			case <-p.donec:
   275  				return
   276  			}
   277  		}
   278  
   279  		p.listenerMu.RLock()
   280  		ln := p.listener
   281  		p.listenerMu.RUnlock()
   282  
   283  		in, err := ln.Accept()
   284  		if err != nil {
   285  			select {
   286  			case p.errc <- err:
   287  				select {
   288  				case <-p.donec:
   289  					return
   290  				default:
   291  				}
   292  			case <-p.donec:
   293  				return
   294  			}
   295  			p.lg.Debug("listener accept error", zap.Error(err))
   296  
   297  			if strings.HasSuffix(err.Error(), "use of closed network connection") {
   298  				select {
   299  				case <-time.After(p.retryInterval):
   300  				case <-p.donec:
   301  					return
   302  				}
   303  				p.lg.Debug("listener is closed; retry listening on", zap.String("from", p.From()))
   304  
   305  				if err = p.ResetListener(); err != nil {
   306  					select {
   307  					case p.errc <- err:
   308  						select {
   309  						case <-p.donec:
   310  							return
   311  						default:
   312  						}
   313  					case <-p.donec:
   314  						return
   315  					}
   316  					p.lg.Warn("failed to reset listener", zap.Error(err))
   317  				}
   318  			}
   319  
   320  			continue
   321  		}
   322  
   323  		var out net.Conn
   324  		if !p.tlsInfo.Empty() {
   325  			var tp *http.Transport
   326  			tp, err = transport.NewTransport(p.tlsInfo, p.dialTimeout)
   327  			if err != nil {
   328  				select {
   329  				case p.errc <- err:
   330  					select {
   331  					case <-p.donec:
   332  						return
   333  					default:
   334  					}
   335  				case <-p.donec:
   336  					return
   337  				}
   338  				continue
   339  			}
   340  			out, err = tp.Dial(p.to.Scheme, p.to.Host)
   341  		} else {
   342  			out, err = net.Dial(p.to.Scheme, p.to.Host)
   343  		}
   344  		if err != nil {
   345  			select {
   346  			case p.errc <- err:
   347  				select {
   348  				case <-p.donec:
   349  					return
   350  				default:
   351  				}
   352  			case <-p.donec:
   353  				return
   354  			}
   355  			p.lg.Debug("failed to dial", zap.Error(err))
   356  			continue
   357  		}
   358  
   359  		go func() {
   360  			// read incoming bytes from listener, dispatch to outgoing connection
   361  			p.transmit(out, in)
   362  			out.Close()
   363  			in.Close()
   364  		}()
   365  		go func() {
   366  			// read response from outgoing connection, write back to listener
   367  			p.receive(in, out)
   368  			in.Close()
   369  			out.Close()
   370  		}()
   371  	}
   372  }
   373  
   374  func (p *proxyServer) transmit(dst io.Writer, src io.Reader) { p.ioCopy(dst, src, true) }
   375  func (p *proxyServer) receive(dst io.Writer, src io.Reader)  { p.ioCopy(dst, src, false) }
   376  func (p *proxyServer) ioCopy(dst io.Writer, src io.Reader, proxySend bool) {
   377  	buf := make([]byte, p.bufferSize)
   378  	for {
   379  		nr, err := src.Read(buf)
   380  		if err != nil {
   381  			if err == io.EOF {
   382  				return
   383  			}
   384  			// connection already closed
   385  			if strings.HasSuffix(err.Error(), "read: connection reset by peer") {
   386  				return
   387  			}
   388  			if strings.HasSuffix(err.Error(), "use of closed network connection") {
   389  				return
   390  			}
   391  			select {
   392  			case p.errc <- err:
   393  				select {
   394  				case <-p.donec:
   395  					return
   396  				default:
   397  				}
   398  			case <-p.donec:
   399  				return
   400  			}
   401  			p.lg.Debug("failed to read", zap.Error(err))
   402  			return
   403  		}
   404  		if nr == 0 {
   405  			return
   406  		}
   407  		data := buf[:nr]
   408  
   409  		var pausec chan struct{}
   410  		var blackholec chan struct{}
   411  		if proxySend {
   412  			p.txMu.Lock()
   413  			pausec = p.pauseTxc
   414  			blackholec = p.blackholeTxc
   415  			p.txMu.Unlock()
   416  		} else {
   417  			p.rxMu.Lock()
   418  			pausec = p.pauseRxc
   419  			blackholec = p.blackholeRxc
   420  			p.rxMu.Unlock()
   421  		}
   422  		select {
   423  		case <-pausec:
   424  		case <-p.donec:
   425  			return
   426  		}
   427  		blackholed := false
   428  		select {
   429  		case <-blackholec:
   430  			blackholed = true
   431  		case <-p.donec:
   432  			return
   433  		default:
   434  		}
   435  		if blackholed {
   436  			if proxySend {
   437  				p.lg.Debug(
   438  					"dropped",
   439  					zap.String("data-size", humanize.Bytes(uint64(nr))),
   440  					zap.String("from", p.From()),
   441  					zap.String("to", p.To()),
   442  				)
   443  			} else {
   444  				p.lg.Debug(
   445  					"dropped",
   446  					zap.String("data-size", humanize.Bytes(uint64(nr))),
   447  					zap.String("from", p.To()),
   448  					zap.String("to", p.From()),
   449  				)
   450  			}
   451  			continue
   452  		}
   453  
   454  		var lat time.Duration
   455  		if proxySend {
   456  			p.latencyTxMu.RLock()
   457  			lat = p.latencyTx
   458  			p.latencyTxMu.RUnlock()
   459  		} else {
   460  			p.latencyRxMu.RLock()
   461  			lat = p.latencyRx
   462  			p.latencyRxMu.RUnlock()
   463  		}
   464  		if lat > 0 {
   465  			select {
   466  			case <-time.After(lat):
   467  			case <-p.donec:
   468  				return
   469  			}
   470  		}
   471  
   472  		if proxySend {
   473  			p.corruptTxMu.RLock()
   474  			if p.corruptTx != nil {
   475  				data = p.corruptTx(data)
   476  			}
   477  			p.corruptTxMu.RUnlock()
   478  		} else {
   479  			p.corruptRxMu.RLock()
   480  			if p.corruptRx != nil {
   481  				data = p.corruptRx(data)
   482  			}
   483  			p.corruptRxMu.RUnlock()
   484  		}
   485  
   486  		var nw int
   487  		nw, err = dst.Write(data)
   488  		if err != nil {
   489  			if err == io.EOF {
   490  				return
   491  			}
   492  			select {
   493  			case p.errc <- err:
   494  				select {
   495  				case <-p.donec:
   496  					return
   497  				default:
   498  				}
   499  			case <-p.donec:
   500  				return
   501  			}
   502  			if proxySend {
   503  				p.lg.Debug("failed to write while sending", zap.Error(err))
   504  			} else {
   505  				p.lg.Debug("failed to write while receiving", zap.Error(err))
   506  			}
   507  			return
   508  		}
   509  
   510  		if nr != nw {
   511  			select {
   512  			case p.errc <- io.ErrShortWrite:
   513  				select {
   514  				case <-p.donec:
   515  					return
   516  				default:
   517  				}
   518  			case <-p.donec:
   519  				return
   520  			}
   521  			if proxySend {
   522  				p.lg.Debug(
   523  					"failed to write while sending; read/write bytes are different",
   524  					zap.Int("read-bytes", nr),
   525  					zap.Int("write-bytes", nw),
   526  					zap.Error(io.ErrShortWrite),
   527  				)
   528  			} else {
   529  				p.lg.Debug(
   530  					"failed to write while receiving; read/write bytes are different",
   531  					zap.Int("read-bytes", nr),
   532  					zap.Int("write-bytes", nw),
   533  					zap.Error(io.ErrShortWrite),
   534  				)
   535  			}
   536  			return
   537  		}
   538  
   539  		if proxySend {
   540  			p.lg.Debug(
   541  				"transmitted",
   542  				zap.String("data-size", humanize.Bytes(uint64(nr))),
   543  				zap.String("from", p.From()),
   544  				zap.String("to", p.To()),
   545  			)
   546  		} else {
   547  			p.lg.Debug(
   548  				"received",
   549  				zap.String("data-size", humanize.Bytes(uint64(nr))),
   550  				zap.String("from", p.To()),
   551  				zap.String("to", p.From()),
   552  			)
   553  		}
   554  
   555  	}
   556  }
   557  
   558  func (p *proxyServer) Ready() <-chan struct{} { return p.readyc }
   559  func (p *proxyServer) Done() <-chan struct{}  { return p.donec }
   560  func (p *proxyServer) Error() <-chan error    { return p.errc }
   561  func (p *proxyServer) Close() (err error) {
   562  	p.closeOnce.Do(func() {
   563  		close(p.donec)
   564  		p.listenerMu.Lock()
   565  		if p.listener != nil {
   566  			err = p.listener.Close()
   567  			p.lg.Info(
   568  				"closed proxy listener",
   569  				zap.String("from", p.From()),
   570  				zap.String("to", p.To()),
   571  			)
   572  		}
   573  		p.lg.Sync()
   574  		p.listenerMu.Unlock()
   575  	})
   576  	p.closeWg.Wait()
   577  	return err
   578  }
   579  
   580  func (p *proxyServer) DelayAccept(latency, rv time.Duration) {
   581  	if latency <= 0 {
   582  		return
   583  	}
   584  	d := computeLatency(latency, rv)
   585  	p.latencyAcceptMu.Lock()
   586  	p.latencyAccept = d
   587  	p.latencyAcceptMu.Unlock()
   588  
   589  	p.lg.Info(
   590  		"set accept latency",
   591  		zap.Duration("latency", d),
   592  		zap.Duration("given-latency", latency),
   593  		zap.Duration("given-latency-random-variable", rv),
   594  		zap.String("from", p.From()),
   595  		zap.String("to", p.To()),
   596  	)
   597  }
   598  
   599  func (p *proxyServer) UndelayAccept() {
   600  	p.latencyAcceptMu.Lock()
   601  	d := p.latencyAccept
   602  	p.latencyAccept = 0
   603  	p.latencyAcceptMu.Unlock()
   604  
   605  	p.lg.Info(
   606  		"removed accept latency",
   607  		zap.Duration("latency", d),
   608  		zap.String("from", p.From()),
   609  		zap.String("to", p.To()),
   610  	)
   611  }
   612  
   613  func (p *proxyServer) LatencyAccept() time.Duration {
   614  	p.latencyAcceptMu.RLock()
   615  	d := p.latencyAccept
   616  	p.latencyAcceptMu.RUnlock()
   617  	return d
   618  }
   619  
   620  func (p *proxyServer) DelayTx(latency, rv time.Duration) {
   621  	if latency <= 0 {
   622  		return
   623  	}
   624  	d := computeLatency(latency, rv)
   625  	p.latencyTxMu.Lock()
   626  	p.latencyTx = d
   627  	p.latencyTxMu.Unlock()
   628  
   629  	p.lg.Info(
   630  		"set transmit latency",
   631  		zap.Duration("latency", d),
   632  		zap.Duration("given-latency", latency),
   633  		zap.Duration("given-latency-random-variable", rv),
   634  		zap.String("from", p.From()),
   635  		zap.String("to", p.To()),
   636  	)
   637  }
   638  
   639  func (p *proxyServer) UndelayTx() {
   640  	p.latencyTxMu.Lock()
   641  	d := p.latencyTx
   642  	p.latencyTx = 0
   643  	p.latencyTxMu.Unlock()
   644  
   645  	p.lg.Info(
   646  		"removed transmit latency",
   647  		zap.Duration("latency", d),
   648  		zap.String("from", p.From()),
   649  		zap.String("to", p.To()),
   650  	)
   651  }
   652  
   653  func (p *proxyServer) LatencyTx() time.Duration {
   654  	p.latencyTxMu.RLock()
   655  	d := p.latencyTx
   656  	p.latencyTxMu.RUnlock()
   657  	return d
   658  }
   659  
   660  func (p *proxyServer) DelayRx(latency, rv time.Duration) {
   661  	if latency <= 0 {
   662  		return
   663  	}
   664  	d := computeLatency(latency, rv)
   665  	p.latencyRxMu.Lock()
   666  	p.latencyRx = d
   667  	p.latencyRxMu.Unlock()
   668  
   669  	p.lg.Info(
   670  		"set receive latency",
   671  		zap.Duration("latency", d),
   672  		zap.Duration("given-latency", latency),
   673  		zap.Duration("given-latency-random-variable", rv),
   674  		zap.String("from", p.To()),
   675  		zap.String("to", p.From()),
   676  	)
   677  }
   678  
   679  func (p *proxyServer) UndelayRx() {
   680  	p.latencyRxMu.Lock()
   681  	d := p.latencyRx
   682  	p.latencyRx = 0
   683  	p.latencyRxMu.Unlock()
   684  
   685  	p.lg.Info(
   686  		"removed receive latency",
   687  		zap.Duration("latency", d),
   688  		zap.String("from", p.To()),
   689  		zap.String("to", p.From()),
   690  	)
   691  }
   692  
   693  func (p *proxyServer) LatencyRx() time.Duration {
   694  	p.latencyRxMu.RLock()
   695  	d := p.latencyRx
   696  	p.latencyRxMu.RUnlock()
   697  	return d
   698  }
   699  
   700  func computeLatency(lat, rv time.Duration) time.Duration {
   701  	if rv == 0 {
   702  		return lat
   703  	}
   704  	if rv < 0 {
   705  		rv *= -1
   706  	}
   707  	if rv > lat {
   708  		rv = lat / 10
   709  	}
   710  	now := time.Now()
   711  	mrand.Seed(int64(now.Nanosecond()))
   712  	sign := 1
   713  	if now.Second()%2 == 0 {
   714  		sign = -1
   715  	}
   716  	return lat + time.Duration(int64(sign)*mrand.Int63n(rv.Nanoseconds()))
   717  }
   718  
   719  func (p *proxyServer) PauseAccept() {
   720  	p.acceptMu.Lock()
   721  	p.pauseAcceptc = make(chan struct{})
   722  	p.acceptMu.Unlock()
   723  
   724  	p.lg.Info(
   725  		"paused accepting new connections",
   726  		zap.String("from", p.From()),
   727  		zap.String("to", p.To()),
   728  	)
   729  }
   730  
   731  func (p *proxyServer) UnpauseAccept() {
   732  	p.acceptMu.Lock()
   733  	select {
   734  	case <-p.pauseAcceptc: // already unpaused
   735  	case <-p.donec:
   736  		p.acceptMu.Unlock()
   737  		return
   738  	default:
   739  		close(p.pauseAcceptc)
   740  	}
   741  	p.acceptMu.Unlock()
   742  
   743  	p.lg.Info(
   744  		"unpaused accepting new connections",
   745  		zap.String("from", p.From()),
   746  		zap.String("to", p.To()),
   747  	)
   748  }
   749  
   750  func (p *proxyServer) PauseTx() {
   751  	p.txMu.Lock()
   752  	p.pauseTxc = make(chan struct{})
   753  	p.txMu.Unlock()
   754  
   755  	p.lg.Info(
   756  		"paused transmit listen",
   757  		zap.String("from", p.From()),
   758  		zap.String("to", p.To()),
   759  	)
   760  }
   761  
   762  func (p *proxyServer) UnpauseTx() {
   763  	p.txMu.Lock()
   764  	select {
   765  	case <-p.pauseTxc: // already unpaused
   766  	case <-p.donec:
   767  		p.txMu.Unlock()
   768  		return
   769  	default:
   770  		close(p.pauseTxc)
   771  	}
   772  	p.txMu.Unlock()
   773  
   774  	p.lg.Info(
   775  		"unpaused transmit listen",
   776  		zap.String("from", p.From()),
   777  		zap.String("to", p.To()),
   778  	)
   779  }
   780  
   781  func (p *proxyServer) PauseRx() {
   782  	p.rxMu.Lock()
   783  	p.pauseRxc = make(chan struct{})
   784  	p.rxMu.Unlock()
   785  
   786  	p.lg.Info(
   787  		"paused receive listen",
   788  		zap.String("from", p.To()),
   789  		zap.String("to", p.From()),
   790  	)
   791  }
   792  
   793  func (p *proxyServer) UnpauseRx() {
   794  	p.rxMu.Lock()
   795  	select {
   796  	case <-p.pauseRxc: // already unpaused
   797  	case <-p.donec:
   798  		p.rxMu.Unlock()
   799  		return
   800  	default:
   801  		close(p.pauseRxc)
   802  	}
   803  	p.rxMu.Unlock()
   804  
   805  	p.lg.Info(
   806  		"unpaused receive listen",
   807  		zap.String("from", p.To()),
   808  		zap.String("to", p.From()),
   809  	)
   810  }
   811  
   812  func (p *proxyServer) BlackholeTx() {
   813  	p.txMu.Lock()
   814  	select {
   815  	case <-p.blackholeTxc: // already blackholed
   816  	case <-p.donec:
   817  		p.txMu.Unlock()
   818  		return
   819  	default:
   820  		close(p.blackholeTxc)
   821  	}
   822  	p.txMu.Unlock()
   823  
   824  	p.lg.Info(
   825  		"blackholed transmit",
   826  		zap.String("from", p.From()),
   827  		zap.String("to", p.To()),
   828  	)
   829  }
   830  
   831  func (p *proxyServer) UnblackholeTx() {
   832  	p.txMu.Lock()
   833  	p.blackholeTxc = make(chan struct{})
   834  	p.txMu.Unlock()
   835  
   836  	p.lg.Info(
   837  		"unblackholed transmit",
   838  		zap.String("from", p.From()),
   839  		zap.String("to", p.To()),
   840  	)
   841  }
   842  
   843  func (p *proxyServer) BlackholeRx() {
   844  	p.rxMu.Lock()
   845  	select {
   846  	case <-p.blackholeRxc: // already blackholed
   847  	case <-p.donec:
   848  		p.rxMu.Unlock()
   849  		return
   850  	default:
   851  		close(p.blackholeRxc)
   852  	}
   853  	p.rxMu.Unlock()
   854  
   855  	p.lg.Info(
   856  		"blackholed receive",
   857  		zap.String("from", p.To()),
   858  		zap.String("to", p.From()),
   859  	)
   860  }
   861  
   862  func (p *proxyServer) UnblackholeRx() {
   863  	p.rxMu.Lock()
   864  	p.blackholeRxc = make(chan struct{})
   865  	p.rxMu.Unlock()
   866  
   867  	p.lg.Info(
   868  		"unblackholed receive",
   869  		zap.String("from", p.To()),
   870  		zap.String("to", p.From()),
   871  	)
   872  }
   873  
   874  func (p *proxyServer) CorruptTx(f func([]byte) []byte) {
   875  	p.corruptTxMu.Lock()
   876  	p.corruptTx = f
   877  	p.corruptTxMu.Unlock()
   878  
   879  	p.lg.Info(
   880  		"corrupting transmit",
   881  		zap.String("from", p.From()),
   882  		zap.String("to", p.To()),
   883  	)
   884  }
   885  
   886  func (p *proxyServer) UncorruptTx() {
   887  	p.corruptTxMu.Lock()
   888  	p.corruptTx = nil
   889  	p.corruptTxMu.Unlock()
   890  
   891  	p.lg.Info(
   892  		"stopped corrupting transmit",
   893  		zap.String("from", p.From()),
   894  		zap.String("to", p.To()),
   895  	)
   896  }
   897  
   898  func (p *proxyServer) CorruptRx(f func([]byte) []byte) {
   899  	p.corruptRxMu.Lock()
   900  	p.corruptRx = f
   901  	p.corruptRxMu.Unlock()
   902  	p.lg.Info(
   903  		"corrupting receive",
   904  		zap.String("from", p.To()),
   905  		zap.String("to", p.From()),
   906  	)
   907  }
   908  
   909  func (p *proxyServer) UncorruptRx() {
   910  	p.corruptRxMu.Lock()
   911  	p.corruptRx = nil
   912  	p.corruptRxMu.Unlock()
   913  
   914  	p.lg.Info(
   915  		"stopped corrupting receive",
   916  		zap.String("from", p.To()),
   917  		zap.String("to", p.From()),
   918  	)
   919  }
   920  
   921  func (p *proxyServer) ResetListener() error {
   922  	p.listenerMu.Lock()
   923  	defer p.listenerMu.Unlock()
   924  
   925  	if err := p.listener.Close(); err != nil {
   926  		// already closed
   927  		if !strings.HasSuffix(err.Error(), "use of closed network connection") {
   928  			return err
   929  		}
   930  	}
   931  
   932  	var ln net.Listener
   933  	var err error
   934  	if !p.tlsInfo.Empty() {
   935  		ln, err = transport.NewListener(p.from.Host, p.from.Scheme, &p.tlsInfo)
   936  	} else {
   937  		ln, err = net.Listen(p.from.Scheme, p.from.Host)
   938  	}
   939  	if err != nil {
   940  		return err
   941  	}
   942  	p.listener = ln
   943  
   944  	p.lg.Info(
   945  		"reset listener on",
   946  		zap.String("from", p.From()),
   947  	)
   948  	return nil
   949  }