static void ft_transfer_operation_callback (EmpathyTpFile *tp_file, const GError *error, gpointer user_data) { EmpathyFTHandler *handler = user_data; EmpathyFTHandlerPriv *priv = GET_PRIV (handler); DEBUG ("Transfer operation callback, error %p", error); if (error != NULL) { emit_error_signal (handler, error); } else { priv->is_completed = TRUE; g_signal_emit (handler, signals[TRANSFER_DONE], 0, tp_file); empathy_tp_file_close (tp_file); if (empathy_ft_handler_is_incoming (handler) && priv->use_hash) { check_hash_incoming (handler); } } }
static void ft_transfer_state_cb (TpFileTransferChannel *channel, GParamSpec *pspec, EmpathyFTHandler *handler) { EmpathyFTHandlerPriv *priv = handler->priv; TpFileTransferStateChangeReason reason; TpFileTransferState state = tp_file_transfer_channel_get_state ( channel, &reason); (void)pspec; /* suppress unused-parameter warning */ if (state == TP_FILE_TRANSFER_STATE_COMPLETED) { priv->is_completed = TRUE; g_signal_emit (handler, signals[TRANSFER_DONE], 0, channel); tp_channel_close_async (TP_CHANNEL (channel), NULL, NULL); if (empathy_ft_handler_is_incoming (handler) && priv->use_hash) { check_hash_incoming (handler); } } else if (state == TP_FILE_TRANSFER_STATE_CANCELLED) { GError *error = error_from_state_change_reason (reason); emit_error_signal (handler, error); g_clear_error (&error); } }
static void ft_transfer_accept_cb (GObject *source, GAsyncResult *result, gpointer user_data) { TpFileTransferChannel *channel = TP_FILE_TRANSFER_CHANNEL (source); EmpathyFTHandler *handler = user_data; GError *error = NULL; if (!tp_file_transfer_channel_accept_file_finish (channel, result, &error)) { emit_error_signal (handler, error); g_clear_error (&error); } }
static void ft_handler_read_async_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GFileInputStream *stream; GError *error = NULL; HashingData *hash_data; EmpathyFTHandler *handler = user_data; EmpathyFTHandlerPriv *priv = handler->priv; (void)source; /* suppress unused-parameter warning */ DEBUG ("GFile read async CB."); stream = g_file_read_finish (priv->gfile, res, &error); if (error != NULL) { emit_error_signal (handler, error); g_clear_error (&error); return; } hash_data = g_slice_new0 (HashingData); hash_data->stream = G_INPUT_STREAM (stream); hash_data->total_bytes = priv->total_bytes; hash_data->handler = g_object_ref (handler); /* FIXME: MD5 is the only ContentHashType supported right now */ hash_data->checksum = g_checksum_new (G_CHECKSUM_MD5); tp_asv_set_uint32 (priv->request, TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_HASH_TYPE, TP_FILE_HASH_TYPE_MD5); g_signal_emit (handler, signals[HASHING_STARTED], 0); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" g_io_scheduler_push_job (do_hash_job, hash_data, NULL, G_PRIORITY_DEFAULT, priv->cancellable); #pragma GCC diagnostic pop }
static void ft_handler_create_channel_cb (GObject *source, GAsyncResult *result, gpointer user_data) { EmpathyFTHandler *handler = user_data; EmpathyFTHandlerPriv *priv = handler->priv; GError *error = NULL; TpChannel *channel; DEBUG ("Dispatcher create channel CB"); channel = tp_account_channel_request_create_and_handle_channel_finish ( TP_ACCOUNT_CHANNEL_REQUEST (source), result, NULL, &error); if (channel == NULL) DEBUG ("Failed to request FT channel: %s", error->message); else g_cancellable_set_error_if_cancelled (priv->cancellable, &error); if (error != NULL) { emit_error_signal (handler, error); g_clear_object (&channel); g_error_free (error); return; } priv->channel = TP_FILE_TRANSFER_CHANNEL (channel); tp_g_signal_connect_object (priv->channel, "notify::state", G_CALLBACK (ft_transfer_state_cb), handler, 0); tp_g_signal_connect_object (priv->channel, "notify::transferred-bytes", G_CALLBACK (ft_transfer_transferred_bytes_cb), handler, 0); tp_file_transfer_channel_provide_file_async (priv->channel, priv->gfile, ft_transfer_provide_cb, handler); }
static void ft_handler_create_channel_cb (GObject *source, GAsyncResult *result, gpointer user_data) { EmpathyFTHandler *handler = user_data; EmpathyFTHandlerPriv *priv = GET_PRIV (handler); GError *error = NULL; TpChannel *channel = NULL; DEBUG ("Dispatcher create channel CB"); channel = tp_account_channel_request_create_and_handle_channel_finish ( TP_ACCOUNT_CHANNEL_REQUEST (source), result, NULL, &error); if (channel == NULL) DEBUG ("Failed to request FT channel: %s", error->message); else g_cancellable_set_error_if_cancelled (priv->cancellable, &error); if (error != NULL) { emit_error_signal (handler, error); g_error_free (error); goto out; } priv->tpfile = empathy_tp_file_new (channel); empathy_tp_file_offer (priv->tpfile, priv->gfile, priv->cancellable, ft_transfer_progress_callback, handler, ft_transfer_operation_callback, handler); out: tp_clear_object (&channel); }
static gboolean hash_job_done (gpointer user_data) { HashingData *hash_data = user_data; EmpathyFTHandler *handler = hash_data->handler; EmpathyFTHandlerPriv *priv; GError *error = NULL; DEBUG ("Closing stream after hashing."); priv = GET_PRIV (handler); if (hash_data->error != NULL) { error = hash_data->error; hash_data->error = NULL; goto cleanup; } DEBUG ("Got file hash %s", g_checksum_get_string (hash_data->checksum)); if (empathy_ft_handler_is_incoming (handler)) { if (g_strcmp0 (g_checksum_get_string (hash_data->checksum), priv->content_hash)) { DEBUG ("Hash mismatch when checking incoming handler: " "received %s, calculated %s", priv->content_hash, g_checksum_get_string (hash_data->checksum)); error = g_error_new_literal (EMPATHY_FT_ERROR_QUARK, EMPATHY_FT_ERROR_HASH_MISMATCH, _("File transfer completed, but the file was corrupted")); goto cleanup; } else { DEBUG ("Hash verification matched, received %s, calculated %s", priv->content_hash, g_checksum_get_string (hash_data->checksum)); } } else { /* set the checksum in the request... * org.freedesktop.Telepathy.Channel.Type.FileTransfer.ContentHash */ tp_asv_set_string (priv->request, TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_HASH, g_checksum_get_string (hash_data->checksum)); } cleanup: if (error != NULL) { emit_error_signal (handler, error); g_clear_error (&error); } else { g_signal_emit (handler, signals[HASHING_DONE], 0); if (!empathy_ft_handler_is_incoming (handler)) /* the request is complete now, push it to the dispatcher */ ft_handler_push_to_dispatcher (handler); } hash_data_free (hash_data); return FALSE; }