From 90ba4814c86b41b8e1dcd6cd68896219811d8003 Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Thu, 8 Oct 2020 14:38:33 +0200 Subject: [PATCH] Discard old history entries. --- README | 2 + group/group.go | 41 ++++++++++++++++++- .../webclient_test.go => group/group_test.go | 8 ++-- rtpconn/webclient.go | 18 +------- 4 files changed, 47 insertions(+), 22 deletions(-) rename rtpconn/webclient_test.go => group/group_test.go (77%) diff --git a/README b/README index 5537f67..7d75acc 100644 --- a/README +++ b/README @@ -103,6 +103,8 @@ fields, all of which are optional. displayed on the landing page for public groups; - `max-clients`: the maximum number of clients that may join the group at a time; + - `max-history-age`: the time, in seconds, during which chat history is + kept (default 14400, i.e. 4 hours); - `allow-recording`: if true, then recording is allowed in this group; - `allow-anonymous`: if true, then users may connect with an empty username; this is not recommended, since anonymous users are not diff --git a/group/group.go b/group/group.go index 6770e1c..0799d9b 100644 --- a/group/group.go +++ b/group/group.go @@ -65,7 +65,7 @@ func IceConfiguration() webrtc.Configuration { type ChatHistoryEntry struct { Id string User string - Time uint64 + Time int64 Kind string Value string } @@ -396,6 +396,18 @@ func (g *Group) Shutdown(message string) { }) } +func FromJSTime(tm int64) time.Time { + if tm == 0 { + return time.Time{} + } + return time.Unix(int64(tm)/1000, (int64(tm)%1000)*1000000) +} + +func ToJSTime(tm time.Time) int64 { + return int64((tm.Sub(time.Unix(0, 0)) + time.Millisecond/2) / + time.Millisecond) +} + const maxChatHistory = 50 func (g *Group) ClearChatHistory() { @@ -404,7 +416,7 @@ func (g *Group) ClearChatHistory() { g.history = nil } -func (g *Group) AddToChatHistory(id, user string, time uint64, kind, value string) { +func (g *Group) AddToChatHistory(id, user string, time int64, kind, value string) { g.mu.Lock() defer g.mu.Unlock() @@ -417,10 +429,34 @@ func (g *Group) AddToChatHistory(id, user string, time uint64, kind, value strin ) } +func discardObsoleteHistory(h []ChatHistoryEntry, seconds int) []ChatHistoryEntry { + now := time.Now() + d := 4 * time.Hour + if seconds > 0 { + d = time.Duration(seconds) * time.Second + } + + i := 0 + for i < len(h) { + log.Println(h[i].Time, FromJSTime(h[i].Time), now.Sub(FromJSTime(h[i].Time))) + if now.Sub(FromJSTime(h[i].Time)) <= d { + break + } + i++ + } + if i > 0 { + copy(h, h[i:]) + h = h[:len(h)-i] + } + return h +} + func (g *Group) GetChatHistory() []ChatHistoryEntry { g.mu.Lock() defer g.mu.Unlock() + g.history = discardObsoleteHistory(g.history, g.description.MaxHistoryAge) + h := make([]ChatHistoryEntry, len(g.history)) copy(h, g.history) return h @@ -448,6 +484,7 @@ type description struct { Redirect string `json:"redirect,omitempty"` Public bool `json:"public,omitempty"` MaxClients int `json:"max-clients,omitempty"` + MaxHistoryAge int `json:"max-history-age",omitempty` AllowAnonymous bool `json:"allow-anonymous,omitempty"` AllowRecording bool `json:"allow-recording,omitempty"` Op []ClientCredentials `json:"op,omitempty"` diff --git a/rtpconn/webclient_test.go b/group/group_test.go similarity index 77% rename from rtpconn/webclient_test.go rename to group/group_test.go index 4d84b16..d2346ab 100644 --- a/rtpconn/webclient_test.go +++ b/group/group_test.go @@ -1,4 +1,4 @@ -package rtpconn +package group import ( "testing" @@ -7,9 +7,9 @@ import ( func TestJSTime(t *testing.T) { tm := time.Now() - js := toJSTime(tm) - tm2 := fromJSTime(js) - js2 := toJSTime(tm2) + js := ToJSTime(tm) + tm2 := FromJSTime(js) + js2 := ToJSTime(tm2) if js != js2 { t.Errorf("%v != %v", js, js2) diff --git a/rtpconn/webclient.go b/rtpconn/webclient.go index b705d8f..b0bc5cb 100644 --- a/rtpconn/webclient.go +++ b/rtpconn/webclient.go @@ -147,7 +147,7 @@ type clientMessage struct { Permissions group.ClientPermissions `json:"permissions,omitempty"` Group string `json:"group,omitempty"` Value string `json:"value,omitempty"` - Time uint64 `json:"time,omitempty"` + Time int64 `json:"time,omitempty"` Offer *webrtc.SessionDescription `json:"offer,omitempty"` Answer *webrtc.SessionDescription `json:"answer,omitempty"` Candidate *webrtc.ICECandidateInit `json:"candidate,omitempty"` @@ -155,20 +155,6 @@ type clientMessage struct { Request rateMap `json:"request,omitempty"` } -func fromJSTime(tm uint64) time.Time { - if tm == 0 { - return time.Time{} - } - return time.Unix(int64(tm)/1000, (int64(tm)%1000)*1000000) -} - -func toJSTime(tm time.Time) uint64 { - if tm.Before(time.Unix(0, 0)) { - return 0 - } - return uint64((tm.Sub(time.Unix(0, 0)) + time.Millisecond/2) / time.Millisecond) -} - type closeMessage struct { data []byte } @@ -1060,7 +1046,7 @@ func handleClientMessage(c *webClient, m clientMessage) error { log.Printf("ICE: %v", err) } case "chat": - tm := toJSTime(time.Now()) + tm := group.ToJSTime(time.Now()) if m.Dest == "" { c.group.AddToChatHistory( m.Id, m.Username, tm, m.Kind, m.Value,