57 |
57 |
58 static void jingle_ft_init(void); |
58 static void jingle_ft_init(void); |
59 static void jingle_ft_uninit(void); |
59 static void jingle_ft_uninit(void); |
60 // Return must be free |
60 // Return must be free |
61 static gchar *_convert_size(guint64 size); |
61 static gchar *_convert_size(guint64 size); |
|
62 static int _next_index(void); |
|
63 static void _free(gconstpointer data); |
62 |
64 |
63 const gchar *deps[] = { "jingle", NULL }; |
65 const gchar *deps[] = { "jingle", NULL }; |
64 |
66 |
65 static GSList *info_list = NULL; |
67 static GSList *info_list = NULL; |
66 static guint jft_cid = 0; |
68 static guint jft_cid = 0; |
|
69 |
|
70 const gchar* strstate[] = { |
|
71 "PENDING", |
|
72 "STARTING", |
|
73 "ENDING", |
|
74 "REJECT", |
|
75 "ERROR" |
|
76 }; |
67 |
77 |
68 static JingleAppFuncs funcs = { |
78 static JingleAppFuncs funcs = { |
69 .check = check, |
79 .check = check, |
70 .handle = handle, |
80 .handle = handle, |
71 .tomessage = tomessage, |
81 .tomessage = tomessage, |
120 datestr = lm_message_node_get_attribute(node, "date"); |
130 datestr = lm_message_node_get_attribute(node, "date"); |
121 ft->hash = (gchar *) lm_message_node_get_attribute(node, "hash"); |
131 ft->hash = (gchar *) lm_message_node_get_attribute(node, "hash"); |
122 ft->name = (gchar *) lm_message_node_get_attribute(node, "name"); |
132 ft->name = (gchar *) lm_message_node_get_attribute(node, "name"); |
123 sizestr = lm_message_node_get_attribute(node, "size"); |
133 sizestr = lm_message_node_get_attribute(node, "size"); |
124 ft->transmit = 0; |
134 ft->transmit = 0; |
125 |
|
126 ft->dir = JINGLE_FT_INCOMING; |
135 ft->dir = JINGLE_FT_INCOMING; |
127 |
136 |
128 if (!ft->name || !sizestr) { |
137 if (!ft->name || !sizestr) { |
129 g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_MISSING, |
138 g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_MISSING, |
130 "an attribute of the file element is missing"); |
139 "an attribute of the file element is missing"); |
166 g_free(ft->name); |
175 g_free(ft->name); |
167 g_free(ft); |
176 g_free(ft); |
168 return NULL; |
177 return NULL; |
169 } |
178 } |
170 ft->hash = g_strndup(ft->hash, 32); |
179 ft->hash = g_strndup(ft->hash, 32); |
|
180 |
|
181 { |
|
182 JingleFTInfo *jfti = g_new0(JingleFTInfo, 1); |
|
183 jfti->index = _next_index(); |
|
184 jfti->jft = ft; |
|
185 info_list = g_slist_append(info_list, jfti); |
|
186 } |
171 |
187 |
172 return (gconstpointer) ft; |
188 return (gconstpointer) ft; |
173 } |
189 } |
174 |
190 |
175 static gboolean handle(JingleAction action, gconstpointer data, |
191 static gboolean handle(JingleAction action, gconstpointer data, |
224 jft->name); |
240 jft->name); |
225 //TODO: propagate the GError ? |
241 //TODO: propagate the GError ? |
226 g_error_free(err); |
242 g_error_free(err); |
227 return FALSE; |
243 return FALSE; |
228 } |
244 } |
|
245 jft->state = JINGLE_FT_STARTING; |
229 status = g_io_channel_set_encoding(jft->outfile, NULL, &err); |
246 status = g_io_channel_set_encoding(jft->outfile, NULL, &err); |
230 if (status != G_IO_STATUS_NORMAL || err != NULL) { |
247 if (status != G_IO_STATUS_NORMAL || err != NULL) { |
231 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message, |
248 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message, |
232 jft->name); |
249 jft->name); |
233 g_error_free(err); |
250 g_error_free(err); |
234 return FALSE; |
251 return FALSE; |
235 } |
252 } |
236 } |
253 } |
237 |
254 |
|
255 jft->state = JINGLE_FT_STARTING; |
|
256 |
238 status = g_io_channel_write_chars(jft->outfile, data, (gssize) len, |
257 status = g_io_channel_write_chars(jft->outfile, data, (gssize) len, |
239 &bytes_written, &err); |
258 &bytes_written, &err); |
240 if (status != G_IO_STATUS_NORMAL || err != NULL) { |
259 if (status != G_IO_STATUS_NORMAL || err != NULL) { |
241 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message, |
260 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message, |
242 jft->name); |
261 jft->name); |
328 jft->type = JINGLE_FT_OFFER; |
347 jft->type = JINGLE_FT_OFFER; |
329 jft->name = g_path_get_basename(filename); |
348 jft->name = g_path_get_basename(filename); |
330 jft->date = fileinfo.st_mtime; |
349 jft->date = fileinfo.st_mtime; |
331 jft->size = fileinfo.st_size; |
350 jft->size = fileinfo.st_size; |
332 jft->transmit = 0; |
351 jft->transmit = 0; |
|
352 jft->state = JINGLE_FT_PENDING; |
333 jft->dir = JINGLE_FT_OUTGOING; |
353 jft->dir = JINGLE_FT_OUTGOING; |
334 jft->outfile = g_io_channel_new_file (filename, "r", &err); |
354 jft->outfile = g_io_channel_new_file (filename, "r", &err); |
335 if (jft->outfile == NULL || err != NULL) { |
355 if (jft->outfile == NULL || err != NULL) { |
336 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message, |
356 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message, |
337 args[1]); |
357 args[1]); |
368 |
388 |
369 if (!info_list) |
389 if (!info_list) |
370 scr_LogPrint(LPRINT_LOGNORM, "JFT: no file"); |
390 scr_LogPrint(LPRINT_LOGNORM, "JFT: no file"); |
371 |
391 |
372 for (el = info_list; el; el = el->next) { |
392 for (el = info_list; el; el = el->next) { |
373 JingleFTInfo* jftio = el->data; |
393 JingleFTInfo *jftio = el->data; |
374 gchar *strsize = _convert_size(jftio->jft->size); |
394 gchar *strsize = _convert_size(jftio->jft->size); |
375 scr_LogPrint(LPRINT_LOGNORM, "[%i]%s %s %s %.2f%%: %s", jftio->index, |
395 scr_LogPrint(LPRINT_LOGNORM, "[%i]%s %s %s %.2f%%: %s %s", jftio->index, |
376 (jftio->jft->dir == JINGLE_FT_INCOMING)?"<==":"-->", |
396 (jftio->jft->dir == JINGLE_FT_INCOMING)?"<==":"-->", |
377 jftio->jft->name, strsize, |
397 jftio->jft->name, strsize, |
378 (gfloat)jftio->jft->transmit/(gfloat)jftio->jft->size * 100, |
398 (gfloat)jftio->jft->transmit/(gfloat)jftio->jft->size * 100, |
379 jftio->jft->desc); |
399 jftio->jft->desc?jftio->jft->desc:"", |
|
400 strstate[jftio->jft->state]); |
380 g_free(strsize); |
401 g_free(strsize); |
381 } |
402 } |
382 |
403 } else if (!g_strcmp0(args[0], "flush")) { |
|
404 GSList *el, *el2 = NULL; |
|
405 int count = 0; |
|
406 for (el = info_list; el; el = el -> next) { |
|
407 JingleFTInfo *jftio = el->data; |
|
408 if (jftio->jft->state == JINGLE_FT_ERROR || |
|
409 jftio->jft->state == JINGLE_FT_REJECT || |
|
410 jftio->jft->state == JINGLE_FT_ENDING) { |
|
411 g_slist_free_1(el2); |
|
412 count++; |
|
413 _free(jftio->jft); |
|
414 info_list = g_slist_remove(info_list, jftio); |
|
415 el2 = el; |
|
416 } |
|
417 } |
|
418 g_slist_free_1(el2); |
|
419 scr_LogPrint(LPRINT_LOGNORM, "JFT: %i files removed", count); |
|
420 } else { |
|
421 scr_LogPrint(LPRINT_LOGNORM, "/jft: %s is not a correct option.", args[1]); |
383 } |
422 } |
384 |
423 |
385 free_arg_lst(args); |
424 free_arg_lst(args); |
|
425 } |
|
426 |
|
427 static void _free(gconstpointer data) |
|
428 { |
|
429 JingleFT *jft = (JingleFT *)data; |
|
430 g_free(jft->hash); |
|
431 g_free(jft->name); |
|
432 g_free(jft->desc); |
|
433 g_io_channel_unref(jft->outfile); |
|
434 if (jft->dir == JINGLE_FT_INCOMING) |
|
435 g_checksum_free(jft->md5); |
|
436 g_free(jft); |
386 } |
437 } |
387 |
438 |
388 static void tomessage(gconstpointer data, LmMessageNode *node) |
439 static void tomessage(gconstpointer data, LmMessageNode *node) |
389 { |
440 { |
390 JingleFT *jft = (JingleFT*) data; |
441 JingleFT *jft = (JingleFT*) data; |
422 lm_message_node_add_child(node2, "desc", jft->desc); |
473 lm_message_node_add_child(node2, "desc", jft->desc); |
423 |
474 |
424 //if (jft->data != 0) |
475 //if (jft->data != 0) |
425 } |
476 } |
426 |
477 |
427 static void send_hash(gchar *sid, gchar *to, gchar *hash) |
478 static void send_hash(const gchar *sid, const gchar *to, const gchar *hash) |
428 { |
479 { |
429 JingleAckHandle *ackhandle; |
480 JingleAckHandle *ackhandle; |
430 GError *err = NULL; |
481 GError *err = NULL; |
431 gboolean ret; |
482 gboolean ret; |
432 |
483 |
538 } |
589 } |
539 |
590 |
540 SessionContent *sc2 = session_find_sessioncontent(sess, sc->name); |
591 SessionContent *sc2 = session_find_sessioncontent(sess, sc->name); |
541 |
592 |
542 jft = (JingleFT*)sc2->description; |
593 jft = (JingleFT*)sc2->description; |
543 |
594 jft->state = JINGLE_FT_STARTING; |
544 jft->md5 = g_checksum_new(G_CHECKSUM_MD5); |
595 jft->md5 = g_checksum_new(G_CHECKSUM_MD5); |
545 |
596 |
546 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: Transfer start (%s)", |
597 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: Transfer start (%s)", |
547 jft->name); |
598 jft->name); |
548 |
599 |
554 { |
605 { |
555 JingleFT *jft = (JingleFT*)data; |
606 JingleFT *jft = (JingleFT*)data; |
556 GError *err = NULL; |
607 GError *err = NULL; |
557 GIOStatus status; |
608 GIOStatus status; |
558 |
609 |
|
610 jft->state = JINGLE_FT_ENDING; |
559 if (jft->outfile != NULL) { |
611 if (jft->outfile != NULL) { |
560 status = g_io_channel_flush(jft->outfile, &err); |
612 status = g_io_channel_shutdown(jft->outfile, TRUE, &err); |
561 if (status != G_IO_STATUS_NORMAL || err != NULL) { |
613 if (status != G_IO_STATUS_NORMAL || err != NULL) { |
562 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s", |
614 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s", |
563 err->message); |
615 err->message); |
564 g_error_free(err); |
616 g_error_free(err); |
565 } |
617 } |
566 g_io_channel_unref(jft->outfile); |
|
567 } |
618 } |
568 |
619 |
569 if (jft->hash != NULL && jft->md5 != NULL) { |
620 if (jft->hash != NULL && jft->md5 != NULL) { |
570 if (g_strcmp0(jft->hash, g_checksum_get_string(jft->md5))) { |
621 if (g_strcmp0(jft->hash, g_checksum_get_string(jft->md5))) { |
571 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: File corrupt (%s)", |
622 scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: File corrupt (%s)", |
617 jft_cid = compl_new_category(); |
665 jft_cid = compl_new_category(); |
618 if (jft_cid) { |
666 if (jft_cid) { |
619 compl_add_category_word(jft_cid, "send"); |
667 compl_add_category_word(jft_cid, "send"); |
620 //compl_add_category_word(jft_cid, "request"); |
668 //compl_add_category_word(jft_cid, "request"); |
621 compl_add_category_word(jft_cid, "info"); |
669 compl_add_category_word(jft_cid, "info"); |
|
670 compl_add_category_word(jft_cid, "flush"); |
622 } |
671 } |
623 /* Add command */ |
672 /* Add command */ |
624 cmd_add("jft", "Manage file transfer", jft_cid, 0, do_sendfile, NULL); |
673 cmd_add("jft", "Manage file transfer", jft_cid, 0, do_sendfile, NULL); |
625 } |
674 } |
626 |
675 |
627 static void jingle_ft_uninit(void) |
676 static void jingle_ft_uninit(void) |
628 { |
677 { |
|
678 g_slist_free(info_list); |
629 xmpp_del_feature(NS_JINGLE_APP_FT); |
679 xmpp_del_feature(NS_JINGLE_APP_FT); |
630 jingle_unregister_app(NS_JINGLE_APP_FT); |
680 jingle_unregister_app(NS_JINGLE_APP_FT); |
631 cmd_del("file"); |
681 cmd_del("file"); |
632 if (jft_cid) |
682 if (jft_cid) |
633 compl_del_category(jft_cid); |
683 compl_del_category(jft_cid); |