--- a/src/protocols/msn/slp.c Sun Feb 05 20:06:31 2006 +0000 +++ b/src/protocols/msn/slp.c Sun Feb 05 21:30:43 2006 +0000 @@ -31,6 +31,9 @@ #include "user.h" #include "switchboard.h" +/* ms to delay between sending buddy icon requests to the server. */ +#define BUDDY_ICON_DELAY 20000 + static void send_ok(MsnSlpCall *slpcall, const char *branch, const char *type, const char *content); @@ -141,7 +144,7 @@ } void -msn_xfer_end_cb(MsnSlpCall *slpcall) +msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session) { if ((gaim_xfer_get_status(slpcall->xfer) != GAIM_XFER_STATUS_DONE) && (gaim_xfer_get_status(slpcall->xfer) != GAIM_XFER_STATUS_CANCEL_REMOTE) && @@ -887,7 +890,7 @@ gaim_debug_info("msn", "Releasing buddy icon request\n"); #endif - while (userlist->buddy_icon_window > 0) + if (userlist->buddy_icon_window > 0) { GQueue *queue; GaimAccount *account; @@ -896,15 +899,15 @@ queue = userlist->buddy_icon_requests; if (g_queue_is_empty(userlist->buddy_icon_requests)) - break; + return; user = g_queue_pop_head(queue); account = userlist->session->account; username = user->passport; + userlist->buddy_icon_window--; msn_request_user_display(user); - userlist->buddy_icon_window--; #ifdef MSN_DEBUG_UD gaim_debug_info("msn", "msn_release_buddy_icon_request(): buddy_icon_window-- yields =%d\n", @@ -913,6 +916,26 @@ } } +/* + * Called on a timeout from end_user_display(). Frees a buddy icon window slow and dequeues the next + * buddy icon request if there is one. + */ +static gboolean +msn_release_buddy_icon_request_timeout(gpointer data) +{ + MsnUserList *userlist = (MsnUserList *)data; + + /* Free one window slot */ + userlist->buddy_icon_window++; + + /* Clear the tag for our former request timer */ + userlist->buddy_icon_request_timer = 0; + + msn_release_buddy_icon_request(userlist); + + return FALSE; +} + void msn_queue_buddy_icon_request(MsnUser *user) { @@ -954,17 +977,12 @@ queue = userlist->buddy_icon_requests; #ifdef MSN_DEBUG_UD - gaim_debug_info("msn", "Queueing buddy icon request: %s\n", - user->passport); + gaim_debug_info("msn", "Queueing buddy icon request for %s (buddy_icon_window = %i)\n", + user->passport, userlist->buddy_icon_window); #endif g_queue_push_tail(queue, user); -#ifdef MSN_DEBUG_UD - gaim_debug_info("msn", "msn_queue_buddy_icon_request(): buddy_icon_window=%d\n", - userlist->buddy_icon_window); -#endif - if (userlist->buddy_icon_window > 0) msn_release_buddy_icon_request(userlist); } @@ -983,7 +1001,7 @@ info = slpcall->data_info; #ifdef MSN_DEBUG_UD - gaim_debug_info("msn", "Got User Display: %s\n", info); + gaim_debug_info("msn", "Got User Display: %s\n", slpcall->slplink->remote_user); #endif userlist = slpcall->slplink->session->userlist; @@ -1014,43 +1032,40 @@ } static void -end_user_display(MsnSlpCall *slpcall) +end_user_display(MsnSlpCall *slpcall, MsnSession *session) { MsnUserList *userlist; - g_return_if_fail(slpcall != NULL); + g_return_if_fail(session != NULL); #ifdef MSN_DEBUG_UD gaim_debug_info("msn", "End User Display\n"); #endif - /* Maybe the slplink was destroyed. */ - if (slpcall->slplink == NULL) { - #ifdef MSN_DEBUG_UD - gaim_debug_info("msn", "end_user_display(): returning because slpcall->slplink is NULL\n"); - #endif - return; - } - - userlist = slpcall->slplink->session->userlist; + userlist = session->userlist; /* If the session is being destroyed we better stop doing anything. */ - if (slpcall->slplink->session->destroying) { - #ifdef MSN_DEBUG_UD - gaim_debug_info("msn", "end_user_display(): returning because slpcall->slplink->session->destroying is TRUE\n"); - #endif + if (session->destroying) return; + + /* Delay before freeing a buddy icon window slot and requesting the next icon, if appropriate. + * If we don't delay, we'll rapidly hit the MSN equivalent of AIM's rate limiting; the server will + * send us an error 800 like so: + * + * C: NS 000: XFR 21 SB + * S: NS 000: 800 21 + */ + if (userlist->buddy_icon_request_timer) { + /* Free the window slot used by this previous request */ + userlist->buddy_icon_window++; + + /* Clear our pending timeout */ + gaim_timeout_remove(userlist->buddy_icon_request_timer); } - /* Free one window slot */ - userlist->buddy_icon_window++; - -#ifdef MSN_DEBUG_UD - gaim_debug_info("msn", "end_user_display(): buddy_icon_window++ yields =%d\n", - userlist->buddy_icon_window); -#endif - - msn_release_buddy_icon_request(userlist); + /* Wait BUDDY_ICON_DELAY ms before freeing our window slot and requesting the next icon. */ + userlist->buddy_icon_request_timer = gaim_timeout_add(BUDDY_ICON_DELAY, + msn_release_buddy_icon_request_timeout, userlist); } void