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 6302a5c..45c8576 100644
--- a/downstream.go+++ b/downstream.go
@@ -2280,7 +2280,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"] = irc.TagValue(xirc.FormatServerTime(time.Now()))+ broadcastTags["time"] = irc.TagValue(dc.user.FormatServerTime(time.Now())) broadcastMsg := &irc.Message{
Tags: broadcastTags,
Prefix: servicePrefix,
@@ -2306,7 +2306,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"] = irc.TagValue(xirc.FormatServerTime(time.Now()))+ echoTags["time"] = irc.TagValue(dc.user.FormatServerTime(time.Now())) dc.SendMessage(&irc.Message{
Tags: echoTags,
Prefix: dc.prefix(),
@@ -2350,7 +2350,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
}
echoTags := tags.Copy()
- echoTags["time"] = irc.TagValue(xirc.FormatServerTime(time.Now()))+ echoTags["time"] = irc.TagValue(dc.user.FormatServerTime(time.Now())) if uc.account != "" {
echoTags["account"] = irc.TagValue(uc.account)
}
diff --git a/msgstore/fs.go b/msgstore/fs.go
index 53f9977..65db04e 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 e1030a2..4aa3ff9 100644
--- a/upstream.go+++ b/upstream.go
@@ -485,8 +485,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"] = irc.TagValue(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"] = irc.TagValue(uc.user.FormatServerTime(t)) }
switch msg.Command {
diff --git a/user.go b/user.go
index 7468483..43ea79a 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.v3"
@@ -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) {
base-commit: 90be9a8ab95a06d7e622852bf312116c7e199d48
--
2.17.1