api_rest_record.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package api_rest
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "time"
  8. "github.com/bettercap/recording"
  9. "github.com/evilsocket/islazy/fs"
  10. )
  11. var (
  12. errNotRecording = errors.New("not recording")
  13. )
  14. func (mod *RestAPI) errAlreadyRecording() error {
  15. return fmt.Errorf("the module is already recording to %s", mod.recordFileName)
  16. }
  17. func (mod *RestAPI) recordState() error {
  18. mod.Session.Lock()
  19. defer mod.Session.Unlock()
  20. session := new(bytes.Buffer)
  21. encoder := json.NewEncoder(session)
  22. if err := encoder.Encode(mod.Session); err != nil {
  23. return err
  24. }
  25. events := new(bytes.Buffer)
  26. encoder = json.NewEncoder(events)
  27. if err := encoder.Encode(mod.getEvents(0)); err != nil {
  28. return err
  29. }
  30. return mod.record.NewState(session.Bytes(), events.Bytes())
  31. }
  32. func (mod *RestAPI) recorder() {
  33. clock := time.Duration(mod.recClock) * time.Second
  34. mod.recTime = 0
  35. mod.recording = true
  36. mod.replaying = false
  37. mod.record = recording.New(mod.recordFileName)
  38. mod.Info("started recording to %s (clock %s) ...", mod.recordFileName, clock)
  39. mod.recordWait.Add(1)
  40. defer mod.recordWait.Done()
  41. tick := time.NewTicker(1 * time.Second)
  42. lastSampled := time.Time{}
  43. for range tick.C {
  44. if !mod.recording {
  45. break
  46. }
  47. mod.recTime++
  48. if time.Since(lastSampled) >= clock {
  49. lastSampled = time.Now()
  50. if err := mod.recordState(); err != nil {
  51. mod.Error("error while recording: %s", err)
  52. mod.recording = false
  53. break
  54. }
  55. }
  56. }
  57. mod.Info("stopped recording to %s ...", mod.recordFileName)
  58. }
  59. func (mod *RestAPI) startRecording(filename string) (err error) {
  60. if mod.recording {
  61. return mod.errAlreadyRecording()
  62. } else if mod.replaying {
  63. return mod.errAlreadyReplaying()
  64. } else if err, mod.recClock = mod.IntParam("api.rest.record.clock"); err != nil {
  65. return err
  66. } else if mod.recordFileName, err = fs.Expand(filename); err != nil {
  67. return err
  68. }
  69. // we need the api itself up and running
  70. if !mod.Running() {
  71. if err = mod.Start(); err != nil {
  72. return err
  73. }
  74. }
  75. go mod.recorder()
  76. return nil
  77. }
  78. func (mod *RestAPI) stopRecording() error {
  79. if !mod.recording {
  80. return errNotRecording
  81. }
  82. mod.recording = false
  83. mod.recordWait.Wait()
  84. err := mod.record.Flush()
  85. mod.recordFileName = ""
  86. mod.record = nil
  87. return err
  88. }