Centralize logged messages marshaling
This allows messages added to logs to be handled just like messages added to the ring buffer.
This commit is contained in:
parent
37cd9e4d89
commit
3195809c30
@ -222,17 +222,35 @@ func (dc *downstreamConn) SendMessage(msg *irc.Message) {
|
|||||||
dc.conn.SendMessage(msg)
|
dc.conn.SendMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *downstreamConn) sendFromUpstream(msg *irc.Message, uc *upstreamConn) {
|
// marshalMessage re-formats a message coming from an upstream connection so
|
||||||
|
// that it's suitable for being sent on this downstream connection. Only
|
||||||
|
// messages that may appear in logs are supported.
|
||||||
|
func (dc *downstreamConn) marshalMessage(msg *irc.Message, uc *upstreamConn) *irc.Message {
|
||||||
msg = msg.Copy()
|
msg = msg.Copy()
|
||||||
|
msg.Prefix = dc.marshalUserPrefix(uc, msg.Prefix)
|
||||||
|
|
||||||
switch msg.Command {
|
switch msg.Command {
|
||||||
case "PRIVMSG", "NOTICE":
|
case "PRIVMSG", "NOTICE":
|
||||||
msg.Prefix = dc.marshalUserPrefix(uc, msg.Prefix)
|
|
||||||
msg.Params[0] = dc.marshalEntity(uc, msg.Params[0])
|
msg.Params[0] = dc.marshalEntity(uc, msg.Params[0])
|
||||||
|
case "NICK":
|
||||||
|
// Nick change for another user
|
||||||
|
msg.Params[0] = dc.marshalNick(uc, msg.Params[0])
|
||||||
|
case "JOIN", "PART":
|
||||||
|
msg.Params[0] = dc.marshalChannel(uc, msg.Params[0])
|
||||||
|
case "KICK":
|
||||||
|
msg.Params[0] = dc.marshalChannel(uc, msg.Params[0])
|
||||||
|
msg.Params[1] = dc.marshalNick(uc, msg.Params[1])
|
||||||
|
case "TOPIC":
|
||||||
|
msg.Params[0] = dc.marshalChannel(uc, msg.Params[0])
|
||||||
|
case "MODE":
|
||||||
|
msg.Params[0] = dc.marshalEntity(uc, msg.Params[0])
|
||||||
|
case "QUIT":
|
||||||
|
// This space is intentinally left blank
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unexpected %q message", msg.Command))
|
panic(fmt.Sprintf("unexpected %q message", msg.Command))
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(msg)
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *downstreamConn) handleMessage(msg *irc.Message) error {
|
func (dc *downstreamConn) handleMessage(msg *irc.Message) error {
|
||||||
@ -684,7 +702,19 @@ func (dc *downstreamConn) welcome() error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.sendFromUpstream(msg, uc)
|
// Don't replay all messages, because that would mess up client
|
||||||
|
// state. For instance we just sent the list of users, sending
|
||||||
|
// PART messages for one of these users would be incorrect.
|
||||||
|
ignore := true
|
||||||
|
switch msg.Command {
|
||||||
|
case "PRIVMSG", "NOTICE":
|
||||||
|
ignore = false
|
||||||
|
}
|
||||||
|
if ignore {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dc.SendMessage(dc.marshalMessage(msg, uc))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
99
upstream.go
99
upstream.go
@ -562,12 +562,9 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !me {
|
if !me {
|
||||||
|
uc.network.ring.Produce(msg)
|
||||||
uc.forEachDownstream(func(dc *downstreamConn) {
|
uc.forEachDownstream(func(dc *downstreamConn) {
|
||||||
dc.SendMessage(&irc.Message{
|
dc.SendMessage(dc.marshalMessage(msg, uc))
|
||||||
Prefix: dc.marshalUserPrefix(uc, msg.Prefix),
|
|
||||||
Command: "NICK",
|
|
||||||
Params: []string{dc.marshalEntity(uc, newNick)},
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case "JOIN":
|
case "JOIN":
|
||||||
@ -601,15 +598,9 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
ch.Members[msg.Prefix.Name] = nil
|
ch.Members[msg.Prefix.Name] = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
uc.appendLog(ch, msg)
|
chMsg := msg.Copy()
|
||||||
|
chMsg.Params[0] = ch
|
||||||
uc.forEachDownstream(func(dc *downstreamConn) {
|
uc.produce(ch, chMsg, nil)
|
||||||
dc.SendMessage(&irc.Message{
|
|
||||||
Prefix: dc.marshalUserPrefix(uc, msg.Prefix),
|
|
||||||
Command: "JOIN",
|
|
||||||
Params: []string{dc.marshalChannel(uc, ch)},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
case "PART":
|
case "PART":
|
||||||
if msg.Prefix == nil {
|
if msg.Prefix == nil {
|
||||||
@ -621,11 +612,6 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var reason string
|
|
||||||
if len(msg.Params) > 1 {
|
|
||||||
reason = msg.Params[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ch := range strings.Split(channels, ",") {
|
for _, ch := range strings.Split(channels, ",") {
|
||||||
if msg.Prefix.Name == uc.nick {
|
if msg.Prefix.Name == uc.nick {
|
||||||
uc.logger.Printf("parted channel %q", ch)
|
uc.logger.Printf("parted channel %q", ch)
|
||||||
@ -638,19 +624,9 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
delete(ch.Members, msg.Prefix.Name)
|
delete(ch.Members, msg.Prefix.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
uc.appendLog(ch, msg)
|
chMsg := msg.Copy()
|
||||||
|
chMsg.Params[0] = ch
|
||||||
uc.forEachDownstream(func(dc *downstreamConn) {
|
uc.produce(ch, chMsg, nil)
|
||||||
params := []string{dc.marshalChannel(uc, ch)}
|
|
||||||
if reason != "" {
|
|
||||||
params = append(params, reason)
|
|
||||||
}
|
|
||||||
dc.SendMessage(&irc.Message{
|
|
||||||
Prefix: dc.marshalUserPrefix(uc, msg.Prefix),
|
|
||||||
Command: "PART",
|
|
||||||
Params: params,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
case "KICK":
|
case "KICK":
|
||||||
if msg.Prefix == nil {
|
if msg.Prefix == nil {
|
||||||
@ -662,11 +638,6 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var reason string
|
|
||||||
if len(msg.Params) > 2 {
|
|
||||||
reason = msg.Params[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
if user == uc.nick {
|
if user == uc.nick {
|
||||||
uc.logger.Printf("kicked from channel %q by %s", channel, msg.Prefix.Name)
|
uc.logger.Printf("kicked from channel %q by %s", channel, msg.Prefix.Name)
|
||||||
delete(uc.channels, channel)
|
delete(uc.channels, channel)
|
||||||
@ -678,19 +649,7 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
delete(ch.Members, user)
|
delete(ch.Members, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
uc.appendLog(channel, msg)
|
uc.produce(channel, msg, nil)
|
||||||
|
|
||||||
uc.forEachDownstream(func(dc *downstreamConn) {
|
|
||||||
params := []string{dc.marshalChannel(uc, channel), dc.marshalNick(uc, user)}
|
|
||||||
if reason != "" {
|
|
||||||
params = append(params, reason)
|
|
||||||
}
|
|
||||||
dc.SendMessage(&irc.Message{
|
|
||||||
Prefix: dc.marshalUserPrefix(uc, msg.Prefix),
|
|
||||||
Command: "KICK",
|
|
||||||
Params: params,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
case "QUIT":
|
case "QUIT":
|
||||||
if msg.Prefix == nil {
|
if msg.Prefix == nil {
|
||||||
return fmt.Errorf("expected a prefix")
|
return fmt.Errorf("expected a prefix")
|
||||||
@ -709,12 +668,9 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if msg.Prefix.Name != uc.nick {
|
if msg.Prefix.Name != uc.nick {
|
||||||
|
uc.network.ring.Produce(msg)
|
||||||
uc.forEachDownstream(func(dc *downstreamConn) {
|
uc.forEachDownstream(func(dc *downstreamConn) {
|
||||||
dc.SendMessage(&irc.Message{
|
dc.SendMessage(dc.marshalMessage(msg, uc))
|
||||||
Prefix: dc.marshalUserPrefix(uc, msg.Prefix),
|
|
||||||
Command: "QUIT",
|
|
||||||
Params: msg.Params,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case irc.RPL_TOPIC, irc.RPL_NOTOPIC:
|
case irc.RPL_TOPIC, irc.RPL_NOTOPIC:
|
||||||
@ -745,18 +701,7 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
} else {
|
} else {
|
||||||
ch.Topic = ""
|
ch.Topic = ""
|
||||||
}
|
}
|
||||||
uc.appendLog(ch.Name, msg)
|
uc.produce(ch.Name, msg, nil)
|
||||||
uc.forEachDownstream(func(dc *downstreamConn) {
|
|
||||||
params := []string{dc.marshalChannel(uc, name)}
|
|
||||||
if ch.Topic != "" {
|
|
||||||
params = append(params, ch.Topic)
|
|
||||||
}
|
|
||||||
dc.SendMessage(&irc.Message{
|
|
||||||
Prefix: dc.marshalUserPrefix(uc, msg.Prefix),
|
|
||||||
Command: "TOPIC",
|
|
||||||
Params: params,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
case "MODE":
|
case "MODE":
|
||||||
var name, modeStr string
|
var name, modeStr string
|
||||||
if err := parseMessageParams(msg, &name, &modeStr); err != nil {
|
if err := parseMessageParams(msg, &name, &modeStr); err != nil {
|
||||||
@ -781,18 +726,7 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uc.appendLog(ch.Name, msg)
|
uc.produce(ch.Name, msg, nil)
|
||||||
|
|
||||||
uc.forEachDownstream(func(dc *downstreamConn) {
|
|
||||||
params := []string{dc.marshalChannel(uc, name), modeStr}
|
|
||||||
params = append(params, msg.Params[2:]...)
|
|
||||||
|
|
||||||
dc.SendMessage(&irc.Message{
|
|
||||||
Prefix: dc.marshalUserPrefix(uc, msg.Prefix),
|
|
||||||
Command: "MODE",
|
|
||||||
Params: params,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
case irc.RPL_UMODEIS:
|
case irc.RPL_UMODEIS:
|
||||||
if err := parseMessageParams(msg, nil); err != nil {
|
if err := parseMessageParams(msg, nil); err != nil {
|
||||||
@ -1362,6 +1296,11 @@ func (uc *upstreamConn) appendLog(entity string, msg *irc.Message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// produce appends a message to the logs, adds it to the history and forwards
|
||||||
|
// it to connected downstream connections.
|
||||||
|
//
|
||||||
|
// If origin is not nil and origin doesn't support echo-message, the message is
|
||||||
|
// forwarded to all connections except origin.
|
||||||
func (uc *upstreamConn) produce(target string, msg *irc.Message, origin *downstreamConn) {
|
func (uc *upstreamConn) produce(target string, msg *irc.Message, origin *downstreamConn) {
|
||||||
if target != "" {
|
if target != "" {
|
||||||
uc.appendLog(target, msg)
|
uc.appendLog(target, msg)
|
||||||
@ -1371,7 +1310,7 @@ func (uc *upstreamConn) produce(target string, msg *irc.Message, origin *downstr
|
|||||||
|
|
||||||
uc.forEachDownstream(func(dc *downstreamConn) {
|
uc.forEachDownstream(func(dc *downstreamConn) {
|
||||||
if dc != origin || dc.caps["echo-message"] {
|
if dc != origin || dc.caps["echo-message"] {
|
||||||
dc.sendFromUpstream(msg, uc)
|
dc.SendMessage(dc.marshalMessage(msg, uc))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user