Rate-limits   

 
     Rate limits is a way to control client->server data flow. This is done by calculating rate level on every client snac. If client rate goes above alert server send warning, if it goes above limit server send warning and drop snacs from client, if it goes above disconnect level client disconnected from server and can't connect again for some time.
     At some point in the logon sequence the client should send SNAC(01,06) which is the "rate request" packet. In reply, the server will send the "rate response" SNAC(01,07) which contain rate limit parameters formatted as follows:

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

 xx xx   word   Rate class ID
 xx xx xx xx   dword   Window size
 xx xx xx xx   dword   Clear level
 xx xx xx xx   dword   Alert level
 xx xx xx xx   dword   Limit level
 xx xx xx xx   dword   Disconnect level
 xx xx xx xx   dword   Current level
 xx xx xx xx   dword   Max level
 xx xx xx xx   dword   Last time;
 xx   byte   Current state;

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

 xx xx   word   rate group id
 xx xx   word   count of pairs in group
 xx xx xx xx   dword   family/subtype pair #1
 ....   ....   ....
 xx xx xx xx   dword   family/subtype pair #n

     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(01,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

     There is also a Maximum Level at which this value will be capped. This formula is for both server and client because they both should calculate current level. You can check if your calculations is ok - just send SNAC(01,06) in the middle of a session and compare server value from SNAC(01,07) with yours.
     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"). And one more thing - icq often receive SNAC(01,07) with state=114 - this is ok, this mean that you not limited.
     Incidentally, 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. Disconnect level is the level at which the ICQ server will disconnect you so it doesn't used by the client. The Current level is what the level is initially set to you 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 above).


  Main | Basic | Login | Snaclist | Sequences | Misc | Changes | Credits | Terms