Mercurial > pidgin
changeset 5506:4f72b611f0ee
[gaim-migrate @ 5905]
A few changes here.
- Messages now have reference counting.
- There's a message queue API in servconn. This was needed for times when
we have a message but need further information from a command before
processing it, like initial e-mail notifications.
- As a result of the two above, we now have initial e-mail notifications
again!
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Sun, 25 May 2003 09:04:32 +0000 |
parents | 870207a49f2f |
children | b87d7459e7d2 |
files | src/protocols/msn/buddyicon.c src/protocols/msn/buddyicon.h src/protocols/msn/msg.c src/protocols/msn/msg.h src/protocols/msn/msn.c src/protocols/msn/notification.c src/protocols/msn/servconn.c src/protocols/msn/servconn.h src/protocols/msn/switchboard.c |
diffstat | 9 files changed, 207 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/src/protocols/msn/buddyicon.c Sat May 24 19:15:58 2003 +0000 +++ b/src/protocols/msn/buddyicon.c Sun May 25 09:04:32 2003 +0000 @@ -464,7 +464,7 @@ } gboolean -msn_buddy_icon_msg(MsnServConn *servconn, const MsnMessage *msg) +msn_buddy_icon_msg(MsnServConn *servconn, MsnMessage *msg) { if (!strncmp(msn_message_get_body(msg), "ICON", 4)) return __process_data(servconn, msg);
--- a/src/protocols/msn/buddyicon.h Sat May 24 19:15:58 2003 +0000 +++ b/src/protocols/msn/buddyicon.h Sun May 25 09:04:32 2003 +0000 @@ -65,7 +65,7 @@ * * @return TRUE */ -gboolean msn_buddy_icon_msg(MsnServConn *servconn, const MsnMessage *msg); +gboolean msn_buddy_icon_msg(MsnServConn *servconn, MsnMessage *msg); /** * Sends a buddy icon invitation message.
--- a/src/protocols/msn/msg.c Sat May 24 19:15:58 2003 +0000 +++ b/src/protocols/msn/msg.c Sun May 25 09:04:32 2003 +0000 @@ -63,6 +63,8 @@ msn_message_set_charset(msg, "UTF-8"); msn_message_set_flag(msg, 'N'); + msn_message_ref(msg); + return msg; } @@ -174,6 +176,12 @@ { g_return_if_fail(msg != NULL); + if (msg->ref_count > 0) { + msn_message_unref(msg); + + return; + } + if (msg->sender != NULL) msn_user_unref(msg->sender); @@ -192,9 +200,39 @@ g_hash_table_destroy(msg->attr_table); g_list_free(msg->attr_list); + gaim_debug(GAIM_DEBUG_INFO, "msn", "Destroying message\n"); g_free(msg); } +MsnMessage * +msn_message_ref(MsnMessage *msg) +{ + g_return_val_if_fail(msg != NULL, NULL); + + msg->ref_count++; + + return msg; +} + +MsnMessage * +msn_message_unref(MsnMessage *msg) +{ + g_return_val_if_fail(msg != NULL, NULL); + + if (msg->ref_count <= 0) + return NULL; + + msg->ref_count--; + + if (msg->ref_count == 0) { + msn_message_destroy(msg); + + return NULL; + } + + return msg; +} + char * msn_message_build_string(const MsnMessage *msg) {
--- a/src/protocols/msn/msg.h Sat May 24 19:15:58 2003 +0000 +++ b/src/protocols/msn/msg.h Sun May 25 09:04:32 2003 +0000 @@ -32,6 +32,8 @@ */ struct _MsnMessage { + size_t ref_count; /**< The reference count. */ + MsnUser *sender; MsnUser *receiver; @@ -73,6 +75,26 @@ void msn_message_destroy(MsnMessage *msg); /** + * Increments the reference count on a message. + * + * @param msg The message. + * + * @return @a msg + */ +MsnMessage *msn_message_ref(MsnMessage *msg); + +/** + * Decrements the reference count on a message. + * + * This will destroy the structure if the count hits 0. + * + * @param msg The message. + * + * @return @a msg, or @c NULL if the new count is 0. + */ +MsnMessage *msn_message_unref(MsnMessage *msg); + +/** * Converts a message to a string. * * @param msg The message.
--- a/src/protocols/msn/msn.c Sat May 24 19:15:58 2003 +0000 +++ b/src/protocols/msn/msn.c Sun May 25 09:04:32 2003 +0000 @@ -454,6 +454,7 @@ user = msn_user_new(session, who, NULL); msg = msn_message_new(); + msn_message_set_flag(msg, 'D'); msn_message_set_receiver(msg, user); msn_message_set_attr(msg, "X-MMS-IM-Format", "FN=Arial; EF=; CO=0; PF=0");
--- a/src/protocols/msn/notification.c Sat May 24 19:15:58 2003 +0000 +++ b/src/protocols/msn/notification.c Sun May 25 09:04:32 2003 +0000 @@ -1139,7 +1139,7 @@ * Message Types **************************************************************************/ static gboolean -__profile_msg(MsnServConn *servconn, const MsnMessage *msg) +__profile_msg(MsnServConn *servconn, MsnMessage *msg) { MsnSession *session = servconn->session; const char *value; @@ -1162,7 +1162,7 @@ } static gboolean -__initial_email_msg(MsnServConn *servconn, const MsnMessage *msg) +__initial_email_msg(MsnServConn *servconn, MsnMessage *msg) { MsnSession *session = servconn->session; struct gaim_connection *gc = session->account->gc; @@ -1176,6 +1176,9 @@ if (session->passport_info.file == NULL) { msn_servconn_send_command(servconn, "URL", "INBOX"); + + msn_servconn_queue_message(servconn, "URL", msg); + return TRUE; } @@ -1193,7 +1196,7 @@ } static gboolean -__email_msg(MsnServConn *servconn, const MsnMessage *msg) +__email_msg(MsnServConn *servconn, MsnMessage *msg) { MsnSession *session = servconn->session; struct gaim_connection *gc = session->account->gc; @@ -1207,6 +1210,9 @@ if (session->passport_info.file == NULL) { msn_servconn_send_command(servconn, "URL", "INBOX"); + + msn_servconn_queue_message(servconn, "URL", msg); + return TRUE; } @@ -1229,7 +1235,7 @@ } static gboolean -__system_msg(MsnServConn *servconn, const MsnMessage *msg) +__system_msg(MsnServConn *servconn, MsnMessage *msg) { GHashTable *table; const char *type_s;
--- a/src/protocols/msn/servconn.c Sat May 24 19:15:58 2003 +0000 +++ b/src/protocols/msn/servconn.c Sun May 25 09:04:32 2003 +0000 @@ -22,10 +22,40 @@ #include "msn.h" #include "servconn.h" +typedef struct +{ + char *command; + MsnMessage *msg; + +} MsnQueueEntry; + +static gboolean +__process_message(MsnServConn *servconn, MsnMessage *msg) +{ + MsnServConnMsgCb cb; + + cb = g_hash_table_lookup(servconn->msg_types, + msn_message_get_content_type(msg)); + + if (cb == NULL) { + gaim_debug(GAIM_DEBUG_WARNING, "msn", + "Unhandled content-type '%s': %s\n", + msn_message_get_content_type(msg), + msn_message_get_body(msg)); + + return FALSE; + } + + cb(servconn, msg); + + return TRUE; +} + static gboolean __process_single_line(MsnServConn *servconn, char *str) { MsnServConnCommandCb cb; + GSList *l, *l_next; gboolean result; size_t param_count = 0; char *command, *param_start; @@ -68,45 +98,64 @@ if (params != NULL) g_strfreev(params); + + /* Process all queued messages that are waiting on this command. */ + for (l = servconn->msg_queue; l != NULL; l = l_next) { + MsnQueueEntry *entry = l->data; + MsnMessage *msg; + + l_next = l->next; + + if (entry->command == NULL || + !g_ascii_strcasecmp(entry->command, command)) { + + MsnUser *sender; + + msg = entry->msg; + + msn_message_ref(msg); + + msn_servconn_unqueue_message(servconn, entry->msg); + + sender = msn_message_get_sender(msg); + + servconn->msg_passport = g_strdup(msn_user_get_passport(sender)); + servconn->msg_friendly = g_strdup(msn_user_get_name(sender)); + + __process_message(servconn, msg); + + g_free(servconn->msg_passport); + g_free(servconn->msg_friendly); + + msn_message_destroy(msg); + } + } + return result; } static gboolean __process_multi_line(MsnServConn *servconn, char *buffer) { - MsnServConnMsgCb cb; MsnMessage *msg; char msg_str[MSN_BUF_LEN]; + gboolean result; g_snprintf(msg_str, sizeof(msg_str), "MSG %s %s %d\r\n%s", servconn->msg_passport, servconn->msg_friendly, servconn->msg_len, buffer); - msg = msn_message_new_from_str(servconn->session, msg_str); - - cb = g_hash_table_lookup(servconn->msg_types, - msn_message_get_content_type(msg)); - - if (cb == NULL) { - gaim_debug(GAIM_DEBUG_WARNING, "msn", - "Unhandled content-type '%s': %s\n", - msn_message_get_content_type(msg), - msn_message_get_body(msg)); - - msn_message_destroy(msg); - - return FALSE; - } - gaim_debug(GAIM_DEBUG_MISC, "msn", "Message: {%s}\n", buffer); - cb(servconn, msg); + msg = msn_message_new_from_str(servconn->session, msg_str); + + result = __process_message(servconn, msg); msn_message_destroy(msg); - return TRUE; + return result; } static void @@ -171,13 +220,19 @@ g_free(servconn->rxqueue); - while (servconn->txqueue) { + while (servconn->txqueue != NULL) { g_free(servconn->txqueue->data); servconn->txqueue = g_slist_remove(servconn->txqueue, servconn->txqueue->data); } + while (servconn->msg_queue != NULL) { + MsnQueueEntry *entry = servconn->msg_queue->data; + + msn_servconn_unqueue_message(servconn, entry->msg); + } + servconn->connected = FALSE; } @@ -276,6 +331,54 @@ } void +msn_servconn_queue_message(MsnServConn *servconn, const char *command, + MsnMessage *msg) +{ + MsnQueueEntry *entry; + + g_return_if_fail(servconn != NULL); + g_return_if_fail(msg != NULL); + + entry = g_new0(MsnQueueEntry, 1); + entry->msg = msg; + entry->command = (command == NULL ? NULL : g_strdup(command)); + + servconn->msg_queue = g_slist_append(servconn->msg_queue, entry); + + msn_message_ref(msg); +} + +void +msn_servconn_unqueue_message(MsnServConn *servconn, MsnMessage *msg) +{ + MsnQueueEntry *entry = NULL; + GSList *l; + + g_return_if_fail(servconn != NULL); + g_return_if_fail(msg != NULL); + + for (l = servconn->msg_queue; l != NULL; l = l->next) { + entry = l->data; + + if (entry->msg == msg) + break; + + entry = NULL; + } + + g_return_if_fail(entry != NULL); + + msn_message_unref(msg); + + servconn->msg_queue = g_slist_remove(servconn->msg_queue, entry); + + if (entry->command != NULL) + g_free(entry->command); + + g_free(entry); +} + +void msn_servconn_register_command(MsnServConn *servconn, const char *command, MsnServConnCommandCb cb) {
--- a/src/protocols/msn/servconn.h Sat May 24 19:15:58 2003 +0000 +++ b/src/protocols/msn/servconn.h Sun May 25 09:04:32 2003 +0000 @@ -30,8 +30,7 @@ const char *cmd, const char **params, size_t param_count); -typedef gboolean (*MsnServConnMsgCb)(MsnServConn *servconn, - const MsnMessage *msg); +typedef gboolean (*MsnServConnMsgCb)(MsnServConn *servconn, MsnMessage *msg); #include "session.h" @@ -50,6 +49,8 @@ char *rxqueue; int rxlen; + GSList *msg_queue; + GSList *txqueue; gboolean parsing_msg; @@ -92,6 +93,11 @@ gboolean msn_servconn_send_command(MsnServConn *servconn, const char *command, const char *params); +void msn_servconn_queue_message(MsnServConn *servconn, const char *command, + MsnMessage *msg); + +void msn_servconn_unqueue_message(MsnServConn *servconn, MsnMessage *msg); + void msn_servconn_register_command(MsnServConn *servconn, const char *command, MsnServConnCommandCb cb);
--- a/src/protocols/msn/switchboard.c Sat May 24 19:15:58 2003 +0000 +++ b/src/protocols/msn/switchboard.c Sun May 25 09:04:32 2003 +0000 @@ -262,7 +262,7 @@ * Message Types **************************************************************************/ static gboolean -__plain_msg(MsnServConn *servconn, const MsnMessage *msg) +__plain_msg(MsnServConn *servconn, MsnMessage *msg) { struct gaim_connection *gc = servconn->session->account->gc; MsnSwitchBoard *swboard = servconn->data; @@ -301,7 +301,7 @@ } static gboolean -__control_msg(MsnServConn *servconn, const MsnMessage *msg) +__control_msg(MsnServConn *servconn, MsnMessage *msg) { struct gaim_connection *gc = servconn->session->account->gc; MsnSwitchBoard *swboard = servconn->data; @@ -318,7 +318,7 @@ } static gboolean -__clientcaps_msg(MsnServConn *servconn, const MsnMessage *msg) +__clientcaps_msg(MsnServConn *servconn, MsnMessage *msg) { MsnSession *session = servconn->session; MsnSwitchBoard *swboard = servconn->data;