pidgin: 68d7b337: Added `flap_connection_send_snac_with_pr...
evands at pidgin.im
evands at pidgin.im
Sun Jul 20 01:51:10 EDT 2008
-----------------------------------------------------------------
Revision: 68d7b3372f34b6420c91d6185b81282d1c68b547
Ancestor: 2dfa29ca12fd33d175387e43772c3fba490cb287
Author: evands at pidgin.im
Date: 2008-07-20T05:47:42
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/68d7b3372f34b6420c91d6185b81282d1c68b547
Modified files:
libpurple/protocols/oscar/family_icq.c
libpurple/protocols/oscar/family_locate.c
libpurple/protocols/oscar/flap_connection.c
libpurple/protocols/oscar/oscar.h
ChangeLog:
Added `flap_connection_send_snac_with_priority()`, which allows specifying
high versus low priority for the SNAC to be sent.
If we are not rate limited, a SNAC is always sent immediately.
If we are at or near the rate limit, the SNAC may be queued to be sent
when it wouldn't violate a rate limit to do so.
Previously, SNACs were always sent in the order requested.
A SNAC may now be set to be low priority, in which case other SNACs
will be sent first if a queue is in use. This means that even if we have
120 'get ICQ status note' requests in the queue, a 'send message' SNAC can
still be sent nearly immediately (rather than after a 10 minute or so delay).
`flap_connection_send_snac_()` calls `flap_connection_send_snac_with_priority`
with high priority. Get Info requests (including ICQ Status Note requests) are
the only low priority SNACs at this time.
-------------- next part --------------
============================================================
--- libpurple/protocols/oscar/family_icq.c d25ef53ec879d278dd495ca0f367a552f0f8cd44
+++ libpurple/protocols/oscar/family_icq.c 13e35ab10874b0bc607b81c49fb99130394c4c47
@@ -214,7 +214,7 @@ int aim_icq_getallinfo(OscarData *od, co
byte_stream_putle16(&bs, 0x04b2); /* shrug. */
byte_stream_putle32(&bs, atoi(uin));
- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs);
+ flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs, /* High priority? */ FALSE);
byte_stream_destroy(&bs);
@@ -497,7 +497,7 @@ int aim_icq_getstatusnote(OscarData *od,
byte_stream_put16(&bs, strlen(uin));
byte_stream_putstr(&bs, uin);
- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x000, snacid, &bs);
+ flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x000, snacid, &bs, /* High priority? */ FALSE);
byte_stream_destroy(&bs);
============================================================
--- libpurple/protocols/oscar/family_locate.c 7fbb8f071d020f5c41f0d303b717f70126222a56
+++ libpurple/protocols/oscar/family_locate.c 9413f30a5cb37649dd01be8a4b3a2c51d5418e03
@@ -1386,7 +1386,7 @@ aim_locate_getinfoshort(OscarData *od, c
byte_stream_putstr(&bs, sn);
snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0015, 0x0000, sn, strlen(sn)+1);
- flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0015, 0x0000, snacid, &bs);
+ flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_LOCATE, 0x0015, 0x0000, snacid, &bs, /* High priority? */ FALSE);
byte_stream_destroy(&bs);
============================================================
--- libpurple/protocols/oscar/flap_connection.c 3a8fafba107154dc1cca77737c7aab7af8fba426
+++ libpurple/protocols/oscar/flap_connection.c 31fde6497cfb7f60805b9d4cd9adb530a71bd782
@@ -107,21 +107,18 @@ rateclass_get_new_current(FlapConnection
return MIN(((rateclass->current * (rateclass->windowsize - 1)) + timediff) / rateclass->windowsize, rateclass->max);
}
-static gboolean flap_connection_send_queued(gpointer data)
+/*
+ * Attempt to send the contents of a given queue
+ * @result TRUE if the queue was completely emptied or was iniitally empty; FALSE if rate limiting prevented it from being emptied
+ */
+static gboolean flap_connection_send_snac_queue(FlapConnection *conn, struct timeval now, GQueue *queue)
{
- FlapConnection *conn;
- struct timeval now;
-
- conn = data;
- gettimeofday(&now, NULL);
-
- purple_debug_info("oscar", "Attempting to send %u queued SNACs for %p\n", g_queue_get_length(conn->queued_snacs), conn);
- while (!g_queue_is_empty(conn->queued_snacs))
+ while (!g_queue_is_empty(queue))
{
QueuedSnac *queued_snac;
struct rateclass *rateclass;
- queued_snac = g_queue_peek_head(conn->queued_snacs);
+ queued_snac = g_queue_peek_head(queue);
rateclass = flap_connection_get_rateclass(conn, queued_snac->family, queued_snac->subtype);
if (rateclass != NULL)
@@ -133,8 +130,8 @@ static gboolean flap_connection_send_que
/* (Add 100ms padding to account for inaccuracies in the calculation) */
if (new_current < rateclass->alert + 100)
/* Not ready to send this SNAC yet--keep waiting. */
- return TRUE;
-
+ return FALSE;
+
rateclass->current = new_current;
rateclass->last.tv_sec = now.tv_sec;
rateclass->last.tv_usec = now.tv_usec;
@@ -142,13 +139,37 @@ static gboolean flap_connection_send_que
flap_connection_send(conn, queued_snac->frame);
g_free(queued_snac);
- g_queue_pop_head(conn->queued_snacs);
+ g_queue_pop_head(queue);
}
- conn->queued_timeout = 0;
- return FALSE;
+ /* We emptied the queue */
+ return TRUE;
}
+static gboolean flap_connection_send_queued(gpointer data)
+{
+ FlapConnection *conn;
+ struct timeval now;
+
+ conn = data;
+ gettimeofday(&now, NULL);
+
+ purple_debug_info("oscar", "Attempting to send %u queued SNACs and %u queued low-priority SNACs for %p\n",
+ (conn->queued_snacs ? g_queue_get_length(conn->queued_snacs) : 0),
+ (conn->queued_lowpriority_snacs ? g_queue_get_length(conn->queued_lowpriority_snacs) : 0),
+ conn);
+ if (!conn->queued_snacs || flap_connection_send_snac_queue(conn, now, conn->queued_snacs)) {
+ if (!conn->queued_lowpriority_snacs || flap_connection_send_snac_queue(conn, now, conn->queued_lowpriority_snacs)) {
+ /* Both queues emptied. */
+ conn->queued_timeout = 0;
+ return FALSE;
+ }
+ }
+
+ /* We couldn't send all our SNACs. Keep trying */
+ return TRUE;
+}
+
/**
* This sends a channel 2 FLAP containing a SNAC. The SNAC family and
* subtype are looked up in the rate info for this connection, and if
@@ -157,9 +178,10 @@ static gboolean flap_connection_send_que
*
* @param data The optional bytestream that makes up the data portion
* of this SNAC. For empty SNACs this should be NULL.
+ * @param high_priority If TRUE, the SNAC will be queued normally if needed. If FALSE, it wil be queued separately, to be sent only if all high priority SNACs have been sent.
*/
void
-flap_connection_send_snac(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, guint16 flags, aim_snacid_t snacid, ByteStream *data)
+flap_connection_send_snac_with_priority(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, guint16 flags, aim_snacid_t snacid, ByteStream *data, gboolean high_priority)
{
FlapFrame *frame;
guint32 length;
@@ -213,8 +235,17 @@ flap_connection_send_snac(OscarData *od,
queued_snac->family = family;
queued_snac->subtype = subtype;
queued_snac->frame = frame;
- g_queue_push_tail(conn->queued_snacs, queued_snac);
+ if (high_priority) {
+ if (!conn->queued_snacs)
+ conn->queued_snacs = g_queue_new();
+ g_queue_push_tail(conn->queued_snacs, queued_snac);
+ } else {
+ if (!conn->queued_lowpriority_snacs)
+ conn->queued_lowpriority_snacs = g_queue_new();
+ g_queue_push_tail(conn->queued_lowpriority_snacs, queued_snac);
+ }
+
if (conn->queued_timeout == 0)
conn->queued_timeout = purple_timeout_add(500, flap_connection_send_queued, conn);
@@ -224,6 +255,12 @@ flap_connection_send_snac(OscarData *od,
flap_connection_send(conn, frame);
}
+void
+flap_connection_send_snac(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, guint16 flags, aim_snacid_t snacid, ByteStream *data)
+{
+ flap_connection_send_snac_with_priority(od, conn, family, subtype, flags, snacid, data, /* High priority? */ TRUE);
+}
+
/**
* This sends an empty channel 4 FLAP. This is sent to signify
* that we're logging off. This shouldn't really be necessary--
@@ -275,7 +312,6 @@ flap_connection_new(OscarData *od, int t
conn->fd = -1;
conn->subtype = -1;
conn->type = type;
- conn->queued_snacs = g_queue_new();
od->oscar_connections = g_slist_prepend(od->oscar_connections, conn);
@@ -434,14 +470,28 @@ flap_connection_destroy_cb(gpointer data
conn->rateclasses = g_slist_delete_link(conn->rateclasses, conn->rateclasses);
}
- while (!g_queue_is_empty(conn->queued_snacs))
- {
- QueuedSnac *queued_snac;
- queued_snac = g_queue_pop_head(conn->queued_snacs);
- flap_frame_destroy(queued_snac->frame);
- g_free(queued_snac);
+ if (conn->queued_snacs) {
+ while (!g_queue_is_empty(conn->queued_snacs))
+ {
+ QueuedSnac *queued_snac;
+ queued_snac = g_queue_pop_head(conn->queued_snacs);
+ flap_frame_destroy(queued_snac->frame);
+ g_free(queued_snac);
+ }
+ g_queue_free(conn->queued_snacs);
}
- g_queue_free(conn->queued_snacs);
+
+ if (conn->queued_lowpriority_snacs) {
+ while (!g_queue_is_empty(conn->queued_lowpriority_snacs))
+ {
+ QueuedSnac *queued_snac;
+ queued_snac = g_queue_pop_head(conn->queued_lowpriority_snacs);
+ flap_frame_destroy(queued_snac->frame);
+ g_free(queued_snac);
+ }
+ g_queue_free(conn->queued_lowpriority_snacs);
+ }
+
if (conn->queued_timeout > 0)
purple_timeout_remove(conn->queued_timeout);
============================================================
--- libpurple/protocols/oscar/oscar.h ab1fe743aec4287710fdb56eb412ee30f43ff318
+++ libpurple/protocols/oscar/oscar.h f45b3ed6f71c21ae20838f95c3b7515f61948fb1
@@ -433,6 +433,7 @@ struct _FlapConnection
GSList *rateclasses; /* Contains nodes of struct rateclass. */
GQueue *queued_snacs; /**< Contains QueuedSnacs. */
+ GQueue *queued_lowpriority_snacs; /**< Contains QueuedSnacs to send only once queued_snacs is empty */
guint queued_timeout;
void *internal; /* internal conn-specific libfaim data */
@@ -625,6 +626,7 @@ void flap_connection_send_snac(OscarData
void flap_connection_send_version(OscarData *od, FlapConnection *conn);
void flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy);
void flap_connection_send_snac(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, guint16 flags, aim_snacid_t snacid, ByteStream *data);
+void flap_connection_send_snac_with_high_priority(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, guint16 flags, aim_snacid_t snacid, ByteStream *data, gboolean high_priority);
void flap_connection_send_keepalive(OscarData *od, FlapConnection *conn);
FlapFrame *flap_frame_new(OscarData *od, guint16 channel, int datalen);
More information about the Commits
mailing list