diff --git a/irc/capability.go b/irc/capability.go index 3cab24c9..1849040b 100644 --- a/irc/capability.go +++ b/irc/capability.go @@ -23,7 +23,7 @@ const ( ExtendedJoin Capability = "extended-join" InviteNotify Capability = "invite-notify" MaxLine Capability = "draft/maxline" - MessageTags Capability = "draft/message-tags" + MessageTags Capability = "draft/message-tags-0.2" MultiPrefix Capability = "multi-prefix" SASL Capability = "sasl" ServerTime Capability = "server-time" diff --git a/irc/client.go b/irc/client.go index 2e8a8c51..70985f85 100644 --- a/irc/client.go +++ b/irc/client.go @@ -135,6 +135,21 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) *Client { // command goroutine // +func (client *Client) maxlens() (int, int) { + maxlenTags := 512 + maxlenRest := 512 + if client.capabilities[MessageTags] { + maxlenTags = 4096 + } + if client.capabilities[MaxLine] { + if maxLineTagsLength > maxlenTags { + maxlenTags = maxLineTagsLength + } + maxlenRest = maxLineRestLength + } + return maxlenTags, maxlenRest +} + func (client *Client) run() { var err error var isExiting bool @@ -152,14 +167,9 @@ func (client *Client) run() { break } - var maxLen int - if client.capabilities[MaxLine] { - maxLen = maxLineLength - } else { - maxLen = 512 - } + maxlenTags, maxlenRest := client.maxlens() - msg, err = ircmsg.ParseLineMaxLen(line, maxLen) + msg, err = ircmsg.ParseLineMaxLen(line, maxlenTags, maxlenRest) if err != nil { client.Quit("received malformed line") break @@ -512,16 +522,10 @@ func (client *Client) Send(tags *map[string]ircmsg.TagValue, prefix string, comm } } - var maxLen int - if client.capabilities[MaxLine] { - maxLen = maxLineLength - } else { - maxLen = 512 - } - // send out the message message := ircmsg.MakeMessage(tags, prefix, command, params...) - line, err := message.LineMaxLen(maxLen) + maxlenTags, maxlenRest := client.maxlens() + line, err := message.LineMaxLen(maxlenTags, maxlenRest) if err != nil { // try not to fail quietly - especially useful when running tests, as a note to dig deeper // log.Println("Error assembling message:") diff --git a/irc/config.go b/irc/config.go index f840e8b9..0a689026 100644 --- a/irc/config.go +++ b/irc/config.go @@ -116,6 +116,11 @@ type ConnectionThrottleConfig struct { Exempted []string } +type LineLenConfig struct { + Tags int + Rest int +} + type Config struct { Network struct { Name string @@ -151,15 +156,15 @@ type Config struct { Opers map[string]*OperConfig Limits struct { - AwayLen uint `yaml:"awaylen"` - ChanListModes uint `yaml:"chan-list-modes"` - ChannelLen uint `yaml:"channellen"` - KickLen uint `yaml:"kicklen"` - LineLen uint `yaml:"linelen"` - MonitorEntries uint `yaml:"monitor-entries"` - NickLen uint `yaml:"nicklen"` - TopicLen uint `yaml:"topiclen"` - WhowasEntries uint `yaml:"whowas-entries"` + AwayLen uint `yaml:"awaylen"` + ChanListModes uint `yaml:"chan-list-modes"` + ChannelLen uint `yaml:"channellen"` + KickLen uint `yaml:"kicklen"` + MonitorEntries uint `yaml:"monitor-entries"` + NickLen uint `yaml:"nicklen"` + TopicLen uint `yaml:"topiclen"` + WhowasEntries uint `yaml:"whowas-entries"` + LineLen LineLenConfig `yaml:"linelen"` } } @@ -336,7 +341,7 @@ func LoadConfig(filename string) (config *Config, err error) { return nil, fmt.Errorf("Could not parse connection-throttle ban-duration: %s", err.Error()) } } - if config.Limits.LineLen < 512 { + if config.Limits.LineLen.Tags < 512 || config.Limits.LineLen.Rest < 512 { return nil, errors.New("Line length must be 512 or greater") } diff --git a/irc/constants.go b/irc/constants.go index 354be513..c8468cce 100644 --- a/irc/constants.go +++ b/irc/constants.go @@ -17,7 +17,8 @@ var ( Ver = fmt.Sprintf("oragono-%s", SemVer) // Used as the standard maximum line length unless overridden at runtime. - maxLineLength = 512 + maxLineTagsLength = 512 + maxLineRestLength = 512 // maxLastArgLength is used to simply cap off the final argument when creating general messages where we need to select a limit. // for instance, in MONITOR lists, RPL_ISUPPORT lists, etc. maxLastArgLength = 400 diff --git a/irc/server.go b/irc/server.go index d9f7f649..74c930f5 100644 --- a/irc/server.go +++ b/irc/server.go @@ -37,7 +37,7 @@ var ( errDbOutOfDate = errors.New("Database schema is old.") ) -// Limits holds the maximum limits for various things such as topic lengths +// Limits holds the maximum limits for various things such as topic lengths. type Limits struct { AwayLen int ChannelLen int @@ -46,7 +46,13 @@ type Limits struct { NickLen int TopicLen int ChanListModes int - LineLen int + LineLen LineLenLimits +} + +// LineLenLimits holds the maximum limits for IRC lines. +type LineLenLimits struct { + Tags int + Rest int } // ListenerInterface represents an interface for a listener. @@ -147,10 +153,9 @@ func NewServer(configFilename string, config *Config) *Server { SupportedCapabilities[SASL] = true } - if config.Limits.LineLen > 512 { - maxLineLength = int(config.Limits.LineLen) + if config.Limits.LineLen.Tags > 512 || config.Limits.LineLen.Rest > 512 { SupportedCapabilities[MaxLine] = true - CapValues[MaxLine] = strconv.Itoa(int(config.Limits.LineLen)) + CapValues[MaxLine] = fmt.Sprintf("%d,%d", config.Limits.LineLen.Tags, config.Limits.LineLen.Rest) } operClasses, err := config.OperatorClasses() @@ -191,7 +196,10 @@ func NewServer(configFilename string, config *Config) *Server { NickLen: int(config.Limits.NickLen), TopicLen: int(config.Limits.TopicLen), ChanListModes: int(config.Limits.ChanListModes), - LineLen: int(config.Limits.LineLen), + LineLen: LineLenLimits{ + Tags: config.Limits.LineLen.Tags, + Rest: config.Limits.LineLen.Rest, + }, }, listeners: make(map[string]ListenerInterface), monitoring: make(map[string][]Client), @@ -1108,7 +1116,7 @@ func (server *Server) rehash() error { } // line lengths cannot be changed after launching the server - if maxLineLength != int(config.Limits.LineLen) { + if maxLineTagsLength != config.Limits.LineLen.Tags || maxLineRestLength != config.Limits.LineLen.Rest { return fmt.Errorf("Maximum line length (linelen) cannot be changed after launching the server, rehash aborted") } diff --git a/oragono.yaml b/oragono.yaml index 2875eb4f..9885298e 100644 --- a/oragono.yaml +++ b/oragono.yaml @@ -204,4 +204,9 @@ limits: chan-list-modes: 60 # maximum length of IRC lines - linelen: 2048 + linelen: + # tags section + tags: 2048 + + # rest of the message + rest: 2048