comparison libpurple/protocols/msn/slpmsg_part.c @ 31292:47b6eda87723

propagate from branch 'im.pidgin.pidgin' (head 07d0765c444a097af45c2650f54323afb900a07b) to branch 'im.pidgin.soc.2010.msn-tlc' (head f3998422a4724ab424e4e2328f58fc0504856557)
author masca@cpw.pidgin.im
date Mon, 19 Jul 2010 21:11:32 +0000
parents e358e16e527f
children 5ad928319db0
comparison
equal deleted inserted replaced
30698:e874875a74a7 31292:47b6eda87723
1 #include "internal.h"
2 #include "debug.h"
3
4 #include "slpmsg.h"
5 #include "slpmsg_part.h"
6
7 MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PHeader *header, MsnP2PFooter *footer)
8 {
9 MsnSlpMessagePart *part;
10
11 part = g_new0(MsnSlpMessagePart, 1);
12
13 if (header)
14 part->header = g_memdup(header, P2P_PACKET_HEADER_SIZE);
15 if (footer)
16 part->footer = g_memdup(footer, P2P_PACKET_FOOTER_SIZE);
17
18 part->ack_cb = msn_slpmsgpart_ack;
19 part->nak_cb = msn_slpmsgpart_nak;
20
21 return msn_slpmsgpart_ref(part);
22 }
23
24 MsnSlpMessagePart *msn_slpmsgpart_new_from_data(const char *data, size_t data_len)
25 {
26 MsnSlpMessagePart *part;
27 MsnP2PHeader *header;
28 const char *tmp;
29 int body_len;
30
31 tmp = data;
32 part = msn_slpmsgpart_new(NULL, NULL);
33
34 if (data_len < sizeof(*header)) {
35 return NULL;
36 }
37
38 /* Extract the binary SLP header */
39 part->header = msn_p2p_header_from_wire((MsnP2PHeader*)tmp);
40 tmp += P2P_PACKET_HEADER_SIZE;
41
42 /* Extract the body */
43 body_len = data_len - P2P_PACKET_HEADER_SIZE - P2P_PACKET_FOOTER_SIZE;
44 /* msg->body_len = msg->msnslp_header.length; */
45
46 if (body_len > 0) {
47 part->size = body_len;
48 part->buffer = g_malloc(body_len);
49 memcpy(part->buffer, tmp, body_len);
50 tmp += body_len;
51 }
52
53 /* Extract the footer */
54 if (body_len >= 0)
55 part->footer = msn_p2p_footer_from_wire((MsnP2PFooter*)tmp);
56
57 return part;
58 }
59
60 void msn_slpmsgpart_destroy(MsnSlpMessagePart *part)
61 {
62 if (!part)
63 return;
64
65 if (part->ref_count > 0) {
66 msn_slpmsgpart_unref(part);
67
68 return;
69 }
70
71 g_free(part->header);
72 g_free(part->footer);
73
74 g_free(part);
75
76 }
77
78 MsnSlpMessagePart *msn_slpmsgpart_ref(MsnSlpMessagePart *part)
79 {
80 g_return_val_if_fail(part != NULL, NULL);
81 part->ref_count ++;
82
83 if (purple_debug_is_verbose())
84 purple_debug_info("msn", "part ref (%p)[%" G_GSIZE_FORMAT "]\n", part, part->ref_count);
85
86 return part;
87 }
88
89 MsnSlpMessagePart *msn_slpmsgpart_unref(MsnSlpMessagePart *part)
90 {
91 g_return_val_if_fail(part != NULL, NULL);
92 g_return_val_if_fail(part->ref_count > 0, NULL);
93
94 part->ref_count--;
95
96 if (purple_debug_is_verbose())
97 purple_debug_info("msn", "part unref (%p)[%" G_GSIZE_FORMAT "]\n", part, part->ref_count);
98
99 if (part->ref_count == 0) {
100 msn_slpmsgpart_destroy(part);
101
102 return NULL;
103 }
104
105 return part;
106 }
107
108 void msn_slpmsgpart_set_bin_data(MsnSlpMessagePart *part, const void *data, size_t len)
109 {
110 g_return_if_fail(part != NULL);
111
112 if (part->buffer != NULL)
113 g_free(part->buffer);
114
115 if (data != NULL && len > 0) {
116 part->buffer = g_malloc(len + 1);
117 memcpy(part->buffer, data, len);
118 part->buffer[len] = '\0';
119 part->size = len;
120 } else {
121 part->buffer = NULL;
122 part->size = 0;
123 }
124
125 }
126
127 char *msn_slpmsgpart_serialize(MsnSlpMessagePart *part, size_t *ret_size)
128 {
129 MsnP2PHeader *header;
130 MsnP2PFooter *footer;
131 char *base;
132 char *tmp;
133 size_t siz;
134
135 base = g_malloc(P2P_PACKET_HEADER_SIZE + part->size + sizeof(MsnP2PFooter));
136 tmp = base;
137
138 header = msn_p2p_header_to_wire(part->header);
139 footer = msn_p2p_footer_to_wire(part->footer);
140
141 siz = sizeof(MsnP2PHeader);
142 /* Copy header */
143 memcpy(tmp, (char*)header, siz);
144 tmp += siz;
145
146 /* Copy body */
147 memcpy(tmp, part->buffer, part->size);
148 tmp += part->size;
149
150 /* Copy footer */
151 siz = sizeof(MsnP2PFooter);
152 memcpy(tmp, (char*)footer, siz);
153 tmp += siz;
154
155 *ret_size = tmp - base;
156
157 return base;
158 }
159 /* We have received the message ack */
160 void
161 msn_slpmsgpart_ack(MsnSlpMessagePart *part, void *data)
162 {
163 MsnSlpMessage *slpmsg;
164 long long real_size;
165
166 slpmsg = data;
167
168 real_size = (slpmsg->flags == P2P_ACK) ? 0 : slpmsg->size;
169
170 slpmsg->offset += part->header->length;
171
172 slpmsg->parts = g_list_remove(slpmsg->parts, part);
173
174 if (slpmsg->offset < real_size)
175 {
176 if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
177 {
178 slpmsg->slpcall->xfer_msg = slpmsg;
179 purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
180 }
181 else
182 msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
183 }
184 else
185 {
186 /* The whole message has been sent */
187 if (slpmsg->flags == P2P_MSN_OBJ_DATA ||
188 slpmsg->flags == (P2P_WML2009_COMP | P2P_MSN_OBJ_DATA) ||
189 slpmsg->flags == P2P_FILE_DATA)
190 {
191 if (slpmsg->slpcall != NULL)
192 {
193 if (slpmsg->slpcall->cb)
194 slpmsg->slpcall->cb(slpmsg->slpcall,
195 NULL, 0);
196 }
197 }
198 }
199 }
200
201 /* We have received the message nak. */
202 void
203 msn_slpmsgpart_nak(MsnSlpMessagePart *part, void *data)
204 {
205 MsnSlpMessage *slpmsg;
206
207 slpmsg = data;
208
209 msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
210
211 slpmsg->parts = g_list_remove(slpmsg->parts, part);
212 }