server.go 20 KB

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