pidgin.mxit: f5e41543: * do not send requests too fast to the ...
pieter.loubser at mxit.com
pieter.loubser at mxit.com
Fri Feb 4 04:15:57 EST 2011
----------------------------------------------------------------------
Revision: f5e415439fcd668fa55f202c719f7d3feecd65bb
Parent: 116c3c0389e69edd90534a89c3d070edaa9892e8
Author: pieter.loubser at mxit.com
Date: 02/04/11 04:13:46
Branch: im.pidgin.pidgin.mxit
URL: http://d.pidgin.im/viewmtn/revision/info/f5e415439fcd668fa55f202c719f7d3feecd65bb
Changelog:
* do not send requests too fast to the mxit server or they will start ignoring you.
Changes against parent 116c3c0389e69edd90534a89c3d070edaa9892e8
patched libpurple/protocols/mxit/login.c
patched libpurple/protocols/mxit/mxit.c
patched libpurple/protocols/mxit/mxit.h
patched libpurple/protocols/mxit/profile.c
patched libpurple/protocols/mxit/protocol.c
patched libpurple/protocols/mxit/protocol.h
-------------- next part --------------
============================================================
--- libpurple/protocols/mxit/login.c 280c74cc5e523a6c0dc438e5ab83e0504cd65288
+++ libpurple/protocols/mxit/login.c c3b11a7c2a04d44237ec6d2cf3fd2f3b3b95a3ec
@@ -84,7 +84,7 @@ static struct MXitSession* mxit_create_o
session->iimages = g_hash_table_new( g_str_hash, g_str_equal );
session->rx_state = RX_STATE_RLEN;
session->http_interval = MXIT_HTTP_POLL_MIN;
- session->http_last_poll = time( NULL );
+ session->http_last_poll = mxit_now_milli();
return session;
}
@@ -106,7 +106,7 @@ static void mxit_connected( struct MXitS
purple_connection_update_progress( session->con, _( "Logging In..." ), 2, 4 );
/* create a timer to send a ping packet if the connection is idle */
- session->last_tx = time( NULL );
+ session->last_tx = mxit_now_milli();
/* encrypt the user password */
session->encpwd = mxit_encrypt_password( session );
@@ -143,7 +143,7 @@ static void mxit_connected( struct MXitS
/* This timer might already exist if we're registering a new account */
if ( session->q_timer == 0 ) {
/* start the tx queue manager timer */
- session->q_timer = purple_timeout_add_seconds( 2, mxit_manage_queue, session );
+ session->q_timer = purple_timeout_add_seconds( 2, mxit_manage_queue_slow, session );
}
}
============================================================
--- libpurple/protocols/mxit/mxit.c 7895738dcd9a6824458c9a3e60f9d168a517a01c
+++ libpurple/protocols/mxit/mxit.c d03869e405a6c42843598342ebd6f4e09da07add
@@ -525,7 +525,7 @@ static void mxit_keepalive( PurpleConnec
if ( session->http )
return;
- if ( session->last_tx <= time( NULL ) - MXIT_PING_INTERVAL ) {
+ if ( session->last_tx <= ( mxit_now_milli() - ( MXIT_PING_INTERVAL * 1000 ) ) ) {
/*
* this connection has been idle for too long, better ping
* the server before it kills our connection.
============================================================
--- libpurple/protocols/mxit/mxit.h 02522588e1f937bee2ea68cfab1eea11968b41da
+++ libpurple/protocols/mxit/mxit.h c3009a770c3cc34d3db8f3d2951dbe3061198e91
@@ -135,7 +135,7 @@ struct MXitSession {
unsigned int http_seqno; /* HTTP request sequence number */
guint http_timer_id; /* timer resource id (pidgin) */
int http_interval; /* poll inverval */
- time_t http_last_poll; /* the last time a poll has been sent */
+ gint64 http_last_poll; /* the last time a poll has been sent */
guint http_handler; /* HTTP connection handler */
void* http_out_req; /* HTTP outstanding request */
@@ -160,7 +160,7 @@ struct MXitSession {
/* transmit */
struct tx_queue queue; /* transmit packet queue (FIFO mode) */
- time_t last_tx; /* timestamp of last packet sent */
+ gint64 last_tx; /* timestamp of last packet sent */
int outack; /* outstanding ack packet */
guint q_timer; /* timer handler for managing queue */
@@ -170,7 +170,7 @@ struct MXitSession {
unsigned int rx_i; /* receive buffer current index */
int rx_res; /* amount of bytes still outstanding for the current packet */
char rx_state; /* current receiver state */
- time_t last_rx; /* timestamp of last packet received */
+ gint64 last_rx; /* timestamp of last packet received */
GList* active_chats; /* list of all our contacts we received messages from (active chats) */
/* groupchat */
============================================================
--- libpurple/protocols/mxit/profile.c 2b7bd748818fa1c6fbf135c8119263441427b57b
+++ libpurple/protocols/mxit/profile.c fc9bef9d9f59005ee7fae5b668415ed6c96a8f46
@@ -108,10 +108,10 @@ static const char* datetime( gint64 msec
*/
static const char* datetime( gint64 msecs )
{
- time_t secs = msecs / 1000;
+ time_t secs = msecs / 1000;
- struct tm t;
- localtime_r( &secs, &t );
+ struct tm t;
+ localtime_r( &secs, &t );
return purple_utf8_strftime( "%d-%m-%Y %H:%M:%S", &t );
}
@@ -140,13 +140,10 @@ void mxit_show_profile( struct MXitSessi
purple_notify_user_info_add_pair( info, _( "Display Name" ), profile->nickname );
purple_notify_user_info_add_pair( info, _( "Birthday" ), profile->birthday );
purple_notify_user_info_add_pair( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) );
-// purple_notify_user_info_add_pair( info, _( "Hidden Number" ), profile->hidden ? _( "Yes" ) : _( "No" ) );
/* optional information */
-// purple_notify_user_info_add_pair( info, _( "Title" ), profile->title );
purple_notify_user_info_add_pair( info, _( "First Name" ), profile->firstname );
purple_notify_user_info_add_pair( info, _( "Last Name" ), profile->lastname );
-// purple_notify_user_info_add_pair( info, _( "Email" ), profile->email );
purple_notify_user_info_add_pair( info, _( "Country" ), profile->regcountry );
purple_notify_user_info_add_section_break( info );
============================================================
--- libpurple/protocols/mxit/protocol.c b7f1d65db1173aefe60880cdfe7d437e248a1e2e
+++ libpurple/protocols/mxit/protocol.c 3043aec5ae922abfa6cf414af63fcc12126875ef
@@ -46,7 +46,19 @@
#define CP_REC_TERM ( ( session->http ) ? CP_HTTP_REC_TERM : CP_SOCK_REC_TERM )
+/*------------------------------------------------------------------------
+ * return the current timestamp in milliseconds
+ */
+gint64 mxit_now_milli( void )
+{
+ GTimeVal now;
+ g_get_current_time( &now );
+
+ return ( ( now.tv_sec * 1000 ) + ( now.tv_usec / 1000 ) );
+}
+
+
/*------------------------------------------------------------------------
* Display a notification popup message to the user.
*
@@ -412,7 +424,7 @@ static void mxit_send_packet( struct MXi
}
/* update the timestamp of the last-transmitted packet */
- session->last_tx = time( NULL );
+ session->last_tx = mxit_now_milli();
/*
* we need to remember that we are still waiting for the ACK from
@@ -475,17 +487,13 @@ static void mxit_queue_packet( struct MX
packet->datalen = datalen;
- /*
- * shortcut: first check if there are any commands still outstanding.
- * if not, then we might as well just write this packet directly and
- * skip the whole queueing thing
- */
- if ( session->outack == 0 ) {
- /* no outstanding ACKs, so we might as well write it directly */
+ /* shortcut */
+ if ( ( session->queue.count == 0 ) && ( session->outack == 0 ) ) {
+ /* the queue is empty and there are no outstanding acks so we can write it directly */
mxit_send_packet( session, packet );
}
else {
- /* ACK still outstanding, so we need to queue this request until we have the ACK */
+ /* we need to queue this packet */
if ( ( packet->cmd == CP_CMD_PING ) || ( packet->cmd == CP_CMD_POLL ) ) {
/* we do NOT queue HTTP poll nor socket ping packets */
@@ -504,42 +512,89 @@ static void mxit_queue_packet( struct MX
/*------------------------------------------------------------------------
- * Callback to manage the packet send queue (send next packet, timeout's, etc).
+ * Manage the packet send queue (send next packet, timeout's, etc).
*
* @param session The MXit session object
*/
-gboolean mxit_manage_queue( gpointer user_data )
+static void mxit_manage_queue( struct MXitSession* session )
{
- struct MXitSession* session = (struct MXitSession*) user_data;
struct tx_packet* packet = NULL;
+ gint64 now = mxit_now_milli();
if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
/* we are not connected, so ignore the queue */
- return TRUE;
+ return;
}
else if ( session->outack > 0 ) {
/* we are still waiting for an outstanding ACK from the MXit server */
- if ( session->last_tx <= time( NULL ) - MXIT_ACK_TIMEOUT ) {
+ if ( session->last_tx <= mxit_now_milli() - ( MXIT_ACK_TIMEOUT * 1000 ) ) {
/* ack timeout! so we close the connection here */
purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%i'\n", session->outack );
purple_connection_error( session->con, _( "Timeout while waiting for a response from the MXit server." ) );
}
- return TRUE;
+ return;
}
- packet = pop_tx_packet( session );
- if ( packet != NULL ) {
- /* there was a packet waiting to be sent to the server, now is the time to do something about it */
+ /*
+ * the mxit server has flood detection and it prevents you from sending messages to fast.
+ * this is a self defense mechanism, a very annoying feature. so the client must ensure that
+ * it does not send messages too fast otherwise mxit will ignore the user for 30 seconds.
+ * this is what we are trying to avoid here..
+ */
+ if ( session->last_tx > ( now - MXIT_TX_DELAY ) ) {
+ /* we need to wait a little before sending the next packet, so schedule a wakeup call */
+ gint64 tdiff = now - ( session->last_tx );
+ guint delay = ( MXIT_TX_DELAY - tdiff ) + 9;
+ if ( delay <= 0 )
+ delay = MXIT_TX_DELAY;
+ purple_timeout_add( delay, mxit_manage_queue_fast, session );
+ }
+ else {
+ /* get the next packet from the queue to send */
+ packet = pop_tx_packet( session );
+ if ( packet != NULL ) {
+ /* there was a packet waiting to be sent to the server, now is the time to do something about it */
- /* send the packet to MXit server */
- mxit_send_packet( session, packet );
+ /* send the packet to MXit server */
+ mxit_send_packet( session, packet );
+ }
}
+}
+
+/*------------------------------------------------------------------------
+ * Slow callback to manage the packet send queue.
+ *
+ * @param session The MXit session object
+ */
+gboolean mxit_manage_queue_slow( gpointer user_data )
+{
+ struct MXitSession* session = (struct MXitSession*) user_data;
+
+ mxit_manage_queue( session );
+
+ /* continue running */
return TRUE;
}
/*------------------------------------------------------------------------
+ * Fast callback to manage the packet send queue.
+ *
+ * @param session The MXit session object
+ */
+gboolean mxit_manage_queue_fast( gpointer user_data )
+{
+ struct MXitSession* session = (struct MXitSession*) user_data;
+
+ mxit_manage_queue( session );
+
+ /* stop running */
+ return FALSE;
+}
+
+
+/*------------------------------------------------------------------------
* Callback to manage HTTP server polling (HTTP connections ONLY)
*
* @param session The MXit session object
@@ -548,9 +603,9 @@ gboolean mxit_manage_polling( gpointer u
{
struct MXitSession* session = (struct MXitSession*) user_data;
gboolean poll = FALSE;
- time_t now = time( NULL );
+ gint64 now = mxit_now_milli();
int polldiff;
- int rxdiff;
+ gint64 rxdiff;
if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
/* we only poll if we are actually logged in */
@@ -580,7 +635,7 @@ gboolean mxit_manage_polling( gpointer u
if ( poll ) {
/* send poll request */
- session->http_last_poll = time( NULL );
+ session->http_last_poll = mxit_now_milli();
mxit_send_poll( session );
}
@@ -2001,7 +2056,7 @@ static int process_success_response( str
{
/* ignore ping/poll packets */
if ( ( packet->cmd != CP_CMD_PING ) && ( packet->cmd != CP_CMD_POLL ) )
- session->last_rx = time( NULL );
+ session->last_rx = mxit_now_milli();
/*
* when we pass the packet records to the next level for parsing
============================================================
--- libpurple/protocols/mxit/protocol.h 957abd9e0c5b3b161acbab0544cce1ae10986b86
+++ libpurple/protocols/mxit/protocol.h 7d9ad1e196c3935b9e52be2dc31c626b8b5d6f8a
@@ -84,6 +84,7 @@
#define MXIT_PING_INTERVAL ( 5 * 60 ) /* ping the server after X seconds of being idle (5 minutes) */
#define MXIT_ACK_TIMEOUT ( 30 ) /* timeout after waiting X seconds for an ack from the server (30 seconds) */
+#define MXIT_TX_DELAY ( 100 ) /* delay between sending consecutive packets (100 ms) */
/* MXit client version */
#define MXIT_CP_DISTCODE 'P' /* client distribution code (magic, do not touch!) */
@@ -107,7 +108,7 @@
#define MXIT_CP_CAP "utf8=true;cid="MXIT_CLIENT_ID
/* Client settings */
-#define MAX_QUEUE_SIZE ( 1 << 4 ) /* tx queue size (16 packets) */
+#define MAX_QUEUE_SIZE ( 1 << 5 ) /* tx queue size (32 packets) */
#define MXIT_POPUP_WIN_NAME "MXit Notification" /* popup window name */
#define MXIT_MAX_ATTRIBS 10 /* maximum profile attributes supported */
#define MXIT_DEFAULT_LOCALE "en" /* default locale setting */
@@ -284,7 +285,8 @@ void mxit_cb_rx( gpointer data, gint sou
gboolean find_active_chat( const GList* chats, const char* who );
void mxit_cb_rx( gpointer data, gint source, PurpleInputCondition cond );
-gboolean mxit_manage_queue( gpointer user_data );
+gboolean mxit_manage_queue_slow( gpointer user_data );
+gboolean mxit_manage_queue_fast( gpointer user_data );
gboolean mxit_manage_polling( gpointer user_data );
void mxit_send_register( struct MXitSession* session );
@@ -324,6 +326,7 @@ void mxit_close_connection( struct MXitS
int mxit_parse_packet( struct MXitSession* session );
void dump_bytes( struct MXitSession* session, const char* buf, int len );
void mxit_close_connection( struct MXitSession* session );
+gint64 mxit_now_milli( void );
#endif /* _MXIT_PROTO_H_ */
More information about the Commits
mailing list