# HG changeset patch # User Christian Hammond # Date 1081829302 0 # Node ID 1e211dde3cae268b0f11607ce03120a8faeb73eb # Parent 47f647dd2ac36b86b45ca7b03261518c1bc8ec43 [gaim-migrate @ 9398] Added a patch by shx to clean up the message-handling code and split the command stuff from it, among a few other things. Also, I fixed a crash in message parsing, which I think may close a couple bug reports. committer: Tailor Script diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/msg.c --- a/src/protocols/msn/msg.c Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/msg.c Tue Apr 13 04:08:22 2004 +0000 @@ -130,86 +130,22 @@ return msg; } -MsnMessage * -msn_message_new_from_str(MsnSession *session, const char *str) +void +msn_message_parse_payload(MsnMessage *msg, const char *payload, + size_t payload_len) { - MsnMessage *msg; - char *command_header; - char *tmp_base, *msg_base, *tmp, *field1, *field2, *c; + char *tmp_base, *tmp, *c; const char *content_type; - const char *c2; - - g_return_val_if_fail(str != NULL, NULL); - g_return_val_if_fail(!g_ascii_strncasecmp(str, "MSG", 3), NULL); - - msg = msn_message_new(); - - /* Clear out the old stuff. */ - msn_message_set_attr(msg, "User-Agent", NULL); - msn_message_set_content_type(msg, NULL); - msn_message_set_charset(msg, NULL); - /* - * We need to grab the header and then the size, since this might have - * binary data. - */ - if ((c2 = strchr(str, '\r')) != NULL) - { - tmp = command_header = g_strndup(str, (c2 - str)); - - GET_NEXT(tmp); /* Skip MSG */ - field1 = tmp; - - GET_NEXT(tmp); /* Skip the passport or TID */ - field2 = tmp; - - GET_NEXT(tmp); /* Skip the username or flag */ - msg->size = atoi(tmp); - } - else - { - /* Kind of screwed :) This won't happen. */ - msn_message_destroy(msg); - - return NULL; - } - - tmp_base = g_malloc(msg->size + 1); - memcpy(tmp_base, c2 + 2, msg->size); - tmp_base[msg->size] = '\0'; + tmp_base = g_malloc(payload_len + 1); + memcpy(tmp_base, payload, payload_len); + tmp_base[payload_len] = '\0'; tmp = tmp_base; - /* - * We're going to make sure this is incoming by checking field1. - * If it has any non-numbers in it, it's incoming. Otherwise, outgoing. - */ - msg->incoming = FALSE; - - for (c = field1; *c != '\0'; c++) { - if (*c < '0' || *c > '9') { - msg->incoming = TRUE; - break; - } - } - - if (msg->incoming) { - msg->sender = msn_users_find_with_passport(session->users, field1); - - if (msg->sender == NULL) - msg->sender = msn_user_new(session, field1, field2); - else - msn_user_ref(msg->sender); - } - else { - msg->tid = atoi(field1); - msg->flag = *field2; - } - - msg_base = tmp; - /* Back to the parsination. */ - while (*tmp != '\r') { + while (*tmp != '\r') + { char *key, *value; key = tmp; @@ -223,11 +159,14 @@ if ((c = strchr(key, ':')) != NULL) *c = '\0'; - if (!g_ascii_strcasecmp(key, "Content-Type")) { + if (!g_ascii_strcasecmp(key, "Content-Type")) + { char *charset; - if ((c = strchr(value, ';')) != NULL) { - if ((charset = strchr(c, '=')) != NULL) { + if ((c = strchr(value, ';')) != NULL) + { + if ((charset = strchr(c, '=')) != NULL) + { charset++; msn_message_set_charset(msg, charset); } @@ -261,15 +200,18 @@ tmp += 48; - body_len = msg->size - (tmp - tmp_base) - 5; - msg->body = g_malloc(body_len + 1); + body_len = payload_len - (tmp - tmp_base) - 5; if (body_len > 0) + { + msg->body = g_malloc(body_len + 1); memcpy(msg->body, tmp, body_len); + msg->body[body_len] = '\0'; - msg->body[body_len] = '\0'; - - tmp++; + tmp++; + } + else + msg->body = NULL; memcpy(footer, tmp, 4); @@ -312,7 +254,7 @@ char *tmp2; size_t body_len; - body_len = msg->size - (tmp - tmp_base); + body_len = payload_len - (tmp - tmp_base); tmp2 = g_malloc(body_len + 1); @@ -326,12 +268,9 @@ g_free(tmp2); } - g_free(command_header); g_free(tmp_base); /* Done! */ - - return msg; } void @@ -339,18 +278,13 @@ { g_return_if_fail(msg != NULL); - if (msg->ref_count > 0) { + if (msg->ref_count > 0) + { msn_message_unref(msg); return; } - if (msg->sender != NULL) - msn_user_unref(msg->sender); - - if (msg->receiver != NULL) - msn_user_unref(msg->receiver); - if (msg->body != NULL) g_free(msg->body); @@ -400,10 +334,9 @@ } char * -msn_message_to_string(const MsnMessage *msg, size_t *ret_size) +msn_message_gen_payload(const MsnMessage *msg, size_t *ret_size) { GList *l; - char *msg_start; char *str; char buf[MSN_BUF_LEN]; int len; @@ -419,35 +352,20 @@ */ g_return_val_if_fail(msg != NULL, NULL); - if (msn_message_is_incoming(msg)) { - MsnUser *sender = msn_message_get_sender(msg); - - g_snprintf(buf, sizeof(buf), "MSG %s %s %d\r\n", - msn_user_get_passport(sender), msn_user_get_name(sender), - (int)msg->size); - } - else { - g_snprintf(buf, sizeof(buf), "MSG %d %c %d\r\n", - msn_message_get_transaction_id(msg), - msn_message_get_flag(msg), (int)msg->size); - } - - len = strlen(buf) + msg->size + 1; + len = msg->size + 1; str = g_new0(char, len + 1); - g_strlcpy(str, buf, len); - - msg_start = str + strlen(str); - /* Standard header. */ - if (msg->charset == NULL) { + if (msg->charset == NULL) + { g_snprintf(buf, sizeof(buf), "MIME-Version: 1.0\r\n" "Content-Type: %s\r\n", msg->content_type); } - else { + else + { g_snprintf(buf, sizeof(buf), "MIME-Version: 1.0\r\n" "Content-Type: %s; charset=%s\r\n", @@ -456,7 +374,8 @@ g_strlcat(str, buf, len); - for (l = msg->attr_list; l != NULL; l = l->next) { + for (l = msg->attr_list; l != NULL; l = l->next) + { const char *key = (char *)l->data; const char *value; @@ -522,7 +441,7 @@ if (body != NULL) { - g_strlcpy(c, body, msg->size - (c - msg_start)); + g_strlcpy(c, body, msg->size - (c - str)); c += strlen(body); @@ -533,11 +452,11 @@ c += msn_put32(c, msg->msnslp_footer.app_id); - if (msg->size != (c - msg_start)) + if (msg->size != (c - str)) { gaim_debug(GAIM_DEBUG_ERROR, "msn", "Outgoing message size (%d) and data length (%d) " - "do not match!\n", msg->size, (c - msg_start)); + "do not match!\n", msg->size, (c - str)); } } else @@ -546,10 +465,11 @@ g_strlcat(str, body, len); - if (msg->size != strlen(msg_start)) { + if (msg->size != strlen(str)) + { gaim_debug(GAIM_DEBUG_ERROR, "msn", "Outgoing message size (%d) and string length (%d) " - "do not match!\n", msg->size, strlen(msg_start)); + "do not match!\n", msg->size, strlen(str)); } } @@ -559,80 +479,6 @@ return str; } -gboolean -msn_message_is_outgoing(const MsnMessage *msg) -{ - g_return_val_if_fail(msg != NULL, FALSE); - - return !msg->incoming; -} - -gboolean -msn_message_is_incoming(const MsnMessage *msg) -{ - g_return_val_if_fail(msg != NULL, FALSE); - - return msg->incoming; -} - -void -msn_message_set_sender(MsnMessage *msg, MsnUser *user) -{ - g_return_if_fail(msg != NULL); - g_return_if_fail(user != NULL); - - msg->sender = user; - - msn_user_ref(msg->sender); -} - -MsnUser * -msn_message_get_sender(const MsnMessage *msg) -{ - g_return_val_if_fail(msg != NULL, NULL); - - return msg->sender; -} - -void -msn_message_set_receiver(MsnMessage *msg, MsnUser *user) -{ - g_return_if_fail(msg != NULL); - g_return_if_fail(user != NULL); - - msg->receiver = user; - - if (msg->msnslp_message) - msn_message_set_attr(msg, "P2P-Dest", msn_user_get_passport(user)); - - msn_user_ref(msg->receiver); -} - -MsnUser * -msn_message_get_receiver(const MsnMessage *msg) -{ - g_return_val_if_fail(msg != NULL, NULL); - - return msg->receiver; -} - -void -msn_message_set_transaction_id(MsnMessage *msg, unsigned int tid) -{ - g_return_if_fail(msg != NULL); - g_return_if_fail(tid > 0); - - msg->tid = tid; -} - -unsigned int -msn_message_get_transaction_id(const MsnMessage *msg) -{ - g_return_val_if_fail(msg != NULL, 0); - - return msg->tid; -} - void msn_message_set_flag(MsnMessage *msg, char flag) { diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/msg.h --- a/src/protocols/msn/msg.h Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/msg.h Tue Apr 13 04:08:22 2004 +0000 @@ -60,14 +60,11 @@ gboolean msnslp_message; gboolean msnslp_ack_message; - MsnUser *sender; - MsnUser *receiver; + char *passport; unsigned int tid; char flag; - gboolean incoming; - size_t size; gboolean bin_content; @@ -112,14 +109,15 @@ MsnMessage *msn_message_new_msnslp_ack(MsnMessage *acked_msg); /** - * Creates a new message based off a string. + * Parse the payload of a message. * - * @param session The MSN session. - * @param str The string. - * - * @return The new message. + * @param msg The message. + * @param payload The payload. + * @param payload_len The length payload. */ -MsnMessage *msn_message_new_from_str(MsnSession *session, const char *str); +void msn_message_parse_payload(MsnMessage *msg, + const char *payload, + size_t payload_len); /** * Destroys a message. @@ -149,83 +147,14 @@ MsnMessage *msn_message_unref(MsnMessage *msg); /** - * Converts a message to a string. + * Generates the payload data of a message. * * @param msg The message. - * @param ret_size The returned size of the string. - * - * @return The string representation of a message. - */ -char *msn_message_to_string(const MsnMessage *msg, size_t *ret_size); - -/** - * Returns TRUE if the message is outgoing. - * - * @param msg The message. - * - * @return @c TRUE if the message is outgoing, or @c FALSE otherwise. - */ -gboolean msn_message_is_outgoing(const MsnMessage *msg); - -/** - * Returns TRUE if the message is incoming. - * - * @param msg The message. - * - * @return @c TRUE if the message is incoming, or @c FALSE otherwise. - */ -gboolean msn_message_is_incoming(const MsnMessage *msg); - -/** - * Sets the message's sender. - * - * @param msg The message. - * @param user The sender. - */ -void msn_message_set_sender(MsnMessage *msg, MsnUser *user); - -/** - * Returns the message's sender. - * - * @param msg The message. + * @param ret_size The returned size of the payload. * - * @return The sender. - */ -MsnUser *msn_message_get_sender(const MsnMessage *msg); - -/** - * Sets the message's receiver. - * - * @param msg The message. - * @param user The receiver. - */ -void msn_message_set_receiver(MsnMessage *msg, MsnUser *user); - -/** - * Returns the message's receiver. - * - * @param msg The message. - * - * @return The receiver. + * @return The payload data of the message. */ -MsnUser *msn_message_get_receiver(const MsnMessage *msg); - -/** - * Sets the message transaction ID. - * - * @param msg The message. - * @param tid The transaction ID. - */ -void msn_message_set_transaction_id(MsnMessage *msg, unsigned int tid); - -/** - * Returns the message transaction ID. - * - * @param msg The message. - * - * @return The transaction ID. - */ -unsigned int msn_message_get_transaction_id(const MsnMessage *msg); +char *msn_message_gen_payload(const MsnMessage *msg, size_t *ret_size); /** * Sets the flag for an outgoing message. diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/msn.c --- a/src/protocols/msn/msn.c Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/msn.c Tue Apr 13 04:08:22 2004 +0000 @@ -138,30 +138,42 @@ static void send_to_mobile_cb(MsnMobileData *data, const char *entry) { - MsnSession *session = data->gc->proto_data; - MsnServConn *servconn = session->notification_conn; - MsnUser *user; + MsnSession *session; + MsnServConn *servconn; MsnPage *page; - char *page_str; + char *buf; + char *payload; + size_t len; + size_t payload_len; - user = msn_user_new(session, data->passport, NULL); + session = data->gc->proto_data; + servconn = session->notification_conn; page = msn_page_new(); - msn_page_set_receiver(page, user); - msn_page_set_transaction_id(page, ++session->trId); msn_page_set_body(page, entry); + buf = g_strdup_printf("PGD %d %s 1 %d\r\n", ++session->trId, + data->passport, page->size); + + len = strlen(buf); + + payload = msn_page_gen_payload(page, &payload_len); - page_str = msn_page_build_string(page); + if (payload != NULL) + { + buf = g_realloc(buf, len + payload_len + 1); + memcpy(buf + len, payload, payload_len); + len += payload_len; + buf[len] = 0; + } - msn_user_destroy(user); msn_page_destroy(page); - if (!msn_servconn_write(servconn, page_str, strlen(page_str))) { - + if (!msn_servconn_write(servconn, buf, len)) + { gaim_connection_error(data->gc, _("Write error")); } - g_free(page_str); + g_free(buf); } static void @@ -541,7 +553,6 @@ msn_import_html(message, &msgformat, &msgtext); msg = msn_message_new(); - msn_message_set_receiver(msg, user); msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); msn_message_set_body(msg, msgtext); @@ -611,7 +622,6 @@ msg = msn_message_new(); msn_message_set_content_type(msg, "text/x-msmsgscontrol"); - msn_message_set_receiver(msg, user); msn_message_set_charset(msg, NULL); msn_message_set_flag(msg, 'U'); msn_message_set_attr(msg, "TypingUser", diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/msnslp.c --- a/src/protocols/msn/msnslp.c Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/msnslp.c Tue Apr 13 04:08:22 2004 +0000 @@ -59,8 +59,7 @@ static void msn_slp_session_send_message(MsnSlpSession *slpsession, - MsnMessage *source_msg, - MsnUser *local_user, MsnUser *remote_user, + const char *local_user, const char *remote_user, const char *header, const char *branch, int cseq, const char *call_id, const char *content) @@ -73,16 +72,6 @@ g_return_if_fail(branch != NULL); g_return_if_fail(call_id != NULL); - if (source_msg != NULL) - { - if (msn_message_is_incoming(source_msg)) - remote_user = msn_message_get_sender(source_msg); - else - remote_user = msn_message_get_receiver(source_msg); - - local_user = slpsession->swboard->servconn->session->user; - } - if (branch == NULL) branch = "null"; @@ -100,8 +89,8 @@ "%s" "\r\n\r\n", header, - msn_user_get_passport(remote_user), - msn_user_get_passport(local_user), + remote_user, + local_user, branch, cseq, call_id, (content == NULL ? 0 : (int)strlen(content) + 5), (content == NULL ? "" : content)); @@ -110,9 +99,6 @@ invite_msg = msn_message_new_msnslp(); - msn_message_set_sender(invite_msg, local_user); - msn_message_set_receiver(invite_msg, remote_user); - msn_message_set_body(invite_msg, body); g_free(body); @@ -123,10 +109,15 @@ static gboolean send_error_500(MsnSlpSession *slpsession, const char *call_id, MsnMessage *msg) { + MsnUser *local_user; + g_return_val_if_fail(slpsession != NULL, TRUE); g_return_val_if_fail(msg != NULL, TRUE); - msn_slp_session_send_message(slpsession, msg, NULL, NULL, + local_user = slpsession->swboard->servconn->session->user; + + msn_slp_session_send_message(slpsession, msg->passport, + msn_user_get_passport(local_user), "MSNSLP/1.0 500 Internal Error", slpsession->branch, 1, call_id, NULL); @@ -146,8 +137,6 @@ slpsession->remaining_size -= len; msg = msn_message_new_msnslp(); - msn_message_set_sender(msg, slpsession->receiver); - msn_message_set_receiver(msg, slpsession->sender); msn_message_set_bin_data(msg, data, len); msn_slp_session_send_msg(slpsession, msg); @@ -197,15 +186,20 @@ * * Say BYE-BYE. */ + MsnUser *local_user; char *header; fclose(slpsession->send_fp); slpsession->send_fp = NULL; header = g_strdup_printf("BYE MSNMSGR:%s MSNSLP/1.0", - msn_user_get_passport(msn_message_get_sender(msg))); + msg->passport); + + local_user = slpsession->swboard->servconn->session->user; - msn_slp_session_send_message(slpsession, msg, NULL, NULL, header, + msn_slp_session_send_message(slpsession, msg->passport, + msn_user_get_passport(local_user), + header, "A0D624A6-6C0C-4283-A9E0-BC97B4B46D32", 0, slpsession->call_id, ""); @@ -300,7 +294,10 @@ if (app_id == 1) { + MsnSession *session; MsnMessage *new_msg; + MsnUser *local_user; + MsnUser *remote_user; char *content; char nil_body[4]; struct stat st; @@ -309,7 +306,12 @@ content = g_strdup_printf("SessionID: %d", session_id); msn_slp_session_send_ack(slpsession, msg); - msn_slp_session_send_message(slpsession, msg, NULL, NULL, + session = slpsession->swboard->servconn->session; + + local_user = session->user; + + msn_slp_session_send_message(slpsession, msg->passport, + msn_user_get_passport(local_user), "MSNSLP/1.0 200 OK", branch, 1, call_id, content); @@ -319,12 +321,13 @@ memset(nil_body, 0, sizeof(nil_body)); slpsession->session_id = session_id; - slpsession->receiver = msn_message_get_sender(msg); - slpsession->sender = slpsession->swboard->servconn->session->user; + + remote_user = msn_user_new(session, msg->passport, NULL); + + slpsession->receiver = remote_user; + slpsession->sender = session->user; new_msg = msn_message_new_msnslp(); - msn_message_set_sender(new_msg, slpsession->sender); - msn_message_set_receiver(new_msg, slpsession->receiver); msn_message_set_bin_data(new_msg, nil_body, 4); new_msg->msnslp_footer.app_id = 1; @@ -532,7 +535,9 @@ header = g_strdup_printf("INVITE MSNMSGR:%s MSNSLP/1.0", msn_user_get_passport(remote_user)); - msn_slp_session_send_message(slpsession, NULL, local_user, remote_user, + msn_slp_session_send_message(slpsession, + msn_user_get_passport(local_user), + msn_user_get_passport(remote_user), header, slpsession->branch, 0, slpsession->call_id, content); diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/notification.c --- a/src/protocols/msn/notification.c Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/notification.c Tue Apr 13 04:08:22 2004 +0000 @@ -199,7 +199,7 @@ size_t param_count) { int errnum = 0; - + if (isdigit(*command)) { errnum = atoi(command); @@ -212,7 +212,7 @@ return TRUE; } } - + msn_error_handle(servconn->session, errnum); return TRUE; @@ -451,18 +451,30 @@ /************************************************************************** * Messages **************************************************************************/ +static void +msg_cmd_post(MsnServConn *servconn, char *payload, size_t len) +{ + MsnMessage *msg = msn_message_new(); + + msg->passport = servconn->msg_passport; + + msn_message_parse_payload(msg, payload, len); + + msn_servconn_process_message(servconn, msg); + + msn_message_destroy(msg); +} + static gboolean msg_cmd(MsnServConn *servconn, const char *command, const char **params, size_t param_count) { gaim_debug(GAIM_DEBUG_INFO, "msn", "Found message. Parsing.\n"); - servconn->parsing_multiline = TRUE; - servconn->multiline_type = MSN_MULTILINE_MSG; - servconn->multiline_len = atoi(params[2]); + servconn->payload_cb = msg_cmd_post; + servconn->payload_len = atoi(params[2]); servconn->msg_passport = g_strdup(params[0]); - servconn->msg_friendly = g_strdup(params[1]); return TRUE; } @@ -746,14 +758,8 @@ ipg_cmd(MsnServConn *servconn, const char *command, const char **params, size_t param_count) { - /* GaimConnection *gc = servconn->session->account->gc; */ - - servconn->parsing_multiline = TRUE; - servconn->multiline_type = MSN_MULTILINE_IPG; - servconn->multiline_len = atoi(params[0]); - - servconn->msg_passport = NULL; - servconn->msg_friendly = NULL; + servconn->payload_cb = NULL; + servconn->payload_len = atoi(params[2]); return TRUE; } @@ -1167,14 +1173,8 @@ not_cmd(MsnServConn *servconn, const char *command, const char **params, size_t param_count) { - /* GaimConnection *gc = servconn->session->account->gc; */ - - servconn->parsing_multiline = TRUE; - servconn->multiline_type = MSN_MULTILINE_NOT; - servconn->multiline_len = atoi(params[0]); - - servconn->msg_passport = NULL; - servconn->msg_friendly = NULL; + servconn->payload_cb = NULL; + servconn->payload_len = atoi(params[2]); return TRUE; } @@ -1604,7 +1604,9 @@ port)) { gaim_connection_error(gc, _("Unable to transfer to " - "notification server")); + "notification server")); + + g_free(host); return FALSE; } @@ -1624,7 +1626,7 @@ MsnSession *session = servconn->session; const char *value; - if (strcmp(servconn->msg_passport, "Hotmail")) { + if (strcmp(msg->passport, "Hotmail")) { /* This isn't an official message. */ return TRUE; } @@ -1655,7 +1657,7 @@ GHashTable *table; const char *unread; - if (strcmp(servconn->msg_passport, "Hotmail")) { + if (strcmp(msg->passport, "Hotmail")) { /* This isn't an official message. */ return TRUE; } @@ -1705,7 +1707,7 @@ GHashTable *table; char *from, *subject; - if (strcmp(servconn->msg_passport, "Hotmail")) { + if (strcmp(msg->passport, "Hotmail")) { /* This isn't an official message. */ return TRUE; } @@ -1743,7 +1745,7 @@ GHashTable *table; const char *type_s; - if (strcmp(servconn->msg_passport, "Hotmail")) { + if (strcmp(msg->passport, "Hotmail")) { /* This isn't an official message. */ return TRUE; } diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/page.c --- a/src/protocols/msn/page.c Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/page.c Tue Apr 13 04:08:22 2004 +0000 @@ -56,25 +56,11 @@ return page; } -MsnPage * -msn_page_new_from_str(MsnSession *session, const char *str) -{ - g_return_val_if_fail(str != NULL, NULL); - - return NULL; -} - void msn_page_destroy(MsnPage *page) { g_return_if_fail(page != NULL); - if (page->sender != NULL) - msn_user_unref(page->sender); - - if (page->receiver != NULL) - msn_user_unref(page->receiver); - if (page->body != NULL) g_free(page->body); @@ -88,138 +74,37 @@ } char * -msn_page_build_string(const MsnPage *page) +msn_page_gen_payload(const MsnPage *page, size_t *ret_size) { - char *page_start; char *str; - char buf[MSN_BUF_LEN]; - int len; - /* - * Okay, how we do things here is just bad. I don't like writing to - * a static buffer and then copying to the string. Unfortunately, - * just trying to append to the string is causing issues.. Such as - * the string you're appending to being erased. Ugh. So, this is - * good enough for now. - * - * -- ChipX86 - */ g_return_val_if_fail(page != NULL, NULL); - if (msn_page_is_incoming(page)) { - /* We don't know this yet :) */ - return NULL; - } - else { - MsnUser *receiver = msn_page_get_receiver(page); + str = + g_strdup_printf("%s", + msn_page_get_body(page)); - g_snprintf(buf, sizeof(buf), "PGD %d %s 1 %d\r\n", - msn_page_get_transaction_id(page), - msn_user_get_passport(receiver), - (int)page->size); + if (page->size != strlen(str)) + { + gaim_debug(GAIM_DEBUG_ERROR, "msn", + "Outgoing page size (%d) and string length (%d) " + "do not match!\n", page->size, strlen(str)); } - len = strlen(buf) + page->size + 1; - - str = g_new0(char, len); - - g_strlcpy(str, buf, len); - - page_start = str + strlen(str); - - g_snprintf(buf, sizeof(buf), - "%s", - msn_page_get_body(page)); - - g_strlcat(str, buf, len); - - if (page->size != strlen(page_start)) { - gaim_debug(GAIM_DEBUG_ERROR, "msn", - "Outgoing page size (%d) and string length (%d) " - "do not match!\n", page->size, strlen(page_start)); - } + if (ret_size != NULL) + *ret_size = page->size - 1; return str; } -gboolean -msn_page_is_outgoing(const MsnPage *page) -{ - g_return_val_if_fail(page != NULL, FALSE); - - return !page->incoming; -} - -gboolean -msn_page_is_incoming(const MsnPage *page) -{ - g_return_val_if_fail(page != NULL, FALSE); - - return page->incoming; -} - -void -msn_page_set_sender(MsnPage *page, MsnUser *user) -{ - g_return_if_fail(page != NULL); - g_return_if_fail(user != NULL); - - page->sender = user; - - msn_user_ref(page->sender); -} - -MsnUser * -msn_page_get_sender(const MsnPage *page) -{ - g_return_val_if_fail(page != NULL, NULL); - - return page->sender; -} - -void -msn_page_set_receiver(MsnPage *page, MsnUser *user) -{ - g_return_if_fail(page != NULL); - g_return_if_fail(user != NULL); - - page->receiver = user; - - msn_user_ref(page->receiver); -} - -MsnUser * -msn_page_get_receiver(const MsnPage *page) -{ - g_return_val_if_fail(page != NULL, NULL); - - return page->receiver; -} - -void -msn_page_set_transaction_id(MsnPage *page, unsigned int tid) -{ - g_return_if_fail(page != NULL); - g_return_if_fail(tid > 0); - - page->trId = tid; -} - -unsigned int -msn_page_get_transaction_id(const MsnPage *page) -{ - g_return_val_if_fail(page != NULL, 0); - - return page->trId; -} - void msn_page_set_body(MsnPage *page, const char *body) { g_return_if_fail(page != NULL); g_return_if_fail(body != NULL); - if (page->body != NULL) { + if (page->body != NULL) + { page->size -= strlen(page->body); g_free(page->body); } diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/page.h --- a/src/protocols/msn/page.h Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/page.h Tue Apr 13 04:08:22 2004 +0000 @@ -32,16 +32,9 @@ */ struct _MsnPage { - MsnUser *sender; - MsnUser *receiver; - char *from_location; char *from_phone; - gboolean incoming; - - unsigned int trId; - size_t size; char *body; @@ -55,98 +48,19 @@ MsnPage *msn_page_new(void); /** - * Creates a new page based off a string. - * - * @param session The MSN session. - * @param str The string. - * - * @return The new page. - */ -MsnPage *msn_page_new_from_str(MsnSession *session, const char *str); - -/** * Destroys a page. */ void msn_page_destroy(MsnPage *page); /** - * Converts a page to a string. - * - * @param page The page. - * - * @return The string representation of a page. - */ -char *msn_page_build_string(const MsnPage *page); - -/** - * Returns TRUE if the page is outgoing. - * - * @param page The page. - * - * @return @c TRUE if the page is outgoing, or @c FALSE otherwise. - */ -gboolean msn_page_is_outgoing(const MsnPage *page); - -/** - * Returns TRUE if the page is incoming. - * - * @param page The page. - * - * @return @c TRUE if the page is incoming, or @c FALSE otherwise. - */ -gboolean msn_page_is_incoming(const MsnPage *page); - -/** - * Sets the page's sender. - * - * @param page The page. - * @param user The sender. - */ -void msn_page_set_sender(MsnPage *page, MsnUser *user); - -/** - * Returns the page's sender. - * - * @param page The page. + * Converts a page to a payload string. * - * @return The sender. - */ -MsnUser *msn_page_get_sender(const MsnPage *page); - -/** - * Sets the page's receiver. + * @param page The page. + * @param ret_size The returned size of the payload. * - * @param page The page. - * @param user The receiver. - */ -void msn_page_set_receiver(MsnPage *page, MsnUser *user); - -/** - * Returns the page's receiver. - * - * @param page The page. - * - * @return The receiver. + * @return The payload string of a page. */ -MsnUser *msn_page_get_receiver(const MsnPage *page); - -/** - * Sets the page transaction ID. - * - * @param page The page. - * @param tid The transaction ID. - */ -void msn_page_set_transaction_id(MsnPage *page, unsigned int tid); - -/** - * Returns the page transaction ID. - * - * @param page The page. - * - * @return The transaction ID. - */ -unsigned int msn_page_get_transaction_id(const MsnPage *page); - +char *msn_page_gen_payload(const MsnPage *page, size_t *ret_size); /** * Sets the body of a page. diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/servconn.c --- a/src/protocols/msn/servconn.c Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/servconn.c Tue Apr 13 04:08:22 2004 +0000 @@ -32,15 +32,16 @@ } MsnQueueEntry; -static gboolean -process_message(MsnServConn *servconn, MsnMessage *msg) +gboolean +msn_servconn_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) { + if (cb == NULL) + { gaim_debug(GAIM_DEBUG_WARNING, "msn", "Unhandled content-type '%s': %s\n", msn_message_get_content_type(msg), @@ -54,144 +55,6 @@ return TRUE; } -static gboolean -process_single_line(MsnServConn *servconn, char *str) -{ - MsnSession *session = servconn->session; - MsnServConnCommandCb cb; - GSList *l, *l_next = NULL; - gboolean result; - size_t param_count = 0; - char *command, *param_start; - char **params = NULL; - - command = str; - - /** - * See how many spaces we have in this. - */ - param_start = strchr(command, ' '); - - if (param_start != NULL) { - params = g_strsplit(param_start + 1, " ", 0); - - for (param_count = 0; params[param_count] != NULL; param_count++) - ; - - *param_start = '\0'; - } - - cb = g_hash_table_lookup(servconn->commands, command); - - if (cb == NULL) { - cb = g_hash_table_lookup(servconn->commands, "_unknown_"); - - if (cb == NULL) { - if (isdigit(*str)) - msn_error_handle(session, atoi(str)); - else - gaim_debug(GAIM_DEBUG_WARNING, "msn", - "Unhandled command '%s'\n", str); - - if (params != NULL) - g_strfreev(params); - - return TRUE; - } - } - - result = cb(servconn, command, (const char **)params, param_count); - - if (params != NULL) - g_strfreev(params); - - if (g_list_find(session->servconns, servconn) == NULL) - return result; - - /* 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); - - 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_servconn_unqueue_message(servconn, entry->msg); - - msn_message_destroy(msg); - entry->msg = NULL; - } - } - - return result; -} - -static gboolean -process_multi_line(MsnServConn *servconn, char *buffer) -{ - char msg_str[MSN_BUF_LEN]; - gboolean result = TRUE; - - if (servconn->multiline_type == MSN_MULTILINE_MSG) { - MsnMessage *msg; - size_t header_len; - - g_snprintf(msg_str, sizeof(msg_str), - "MSG %s %s %d\r\n", - servconn->msg_passport, servconn->msg_friendly, - servconn->multiline_len); - - header_len = strlen(msg_str); - - memcpy(msg_str + header_len, buffer, servconn->multiline_len); - - gaim_debug(GAIM_DEBUG_MISC, "msn", - "Message: {%s}\n", buffer); - - msg = msn_message_new_from_str(servconn->session, msg_str); - - result = process_message(servconn, msg); - - msn_message_destroy(msg); - } - else if (servconn->multiline_type == MSN_MULTILINE_IPG) { - g_snprintf(msg_str, sizeof(msg_str), - "IPG %d\r\n%s", - servconn->multiline_len, buffer); - - gaim_debug(GAIM_DEBUG_MISC, "msn", - "Incoming Page: {%s}\n", buffer); - } - else if (servconn->multiline_type == MSN_MULTILINE_NOT) { - g_snprintf(msg_str, sizeof(msg_str), - "NOT %d\r\n%s", - servconn->multiline_len, buffer); - - gaim_debug(GAIM_DEBUG_MISC, "msn", - "Notification: {%s}\n", buffer); - } - - return result; -} - static void connect_cb(gpointer data, gint source, GaimInputCondition cond) { @@ -284,13 +147,14 @@ session = servconn->session; - if (servconn->inpa) + if (servconn->inpa > 0) + { gaim_input_remove(servconn->inpa); + servconn->inpa = 0; + } close(servconn->fd); - servconn->connected = FALSE; - if (servconn->http_data != NULL) { if (servconn->http_data->session_id != NULL) @@ -308,8 +172,8 @@ g_free(servconn->http_data); } - if (servconn->rxqueue != NULL) - g_free(servconn->rxqueue); + servconn->rx_len = 0; + servconn->payload_len = 0; while (servconn->txqueue != NULL) { g_free(servconn->txqueue->data); @@ -324,8 +188,10 @@ msn_servconn_unqueue_message(servconn, entry->msg); } - if (servconn->disconnect_cb) + if (servconn->disconnect_cb != NULL) servconn->disconnect_cb(servconn); + + servconn->connected = FALSE; } void @@ -526,15 +392,103 @@ } static void +process_payload(MsnServConn *servconn, char *payload, int payload_len) +{ + g_return_if_fail(servconn != NULL); + g_return_if_fail(servconn->payload_cb != NULL); + + servconn->payload_cb(servconn, payload, payload_len); +} + +static int +process_cmd_text(MsnServConn *servconn, const char *command) +{ + MsnSession *session = servconn->session; + MsnServConnCommandCb cb; + GSList *l, *l_next = NULL; + gboolean result; + size_t param_count = 0; + char *param_start; + char **params = NULL; + +#if 0 + if (servconn->last_cmd != NULL) + gfree(servconn->last_cmd); + + servconn->last_cmd = gstrdup(command); +#endif + + /** + * See how many spaces we have in this. + */ + param_start = strchr(command, ' '); + + if (param_start != NULL) { + params = g_strsplit(param_start + 1, " ", 0); + + for (param_count = 0; params[param_count] != NULL; param_count++) + ; + + *param_start = '\0'; + } + + cb = g_hash_table_lookup(servconn->commands, command); + + if (cb == NULL) { + cb = g_hash_table_lookup(servconn->commands, "_unknown_"); + + if (cb == NULL) { + gaim_debug(GAIM_DEBUG_WARNING, "msn", + "Unhandled command '%s'\n", command); + + if (params != NULL) + g_strfreev(params); + + return TRUE; + } + } + + result = cb(servconn, command, (const char **)params, param_count); + + if (params != NULL) + g_strfreev(params); + + if (g_list_find(session->servconns, servconn) == NULL) + return result; + + /* 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)) { + + msg = entry->msg; + + msn_servconn_process_message(servconn, msg); + + msn_servconn_unqueue_message(servconn, msg); + + entry->msg = NULL; + } + } + + return result; +} + +static void read_cb(gpointer data, gint source, GaimInputCondition cond) { MsnServConn *servconn = (MsnServConn *)data; MsnSession *session = servconn->session; char buf[MSN_BUF_LEN]; - gboolean cont = TRUE; - int len; + char *cur, *end, *old_rx_buf; + int len, cur_len; - len = read(servconn->fd, buf, sizeof(buf)); + len = read(servconn->fd, buf, sizeof(buf) - 1); if (len <= 0) { @@ -543,9 +497,9 @@ return; } - servconn->rxqueue = g_realloc(servconn->rxqueue, len + servconn->rxlen); - memcpy(servconn->rxqueue + servconn->rxlen, buf, len); - servconn->rxlen += len; + servconn->rx_buf = g_realloc(servconn->rx_buf, len + servconn->rx_len); + memcpy(servconn->rx_buf + servconn->rx_len, buf, len); + servconn->rx_len += len; if (session->http_method) { @@ -554,10 +508,10 @@ gboolean error; char *tmp; - tmp = g_strndup(servconn->rxqueue, servconn->rxlen); + tmp = g_strndup(servconn->rx_buf, servconn->rx_len); if (!msn_http_servconn_parse_data(servconn, tmp, - servconn->rxlen, &result_msg, + servconn->rx_len, &result_msg, &result_len, &error)) { g_free(tmp); @@ -607,90 +561,63 @@ } #endif - g_free(servconn->rxqueue); - servconn->rxqueue = result_msg; - servconn->rxlen = result_len; + g_free(servconn->rx_buf); + servconn->rx_buf = result_msg; + servconn->rx_len = result_len; } - while (cont) + end = old_rx_buf = servconn->rx_buf; + + do { - if (servconn->parsing_multiline) + cur = end; + + if (servconn->payload_len) { - char *msg; - - if (servconn->rxlen == 0) + if (servconn->payload_len > servconn->rx_len) + /* The payload is still not complete. */ break; - if (servconn->multiline_len > servconn->rxlen) + cur_len = servconn->payload_len; + end += cur_len; + } + else + { + end = strstr(cur, "\r\n"); + + if (!end) + /* The command is still not complete. */ break; - msg = servconn->rxqueue; - servconn->rxlen -= servconn->multiline_len; - - if (servconn->rxlen) { - servconn->rxqueue = g_memdup(msg + servconn->multiline_len, - servconn->rxlen); - } - else { - servconn->rxqueue = NULL; - msg = g_realloc(msg, servconn->multiline_len + 1); - } - - msg[servconn->multiline_len] = '\0'; - servconn->parsing_multiline = FALSE; + *end = '\0'; + cur_len = end - cur + 2; + end += 2; + } - process_multi_line(servconn, msg); - - if (g_list_find(session->servconns, servconn) != NULL) { - servconn->multiline_len = 0; - - if (servconn->msg_passport != NULL) - g_free(servconn->msg_passport); + servconn->rx_len -= cur_len; - if (servconn->msg_friendly != NULL) - g_free(servconn->msg_friendly); - } - else - cont = 0; - - g_free(msg); + if (servconn->payload_len) + { + process_payload(servconn, cur, cur_len); + servconn->payload_len = 0; } - else { - char *end = servconn->rxqueue; - char *cmd; - int cmdlen, i; - - if (!servconn->rxlen) - return; - - for (i = 0; i < servconn->rxlen - 1; end++, i++) { - if (*end == '\r' && end[1] == '\n') - break; - } - - if (i == servconn->rxlen - 1) - return; - - cmdlen = end - servconn->rxqueue + 2; - cmd = servconn->rxqueue; - servconn->rxlen -= cmdlen; + else + { + gaim_debug(GAIM_DEBUG_MISC, "msn", "S: %s\n", cur); + process_cmd_text(servconn, cur); + } + } while (servconn->connected && servconn->rx_len); - if (servconn->rxlen) - servconn->rxqueue = g_memdup(cmd + cmdlen, servconn->rxlen); - else { - servconn->rxqueue = NULL; - cmd = g_realloc(cmd, cmdlen + 1); - } - - cmd[cmdlen] = '\0'; + if (servconn->connected) + { + if (servconn->rx_len) + servconn->rx_buf = g_memdup(cur, servconn->rx_len); + else + servconn->rx_buf = NULL; + } - gaim_debug(GAIM_DEBUG_MISC, "msn", "S: %s", cmd); - - g_strchomp(cmd); + if (servconn->wasted) + msn_servconn_destroy(servconn); - cont = process_single_line(servconn, cmd); - - g_free(cmd); - } - } + g_free(old_rx_buf); } diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/servconn.h --- a/src/protocols/msn/servconn.h Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/servconn.h Tue Apr 13 04:08:22 2004 +0000 @@ -35,21 +35,17 @@ typedef gboolean (*MsnServConnMsgCb)(MsnServConn *servconn, MsnMessage *msg); -#include "session.h" +typedef void (*MsnPayloadCb)(MsnServConn *servconn, char *payload, + size_t len); -typedef enum -{ - MSN_MULTILINE_MSG, - MSN_MULTILINE_IPG, - MSN_MULTILINE_NOT - -} MsnMultilineType; +#include "session.h" struct _MsnServConn { MsnSession *session; gboolean connected; + gboolean wasted; MsnHttpMethodData *http_data; @@ -62,18 +58,17 @@ int fd; int inpa; - char *rxqueue; - int rxlen; + char *rx_buf; + int rx_len; + + MsnPayloadCb payload_cb; + int payload_len; GSList *msg_queue; GSList *txqueue; - gboolean parsing_multiline; - MsnMultilineType multiline_type; char *msg_passport; - char *msg_friendly; - int multiline_len; GHashTable *commands; GHashTable *msg_types; @@ -126,7 +121,7 @@ const char *content_type, MsnServConnMsgCb cb); -void msn_servconn_parse_data(gpointer data, gint source, - GaimInputCondition cond); +gboolean msn_servconn_process_message(MsnServConn *servconn, + MsnMessage *msg); #endif /* _MSN_SERVCONN_H_ */ diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/switchboard.c --- a/src/protocols/msn/switchboard.c Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/switchboard.c Tue Apr 13 04:08:22 2004 +0000 @@ -260,18 +260,30 @@ return send_clientcaps(swboard); } +static void +msg_cmd_post(MsnServConn *servconn, char *payload, size_t len) +{ + MsnMessage *msg = msn_message_new(); + + msg->passport = servconn->msg_passport; + + msn_message_parse_payload(msg, payload, len); + + msn_servconn_process_message(servconn, msg); + + msn_message_destroy(msg); +} + static gboolean msg_cmd(MsnServConn *servconn, const char *command, const char **params, - size_t param_count) + size_t param_count) { gaim_debug(GAIM_DEBUG_INFO, "msn", "Found message. Parsing.\n"); - servconn->parsing_multiline = TRUE; - servconn->multiline_type = MSN_MULTILINE_MSG; - servconn->multiline_len = atoi(params[2]); + servconn->payload_cb = msg_cmd_post; + servconn->payload_len = atoi(params[2]); servconn->msg_passport = g_strdup(params[0]); - servconn->msg_friendly = g_strdup(params[1]); return TRUE; } @@ -338,7 +350,7 @@ body = gaim_escape_html(msn_message_get_body(msg)); - if (!strcmp(servconn->msg_passport, "messenger@microsoft.com") && + if (!strcmp(msg->passport, "messenger@microsoft.com") && strstr(body, "immediate security update")) { g_free(body); @@ -346,11 +358,13 @@ return TRUE; } +#if 0 gaim_debug(GAIM_DEBUG_INFO, "msn", "Checking User-Agent...\n"); if ((value = msn_message_get_attr(msg, "User-Agent")) != NULL) { gaim_debug(GAIM_DEBUG_MISC, "msn", "value = '%s'\n", value); } +#endif if ((value = msn_message_get_attr(msg, "X-MMS-IM-Format")) != NULL) { char *pre_format, *post_format; @@ -367,10 +381,10 @@ { serv_got_chat_in(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(swboard->chat)), - servconn->msg_passport, 0, body, time(NULL)); + msg->passport, 0, body, time(NULL)); } else - serv_got_im(gc, servconn->msg_passport, body, 0, time(NULL)); + serv_got_im(gc, msg->passport, body, 0, time(NULL)); g_free(body); @@ -387,7 +401,7 @@ if (swboard->chat == NULL && (value = msn_message_get_attr(msg, "TypingUser")) != NULL) { - serv_got_typing(gc, servconn->msg_passport, MSN_TYPING_RECV_TIMEOUT, + serv_got_typing(gc, msg->passport, MSN_TYPING_RECV_TIMEOUT, GAIM_TYPING); } @@ -404,7 +418,7 @@ GHashTable *clientcaps; const char *value; - user = msn_user_new(session, servconn->msg_passport, NULL); + user = msn_user_new(session, msg->passport, NULL); clientcaps = msn_message_get_hashtable_from_body(msg); #endif @@ -500,11 +514,11 @@ /* Register the message type callbacks. */ msn_servconn_register_msg_type(servconn, "text/plain",plain_msg); msn_servconn_register_msg_type(servconn, "text/x-msmsgscontrol", - control_msg); + control_msg); msn_servconn_register_msg_type(servconn, "text/x-clientcaps", - clientcaps_msg); + clientcaps_msg); msn_servconn_register_msg_type(servconn, "text/x-clientinfo", - clientcaps_msg); + clientcaps_msg); #if 0 msn_servconn_register_msg_type(servconn, "application/x-msnmsgrp2p", msn_p2p_msg); @@ -652,7 +666,9 @@ msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg) { char *buf; + char *payload; size_t len; + size_t payload_len; int ret; #if 0 FILE *fp; @@ -661,12 +677,23 @@ g_return_val_if_fail(swboard != NULL, FALSE); g_return_val_if_fail(msg != NULL, FALSE); - msn_message_set_transaction_id(msg, ++swboard->trId); - buf = msn_message_to_string(msg, &len); + buf = g_strdup_printf("MSG %d %c %d\r\n", ++swboard->trId, + msn_message_get_flag(msg), (int)msg->size); + + len = strlen(buf); + + payload = msn_message_gen_payload(msg, &payload_len); - g_return_val_if_fail(buf != NULL, FALSE); + if (payload != NULL) + { + buf = g_realloc(buf, len + payload_len + 1); + memcpy(buf + len, payload, payload_len); + len += payload_len; + buf[len] = 0; + } - if (swboard->servconn->txqueue != NULL || !swboard->in_use) { + if (swboard->servconn->txqueue != NULL || !swboard->in_use) + { gaim_debug(GAIM_DEBUG_INFO, "msn", "Appending message to queue.\n"); swboard->servconn->txqueue = diff -r 47f647dd2ac3 -r 1e211dde3cae src/protocols/msn/utils.c --- a/src/protocols/msn/utils.c Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/utils.c Tue Apr 13 04:08:22 2004 +0000 @@ -98,8 +98,6 @@ "", colors[0], colors[1], colors[2]); - gaim_debug_misc("msn", "Got: %s\n", tag); - pre = g_string_append(pre, tag); post = g_string_prepend(post, ""); }