# HG changeset patch # User Christian Hammond # Date 1069557782 0 # Node ID 43803965ef450582246b334b1059657aabe21a28 # Parent dfebaa14bf67ccc7e9e6efb62caa6193a6e3c287 [gaim-migrate @ 8227] Committing what I have of MSN. It's disabled. committer: Tailor Script diff -r dfebaa14bf67 -r 43803965ef45 src/protocols/msn/msg.c --- a/src/protocols/msn/msg.c Sat Nov 22 23:17:31 2003 +0000 +++ b/src/protocols/msn/msg.c Sun Nov 23 03:23:02 2003 +0000 @@ -134,7 +134,9 @@ msn_message_new_from_str(MsnSession *session, const char *str) { MsnMessage *msg; + char *command_header; char *tmp_base, *msg_base, *tmp, *field1, *field2, *c; + const char *c2; g_return_val_if_fail(str != NULL, NULL); g_return_val_if_fail(!g_ascii_strncasecmp(str, "MSG", 3), NULL); @@ -146,25 +148,36 @@ msn_message_set_content_type(msg, NULL); msn_message_set_charset(msg, NULL); - tmp_base = tmp = g_strdup(str); + /* + * 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 MSG */ + field1 = tmp; - GET_NEXT(tmp); /* Skip the passport or TID */ - field2 = tmp; + GET_NEXT(tmp); /* Skip the passport or TID */ + field2 = tmp; - GET_NEXT(tmp); /* Skip the username or flag */ - msg->size = atoi(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); -#if 0 - /* Put this back when we intelligently handle binary strings. */ - if (msg->size != strlen(strchr(str, '\n') + 1)) { - gaim_debug(GAIM_DEBUG_ERROR, "msn", - "Incoming message size (%d) and string length (%d) " - "do not match!\n", msg->size, strlen(str)); + return NULL; } -#endif + + tmp_base = g_malloc(msg->size + 1); + memcpy(tmp_base, c2 + 2, msg->size); + tmp_base[msg->size] = '\0'; + + tmp = tmp_base; /* * We're going to make sure this is incoming by checking field1. @@ -236,6 +249,7 @@ char header[48]; char footer[4]; size_t body_len; + char *tmp2; msg->msnslp_message = TRUE; @@ -243,8 +257,7 @@ tmp += 48; - body_len = msg->size - (tmp - msg_base); - gaim_debug_misc("msn", "Body len = %d\n", body_len); + body_len = msg->size - (tmp - tmp_base) - 5; msg->body = g_malloc(body_len + 1); if (body_len > 0) @@ -256,19 +269,22 @@ memcpy(footer, tmp, 4); + tmp += 4; + /* Import the header. */ - msg->msnslp_header.session_id = msn_get32(tmp); tmp += 4; - msg->msnslp_header.id = msn_get32(tmp); tmp += 4; - msg->msnslp_header.offset_1 = msn_get32(tmp); tmp += 4; - msg->msnslp_header.offset_2 = msn_get32(tmp); tmp += 4; - msg->msnslp_header.total_size_1 = msn_get32(tmp); tmp += 4; - msg->msnslp_header.total_size_2 = msn_get32(tmp); tmp += 4; - msg->msnslp_header.length = msn_get32(tmp); tmp += 4; - msg->msnslp_header.flags = msn_get32(tmp); tmp += 4; - msg->msnslp_header.ack_session_id = msn_get32(tmp); tmp += 4; - msg->msnslp_header.ack_unique_id = msn_get32(tmp); tmp += 4; - msg->msnslp_header.ack_length_1 = msn_get32(tmp); tmp += 4; - msg->msnslp_header.ack_length_2 = msn_get32(tmp); tmp += 4; + tmp2 = header; + msg->msnslp_header.session_id = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.id = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.offset_1 = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.offset_2 = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.total_size_1 = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.total_size_2 = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.length = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.flags = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.ack_session_id = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.ack_unique_id = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.ack_length_1 = msn_get32(tmp2); tmp2 += 4; + msg->msnslp_header.ack_length_2 = msn_get32(tmp2); tmp2 += 4; /* Convert to the right endianness */ msg->msnslp_header.session_id = ntohl(msg->msnslp_header.session_id); @@ -292,6 +308,7 @@ msn_message_set_body(msg, tmp); } + g_free(command_header); g_free(tmp_base); /* Done! */ @@ -476,7 +493,7 @@ if (body != NULL) { - memcpy(c, body, msg->size - (c - msg_start)); + memcpy(c, body, bin_len); c += bin_len; } @@ -626,7 +643,10 @@ g_return_if_fail(msg != NULL); if (msg->bin_content) + { msn_message_set_bin_data(msg, NULL, 0); + return; + } if (msg->body != NULL) { msg->size -= strlen(msg->body); diff -r dfebaa14bf67 -r 43803965ef45 src/protocols/msn/msg.h --- a/src/protocols/msn/msg.h Sat Nov 22 23:17:31 2003 +0000 +++ b/src/protocols/msn/msg.h Sun Nov 23 03:23:02 2003 +0000 @@ -79,7 +79,7 @@ MsnSlpHeader msnslp_header; MsnSlpFooter msnslp_footer; - + MsnMessage *acked_msg; GHashTable *attr_table; diff -r dfebaa14bf67 -r 43803965ef45 src/protocols/msn/msnslp.c --- a/src/protocols/msn/msnslp.c Sat Nov 22 23:17:31 2003 +0000 +++ b/src/protocols/msn/msnslp.c Sun Nov 23 03:23:02 2003 +0000 @@ -51,13 +51,123 @@ if (session->call_id != NULL) g_free(session->call_id); + if (session->branch != NULL) + g_free(session->branch); + g_free(session); } +static void +msn_slp_session_send_message(MsnSlpSession *slpsession, + MsnMessage *source_msg, + MsnUser *local_user, MsnUser *remote_user, + const char *header, const char *branch, + int cseq, const char *call_id, + const char *content) +{ + MsnMessage *invite_msg; + char *body; + + g_return_if_fail(slpsession != NULL); + g_return_if_fail(header != NULL); + 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"; + + body = g_strdup_printf( + "%s\r\n" + "To: \r\n" + "From: \r\n" + "Via: MSNSLP/1.0/TLP ;branch={%s}\r\n" + "CSeq: %d\r\n" + "Call-ID: {%s}\r\n" + "Max-Forwards: 0\r\n" + "Content-Type: application/x-msnmsgr-sessionreqbody\r\n" + "Content-Length: %d\r\n" + "\r\n" + "%s" + "\r\n\r\n", + header, + msn_user_get_passport(remote_user), + msn_user_get_passport(local_user), + branch, cseq, call_id, + (content == NULL ? 0 : (int)strlen(content) + 5), + (content == NULL ? "" : content)); + + gaim_debug_misc("msn", "Message = {%s}\n", body); + + 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); + + msn_slp_session_send_msg(slpsession, invite_msg); +} + +static gboolean +send_error_500(MsnSlpSession *slpsession, const char *call_id, MsnMessage *msg) +{ + 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, + "MSNSLP/1.0 500 Internal Error", + slpsession->branch, 1, call_id, NULL); + + return TRUE; +} + +static gboolean +send_cb(gpointer user_data) +{ + MsnSlpSession *slpsession = (MsnSlpSession *)user_data; + MsnMessage *msg; + char data[1200]; + size_t len; + + len = fread(data, 1, 1200, slpsession->send_fp); + + 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); + + if (slpsession->remaining_size <= 0) + { + slpsession->send_timer = 0; + + return FALSE; + } + + return TRUE; +} + gboolean msn_slp_session_msg_received(MsnSlpSession *slpsession, MsnMessage *msg) { const char *body; + const char *c, *c2; + GaimAccount *account; g_return_val_if_fail(slpsession != NULL, TRUE); g_return_val_if_fail(msg != NULL, TRUE); @@ -65,9 +175,13 @@ g_return_val_if_fail(!strcmp(msn_message_get_content_type(msg), "application/x-msnmsgrp2p"), TRUE); + account = slpsession->swboard->servconn->session->account; + body = msn_message_get_body(msg); - if (strlen(body) == 0) + gaim_debug_misc("msn", "MSNSLP Message: {%s}\n", body); + + if (*body == '\0') { /* ACK. Ignore it. */ gaim_debug_info("msn", "Received MSNSLP ACK\n"); @@ -75,6 +189,161 @@ return FALSE; } + if (slpsession->send_fp != NULL && slpsession->remaining_size == 0) + { + /* + * In theory, if we received something while send_fp is non-NULL, + * but remaining_size is 0, then this is a data ack message. + * + * Say BYE-BYE. + */ + 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))); + + msn_slp_session_send_message(slpsession, msg, NULL, NULL, header, + "A0D624A6-6C0C-4283-A9E0-BC97B4B46D32", + 0, slpsession->call_id, ""); + + g_free(header); + + return TRUE; + } + + if (!strncmp(body, "MSNSLP/1.0 ", strlen("MSNSLP/1.0 "))) + { + /* Make sure this is "OK" */ + const char *status = body + strlen("MSNSLP/1.0 "); + + if (strncmp(status, "200 OK", 6)) + { + /* It's not valid. Kill this off. */ + char temp[32]; + const char *c; + + /* Eww */ + if ((c = strchr(status, '\r')) || (c = strchr(status, '\n')) || + (c = strchr(status, '\0'))) + { + strncpy(temp, status, c - status); + temp[c - status] = '\0'; + } + + gaim_debug_error("msn", "Received non-OK result: %s\n", temp); + + return TRUE; + } + } + else if (!strncmp(body, "INVITE", strlen("INVITE"))) + { + /* Parse it. Oh this is fun. */ + char *branch, *call_id, *temp; + unsigned int session_id, app_id; + + /* First, branch. */ + if ((c = strstr(body, ";branch={")) == NULL) + return send_error_500(slpsession, NULL, msg); + + c += strlen(";branch={"); + + if ((c2 = strchr(c, '}')) == NULL) + return send_error_500(slpsession, NULL, msg); + + branch = g_strndup(c, c2 - c); + + if (slpsession->branch != NULL) + slpsession->branch = branch; + + /* Second, Call-ID */ + if ((c = strstr(body, "Call-ID: {")) == NULL) + return send_error_500(slpsession, NULL, msg); + + c += strlen("Call-ID: {"); + + if ((c2 = strchr(c, '}')) == NULL) + return send_error_500(slpsession, NULL, msg); + + call_id = g_strndup(c, c2 - c); + + if (slpsession->call_id != NULL) + slpsession->call_id = call_id; + + /* Third, SessionID */ + if ((c = strstr(body, "SessionID: ")) == NULL) + return send_error_500(slpsession, NULL, msg); + + c += strlen("SessionID: "); + + if ((c2 = strchr(c, '\r')) == NULL) + return send_error_500(slpsession, NULL, msg); + + temp = g_strndup(c, c2 - c); + session_id = atoi(temp); + g_free(temp); + + /* Fourth, AppID */ + if ((c = strstr(body, "AppID: ")) == NULL) + return send_error_500(slpsession, NULL, msg); + + c += strlen("AppID: "); + + if ((c2 = strchr(c, '\r')) == NULL) + return send_error_500(slpsession, NULL, msg); + + temp = g_strndup(c, c2 - c); + app_id = atoi(temp); + g_free(temp); + + if (app_id == 1) + { + MsnMessage *new_msg; + char *content; + char nil_body[4]; + struct stat st; + + /* Send the 200 OK message. */ + content = g_strdup_printf("SessionID: %d", session_id); + msn_slp_session_send_ack(slpsession, msg); + + msn_slp_session_send_message(slpsession, msg, NULL, NULL, + "MSNSLP/1.0 200 OK", + branch, 1, call_id, content); + + g_free(content); + + /* Send the Data Preparation message. */ + 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; + + 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; + + msn_slp_session_send_msg(slpsession, new_msg); + + slpsession->send_fp = + fopen(gaim_account_get_buddy_icon(account), "rb"); + + if (stat(gaim_account_get_buddy_icon(account), &st) == 0) + slpsession->remaining_size = st.st_size; + + slpsession->send_timer = g_timeout_add(10, send_cb, slpsession); + } + else + return send_error_500(slpsession, call_id, msg); + + return FALSE; + } + /* Now send an ack, since we got this. */ msn_slp_session_send_ack(slpsession, msg); @@ -207,14 +476,11 @@ MsnUser *remote_user, const MsnObject *obj) { - MsnMessage *invite_msg; long session_id; char *msnobj_data; char *msnobj_base64; - char *branch; + char *header; char *content; - char *body; - char *c; g_return_if_fail(slpsession != NULL); g_return_if_fail(local_user != NULL); @@ -225,20 +491,23 @@ msnobj_base64 = gaim_base64_encode(msnobj_data, strlen(msnobj_data)); g_free(msnobj_data); - if ((c = strchr(msnobj_base64, '=')) != NULL) - *c = '\0'; - session_id = rand() % 0xFFFFFF00 + 4; - branch = g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X", - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111); + if (slpsession->branch != NULL) + g_free(slpsession->branch); + + slpsession->branch = g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X", + rand() % 0xAAFF + 0x1111, + rand() % 0xAAFF + 0x1111, + rand() % 0xAAFF + 0x1111, + rand() % 0xAAFF + 0x1111, + rand() % 0xAAFF + 0x1111, + rand() % 0xAAFF + 0x1111, + rand() % 0xAAFF + 0x1111, + rand() % 0xAAFF + 0x1111); + + if (slpsession->call_id != NULL) + g_free(slpsession->call_id); slpsession->call_id = g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X", rand() % 0xAAFF + 0x1111, @@ -260,44 +529,15 @@ g_free(msnobj_base64); - body = g_strdup_printf( - "INVITE MSNMSGR:%s MSNSLP/1.0\r\n" - "To: \r\n" - "From: \r\n" - "Via: MSNSLP/1.0/TLP ;branch={%s}\r\n" - "CSeq: 0\r\n" - "Call-ID: {%s}\r\n" - "Max-Forwards: 0\r\n" - "Content-Type: application/x-msnmsgr-sessionreqbody\r\n" - "Content-Length: %d\r\n" - "\r\n" - "%s" - "\r\n\r\n", - msn_user_get_passport(remote_user), - msn_user_get_passport(remote_user), - msn_user_get_passport(local_user), - branch, - slpsession->call_id, - (int)strlen(content) + 5, - content); + header = g_strdup_printf("INVITE MSNMSGR:%s MSNSLP/1.0", + msn_user_get_passport(remote_user)); - g_free(content); - g_free(branch); - - gaim_debug_misc("msn", "Message = {%s}\n", body); - - invite_msg = msn_message_new_msnslp(); + msn_slp_session_send_message(slpsession, NULL, local_user, remote_user, + header, slpsession->branch, 0, + slpsession->call_id, content); - 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); - - msn_slp_session_send_msg(slpsession, invite_msg); - - msn_message_destroy(invite_msg); + g_free(header); + g_free(content); } gboolean diff -r dfebaa14bf67 -r 43803965ef45 src/protocols/msn/msnslp.h --- a/src/protocols/msn/msnslp.h Sat Nov 22 23:17:31 2003 +0000 +++ b/src/protocols/msn/msnslp.h Sun Nov 23 03:23:02 2003 +0000 @@ -35,6 +35,7 @@ MsnSwitchBoard *swboard; + char *branch; char *call_id; long session_id; @@ -46,6 +47,14 @@ void *orig_body; size_t orig_len; + guint send_timer; + FILE *send_fp; + + size_t remaining_size; + + MsnUser *receiver; + MsnUser *sender; + MsnMessage *outgoing_msg; }; diff -r dfebaa14bf67 -r 43803965ef45 src/protocols/msn/servconn.c --- a/src/protocols/msn/servconn.c Sat Nov 22 23:17:31 2003 +0000 +++ b/src/protocols/msn/servconn.c Sun Nov 23 03:23:02 2003 +0000 @@ -146,11 +146,16 @@ 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%s", + "MSG %s %s %d\r\n", servconn->msg_passport, servconn->msg_friendly, - servconn->multiline_len, buffer); + 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);