Add time tag to all messages

This commit is contained in:
Simon Ser 2020-04-03 20:48:23 +02:00
parent 27e0906450
commit 3d142cae9f
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
3 changed files with 34 additions and 27 deletions

View file

@ -71,12 +71,12 @@ type downstreamConn struct {
negociatingCaps bool negociatingCaps bool
capVersion int capVersion int
caps map[string]bool
saslServer sasl.Server saslServer sasl.Server
lock sync.Mutex lock sync.Mutex
ourMessages map[*irc.Message]struct{} ourMessages map[*irc.Message]struct{}
caps map[string]bool
} }
func newDownstreamConn(srv *Server, netConn net.Conn, id uint64) *downstreamConn { func newDownstreamConn(srv *Server, netConn net.Conn, id uint64) *downstreamConn {
@ -85,8 +85,8 @@ func newDownstreamConn(srv *Server, netConn net.Conn, id uint64) *downstreamConn
conn: *newConn(srv, netConn, logger), conn: *newConn(srv, netConn, logger),
id: id, id: id,
ringConsumers: make(map[*network]*RingConsumer), ringConsumers: make(map[*network]*RingConsumer),
caps: make(map[string]bool),
ourMessages: make(map[*irc.Message]struct{}), ourMessages: make(map[*irc.Message]struct{}),
caps: make(map[string]bool),
} }
dc.hostname = netConn.RemoteAddr().String() dc.hostname = netConn.RemoteAddr().String()
if host, _, err := net.SplitHostPort(dc.hostname); err == nil { if host, _, err := net.SplitHostPort(dc.hostname); err == nil {
@ -209,8 +209,27 @@ func (dc *downstreamConn) readMessages(ch chan<- event) error {
return nil return nil
} }
func (dc *downstreamConn) getCap(name string) bool {
dc.lock.Lock()
defer dc.lock.Unlock()
return dc.caps[name]
}
func (dc *downstreamConn) SendMessage(msg *irc.Message) { func (dc *downstreamConn) SendMessage(msg *irc.Message) {
// TODO: strip tags if the client doesn't support them (see runNetwork) if !dc.getCap("message-tags") {
msg = msg.Copy()
for name := range msg.Tags {
supported := false
switch name {
case "time":
supported = dc.getCap("server-time")
}
if !supported {
delete(msg.Tags, name)
}
}
}
dc.conn.SendMessage(msg) dc.conn.SendMessage(msg)
} }
@ -258,7 +277,7 @@ func (dc *downstreamConn) handleMessageUnregistered(msg *irc.Message) error {
return err return err
} }
case "AUTHENTICATE": case "AUTHENTICATE":
if !dc.caps["sasl"] { if !dc.getCap("sasl") {
return ircError{&irc.Message{ return ircError{&irc.Message{
Command: irc.ERR_SASLFAIL, Command: irc.ERR_SASLFAIL,
Params: []string{"*", "AUTHENTICATE requires the \"sasl\" capability to be enabled"}, Params: []string{"*", "AUTHENTICATE requires the \"sasl\" capability to be enabled"},
@ -399,9 +418,11 @@ func (dc *downstreamConn) handleCapCommand(cmd string, args []string) error {
} }
case "LIST": case "LIST":
var caps []string var caps []string
dc.lock.Lock()
for name := range dc.caps { for name := range dc.caps {
caps = append(caps, name) caps = append(caps, name)
} }
dc.lock.Unlock()
// TODO: multi-line replies // TODO: multi-line replies
dc.SendMessage(&irc.Message{ dc.SendMessage(&irc.Message{
@ -419,6 +440,7 @@ func (dc *downstreamConn) handleCapCommand(cmd string, args []string) error {
caps := strings.Fields(args[0]) caps := strings.Fields(args[0])
ack := true ack := true
dc.lock.Lock()
for _, name := range caps { for _, name := range caps {
name = strings.ToLower(name) name = strings.ToLower(name)
enable := !strings.HasPrefix(name, "-") enable := !strings.HasPrefix(name, "-")
@ -438,6 +460,7 @@ func (dc *downstreamConn) handleCapCommand(cmd string, args []string) error {
ack = false ack = false
} }
} }
dc.lock.Unlock()
reply := "NAK" reply := "NAK"
if ack { if ack {
@ -663,11 +686,6 @@ func (dc *downstreamConn) runNetwork(net *network, loadHistory bool) {
} }
} }
// TODO: can't be enabled/disabled on-the-fly
msgTagsEnabled := dc.caps["message-tags"]
serverTimeEnabled := dc.caps["server-time"]
echoMessageEnabled := dc.caps["echo-message"]
consumer, ch := net.ring.NewConsumer(seqPtr) consumer, ch := net.ring.NewConsumer(seqPtr)
if _, ok := dc.ringConsumers[net]; ok { if _, ok := dc.ringConsumers[net]; ok {
@ -693,7 +711,7 @@ func (dc *downstreamConn) runNetwork(net *network, loadHistory bool) {
_, ours := dc.ourMessages[msg] _, ours := dc.ourMessages[msg]
delete(dc.ourMessages, msg) delete(dc.ourMessages, msg)
dc.lock.Unlock() dc.lock.Unlock()
if ours && !echoMessageEnabled { if ours && !dc.getCap("echo-message") {
// The message comes from our connection, don't echo it // The message comes from our connection, don't echo it
// back // back
consumer.Consume() consumer.Consume()
@ -709,19 +727,6 @@ func (dc *downstreamConn) runNetwork(net *network, loadHistory bool) {
panic("expected to consume a PRIVMSG message") panic("expected to consume a PRIVMSG message")
} }
if !msgTagsEnabled {
for name := range msg.Tags {
supported := false
switch name {
case "time":
supported = serverTimeEnabled
}
if !supported {
delete(msg.Tags, name)
}
}
}
dc.SendMessage(msg) dc.SendMessage(msg)
consumer.Consume() consumer.Consume()
} }

View file

@ -31,6 +31,8 @@ func (ml *messageLogger) Append(msg *irc.Message) error {
return nil return nil
} }
// TODO: parse time from msg.Tags["time"], if available
// TODO: enforce maximum open file handles (LRU cache of file handles) // TODO: enforce maximum open file handles (LRU cache of file handles)
// TODO: handle non-monotonic clock behaviour // TODO: handle non-monotonic clock behaviour
now := time.Now() now := time.Now()

View file

@ -245,6 +245,10 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
} }
} }
if _, ok := msg.Tags["time"]; !ok {
msg.Tags["time"] = irc.TagValue(time.Now().Format(serverTimeLayout))
}
switch msg.Command { switch msg.Command {
case "PING": case "PING":
uc.SendMessage(&irc.Message{ uc.SendMessage(&irc.Message{
@ -1149,10 +1153,6 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
break break
} }
if _, ok := msg.Tags["time"]; !ok {
msg.Tags["time"] = irc.TagValue(time.Now().Format(serverTimeLayout))
}
target := nick target := nick
if nick == uc.nick { if nick == uc.nick {
target = msg.Prefix.Name target = msg.Prefix.Name