ircevent: add MaxMsgByteLen#114
Conversation
|
Thanks, this looks useful! I need to carefully consider potential edge cases here. Here's the corresponding code in Ergo: https://github.com/ergochat/ergo/blob/5bb94efaf6b865f5e52404bf9b9dfc3d638369d7/irc/handlers.go#L2195 and here's a bug we had historically: ergochat/ergo#2170 |
| select { | ||
| case <-irc.userHostChan: | ||
| return irc.userHost, nil | ||
| case <-timer.C: | ||
| return "", ServerTimedOut | ||
| } |
There was a problem hiding this comment.
This is a soft deadlock if UserHost or MaxMsgByteLen is called from a callback, right? Since processing of the RPL_USERHOST response cannot proceed until the current callback finishes, so we'll wait until timer.C on the first invocation.
I'm wondering if instead it might make sense to expose only MaxMsgByteLen, and if the userhost is not (yet) available return a safe fallback value (350 is a common conservative default).
There was a problem hiding this comment.
Ah, good point, I hadn't considered calling it from another callback. What I was trying to solve for is how to get the current max value without polling. Userhost could be private, but would MaxMsgByteLen still call that function?
There was a problem hiding this comment.
The querying for USERHOST could also be done in performHandshake(), but I'm not sure if that is desirable.
Thanks for looking at it, I'm sure there are some edge cases. I only have novice's understanding of the IRC protocol. The IRCv3 draft for multiline adds a 10 byte safety buffer, but I left that out as I thought we could iterate once people try it against other servers. I also considered changes to the userhost, such as someone adding obtaining cloak. But, I wasn't sure there was a way to receive those updates, outside of polling, which is what Konversation does on every ping pong. |
|
This is covered by CHGHOST but it's not that widely supported. |
Add a function to calculate the maximum message size in bytes based on the nick, userhost, command, and target of the message to be sent. This is useful when sending a long message that may need to be wrapped into multiple messages, in order to be sent. The implementation was inspired by Catgirl's and Konversation's.
1f59ab7 to
e37bccc
Compare
|
@slingamn I pushed a new version based on your feedback. Only MaxMsgByteLen() is exposed and the function now returns a sensible value, even if we have not yet received a reply to our UESRHOST query. Would love your thoughts when you have the time. |
|
I also double checked that the accounting is the same as ergo's |
|
Just checking in: I'm still looking at this issue. I did a refactoring pass on this implementation, but I'm also talking to the IRCv3 community about other possibilities for a fix. (The continued existence of this problem is kind of an embarrassment for IRC as a protocol --- it's really not great that there's no good way to tell how long of a message you can send.) |
|
Thanks for the update @slingamn and thanks for reviewing my latest rev. I'm happy to iterate, if there are parts you don't like. I agree that the need to calculate the max byte length is a bit of a wart on the IRC protocol and it would be great if it was solved in a more elegant manner as part of the IRCv3 work. However, I do think a version that works for existing servers in the wild has value as an interim step. Anecdotally, I started working on this after our incident bot choked on a long line, \o/. |
|
I'm curious, what was the failure mode you saw with your bot? Did the line just get dropped? One of the reasons I'm being cautious here is that computing the exact length limit is always going to be somewhat fallible (the server can unilaterally change the userhost at any time, and even with a mechanism like |
|
I pushed a round of changes. Two things I'm thinking about:
|
The line was dropped, because I didn't want truncated lines.
True, but I think we can adjust if people see failures. Given that Konversation and catgirl use a similar algorithm, I would assume it is pretty reliable? |
Thanks, questions:
I'm not sure, but as I said, it seems to be a common practice, so I would assume it is pretty robust. Also, since we are only exposing
That would guarantee that you never receive the max length on the first call to |
re.
I would not assume this, most IRC software exists in a state of delicate semi-brokenness :-) |
|
Libera's help says: :-( |
|
Running |
ugh, Konversation made a similar decision, they issue a |
|
I think a reasonable compromise would be:
|
|
(I can work on this later) |
* Use WHO / RPL_WHOREPLY instead of USERHOST * Make the WHO request only if needed * Prepare for a future cap that will send the userhost without a request * Handle CHGHOST
|
This version implements the proposal at ircv3/ircv3-specifications#603 |
Looks good, thanks for working on this. |
Add a function to calculate the maximum message size in bytes based on the nick, userhost, command, and target of the message to be sent.
This is useful when sending a long message that may need to be wrapped into multiple messages, in order to be sent.
The implementation was inspired by Catgirl's and Konversation's.