From 897c21dbb4f2bcad561d4fd08100f54f1c996428 Mon Sep 17 00:00:00 2001 From: delthas Date: Tue, 18 Oct 2022 14:57:33 +0200 Subject: [PATCH] Truncate message times to the second when using the FS message store The FS message store truncates message times to the second. This means that a message sent out as 2020-01-01T00:00:00.123Z could be sent later as part of a CHATHISTORY batch as 2020-01-01T00:00:00.000Z, which could cause issues in clients. One such issue is a client sending a MARKREAD for 2020-01-01T00:00:00.000Z, with another client considering the 2020-01-01T00:00:00.123Z message it has as unread. This fixes the issue by truncating all message times to the second when using the FS message store. --- downstream.go | 6 +++--- msgstore/fs.go | 5 +++++ upstream.go | 8 ++++++-- user.go | 11 +++++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/downstream.go b/downstream.go index ec00fb5..3a452d5 100644 --- a/downstream.go +++ b/downstream.go @@ -2281,7 +2281,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc. dc.logger.Printf("broadcasting bouncer-wide %v: %v", msg.Command, text) broadcastTags := tags.Copy() - broadcastTags["time"] = xirc.FormatServerTime(time.Now()) + broadcastTags["time"] = dc.user.FormatServerTime(time.Now()) broadcastMsg := &irc.Message{ Tags: broadcastTags, Prefix: servicePrefix, @@ -2307,7 +2307,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc. if casemapASCII(name) == serviceNickCM { if dc.caps.IsEnabled("echo-message") { echoTags := tags.Copy() - echoTags["time"] = xirc.FormatServerTime(time.Now()) + echoTags["time"] = dc.user.FormatServerTime(time.Now()) dc.SendMessage(&irc.Message{ Tags: echoTags, Prefix: dc.prefix(), @@ -2351,7 +2351,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc. } echoTags := tags.Copy() - echoTags["time"] = xirc.FormatServerTime(time.Now()) + echoTags["time"] = dc.user.FormatServerTime(time.Now()) if uc.account != "" { echoTags["account"] = uc.account } diff --git a/msgstore/fs.go b/msgstore/fs.go index e2fddb8..81ec58e 100644 --- a/msgstore/fs.go +++ b/msgstore/fs.go @@ -96,6 +96,11 @@ var ( _ RenameNetworkStore = (*fsMessageStore)(nil) ) +func IsFSStore(store Store) bool { + _, ok := store.(*fsMessageStore) + return ok +} + func NewFSStore(root string, user *database.User) *fsMessageStore { return &fsMessageStore{ root: filepath.Join(root, escapeFilename(user.Username)), diff --git a/upstream.go b/upstream.go index ddc1fb9..032e710 100644 --- a/upstream.go +++ b/upstream.go @@ -486,8 +486,12 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err msg.Prefix = uc.serverPrefix } - if _, ok := msg.Tags["time"]; !ok && !isNumeric(msg.Command) { - msg.Tags["time"] = xirc.FormatServerTime(time.Now()) + if !isNumeric(msg.Command) { + t, err := time.Parse(xirc.ServerTimeLayout, string(msg.Tags["time"])) + if err != nil { + t = time.Now() + } + msg.Tags["time"] = uc.user.FormatServerTime(t) } switch msg.Command { diff --git a/user.go b/user.go index 79bf2a9..ef9433f 100644 --- a/user.go +++ b/user.go @@ -13,6 +13,8 @@ import ( "strings" "time" + "git.sr.ht/~emersion/soju/xirc" + "github.com/SherClockHolmes/webpush-go" "gopkg.in/irc.v4" @@ -1114,6 +1116,15 @@ func (u *user) hasPersistentMsgStore() bool { return !msgstore.IsMemoryStore(u.msgStore) } +func (u *user) FormatServerTime(t time.Time) string { + if u.msgStore != nil && msgstore.IsFSStore(u.msgStore) { + // The FS message store truncates message timestamps to the second, + // so truncate them here to get consistent timestamps. + t = t.Truncate(time.Second) + } + return xirc.FormatServerTime(t) +} + // localAddrForHost returns the local address to use when connecting to host. // A nil address is returned when the OS should automatically pick one. func (u *user) localTCPAddrForHost(ctx context.Context, host string) (*net.TCPAddr, error) {