Mercurial > pidgin
diff src/protocols/msn/servconn.c @ 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 | c6efac0e28ff |
children | 46d7ad0dfa26 |
line wrap: on
line diff
--- 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) {