diff --git a/modules/api_rest/api_rest.go b/modules/api_rest/api_rest.go index b20e8030..28d66565 100644 --- a/modules/api_rest/api_rest.go +++ b/modules/api_rest/api_rest.go @@ -35,6 +35,8 @@ type RestAPI struct { recordFileName string recordWait *sync.WaitGroup record *Record + recStarted time.Time + recStopped time.Time } func NewRestAPI(s *session.Session) *RestAPI { @@ -65,6 +67,8 @@ func NewRestAPI(s *session.Session) *RestAPI { mod.State.Store("rec_filename", &mod.recordFileName) mod.State.Store("rec_frames", 0) mod.State.Store("rec_cur_frame", 0) + mod.State.Store("rec_started", &mod.recStarted) + mod.State.Store("rec_stopped", &mod.recStopped) mod.AddParam(session.NewStringParameter("api.rest.address", "127.0.0.1", diff --git a/modules/api_rest/api_rest_controller.go b/modules/api_rest/api_rest_controller.go index 72e7c43e..da9b4d63 100644 --- a/modules/api_rest/api_rest_controller.go +++ b/modules/api_rest/api_rest_controller.go @@ -36,7 +36,7 @@ func (mod *RestAPI) setAuthFailed(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) toJSON(w http.ResponseWriter, o interface{}) { w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(o); err != nil { - fmt.Printf("error while encoding object to JSON: %v\n", err) + mod.Warning("error while encoding object to JSON: %v", err) } } diff --git a/modules/api_rest/api_rest_replay.go b/modules/api_rest/api_rest_replay.go index 7376f6e3..b04c9ef4 100644 --- a/modules/api_rest/api_rest_replay.go +++ b/modules/api_rest/api_rest_replay.go @@ -50,10 +50,18 @@ func (mod *RestAPI) startReplay(filename string) (err error) { } } + mod.recStarted = mod.record.Session.StartedAt() + mod.recStopped = mod.record.Session.StoppedAt() + duration := mod.recStopped.Sub(mod.recStarted) + mod.recTime = int(duration.Seconds()) mod.replaying = true mod.recording = false - mod.Info("loaded %d frames in %s, started replaying ...", mod.record.Session.Frames(), loadedIn) + mod.Info("loaded %s of recording (%d frames) started at %s in %s, started replaying ...", + duration, + mod.record.Session.Frames(), + mod.recStarted, + loadedIn) return nil } diff --git a/modules/api_rest/record.go b/modules/api_rest/record.go index 4693ce2a..cd52765f 100644 --- a/modules/api_rest/record.go +++ b/modules/api_rest/record.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "os" "sync" + "time" "github.com/bettercap/bettercap/session" @@ -146,6 +147,36 @@ func (e *RecordEntry) Next() []byte { return e.frames[cur] } +func (e *RecordEntry) TimeOf(idx int) time.Time { + e.Lock() + defer e.Unlock() + + buf := e.frames[idx] + frame := make(map[string]interface{}) + + if err := json.Unmarshal(buf, &frame); err != nil { + fmt.Printf("%v\n", err) + return time.Time{} + } else if tm, err := time.Parse(time.RFC3339, frame["polled_at"].(string)); err != nil { + fmt.Printf("%v\n", err) + return time.Time{} + } else { + return tm + } +} + +func (e *RecordEntry) StartedAt() time.Time { + return e.TimeOf(0) +} + +func (e *RecordEntry) StoppedAt() time.Time { + return e.TimeOf(e.NumStates) +} + +func (e *RecordEntry) Duration() time.Duration { + return e.StoppedAt().Sub(e.StartedAt()) +} + // the Record object represents a recorded session type Record struct { sync.Mutex