--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/msnp9/slpmsg.c Sun Nov 11 12:57:52 2007 +0000 @@ -0,0 +1,239 @@ +/** + * @file slpmsg.h SLP Message functions + * + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * 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 "slpmsg.h" +#include "slplink.h" + +/************************************************************************** + * SLP Message + **************************************************************************/ + +MsnSlpMessage * +msn_slpmsg_new(MsnSlpLink *slplink) +{ + MsnSlpMessage *slpmsg; + + slpmsg = g_new0(MsnSlpMessage, 1); + +#ifdef MSN_DEBUG_SLPMSG + purple_debug_info("msn", "slpmsg new (%p)\n", slpmsg); +#endif + + slpmsg->slplink = slplink; + + slplink->slp_msgs = + g_list_append(slplink->slp_msgs, slpmsg); + + return slpmsg; +} + +void +msn_slpmsg_destroy(MsnSlpMessage *slpmsg) +{ + MsnSlpLink *slplink; + GList *cur; + + g_return_if_fail(slpmsg != NULL); + +#ifdef MSN_DEBUG_SLPMSG + purple_debug_info("msn", "slpmsg destroy (%p)\n", slpmsg); +#endif + + slplink = slpmsg->slplink; + + if (slpmsg->fp != NULL) + fclose(slpmsg->fp); + + purple_imgstore_unref(slpmsg->img); + + /* We don't want to free the data of the PurpleStoredImage, + * but to avoid code duplication, it's sharing buffer. */ + if (slpmsg->img == NULL) + g_free(slpmsg->buffer); + +#ifdef MSN_DEBUG_SLP + /* + if (slpmsg->info != NULL) + g_free(slpmsg->info); + */ +#endif + + for (cur = slpmsg->msgs; cur != NULL; cur = cur->next) + { + /* 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; + +#ifdef MSN_DEBUG_SLPMSG + purple_debug_info("msn", "Unlink slpmsg callbacks.\n"); +#endif + + msg->ack_cb = NULL; + msg->nak_cb = NULL; + msg->ack_data = NULL; + } + + slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg); + + g_free(slpmsg); +} + +void +msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body, + long long size) +{ + /* We can only have one data source at a time. */ + g_return_if_fail(slpmsg->buffer == NULL); + g_return_if_fail(slpmsg->img == NULL); + g_return_if_fail(slpmsg->fp == NULL); + + if (body != NULL) + slpmsg->buffer = g_memdup(body, size); + else + slpmsg->buffer = g_new0(guchar, size); + + slpmsg->size = size; +} + +void +msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img) +{ + /* We can only have one data source at a time. */ + g_return_if_fail(slpmsg->buffer == NULL); + g_return_if_fail(slpmsg->img == NULL); + g_return_if_fail(slpmsg->fp == NULL); + + slpmsg->img = purple_imgstore_ref(img); + slpmsg->buffer = (guchar *)purple_imgstore_get_data(img); + slpmsg->size = purple_imgstore_get_size(img); +} + +void +msn_slpmsg_open_file(MsnSlpMessage *slpmsg, const char *file_name) +{ + struct stat st; + + /* We can only have one data source at a time. */ + g_return_if_fail(slpmsg->buffer == NULL); + g_return_if_fail(slpmsg->img == NULL); + g_return_if_fail(slpmsg->fp == NULL); + + slpmsg->fp = g_fopen(file_name, "rb"); + + if (g_stat(file_name, &st) == 0) + slpmsg->size = st.st_size; +} + +#ifdef MSN_DEBUG_SLP +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); +} +#endif + +MsnSlpMessage * +msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq, + const char *header, const char *branch, + const char *content_type, const char *content) +{ + MsnSlpLink *slplink; + MsnSlpMessage *slpmsg; + char *body; + gsize body_len; + gsize content_len; + + g_return_val_if_fail(slpcall != NULL, NULL); + g_return_val_if_fail(header != NULL, NULL); + + slplink = slpcall->slplink; + + /* Let's remember that "content" should end with a 0x00 */ + + content_len = (content != NULL) ? strlen(content) + 1 : 0; + + body = g_strdup_printf( + "%s\r\n" + "To: <msnmsgr:%s>\r\n" + "From: <msnmsgr:%s>\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: %s\r\n" + "Content-Length: %" G_GSIZE_FORMAT "\r\n" + "\r\n", + header, + slplink->remote_user, + slplink->local_user, + branch, + cseq, + slpcall->id, + content_type, + content_len); + + body_len = strlen(body); + + if (content_len > 0) + { + body_len += content_len; + body = g_realloc(body, body_len); + g_strlcat(body, content, body_len); + } + + slpmsg = msn_slpmsg_new(slplink); + msn_slpmsg_set_body(slpmsg, body, body_len); + + slpmsg->sip = TRUE; + slpmsg->slpcall = slpcall; + + g_free(body); + + return slpmsg; +}