Use the leaky bucket algorithm to rate limit irc messages.

Review Request #524 — Created Feb. 24, 2021 and submitted

Information

pidgin/pidgin
release-2.x.y
e053cb52be57

Reviewers

The default values were suggested by an operator of libera.

We don't rate limit the login process, nor parts and quits. However, if you
paste a bunch of text and then part a channel, you will be spammed with a
bunch of "no such nick/channel" error dialogs. I tried to work around this,
but the alternative just makes irc unresponsive until all the pasted messages
are sent. That said, other messages are still delayed while these errors
dialogs are slowly popping up.

Lots

Description From Last Updated

we might need a flag to check if a partial send is in progress before pre-empting that send.

grimgrim

elb is concerned this may lead to an infinite loop an on error.

grimgrim

requeues need to be resized and available messages should NOT be decremented.

grimgrim

we need to make sure this function get called in all close paths.

grimgrim

Can you use gint64 and g_get_monotonic_time?

QuLogicQuLogic

I mean, the rest of the comment means it's not really dangerous, no?

QuLogicQuLogic

If the buffer is full and very very slow, this will cause an (almost) infinite loop. I don't know if …

QuLogicQuLogic

so?

QuLogicQuLogic

ourselves one?

QuLogicQuLogic

Every caller to this function has to do strlen, and in the partial send case, it's even ignored. So it …

QuLogicQuLogic

No message

QuLogicQuLogic

Should set irc->send_handler = 0 before removing.

QuLogicQuLogic

"to move past the characters"

QuLogicQuLogic

s/on/one/?

QuLogicQuLogic

So this means that messages cannot be sent with a granularity of less than 1 second now?

QuLogicQuLogic
grim
grim
grim
  1. 
      
  2. libpurple/protocols/irc/irc.c (Diff revision 2)
     
     
    Show all issues

    we might need a flag to check if a partial send is in progress before pre-empting that send.

    1. The more I think about this, the more I think this isn't possible in the current version of the code.

  3. libpurple/protocols/irc/irc.c (Diff revision 2)
     
     
    Show all issues

    elb is concerned this may lead to an infinite loop an on error.

    1. We should be fine because the condition above is what handles the errors aside from EAGAIN.

  4. libpurple/protocols/irc/irc.c (Diff revision 2)
     
     
    Show all issues

    requeues need to be resized and available messages should NOT be decremented.

  5. libpurple/protocols/irc/irc.c (Diff revision 2)
     
     
    Show all issues

    we need to make sure this function get called in all close paths.

    1. After some digging, purple_connection_error does eventually call the close method in the prpl, but it does so in a timeout callback after 0 seconds for some reason. So in theory, errors could start stacking here. Not really sure how to address that, not sure we need to? Thoughts?

  6. 
      
grim
grim
QuLogic
  1. 
      
  2. libpurple/protocols/irc/irc.h (Diff revision 4)
     
     
    Show all issues

    Can you use gint64 and g_get_monotonic_time?

    1. I can not. Purple 2 depends on glib 2.16.0 and that was added in 2.28.0.

  3. 
      
QuLogic
  1. 
      
  2. libpurple/protocols/irc/irc.c (Diff revision 4)
     
     
    Show all issues

    I mean, the rest of the comment means it's not really dangerous, no?

  3. libpurple/protocols/irc/irc.c (Diff revision 4)
     
     
    Show all issues

    If the buffer is full and very very slow, this will cause an (almost) infinite loop. I don't know if it's better to break early, or decrement available anyway here. Or just ignore that case.

    1. I vote for ignore?

    2. I have an update coming for the priority stuff that will at least let the user disconnect manually once it's made it through the current partial which would break the slow inifite loop.

      But I'm also realizing that the server ping could/will time out which will break the loop too. This is because the priority update queues the priority messages as the next one in the queue if we're currently handling a partial.

  4. libpurple/protocols/irc/irc.c (Diff revision 4)
     
     
    Show all issues

    so?

  5. libpurple/protocols/irc/irc.c (Diff revision 4)
     
     
    Show all issues

    ourselves
    one?

  6. 
      
grim
grim
grim
grim
QuLogic
  1. 
      
  2. libpurple/protocols/irc/irc.c (Diff revision 7)
     
     
    Show all issues

    Every caller to this function has to do strlen, and in the partial send case, it's even ignored. So it would be better to have the strlen in this function's do_send call, and drop the len argument.

  3. libpurple/protocols/irc/irc.c (Diff revision 7)
     
     
    Show all issues

    No message

  4. libpurple/protocols/irc/irc.c (Diff revision 7)
     
     
    Show all issues

    Should set irc->send_handler = 0 before removing.

  5. libpurple/protocols/irc/irc.c (Diff revision 7)
     
     
    Show all issues

    "to move past the characters"

  6. libpurple/protocols/irc/irc.c (Diff revision 7)
     
     
    Show all issues

    s/on/one/?

  7. libpurple/protocols/irc/irc.c (Diff revision 7)
     
     
    Show all issues

    So this means that messages cannot be sent with a granularity of less than 1 second now?

    1. it should always be less than or equal to one second as g_timeout_add_seconds happens at the second mark. The only time it'll go over one second is when we're rate limited.

      We could lower this value, but I have no idea what a good value would be off the top of my head. I know historically we moved to using g_timeout_add_seconds everywhere because we were destroying laptop batteries because we kept waking up the process for timeouts.

  8. 
      
grim
QuLogic
  1. Ship It!
  2. 
      
grim
Review request changed
Status:
Completed