[icq-devel] Rate Limits - SNACs 1/06 1/07 and 1/08

Zoe Smale skyerat at hotmail.com
Tue Dec 3 14:16:38 CET 2002

> :) Zoe... Yesterday I was searching thru this mail-list archive for
> rate-limites snac info. I found that you posted a message discribing
> rate-limites parameters. Could you post detailed information about
> rate-limites ? I want to add this future to my server.

Ok, I'll try and explain the bits that I know. Bare in mind that I don't
actually have an ICQ client of my own, though, so this is mostly

At some point in the logon sequence (I believe after receiving 1/18) the
client should send SNAC 1/06 which is the "rate request" packet. In reply,
the server will send the "rate response" (SNAC 1/07). SNAC 1/06 is just an
empty SNAC. SNAC 1/07 is formated as follows:

First comes a WORD telling you how many rate classes there are. Then for
each class you get a structure like this:

WORD  Class ID
DWORD Window Size
DWORD Clear Level
DWORD Alert Level
DWORD Limit Level
DWORD Disconnect Level
DWORD Start Level
DWORD Max Level
DWORD Last Time
BYTE  Start State

And after those you get another set of structures (one for each class) like

WORD Count

The rest of the structure is just *Count* WORD pairs, a SNAC family and SNAC
subtype for each SNAC that will use the rate information from this class.

If the number of classes received is zero you should not reply. If it is
greater than zero, then you should reply with SNAC 1/08 ("rate acknowledge")
which is just a list of words with the Class ID of each class you received.

Now for some more explanations about the protocol. For each rate class, ICQ
can be in one of three states: "limited" (state 1), in which no data is
sent; "alert" (state 2), which is when you're sending too fast, but you
aren't yet limited; and "clear" (state 3), when everything is cool. Every
time a packet is sent (assuming you aren't being "limited"), ICQ updates a
"Last Time" value to keep track of the last sent time (as with the state
value, there is a separate time for each rate class).

It also looks up the time since the previous packet was sent and uses that
to keep a running average of time between packets (I refer to this as the
rate level). This level is calculated using a window size which specifies
how many of the previous times to take into account, as follows:

  NewLevel = (Window-1)/Window * OldLevel + 1/Window * CurrentTimeDiff

... more or less. :) There is also a Maximum Level at which this value will
be capped.

Once the new level has been calculated, ICQ updates your state as follows:
if your level is less than the Limit Level your state will be set to 1
("limited"); if it's greater than the Limit Level, but less than the Alert
Level, your state will be set to 2 ("alert"); if it's greater than the Alert
Level your state will be 3 ("clear"). If your state was already set to 1,
the calculation is slightly different. It only compares your level against
the Clear Level value - if it's greater than that, your state becomes 3
("clear"), otherwise it remains at 1 ("limited").

Incidently, this calculation happens before your packet is actually sent, so
if your state changes to "limited" at this point, the packet won't be sent.
If your state is not "clear", ICQ will also start a timer for some time in
the future (the actual duration is rather complicated so I won't go into
that now) so that your state can be recalculated, giving you a chance to get
back to "clear".

Now that you know the basic protocol, some of the SNAC parameters will make
more sense. The Window Size is the Window mentioned in calculating the
running average time between packets (the level). The Clear, Alert and Limit
Levels are used in calculating the rate state. I can't find where the
Disconnect Level is used, but I suspect it's just the level at which the ICQ
server will disconnect you so it may not even be used by the client. The
Start level is what the level is initially set to when SNAC 1/07 is
received. The Max Level is what the level is capped at when calculating the
running average.

The Last Time is a duration in milliseconds which is used to set the initial
value of the last sent time (the time is set to the specified duration into
the past, i.e. 1000 milliseconds means 1 second ago). The Start State
specifies the initial rate state, and although the state is immediately
recalculated, the current state does effect that calculation (as explained

I think that about covers everything for SNAC 1/07. There's also a SNAC 1/0A
that you need to worry about, but I'm not going to do that now. I'm getting
tired and this message is getting too long, so I'm afraid it'll have to wait
till later.


PS: This information is for v7 of the protocol. v8 may be slightly

More information about the icq-devel mailing list