bridge.go 5.3 KB

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