Authentication-Results: mail-b.sr.ht; dkim=pass header.d=dille.cc header.i=@dille.cc Received: from mail.saucisseroyale.cc (11.8.91.92.rev.sfr.net [92.91.8.11]) by mail-b.sr.ht (Postfix) with ESMTPS id 0D92911F0E6 for <~emersion/soju-dev@lists.sr.ht>; Tue, 18 Oct 2022 12:57:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=dille.cc; s=mail; t=1666097857; bh=lRhJPbZ3tiZs6unKnCjBphNIkGwVvLDMN3UBRaZ7Euk=; h=From:To:Cc:Subject:Date:From; b=m4fx51Ylc4MzoDcYkcPGLMOGMvURqUxb4O/o3PznQg353z3gWONnCPYf6YpwOTn7E 5ZPp5laVPcweyifZbxUVsLD2RFl2aLpKsMBHBSwxvC37ZhpttDECRtkj71LDBRzRcx 44qEy0g2XZoHs1aj+QomL/Qsr7zSqKZ7639/D/hBdfoJs4hXvdD2fgXNSLWaIkcGFH 9G4S6bQ5S9cFNRfnVJtPr+9gW5FhIw2WZwLEC63PryczNUQxn47KWUkIG8ddkXGFTO OZWENNHKefe+YlrQ2l50uKYcHhc4MafCo8P7Lyd7X8VxApVpAqLP9Lw6ZCN9ICbaES CK0RvmXVx7KpA== Received: from tflament-T490.anevia.com (82-65-230-251.subs.proxad.net [82.65.230.251]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mail.saucisseroyale.cc (Postfix) with ESMTPSA id 772A0816B4; Tue, 18 Oct 2022 14:57:37 +0200 (CEST) From: delthas To: ~emersion/soju-dev@lists.sr.ht Cc: delthas Subject: [PATCH] Truncate message times to the second when using the FS message store Date: Tue, 18 Oct 2022 14:57:33 +0200 Message-Id: <20221018125733.28721-1-delthas@dille.cc> X-Mailer: git-send-email 2.17.1 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