void msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) { MsnMessage *msg; slpmsg->msg = msg = msn_message_new_msnslp(); if (slpmsg->flags == 0x0) { msg->msnslp_header.session_id = slpmsg->session_id; msg->msnslp_header.ack_id = rand() % 0xFFFFFF00; } else if (slpmsg->flags == 0x2) { msg->msnslp_header.session_id = slpmsg->session_id; msg->msnslp_header.ack_id = slpmsg->ack_id; msg->msnslp_header.ack_size = slpmsg->ack_size; msg->msnslp_header.ack_sub_id = slpmsg->ack_sub_id; } else if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) { MsnSlpSession *slpsession; slpsession = slpmsg->slpsession; g_return_if_fail(slpsession != NULL); msg->msnslp_header.session_id = slpsession->id; msg->msnslp_footer.value = slpsession->app_id; msg->msnslp_header.ack_id = rand() % 0xFFFFFF00; } else if (slpmsg->flags == 0x100) { msg->msnslp_header.ack_id = slpmsg->ack_id; msg->msnslp_header.ack_sub_id = slpmsg->ack_sub_id; msg->msnslp_header.ack_size = slpmsg->ack_size; } msg->msnslp_header.id = slpmsg->id; msg->msnslp_header.flags = slpmsg->flags; msg->msnslp_header.total_size = slpmsg->size; msn_message_set_attr(msg, "P2P-Dest", slplink->remote_user); msg->ack_cb = msg_ack; msg->nak_cb = msg_nak; msg->ack_data = slpmsg; msn_slplink_send_msgpart(slplink, slpmsg); msn_message_destroy(msg); }
MsnMessage * msn_message_new_msnslp(void) { MsnMessage *msg; msg = msn_message_new(MSN_MSG_SLP); msn_message_set_attr(msg, "User-Agent", NULL); msg->msnslp_message = TRUE; msn_message_set_flag(msg, 'D'); msn_message_set_content_type(msg, "application/x-msnmsgrp2p"); return msg; }
void msn_message_parse_payload(MsnMessage *msg, const char *payload, size_t payload_len) { char *tmp_base, *tmp; const char *content_type; char *end; char **elems, **cur, **tokens; g_return_if_fail(payload != NULL); tmp_base = tmp = g_malloc0(payload_len + 1); memcpy(tmp_base, payload, payload_len); /* Parse the attributes. */ end = strstr(tmp, "\r\n\r\n"); /* TODO? some clients use \r delimiters instead of \r\n, the official client * doesn't send such messages, but does handle receiving them. We'll just * avoid crashing for now */ if (end == NULL) { g_free(tmp_base); g_return_if_reached(); } *end = '\0'; elems = g_strsplit(tmp, "\r\n", 0); for (cur = elems; *cur != NULL; cur++) { const char *key, *value; tokens = g_strsplit(*cur, ": ", 2); key = tokens[0]; value = tokens[1]; if (!strcmp(key, "MIME-Version")) { g_strfreev(tokens); continue; } if (!strcmp(key, "Content-Type")) { char *charset, *c; if ((c = strchr(value, ';')) != NULL) { if ((charset = strchr(c, '=')) != NULL) { charset++; msn_message_set_charset(msg, charset); } *c = '\0'; } msn_message_set_content_type(msg, value); } else { msn_message_set_attr(msg, key, value); } g_strfreev(tokens); } g_strfreev(elems); /* Proceed to the end of the "\r\n\r\n" */ tmp = end + 4; /* Now we *should* be at the body. */ content_type = msn_message_get_content_type(msg); if (content_type != NULL && !strcmp(content_type, "application/x-msnmsgrp2p")) { MsnSlpHeader header; MsnSlpFooter footer; int body_len; if (payload_len - (tmp - tmp_base) < sizeof(header)) { g_free(tmp_base); g_return_if_reached(); } msg->msnslp_message = TRUE; /* Import the header. */ memcpy(&header, tmp, sizeof(header)); tmp += sizeof(header); msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id); msg->msnslp_header.id = GUINT32_FROM_LE(header.id); msg->msnslp_header.offset = GUINT64_FROM_LE(header.offset); msg->msnslp_header.total_size = GUINT64_FROM_LE(header.total_size); msg->msnslp_header.length = GUINT32_FROM_LE(header.length); msg->msnslp_header.flags = GUINT32_FROM_LE(header.flags); msg->msnslp_header.ack_id = GUINT32_FROM_LE(header.ack_id); msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id); msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size); body_len = payload_len - (tmp - tmp_base) - sizeof(footer); /* Import the body. */ if (body_len > 0) { msg->body_len = body_len; msg->body = g_malloc0(msg->body_len + 1); memcpy(msg->body, tmp, msg->body_len); tmp += body_len; } /* Import the footer. */ if (body_len >= 0) { memcpy(&footer, tmp, sizeof(footer)); tmp += sizeof(footer); msg->msnslp_footer.value = GUINT32_FROM_BE(footer.value); } } else { if (payload_len - (tmp - tmp_base) > 0) { msg->body_len = payload_len - (tmp - tmp_base); msg->body = g_malloc0(msg->body_len + 1); memcpy(msg->body, tmp, msg->body_len); } } g_free(tmp_base); }