File: api_rest_record.go

package info (click to toggle)
bettercap 2.33.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 8,668 kB
  • sloc: sh: 154; makefile: 76; python: 52; ansic: 9
file content (118 lines) | stat: -rw-r--r-- 2,273 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package api_rest

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/bettercap/recording"

	"github.com/evilsocket/islazy/fs"
)

var (
	errNotRecording = errors.New("not recording")
)

func (mod *RestAPI) errAlreadyRecording() error {
	return fmt.Errorf("the module is already recording to %s", mod.recordFileName)
}

func (mod *RestAPI) recordState() error {
	mod.Session.Lock()
	defer mod.Session.Unlock()

	session := new(bytes.Buffer)
	encoder := json.NewEncoder(session)

	if err := encoder.Encode(mod.Session); err != nil {
		return err
	}

	events := new(bytes.Buffer)
	encoder = json.NewEncoder(events)

	if err := encoder.Encode(mod.getEvents(0)); err != nil {
		return err
	}

	return mod.record.NewState(session.Bytes(), events.Bytes())
}

func (mod *RestAPI) recorder() {
	clock := time.Duration(mod.recClock) * time.Second

	mod.recTime = 0
	mod.recording = true
	mod.replaying = false
	mod.record = recording.New(mod.recordFileName)

	mod.Info("started recording to %s (clock %s) ...", mod.recordFileName, clock)

	mod.recordWait.Add(1)
	defer mod.recordWait.Done()

	tick := time.NewTicker(1 * time.Second)
	lastSampled := time.Time{}

	for range tick.C {
		if !mod.recording {
			break
		}

		mod.recTime++

		if time.Since(lastSampled) >= clock {
			lastSampled = time.Now()
			if err := mod.recordState(); err != nil {
				mod.Error("error while recording: %s", err)
				mod.recording = false
				break
			}
		}
	}

	mod.Info("stopped recording to %s ...", mod.recordFileName)
}

func (mod *RestAPI) startRecording(filename string) (err error) {
	if mod.recording {
		return mod.errAlreadyRecording()
	} else if mod.replaying {
		return mod.errAlreadyReplaying()
	} else if err, mod.recClock = mod.IntParam("api.rest.record.clock"); err != nil {
		return err
	} else if mod.recordFileName, err = fs.Expand(filename); err != nil {
		return err
	}

	// we need the api itself up and running
	if !mod.Running() {
		if err = mod.Start(); err != nil {
			return err
		}
	}

	go mod.recorder()

	return nil
}

func (mod *RestAPI) stopRecording() error {
	if !mod.recording {
		return errNotRecording
	}

	mod.recording = false

	mod.recordWait.Wait()

	err := mod.record.Flush()

	mod.recordFileName = ""
	mod.record = nil

	return err
}