31 #include <mcabber/hooks.h> |
32 #include <mcabber/hooks.h> |
32 |
33 |
33 #include <jingle/jingle.h> |
34 #include <jingle/jingle.h> |
34 #include <jingle/check.h> |
35 #include <jingle/check.h> |
35 #include <jingle/register.h> |
36 #include <jingle/register.h> |
|
37 #include <jingle/sessions.h> |
36 |
38 |
37 #include "ibb.h" |
39 #include "ibb.h" |
38 |
40 |
39 static LmMessageHandler* jingle_ibb_handler = NULL; |
41 static LmMessageHandler* jingle_ibb_handler = NULL; |
40 |
42 |
41 gconstpointer jingle_ibb_check(JingleContent *cn, GError **err); |
43 gconstpointer jingle_ibb_check(JingleContent *cn, GError **err); |
42 gboolean jingle_ibb_cmp(gconstpointer data1, gconstpointer data2); |
44 gboolean jingle_ibb_cmp(gconstpointer data1, gconstpointer data2); |
43 void jingle_ibb_tomessage(gconstpointer data, LmMessageNode *node); |
45 void jingle_ibb_tomessage(gconstpointer data, LmMessageNode *node); |
44 const gchar* jingle_ibb_xmlns(void); |
46 const gchar* jingle_ibb_xmlns(void); |
45 gconstpointer jingle_ibb_new(void); |
47 gconstpointer jingle_ibb_new(void); |
46 void jingle_ibb_send(session_content *sc, const gchar *to, gconstpointer data, gchar *buf, gsize size); |
48 void jingle_ibb_send(session_content *sc, gconstpointer data, gchar *buf, gsize size); |
|
49 static void _send_internal(session_content *sc, const gchar *to, gchar *buf, |
|
50 gsize size, const gchar *sid, gint64 *seq); |
47 |
51 |
48 static void jingle_ibb_init(void); |
52 static void jingle_ibb_init(void); |
49 static void jingle_ibb_uninit(void); |
53 static void jingle_ibb_uninit(void); |
50 |
54 |
51 static guint connect_hid = 0; |
55 static guint connect_hid = 0; |
101 |
105 |
102 // the size attribute is a xs:short an therefore can be negative. |
106 // the size attribute is a xs:short an therefore can be negative. |
103 if (ibb->blocksize < 0 || ibb->blocksize > IBB_BLOCK_SIZE_MAX) { |
107 if (ibb->blocksize < 0 || ibb->blocksize > IBB_BLOCK_SIZE_MAX) { |
104 g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_BADVALUE, |
108 g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_BADVALUE, |
105 "block-size is negative"); |
109 "block-size is negative"); |
|
110 g_free(ibb->sid); |
106 g_free(ibb); |
111 g_free(ibb); |
107 return NULL; |
112 return NULL; |
108 } |
113 } |
109 |
114 |
110 return (gconstpointer) ibb; |
115 return (gconstpointer) ibb; |
111 } |
116 } |
112 |
117 |
113 LmHandlerResult jingle_ibb_handle_iq(LmMessageHandler *handler, |
118 LmHandlerResult jingle_ibb_handle_iq(LmMessageHandler *handler, |
114 LmConnection *connection, LmMessage *message, |
119 LmConnection *connection, LmMessage *message, |
190 |
195 |
191 void jingle_ibb_tomessage(gconstpointer data, LmMessageNode *node) |
196 void jingle_ibb_tomessage(gconstpointer data, LmMessageNode *node) |
192 { |
197 { |
193 JingleIBB *jibb = (JingleIBB*) data; |
198 JingleIBB *jibb = (JingleIBB*) data; |
194 gchar *bsize = g_strdup_printf("%i", jibb->blocksize); |
199 gchar *bsize = g_strdup_printf("%i", jibb->blocksize); |
|
200 |
195 if (lm_message_node_get_child(node, "transport") != NULL) |
201 if (lm_message_node_get_child(node, "transport") != NULL) |
196 return; |
202 return; |
197 |
203 |
198 LmMessageNode *node2 = lm_message_node_add_child(node, "transport", NULL); |
204 LmMessageNode *node2 = lm_message_node_add_child(node, "transport", NULL); |
199 |
205 |
205 } |
211 } |
206 |
212 |
207 static void jingle_ibb_handle_ack_iq_send(LmMessage *mess, gpointer data) |
213 static void jingle_ibb_handle_ack_iq_send(LmMessage *mess, gpointer data) |
208 { |
214 { |
209 // TODO: check the sub type (error ??) |
215 // TODO: check the sub type (error ??) |
210 handle_trans_next((session_content*)data); |
216 session_content *sc = (session_content *)data; |
211 } |
217 JingleSession *sess = session_find_by_sid(sc->sid, sc->from); |
212 |
218 SessionContent *sc2 = session_find_sessioncontent(sess, sc->name); |
213 void jingle_ibb_send(session_content *sc, const gchar *to, gconstpointer data, gchar *buf, gsize size) |
219 |
214 { |
220 JingleIBB *jibb = (JingleIBB *)sc2->transport; |
215 JingleIBB *jibb = (JingleIBB*)data; |
221 |
|
222 // We look if there is enough data staying |
|
223 if (jibb->dataleft > jibb->blocksize) { |
|
224 gchar *buf = g_memdup(jibb->buf, jibb->blocksize); |
|
225 jibb->dataleft-=jibb->blocksize; |
|
226 g_memmove(jibb->buf, jibb->buf+jibb->blocksize, jibb->dataleft); |
|
227 _send_internal(sc, sess->to, buf, jibb->blocksize, sess->sid, &jibb->seq); |
|
228 g_free(buf); |
|
229 } else { // ask for more data |
|
230 handle_trans_next(sc); |
|
231 } |
|
232 } |
|
233 |
|
234 static void _send_internal(session_content *sc, const gchar *to, gchar *buf, |
|
235 gsize size, const gchar *sid, gint64 *seq) |
|
236 { |
216 JingleAckHandle *ackhandle; |
237 JingleAckHandle *ackhandle; |
217 LmMessageNode *node; |
238 LmMessage *r = lm_message_new_with_sub_type(to, LM_MESSAGE_TYPE_IQ, |
|
239 LM_MESSAGE_SUB_TYPE_SET); |
|
240 LmMessageNode *node = lm_message_get_node(r); |
|
241 |
218 gchar *base64 = g_base64_encode((const guchar *)buf, size); |
242 gchar *base64 = g_base64_encode((const guchar *)buf, size); |
219 gchar *seq = g_strdup_printf("%" G_GINT64_FORMAT, jibb->seq); |
243 gchar *strseq = g_strdup_printf("%" G_GINT64_FORMAT, *seq); |
220 |
244 |
221 LmMessage *r = lm_message_new_with_sub_type(to, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET); |
245 node = lm_message_node_add_child(node, "data", NULL); |
222 LmMessageNode *node2 = lm_message_get_node(r); |
|
223 node = lm_message_node_add_child(node2, "data", NULL); |
|
224 lm_message_node_set_attributes(node, "xmlns", NS_TRANSPORT_IBB, |
246 lm_message_node_set_attributes(node, "xmlns", NS_TRANSPORT_IBB, |
225 "sid", jibb->sid, |
247 "sid", sid, |
226 "seq", seq, |
248 "seq", strseq, |
227 NULL); |
249 NULL); |
228 lm_message_node_set_value(node, base64); |
250 lm_message_node_set_value(node, base64); |
229 |
251 |
230 ackhandle = g_new0(JingleAckHandle, 1); |
252 ackhandle = g_new0(JingleAckHandle, 1); |
231 ackhandle->callback = jingle_ibb_handle_ack_iq_send; |
253 ackhandle->callback = jingle_ibb_handle_ack_iq_send; |
234 lm_connection_send_with_reply(lconnection, r, |
256 lm_connection_send_with_reply(lconnection, r, |
235 jingle_new_ack_handler(ackhandle), NULL); |
257 jingle_new_ack_handler(ackhandle), NULL); |
236 lm_message_unref(r); |
258 lm_message_unref(r); |
237 |
259 |
238 // The next packet will be seq++ |
260 // The next packet will be seq++ |
239 jibb->seq++; |
261 ++(*seq); |
240 |
262 |
241 g_free(base64); |
263 g_free(base64); |
|
264 g_free(strseq); |
|
265 } |
|
266 |
|
267 void jingle_ibb_send(session_content *sc, gconstpointer data, gchar *buf, |
|
268 gsize size) |
|
269 { |
|
270 JingleIBB *jibb = (JingleIBB*)data; |
|
271 |
|
272 if (jibb->size_buf >= size + jibb->dataleft) { |
|
273 g_memmove(jibb->buf + jibb->dataleft, buf, size); |
|
274 jibb->dataleft+=size; |
|
275 } else { |
|
276 jibb->size_buf = size + jibb->dataleft; |
|
277 jibb->buf = g_realloc(jibb->buf, jibb->size_buf); |
|
278 g_memmove(jibb->buf + jibb->dataleft, buf, size); |
|
279 jibb->dataleft = jibb->size_buf; |
|
280 } |
|
281 |
|
282 // We need more data |
|
283 if (jibb->dataleft < jibb->blocksize) { |
|
284 handle_trans_next(sc); |
|
285 return; |
|
286 } |
|
287 |
|
288 // It's enough |
|
289 { |
|
290 JingleSession *sess = session_find_by_sid(sc->sid, sc->from); |
|
291 |
|
292 gchar *buffer = g_memdup(jibb->buf, jibb->blocksize); |
|
293 |
|
294 jibb->dataleft-=jibb->blocksize; |
|
295 |
|
296 g_memmove(jibb->buf, jibb->buf+jibb->blocksize, jibb->dataleft); |
|
297 |
|
298 _send_internal(sc, sess->to, buffer, jibb->blocksize, sess->sid, &jibb->seq); |
|
299 |
|
300 g_free(buf); |
|
301 } |
242 } |
302 } |
243 |
303 |
244 static void jingle_ibb_unregister_lm_handlers(void) |
304 static void jingle_ibb_unregister_lm_handlers(void) |
245 { |
305 { |
246 if (lconnection) { |
306 if (lconnection) { |