diff options
Diffstat (limited to 'libpurple/protocols/msn/slpmsg.c')
-rw-r--r-- | libpurple/protocols/msn/slpmsg.c | 230 |
1 files changed, 192 insertions, 38 deletions
diff --git a/libpurple/protocols/msn/slpmsg.c b/libpurple/protocols/msn/slpmsg.c index 4b3f96a926..58c08df261 100644 --- a/libpurple/protocols/msn/slpmsg.c +++ b/libpurple/protocols/msn/slpmsg.c @@ -21,8 +21,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "msn.h" + +#include "internal.h" +#include "debug.h" + #include "slpmsg.h" +#include "slpmsg_part.h" #include "slplink.h" /************************************************************************** @@ -39,10 +43,48 @@ msn_slpmsg_new(MsnSlpLink *slplink) if (purple_debug_is_verbose()) purple_debug_info("msn", "slpmsg new (%p)\n", slpmsg); - slpmsg->slplink = slplink; + if (slplink) + msn_slpmsg_set_slplink(slpmsg, slplink); + else + slpmsg->slplink = NULL; - slplink->slp_msgs = - g_list_append(slplink->slp_msgs, slpmsg); + slpmsg->header = g_new0(MsnP2PHeader, 1); + slpmsg->footer = NULL; + + return slpmsg; +} + +MsnSlpMessage *msn_slpmsg_new_from_data(const char *data, size_t data_len) +{ + MsnSlpMessage *slpmsg; + MsnP2PHeader *header; + const char *tmp; + int body_len; + + tmp = data; + slpmsg = msn_slpmsg_new(NULL); + + if (data_len < sizeof(*header)) { + return NULL; + } + + /* Extract the binary SLP header */ + slpmsg->header = msn_p2p_header_from_wire((MsnP2PHeader*)tmp); + + /* Extract the body */ + body_len = data_len - (tmp - data); + /* msg->body_len = msg->msnslp_header.length; */ + + if (body_len > 0) { + slpmsg->size = body_len; + slpmsg->buffer = g_malloc(body_len); + memcpy(slpmsg->buffer, tmp, body_len); + tmp += body_len; + } + + /* Extract the footer */ + if (body_len >= 0) + slpmsg->footer = msn_p2p_footer_from_wire((MsnP2PFooter*)tmp); return slpmsg; } @@ -67,26 +109,41 @@ msn_slpmsg_destroy(MsnSlpMessage *slpmsg) if (slpmsg->img == NULL) g_free(slpmsg->buffer); - for (cur = slpmsg->msgs; cur != NULL; cur = g_list_delete_link(cur, cur)) + for (cur = slpmsg->parts; cur != NULL; cur = g_list_delete_link(cur, cur)) { /* Something is pointing to this slpmsg, so we should remove that * pointer to prevent a crash. */ /* Ex: a user goes offline and after that we receive an ACK */ - MsnMessage *msg = cur->data; + MsnSlpMessagePart *part = cur->data; - msg->ack_cb = NULL; - msg->nak_cb = NULL; - msg->ack_data = NULL; - msn_message_unref(msg); + part->ack_cb = NULL; + part->nak_cb = NULL; + part->ack_data = NULL; + msn_slpmsgpart_destroy(part); } slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg); + g_free(slpmsg->header); + g_free(slpmsg->footer); + g_free(slpmsg); } void +msn_slpmsg_set_slplink(MsnSlpMessage *slpmsg, MsnSlpLink *slplink) +{ + g_return_if_fail(slplink != NULL); + + slpmsg->slplink = slplink; + + slplink->slp_msgs = + g_list_append(slplink->slp_msgs, slpmsg); + +} + +void msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body, long long size) { @@ -116,34 +173,6 @@ msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img) slpmsg->size = purple_imgstore_get_size(img); } -void -msn_slpmsg_show(MsnMessage *msg) -{ - const char *info; - gboolean text; - guint32 flags; - - text = FALSE; - - flags = GUINT32_TO_LE(msg->msnslp_header.flags); - - switch (flags) - { - case 0x0: - info = "SLP CONTROL"; - text = TRUE; - break; - case 0x2: - info = "SLP ACK"; break; - case 0x20: - case 0x1000030: - info = "SLP DATA"; break; - default: - info = "SLP UNKNOWN"; break; - } - - msn_message_show_readable(msg, info, text); -} MsnSlpMessage * msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq, @@ -206,3 +235,128 @@ msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq, return slpmsg; } + +MsnSlpMessage *msn_slpmsg_ack_new(MsnP2PHeader *header) +{ + MsnSlpMessage *slpmsg; + + slpmsg = msn_slpmsg_new(NULL); + + slpmsg->header->session_id = header->session_id; + slpmsg->size = header->total_size; + slpmsg->header->flags = P2P_ACK; + slpmsg->header->ack_id = header->id; + slpmsg->header->ack_sub_id = header->ack_id; + slpmsg->header->ack_size = header->total_size; + slpmsg->info = "SLP ACK"; + + return slpmsg; +} + +MsnSlpMessage *msn_slpmsg_obj_new(MsnSlpCall *slpcall, PurpleStoredImage *img) +{ + MsnSlpMessage *slpmsg; + + slpmsg = msn_slpmsg_new(NULL); + slpmsg->slpcall = slpcall; + slpmsg->header->flags = P2P_MSN_OBJ_DATA; + slpmsg->info = "SLP DATA"; + + msn_slpmsg_set_image(slpmsg, img); + + return slpmsg; +} + +MsnSlpMessage *msn_slpmsg_dataprep_new(MsnSlpCall *slpcall) +{ + MsnSlpMessage *slpmsg; + + slpmsg = msn_slpmsg_new(NULL); + + slpmsg->slpcall = slpcall; + slpmsg->header->session_id = slpcall->session_id; + msn_slpmsg_set_body(slpmsg, NULL, 4); + slpmsg->info = "SLP DATA PREP"; + + return slpmsg; + +} + +MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size) +{ + MsnSlpMessage *slpmsg; + + slpmsg = msn_slpmsg_new(NULL); + + slpmsg->slpcall = slpcall; + slpmsg->header->flags = P2P_FILE_DATA; + slpmsg->info = "SLP FILE"; + slpmsg->size = size; + + return slpmsg; +} + +char *msn_slpmsg_serialize(MsnSlpMessage *slpmsg, size_t *ret_size) +{ + MsnP2PHeader *header; + MsnP2PFooter *footer; + char *base; + char *tmp; + size_t siz; + + base = g_malloc(P2P_PACKET_HEADER_SIZE + slpmsg->size + sizeof(MsnP2PFooter)); + tmp = base; + + header = msn_p2p_header_to_wire(slpmsg->header); + footer = msn_p2p_footer_to_wire(slpmsg->footer); + + siz = sizeof(MsnP2PHeader); + /* Copy header */ + memcpy(tmp, (char*)header, siz); + tmp += siz; + + /* Copy body */ + memcpy(tmp, slpmsg->buffer, slpmsg->size); + tmp += slpmsg->size; + + /* Copy footer */ + siz = sizeof(MsnP2PFooter); + memcpy(tmp, (char*)footer, siz); + tmp += siz; + + *ret_size = tmp - base; + + return base; +} + +void msn_slpmsg_show_readable(MsnSlpMessage *slpmsg) +{ + GString *str; + + str = g_string_new(NULL); + + g_string_append_printf(str, "Session ID: %u\r\n", slpmsg->header->session_id); + g_string_append_printf(str, "ID: %u\r\n", slpmsg->header->id); + g_string_append_printf(str, "Offset: %" G_GUINT64_FORMAT "\r\n", slpmsg->header->offset); + g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", slpmsg->header->total_size); + g_string_append_printf(str, "Length: %u\r\n", slpmsg->header->length); + g_string_append_printf(str, "Flags: 0x%x\r\n", slpmsg->header->flags); + g_string_append_printf(str, "ACK ID: %u\r\n", slpmsg->header->ack_id); + g_string_append_printf(str, "SUB ID: %u\r\n", slpmsg->header->ack_sub_id); + g_string_append_printf(str, "ACK Size: %" G_GUINT64_FORMAT "\r\n", slpmsg->header->ack_size); + + if (purple_debug_is_verbose() && slpmsg->buffer != NULL) { + g_string_append_len(str, (gchar*)slpmsg->buffer, slpmsg->size); + + if (slpmsg->buffer[slpmsg->size - 1] == '\0') { + str->len--; + g_string_append(str, " 0x00"); + } + g_string_append(str, "\r\n"); + + } + + g_string_append_printf(str, "Footer: %u\r\n", slpmsg->footer->value); + + purple_debug_info("msn", "SlpMessage %s:\n{%s}\n", slpmsg->info, str->str); +} |