server.go 20 KB

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