summaryrefslogtreecommitdiff
path: root/libpurple/protocols/msn/slpmsg_part.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpurple/protocols/msn/slpmsg_part.c')
-rw-r--r--libpurple/protocols/msn/slpmsg_part.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/libpurple/protocols/msn/slpmsg_part.c b/libpurple/protocols/msn/slpmsg_part.c
new file mode 100644
index 0000000000..d89a878a67
--- /dev/null
+++ b/libpurple/protocols/msn/slpmsg_part.c
@@ -0,0 +1,210 @@
+#include "internal.h"
+#include "debug.h"
+
+#include "slpmsg.h"
+#include "slpmsg_part.h"
+
+MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PHeader *header, MsnP2PFooter *footer)
+{
+ MsnSlpMessagePart *part;
+
+ part = g_new0(MsnSlpMessagePart, 1);
+
+ if (header)
+ part->header = g_memdup(header, P2P_PACKET_HEADER_SIZE);
+ if (footer)
+ part->footer = g_memdup(footer, P2P_PACKET_FOOTER_SIZE);
+
+ part->ack_cb = msn_slpmsgpart_ack;
+ part->nak_cb = msn_slpmsgpart_nak;
+
+ return msn_slpmsgpart_ref(part);
+}
+
+MsnSlpMessagePart *msn_slpmsgpart_new_from_data(const char *data, size_t data_len)
+{
+ MsnSlpMessagePart *part;
+ MsnP2PHeader *header;
+ const char *tmp;
+ int body_len;
+
+ tmp = data;
+ part = msn_slpmsgpart_new(NULL, NULL);
+
+ if (data_len < sizeof(*header)) {
+ return NULL;
+ }
+
+ /* Extract the binary SLP header */
+ part->header = msn_p2p_header_from_wire((MsnP2PHeader*)tmp);
+ tmp += P2P_PACKET_HEADER_SIZE;
+
+ /* Extract the body */
+ body_len = data_len - P2P_PACKET_HEADER_SIZE - P2P_PACKET_FOOTER_SIZE;
+ /* msg->body_len = msg->msnslp_header.length; */
+
+ if (body_len > 0) {
+ part->size = body_len;
+ part->buffer = g_malloc(body_len);
+ memcpy(part->buffer, tmp, body_len);
+ tmp += body_len;
+ }
+
+ /* Extract the footer */
+ if (body_len >= 0)
+ part->footer = msn_p2p_footer_from_wire((MsnP2PFooter*)tmp);
+
+ return part;
+}
+
+void msn_slpmsgpart_destroy(MsnSlpMessagePart *part)
+{
+ if (!part)
+ return;
+
+ if (part->ref_count > 0) {
+ msn_slpmsgpart_unref(part);
+
+ return;
+ }
+
+ g_free(part->header);
+ g_free(part->footer);
+
+ g_free(part);
+
+}
+
+MsnSlpMessagePart *msn_slpmsgpart_ref(MsnSlpMessagePart *part)
+{
+ g_return_val_if_fail(part != NULL, NULL);
+ part->ref_count ++;
+
+ if (purple_debug_is_verbose())
+ purple_debug_info("msn", "part ref (%p)[%d]\n", part, part->ref_count);
+
+ return part;
+}
+
+MsnSlpMessagePart *msn_slpmsgpart_unref(MsnSlpMessagePart *part)
+{
+ g_return_val_if_fail(part != NULL, NULL);
+ g_return_val_if_fail(part->ref_count > 0, NULL);
+
+ part->ref_count--;
+
+ if (purple_debug_is_verbose())
+ purple_debug_info("msn", "part unref (%p)[%d]\n", part, part->ref_count);
+
+ if (part->ref_count == 0) {
+ msn_slpmsgpart_destroy(part);
+
+ return NULL;
+ }
+
+ return part;
+}
+
+void msn_slpmsgpart_set_bin_data(MsnSlpMessagePart *part, const void *data, size_t len)
+{
+ g_return_if_fail(part != NULL);
+
+ if (part->buffer != NULL)
+ g_free(part->buffer);
+
+ if (data != NULL && len > 0) {
+ part->buffer = g_malloc(len + 1);
+ memcpy(part->buffer, data, len);
+ part->buffer[len] = '\0';
+ part->size = len;
+ } else {
+ part->buffer = NULL;
+ part->size = 0;
+ }
+
+}
+
+char *msn_slpmsgpart_serialize(MsnSlpMessagePart *part, size_t *ret_size)
+{
+ MsnP2PHeader *header;
+ MsnP2PFooter *footer;
+ char *base;
+ char *tmp;
+ size_t siz;
+
+ base = g_malloc(P2P_PACKET_HEADER_SIZE + part->size + sizeof(MsnP2PFooter));
+ tmp = base;
+
+ header = msn_p2p_header_to_wire(part->header);
+ footer = msn_p2p_footer_to_wire(part->footer);
+
+ siz = sizeof(MsnP2PHeader);
+ /* Copy header */
+ memcpy(tmp, (char*)header, siz);
+ tmp += siz;
+
+ /* Copy body */
+ memcpy(tmp, part->buffer, part->size);
+ tmp += part->size;
+
+ /* Copy footer */
+ siz = sizeof(MsnP2PFooter);
+ memcpy(tmp, (char*)footer, siz);
+ tmp += siz;
+
+ *ret_size = tmp - base;
+
+ return base;
+}
+/* We have received the message ack */
+void
+msn_slpmsgpart_ack(MsnSlpMessagePart *part, void *data)
+{
+ MsnSlpMessage *slpmsg;
+ long long real_size;
+
+ slpmsg = data;
+
+ real_size = (slpmsg->header->flags == P2P_ACK) ? 0 : slpmsg->size;
+
+ slpmsg->header->offset += part->header->length;
+
+ slpmsg->parts = g_list_remove(slpmsg->parts, part);
+
+ if (slpmsg->header->offset < real_size)
+ {
+ if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
+ {
+ slpmsg->slpcall->xfer_msg = slpmsg;
+ purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
+ }
+ else
+ msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
+ }
+ else
+ {
+ /* The whole message has been sent */
+ if (msn_p2p_msg_is_data(slpmsg->header->flags))
+ {
+ if (slpmsg->slpcall != NULL)
+ {
+ if (slpmsg->slpcall->cb)
+ slpmsg->slpcall->cb(slpmsg->slpcall,
+ NULL, 0);
+ }
+ }
+ }
+}
+
+/* We have received the message nak. */
+void
+msn_slpmsgpart_nak(MsnSlpMessagePart *part, void *data)
+{
+ MsnSlpMessage *slpmsg;
+
+ slpmsg = data;
+
+ msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
+
+ slpmsg->parts = g_list_remove(slpmsg->parts, part);
+}