bridge.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // Copyright 2016 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 main is the entry point for the local tester network bridge.
  15. package main
  16. import (
  17. "flag"
  18. "io"
  19. "io/ioutil"
  20. "log"
  21. "math/rand"
  22. "net"
  23. "sync"
  24. "time"
  25. )
  26. func bridge(conn net.Conn, remoteAddr string) {
  27. outconn, err := net.Dial("tcp", flag.Args()[1])
  28. if err != nil {
  29. log.Println("oops:", err)
  30. return
  31. }
  32. log.Printf("bridging %v <-> %v\n", outconn.LocalAddr(), outconn.RemoteAddr())
  33. go io.Copy(conn, outconn)
  34. io.Copy(outconn, conn)
  35. }
  36. func blackhole(conn net.Conn) {
  37. log.Printf("blackholing connection %v <-> %v\n", conn.LocalAddr(), conn.RemoteAddr())
  38. io.Copy(ioutil.Discard, conn)
  39. conn.Close()
  40. }
  41. func readRemoteOnly(conn net.Conn, remoteAddr string) {
  42. outconn, err := net.Dial("tcp", flag.Args()[1])
  43. if err != nil {
  44. log.Println("oops:", err)
  45. return
  46. }
  47. log.Printf("one way %v <- %v\n", outconn.LocalAddr(), outconn.RemoteAddr())
  48. io.Copy(conn, outconn)
  49. }
  50. func writeRemoteOnly(conn net.Conn, remoteAddr string) {
  51. outconn, err := net.Dial("tcp", flag.Args()[1])
  52. if err != nil {
  53. log.Println("oops:", err)
  54. return
  55. }
  56. log.Printf("one way %v -> %v\n", outconn.LocalAddr(), outconn.RemoteAddr())
  57. io.Copy(outconn, conn)
  58. }
  59. func randCopy(conn net.Conn, outconn net.Conn) {
  60. for rand.Intn(10) > 0 {
  61. b := make([]byte, 4096)
  62. n, err := outconn.Read(b)
  63. if err != nil {
  64. return
  65. }
  66. _, err = conn.Write(b[:n])
  67. if err != nil {
  68. return
  69. }
  70. }
  71. }
  72. func randomBlackhole(conn net.Conn, remoteAddr string) {
  73. outconn, err := net.Dial("tcp", flag.Args()[1])
  74. if err != nil {
  75. log.Println("oops:", err)
  76. return
  77. }
  78. log.Printf("random blackhole: connection %v <-/-> %v\n", outconn.LocalAddr(), outconn.RemoteAddr())
  79. var wg sync.WaitGroup
  80. wg.Add(2)
  81. go func() {
  82. randCopy(conn, outconn)
  83. wg.Done()
  84. }()
  85. go func() {
  86. randCopy(outconn, conn)
  87. wg.Done()
  88. }()
  89. wg.Wait()
  90. conn.Close()
  91. outconn.Close()
  92. }
  93. type config struct {
  94. delayAccept bool
  95. resetListen bool
  96. connFaultRate float64
  97. immediateClose bool
  98. blackhole bool
  99. timeClose bool
  100. writeRemoteOnly bool
  101. readRemoteOnly bool
  102. randomBlackhole bool
  103. }
  104. type acceptFaultFunc func()
  105. type connFaultFunc func(net.Conn)
  106. func main() {
  107. var cfg config
  108. flag.BoolVar(&cfg.delayAccept, "delay-accept", true, "delays accepting new connections")
  109. flag.BoolVar(&cfg.resetListen, "reset-listen", true, "resets the listening port")
  110. flag.Float64Var(&cfg.connFaultRate, "conn-fault-rate", 0.25, "rate of faulty connections")
  111. flag.BoolVar(&cfg.immediateClose, "immediate-close", true, "close after accept")
  112. flag.BoolVar(&cfg.blackhole, "blackhole", true, "reads nothing, writes go nowhere")
  113. flag.BoolVar(&cfg.timeClose, "time-close", true, "close after random time")
  114. flag.BoolVar(&cfg.writeRemoteOnly, "write-remote-only", true, "only write, no read")
  115. flag.BoolVar(&cfg.readRemoteOnly, "read-remote-only", true, "only read, no write")
  116. flag.BoolVar(&cfg.randomBlackhole, "random-blockhole", true, "blackhole after data xfer")
  117. flag.Parse()
  118. lAddr := flag.Args()[0]
  119. fwdAddr := flag.Args()[1]
  120. log.Println("listening on ", lAddr)
  121. log.Println("forwarding to ", fwdAddr)
  122. l, err := net.Listen("tcp", lAddr)
  123. if err != nil {
  124. log.Fatal(err)
  125. }
  126. defer l.Close()
  127. acceptFaults := []acceptFaultFunc{func() {}}
  128. if cfg.delayAccept {
  129. f := func() {
  130. log.Println("delaying accept")
  131. time.Sleep(3 * time.Second)
  132. }
  133. acceptFaults = append(acceptFaults, f)
  134. }
  135. if cfg.resetListen {
  136. f := func() {
  137. log.Println("reset listen port")
  138. l.Close()
  139. newListener, err := net.Listen("tcp", lAddr)
  140. if err != nil {
  141. log.Fatal(err)
  142. }
  143. l = newListener
  144. }
  145. acceptFaults = append(acceptFaults, f)
  146. }
  147. connFaults := []connFaultFunc{func(c net.Conn) { bridge(c, fwdAddr) }}
  148. if cfg.immediateClose {
  149. f := func(c net.Conn) {
  150. log.Println("terminating connection immediately")
  151. c.Close()
  152. }
  153. connFaults = append(connFaults, f)
  154. }
  155. if cfg.blackhole {
  156. connFaults = append(connFaults, blackhole)
  157. }
  158. if cfg.timeClose {
  159. f := func(c net.Conn) {
  160. go func() {
  161. t := time.Duration(rand.Intn(5)+1) * time.Second
  162. time.Sleep(t)
  163. log.Printf("killing connection %v <-> %v after %v\n",
  164. c.LocalAddr(),
  165. c.RemoteAddr(),
  166. t)
  167. c.Close()
  168. }()
  169. bridge(c, fwdAddr)
  170. }
  171. connFaults = append(connFaults, f)
  172. }
  173. if cfg.writeRemoteOnly {
  174. f := func(c net.Conn) { writeRemoteOnly(c, fwdAddr) }
  175. connFaults = append(connFaults, f)
  176. }
  177. if cfg.readRemoteOnly {
  178. f := func(c net.Conn) { readRemoteOnly(c, fwdAddr) }
  179. connFaults = append(connFaults, f)
  180. }
  181. if cfg.randomBlackhole {
  182. f := func(c net.Conn) { randomBlackhole(c, fwdAddr) }
  183. connFaults = append(connFaults, f)
  184. }
  185. for {
  186. acceptFaults[rand.Intn(len(acceptFaults))]()
  187. conn, err := l.Accept()
  188. if err != nil {
  189. log.Fatal(err)
  190. }
  191. r := rand.Intn(len(connFaults))
  192. if rand.Intn(100) > int(100.0*cfg.connFaultRate) {
  193. r = 0
  194. }
  195. go connFaults[r](conn)
  196. }
  197. }