main.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package main
  2. import (
  3. "bufio"
  4. "context"
  5. "flag"
  6. "fmt"
  7. "net"
  8. "os"
  9. "strings"
  10. "time"
  11. "github.com/google/gopacket"
  12. "github.com/google/gopacket/layers"
  13. "github.com/google/gopacket/pcapgo"
  14. "github.com/ossrs/go-oryx-lib/errors"
  15. "github.com/ossrs/go-oryx-lib/logger"
  16. )
  17. func main() {
  18. ctx := logger.WithContext(context.Background())
  19. if err := doMain(ctx); err != nil {
  20. panic(err)
  21. }
  22. }
  23. func trace(format string, args ...interface{}) {
  24. fmt.Println(fmt.Sprintf(format, args...))
  25. }
  26. func doMain(ctx context.Context) error {
  27. var doRE, doTrace, help bool
  28. var pauseNumber, abortNumber uint64
  29. var filename string
  30. var server string
  31. flag.BoolVar(&help, "h", false, "whether show this help")
  32. flag.BoolVar(&help, "help", false, "whether show this help")
  33. flag.BoolVar(&doRE, "re", true, "whether do real-time emulation")
  34. flag.BoolVar(&doTrace, "trace", true, "whether trace the packet")
  35. flag.Uint64Var(&pauseNumber, "pause", 0, "the packet number to pause")
  36. flag.Uint64Var(&abortNumber, "abort", 0, "the packet number to abort")
  37. flag.StringVar(&filename, "f", "", "the pcap filename, like ./t.pcapng")
  38. flag.StringVar(&server, "s", "", "the server address, like 127.0.0.1:1935")
  39. flag.Parse()
  40. if help {
  41. flag.Usage()
  42. os.Exit(0)
  43. }
  44. if filename == "" || server == "" {
  45. flag.Usage()
  46. os.Exit(1)
  47. }
  48. logger.Tf(ctx, "Forward pcap %v to %v, re=%v, trace=%v, pause=%v, abort=%v",
  49. filename, server, doRE, doTrace, pauseNumber, abortNumber)
  50. f, err := os.Open(filename)
  51. if err != nil {
  52. return errors.Wrapf(err, "open pcap %v", filename)
  53. }
  54. defer f.Close()
  55. var source *gopacket.PacketSource
  56. if strings.HasSuffix(filename, ".pcap") {
  57. r, err := pcapgo.NewReader(f)
  58. if err != nil {
  59. return errors.Wrapf(err, "new reader")
  60. }
  61. source = gopacket.NewPacketSource(r, r.LinkType())
  62. } else {
  63. r, err := pcapgo.NewNgReader(f, pcapgo.DefaultNgReaderOptions)
  64. if err != nil {
  65. return errors.Wrapf(err, "new reader")
  66. }
  67. source = gopacket.NewPacketSource(r, r.LinkType())
  68. }
  69. // TODO: FIXME: Should start a goroutine to consume bytes from conn.
  70. conn, err := net.Dial("tcp", server)
  71. if err != nil {
  72. return errors.Wrapf(err, "dial %v", server)
  73. }
  74. defer conn.Close()
  75. var packetNumber uint64
  76. var previousTime *time.Time
  77. for packet := range source.Packets() {
  78. packetNumber++
  79. if packet.Layer(layers.LayerTypeTCP) == nil {
  80. continue
  81. }
  82. ci := packet.Metadata().CaptureInfo
  83. tcp, _ := packet.Layer(layers.LayerTypeTCP).(*layers.TCP)
  84. payload := tcp.Payload
  85. if len(payload) == 0 {
  86. continue
  87. }
  88. if tcp.DstPort != 1935 && tcp.DstPort != 19350 {
  89. continue
  90. }
  91. if pauseNumber > 0 && packetNumber == pauseNumber {
  92. reader := bufio.NewReader(os.Stdin)
  93. trace("#%v Press Enter to continue...", packetNumber)
  94. _, _ = reader.ReadString('\n')
  95. }
  96. if abortNumber > 0 && packetNumber > abortNumber {
  97. break
  98. }
  99. if _, err := conn.Write(payload); err != nil {
  100. return errors.Wrapf(err, "write to %v", server)
  101. }
  102. if doRE {
  103. if previousTime == nil {
  104. previousTime = &ci.Timestamp
  105. } else {
  106. if diff := ci.Timestamp.Sub(*previousTime); diff > 100*time.Millisecond {
  107. time.Sleep(diff)
  108. previousTime = &ci.Timestamp
  109. }
  110. }
  111. }
  112. if doTrace {
  113. trace("#%v TCP %v=>%v %v Len:%v",
  114. packetNumber, uint16(tcp.SrcPort), uint16(tcp.DstPort),
  115. ci.Timestamp.Format("15:04:05.000"),
  116. len(payload))
  117. }
  118. }
  119. return nil
  120. }