diff --git a/downstream.go b/downstream.go index 32ffd6f..347d042 100644 --- a/downstream.go +++ b/downstream.go @@ -990,9 +990,14 @@ func (dc *downstreamConn) welcome() error { dc.forEachNetwork(func(net *network) { // Only send history if we're the first connected client with that name // for the network - if _, ok := net.offlineClients[dc.clientName]; ok { + firstClient := true + dc.user.forEachDownstream(func(c *downstreamConn) { + if c != dc && c.clientName == dc.clientName && c.network == dc.network { + firstClient = false + } + }) + if firstClient { dc.sendNetworkBacklog(net) - delete(net.offlineClients, dc.clientName) } // Fast-forward history to last message diff --git a/upstream.go b/upstream.go index 616151e..422b82d 100644 --- a/upstream.go +++ b/upstream.go @@ -1740,14 +1740,12 @@ func (uc *upstreamConn) appendLog(entity string, msg *irc.Message) (msgID string return "" } - detached := false - if ch := uc.network.channels.Value(entity); ch != nil { - detached = ch.Detached - } - delivered := uc.network.delivered.Value(entity) entityCM := uc.network.casemap(entity) if delivered == nil { + // This is the first message we receive from this target. Save the last + // message ID in delivery receipts, so that we can send the new message + // in the backlog if an offline client reconnects. lastID, err := uc.user.msgStore.LastMsgID(uc.network, entityCM, time.Now()) if err != nil { uc.logger.Printf("failed to log message: failed to get last message ID: %v", err) @@ -1757,17 +1755,9 @@ func (uc *upstreamConn) appendLog(entity string, msg *irc.Message) (msgID string delivered = make(deliveredClientMap) uc.network.delivered.SetValue(entity, delivered) - for clientName, _ := range uc.network.offlineClients { + for clientName, _ := range uc.network.clients { delivered[clientName] = lastID } - - if detached { - // If the channel is detached, online clients act as offline - // clients too - uc.forEachDownstream(func(dc *downstreamConn) { - delivered[dc.clientName] = lastID - }) - } } msgID, err := uc.user.msgStore.Append(uc.network, entityCM, msg) diff --git a/user.go b/user.go index 9dcc260..fe5f504 100644 --- a/user.go +++ b/user.go @@ -62,12 +62,12 @@ type network struct { user *user stopped chan struct{} - conn *upstreamConn - channels channelCasemapMap - delivered deliveredCasemapMap - offlineClients map[string]struct{} // indexed by client name - lastError error - casemap casemapping + conn *upstreamConn + channels channelCasemapMap + delivered deliveredCasemapMap + clients map[string]struct{} // indexed by client name + lastError error + casemap casemapping } func newNetwork(user *user, record *Network, channels []Channel) *network { @@ -78,13 +78,13 @@ func newNetwork(user *user, record *Network, channels []Channel) *network { } return &network{ - Network: *record, - user: user, - stopped: make(chan struct{}), - channels: m, - delivered: deliveredCasemapMap{newCasemapMap(0)}, - offlineClients: make(map[string]struct{}), - casemap: casemapRFC1459, + Network: *record, + user: user, + stopped: make(chan struct{}), + channels: m, + delivered: deliveredCasemapMap{newCasemapMap(0)}, + clients: make(map[string]struct{}), + casemap: casemapRFC1459, } } @@ -196,8 +196,6 @@ func (net *network) detach(ch *Channel) { } net.forEachDownstream(func(dc *downstreamConn) { - net.offlineClients[dc.clientName] = struct{}{} - dc.SendMessage(&irc.Message{ Prefix: dc.prefix(), Command: "PART", @@ -448,6 +446,7 @@ func (u *user) run() { u.downstreamConns = append(u.downstreamConns, dc) dc.forEachNetwork(func(network *network) { + network.clients[dc.clientName] = struct{}{} if network.lastError != nil { sendServiceNOTICE(dc, fmt.Sprintf("disconnected from %s: %v", network.GetName(), network.lastError)) } @@ -466,22 +465,6 @@ func (u *user) run() { } } - // Save history if we're the last client with this name - skipHistory := make(map[*network]bool) - u.forEachDownstream(func(conn *downstreamConn) { - if dc.clientName == conn.clientName { - skipHistory[conn.network] = true - } - }) - - dc.forEachNetwork(func(net *network) { - if skipHistory[net] || skipHistory[nil] { - return - } - - net.offlineClients[dc.clientName] = struct{}{} - }) - u.forEachUpstream(func(uc *upstreamConn) { uc.updateAway() })