[Libreoffice-commits] .: Branch 'feature/tubes2' - 3 commits - tubes/inc tubes/qa tubes/source

Will Thompson wjt at kemper.freedesktop.org
Fri Mar 23 02:00:12 PDT 2012


 tubes/inc/tubes/conference.hxx         |    2 
 tubes/inc/tubes/file-transfer-helper.h |    3 
 tubes/inc/tubes/manager.hxx            |    9 ++
 tubes/qa/test_manager.cxx              |   30 ++++++
 tubes/source/conference.cxx            |    5 -
 tubes/source/file-transfer-helper.c    |   29 +++++-
 tubes/source/manager.cxx               |  148 +++++++++++++++++++++++++++++++--
 7 files changed, 212 insertions(+), 14 deletions(-)

New commits:
commit 7b662a91f6452f22265fb99ff782539f43dd2095
Author: Will Thompson <will.thompson at collabora.co.uk>
Date:   Fri Mar 23 08:57:52 2012 +0000

    tubes: remove "account without account??" warning
    
    It's completely kosher for Telepathy accounts not to have a parameter
    called 'account' (which really means 'username'): Salut (link-local
    XMPP) accounts do not, for example, because you don't need to specify a
    username.
    
    tp_account_get_normalized_name() gets your contact ID for an account,
    which is really what we're looking for here.

diff --git a/tubes/source/manager.cxx b/tubes/source/manager.cxx
index b479d5d..cb9e5d7 100644
--- a/tubes/source/manager.cxx
+++ b/tubes/source/manager.cxx
@@ -668,9 +668,7 @@ TpAccount* TeleManager::getAccount( const rtl::OString& rAccountID )
     for (GList* pA = pAccounts; pA; pA = pA->next)
     {
         TpAccount* pAcc = TP_ACCOUNT( pA->data);
-        const GHashTable* pPar = tp_account_get_parameters( pAcc);
-        const gchar* pID = tp_asv_get_string( pPar, "account");
-        SAL_WARN_IF( !pID, "tubes", "TeleManager::getMyAccount: account without account??");
+        const gchar* pID = tp_account_get_normalized_name( pAcc);
         if (pID && rAccountID == pID)
         {
             pAccount = pAcc;
commit 25c39927fd338283d2441694eb00b7e595b68f4c
Author: Will Thompson <will.thompson at collabora.co.uk>
Date:   Fri Mar 23 08:53:21 2012 +0000

    tubes: implement receiving files.

diff --git a/tubes/inc/tubes/conference.hxx b/tubes/inc/tubes/conference.hxx
index 7428bcb..7c5fd30 100644
--- a/tubes/inc/tubes/conference.hxx
+++ b/tubes/inc/tubes/conference.hxx
@@ -94,6 +94,8 @@ public:
                                 { return mbTubeChannelStateChangedHandlerInvoked; }
     void                    setTubeChannelState( TpTubeChannelState eState ) { meTubeChannelState = eState; }
 
+    static void             FTReady( EmpathyFTHandler *handler, GError *error, gpointer user_data);
+
 private:
 
     rtl::OString            maSessionId;
diff --git a/tubes/inc/tubes/file-transfer-helper.h b/tubes/inc/tubes/file-transfer-helper.h
index fe0678f..8960d14 100644
--- a/tubes/inc/tubes/file-transfer-helper.h
+++ b/tubes/inc/tubes/file-transfer-helper.h
@@ -90,6 +90,9 @@ void empathy_ft_handler_new_outgoing (
     gint64 action_time,
     EmpathyFTHandlerReadyCallback callback,
     gpointer user_data);
+void empathy_ft_handler_set_service_name (
+    EmpathyFTHandler *self,
+    const gchar *service_name);
 
 void empathy_ft_handler_new_incoming (TpFileTransferChannel *channel,
     EmpathyFTHandlerReadyCallback callback,
diff --git a/tubes/inc/tubes/manager.hxx b/tubes/inc/tubes/manager.hxx
index 97f5de8..0d2ef3e 100644
--- a/tubes/inc/tubes/manager.hxx
+++ b/tubes/inc/tubes/manager.hxx
@@ -140,6 +140,9 @@ public:
 
     void                    sendFile( rtl::OUString &localUri, TeleConference::FileSentCallback pCallback, void* pUserData);
 
+    typedef void          (*FileReceivedCallback)( rtl::OUString &localUri, void* pUserData );
+    void                    setFileReceivedCallback( FileReceivedCallback callback, void* pUserData );
+
     /// Only for use with MainLoopFlusher
     GMainLoop*              getMainLoop() const;
 
@@ -197,6 +200,9 @@ public:
 
     TpAccount*              getAccount( const rtl::OString& rAccountID );
 
+/* Callbacks; not for use outside this class. */
+    static void             TransferDone( EmpathyFTHandler *handler, TpFileTransferChannel *, gpointer user_data);
+
 private:
 
     TeleConferenceVector    maConferences;
@@ -207,6 +213,9 @@ private:
     static sal_uInt32       nRefCount;
     static rtl::OString     aNameSuffix;
 
+    FileReceivedCallback    mpFileReceivedCallback;
+    void                   *mpFileReceivedCallbackData;
+
     friend class TeleManagerImpl;   // access to mutex
 
     TUBES_DLLPRIVATE static ::osl::Mutex&   GetMutex();
diff --git a/tubes/qa/test_manager.cxx b/tubes/qa/test_manager.cxx
index d08190d..540728a 100644
--- a/tubes/qa/test_manager.cxx
+++ b/tubes/qa/test_manager.cxx
@@ -70,6 +70,7 @@ public:
     void spinMainLoop();
 
     static void FileSent( bool success, void *user_data);
+    static void FileReceived( rtl::OUString& aUri, void *user_data);
 
     // Order is significant.
     CPPUNIT_TEST_SUITE( TestTeleTubes );
@@ -102,6 +103,7 @@ private:
     rtl::OString              maAccepterIdentifier;
 
     bool                      maFileSentSuccess;
+    rtl::OUString             maFileReceivedUri;
 };
 
 // static, not members, so they actually survive cppunit test iteration
@@ -299,17 +301,33 @@ void TestTeleTubes::FileSent( bool success, void *user_data)
     g_main_loop_quit (self->mpMainLoop);
 }
 
+void TestTeleTubes::FileReceived( rtl::OUString& aUri, void *user_data)
+{
+    TestTeleTubes *self = reinterpret_cast<TestTeleTubes *>(user_data);
+
+    self->maFileReceivedUri = aUri;
+    g_main_loop_quit (self->mpMainLoop);
+}
+
 void TestTeleTubes::testSendFile()
 {
     TpAccount *pAcc1 = mpManager1->getAccount(maOffererIdentifier);
     CPPUNIT_ASSERT( pAcc1 != 0);
     /* This has to run after testContactList has run successfully. */
     CPPUNIT_ASSERT( mpAccepterContact != 0);
+
+    mpManager1->setFileReceivedCallback(&TestTeleTubes::FileReceived, this);
+
     mpManager1->sendFile( maTestConfigIniURL,
         &TestTeleTubes::FileSent, this);
+    /* Waiting for two events: FileSent and FileReceived both quit the mainloop */
+    spinMainLoop();
     spinMainLoop();
 
     CPPUNIT_ASSERT( maFileSentSuccess);
+    CPPUNIT_ASSERT_MESSAGE(
+        OUStringToOString( maFileReceivedUri, RTL_TEXTENCODING_UTF8).getStr(),
+        maFileReceivedUri == "file:///tmp/fixme.ods");
 }
 
 void TestTeleTubes::testFlushLoops()
diff --git a/tubes/source/conference.cxx b/tubes/source/conference.cxx
index 9a35c70..88ec817 100644
--- a/tubes/source/conference.cxx
+++ b/tubes/source/conference.cxx
@@ -479,7 +479,7 @@ static void TeleConference_TransferError( EmpathyFTHandler *handler, const GErro
     g_object_unref (handler);
 }
 
-static void TeleConference_FTReady( EmpathyFTHandler *handler, GError *error, gpointer user_data)
+void TeleConference::FTReady( EmpathyFTHandler *handler, GError *error, gpointer user_data)
 {
     SendFileRequest *request = reinterpret_cast<SendFileRequest *>(user_data);
 
@@ -495,6 +495,7 @@ static void TeleConference_FTReady( EmpathyFTHandler *handler, GError *error, gp
             G_CALLBACK (TeleConference_TransferDone), request);
         g_signal_connect(handler, "transfer-error",
             G_CALLBACK (TeleConference_TransferError), request);
+        empathy_ft_handler_set_service_name(handler, request->mpSelf->mpManager->getFullServiceName().getStr());
         empathy_ft_handler_start_transfer(handler);
     }
 }
@@ -517,7 +518,7 @@ void TeleConference::sendFile( rtl::OUString &localUri, FileSentCallback pCallba
         tp_channel_get_target_contact( mpChannel),
         pSource,
         0,
-        &TeleConference_FTReady, pReq);
+        &TeleConference::FTReady, pReq);
 }
 
 
diff --git a/tubes/source/file-transfer-helper.c b/tubes/source/file-transfer-helper.c
index ca1a70b..15e3dfd 100644
--- a/tubes/source/file-transfer-helper.c
+++ b/tubes/source/file-transfer-helper.c
@@ -134,6 +134,7 @@ struct _EmpathyFTHandlerPriv {
   guint64 mtime;
   gchar *content_hash;
   TpFileHashType content_hash_type;
+  gchar *service_name;
 
   gint64 user_action_time;
 
@@ -260,6 +261,11 @@ do_dispose (GObject *object)
 
   priv->dispose_run = TRUE;
 
+  if (priv->account != NULL) {
+    g_object_unref (priv->account);
+    priv->account = NULL;
+  }
+
   if (priv->contact != NULL) {
     g_object_unref (priv->contact);
     priv->contact = NULL;
@@ -310,6 +316,9 @@ do_finalize (GObject *object)
   g_free (priv->content_hash);
   priv->content_hash = NULL;
 
+  g_free (priv->service_name);
+  priv->service_name = NULL;
+
   G_OBJECT_CLASS (empathy_ft_handler_parent_class)->finalize (object);
 }
 
@@ -907,6 +916,9 @@ ft_handler_populate_outgoing_request (EmpathyFTHandler *handler)
       TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_URI, G_TYPE_STRING, uri,
       NULL);
 
+  if (priv->service_name != NULL)
+    tp_asv_set_string (priv->request, TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME, priv->service_name);
+
   g_free (uri);
 }
 
@@ -1358,11 +1370,11 @@ channel_prepared_cb (
 
   properties = tp_channel_borrow_immutable_properties (TP_CHANNEL (channel));
 
-  priv->content_hash = g_value_dup_string (
-      g_hash_table_lookup (properties, "ContentHash"));
+  priv->content_hash = g_strdup (
+      tp_asv_get_string (properties, "ContentHash"));
 
-  priv->content_hash_type = g_value_get_uint (
-      g_hash_table_lookup (properties, "ContentHashType"));
+  priv->content_hash_type = tp_asv_get_uint32 (
+      properties, "ContentHashType", NULL);
 
   priv->contact = g_object_ref (tp_channel_get_target_contact (TP_CHANNEL (channel)));
 
@@ -1426,6 +1438,15 @@ empathy_ft_handler_new_outgoing (
       NULL, (GAsyncReadyCallback) ft_handler_gfile_ready_cb, data);
 }
 
+void
+empathy_ft_handler_set_service_name (
+    EmpathyFTHandler *self,
+    const gchar *service_name)
+{
+  g_free (self->priv->service_name);
+  self->priv->service_name = g_strdup (service_name);
+}
+
 /**
  * empathy_ft_handler_new_incoming:
  * @channel: the #TpFileTransferChannel proxy to the incoming channel
diff --git a/tubes/source/manager.cxx b/tubes/source/manager.cxx
index 8403270..b479d5d 100644
--- a/tubes/source/manager.cxx
+++ b/tubes/source/manager.cxx
@@ -31,6 +31,7 @@
 #include <rtl/strbuf.hxx>
 #include <rtl/uuid.h>
 #include <osl/mutex.hxx>
+#include <cstring>
 
 
 #if defined SAL_LOG_INFO
@@ -77,6 +78,7 @@ public:
     GMainLoop*                          mpLoop;
     TpDBusDaemon*                       mpDBus;
     TpBaseClient*                       mpClient;
+    TpBaseClient*                       mpFileTransferClient;
     TpAccountManager*                   mpAccountManager;
     TeleManager::AccountManagerStatus   meAccountManagerStatus;
     bool                                mbAccountManagerReadyHandlerInvoked;
@@ -172,6 +174,102 @@ static void TeleManager_DBusChannelHandler(
     }
 }
 
+void TeleManager::TransferDone( EmpathyFTHandler *handler, TpFileTransferChannel *, gpointer pUserData)
+{
+    TeleManager* pManager = reinterpret_cast<TeleManager*>(pUserData);
+
+    SAL_INFO( "tubes", "TeleConference_TransferDone: hooray!");
+    GFile *gfile = empathy_ft_handler_get_gfile( handler);
+    char *uri = g_file_get_uri( gfile);
+    rtl::OUString aUri( uri, strlen( uri), RTL_TEXTENCODING_UTF8);
+    g_free( uri);
+
+    pManager->mpFileReceivedCallback( aUri, pManager->mpFileReceivedCallbackData);
+
+    //g_object_unref( handler);
+}
+
+static void TeleManager_TransferError( EmpathyFTHandler *handler, const GError *error, void*)
+{
+    SAL_INFO( "tubes", "TeleConference_TransferError: " << error->message);
+
+    //g_object_unref( handler);
+}
+
+static void
+TeleManager_IncomingHandlerReady (
+    EmpathyFTHandler*   pHandler,
+    GError*             pError,
+    void*               pUserData)
+{
+    TeleManager* pManager = reinterpret_cast<TeleManager*>(pUserData);
+
+    if (pError)
+    {
+        SAL_INFO ("tubes", "failed to prepare incoming transfer: " << pError->message);
+        g_object_unref( pHandler);
+        return;
+    }
+
+    GFile *pDestination = g_file_new_for_uri( "file:///tmp/fixme.ods");
+
+    empathy_ft_handler_incoming_set_destination( pHandler, pDestination);
+    g_object_unref( pDestination);
+
+    g_signal_connect( pHandler, "transfer-done", G_CALLBACK (&TeleManager::TransferDone), pManager);
+    g_signal_connect( pHandler, "transfer-error", G_CALLBACK (TeleManager_TransferError), pManager);
+    empathy_ft_handler_start_transfer( pHandler);
+}
+
+static void TeleManager_FileTransferHandler(
+        TpSimpleHandler*            /*handler*/,
+        TpAccount*                  /*Account*/,
+        TpConnection*               /*connection*/,
+        GList*                      pChannels,
+        GList*                      /*requests_satisfied*/,
+        gint64                      /*user_action_time*/,
+        TpHandleChannelsContext*    pContext,
+        gpointer                    pUserData)
+{
+    bool aAccepted = false;
+    INFO_LOGGER_F( "TeleManager_FileTransferHandler");
+
+    TeleManager* pManager = reinterpret_cast<TeleManager*>(pUserData);
+    SAL_WARN_IF( !pManager, "tubes", "TeleManager_FileTransferHandler: no manager");
+    if (!pManager)
+        return;
+
+    for (GList* p = pChannels; p; p = p->next)
+    {
+        TpChannel* pChannel = TP_CHANNEL(p->data);
+
+        SAL_INFO( "tubes", "TeleManager_FileTransferHandler: incoming dbus channel: "
+                << tp_channel_get_identifier( pChannel));
+
+        if (TP_IS_FILE_TRANSFER_CHANNEL( pChannel))
+        {
+            SAL_INFO( "tubes", "accepting file transfer");
+            empathy_ft_handler_new_incoming( TP_FILE_TRANSFER_CHANNEL( pChannel),
+                TeleManager_IncomingHandlerReady, pManager);
+            aAccepted = true;
+        }
+        else
+        {
+            SAL_INFO( "tubes", "ignored");
+        }
+    }
+
+    if (aAccepted)
+        tp_handle_channels_context_accept( pContext);
+    else
+    {
+        GError *pError = g_error_new_literal( TP_ERRORS, TP_ERROR_CONFUSED,
+            "None of these channels were file transfers; "
+            "why did the Channel Dispatcher give them to us?");
+        tp_handle_channels_context_fail( pContext, pError);
+        g_clear_error (&pError);
+    }
+}
 
 static void TeleManager_ChannelReadyHandler(
         GObject*        pSourceObject,
@@ -296,13 +394,13 @@ bool TeleManager::connect()
         return false;
     }
 
-    TpSimpleClientFactory* pFactory = tp_simple_client_factory_new( pImpl->mpDBus);
+    TpAutomaticClientFactory* pFactory = tp_automatic_client_factory_new( pImpl->mpDBus);
     SAL_WARN_IF( !pFactory, "tubes", "TeleManager::connect: no client factory");
     if (!pFactory)
         return false;
 
     pImpl->mpClient = tp_simple_handler_new_with_factory(
-            pFactory,                       // factory
+            TP_SIMPLE_CLIENT_FACTORY (pFactory), // factory
             FALSE,                          // bypass_approval
             FALSE,                          // requests
             getFullClientName().getStr(),   // name
@@ -346,6 +444,36 @@ bool TeleManager::connect()
     SAL_INFO( "tubes", "TeleManager::connect: bus name: " << tp_base_client_get_bus_name( pImpl->mpClient));
     SAL_INFO( "tubes", "TeleManager::connect: object path: " << tp_base_client_get_object_path( pImpl->mpClient));
 
+    /* Register a second "head" for incoming file transfers. This uses a more
+     * specific filter than Empathy's handler by matching on the file
+     * transfer's ServiceName property, and uses bypass_approval to ensure the
+     * user isn't prompted before the channel gets passed to us.
+     */
+    pImpl->mpFileTransferClient = tp_simple_handler_new_with_factory (
+            TP_SIMPLE_CLIENT_FACTORY( pFactory),            // factory
+            TRUE,                                           // bypass_approval
+            FALSE,                                          // requests
+            getFullClientName().getStr(),                   // name
+            TRUE,                                           // uniquify to get a different bus name to the main client, above
+            TeleManager_FileTransferHandler,                // callback
+            this,                                           // user_data
+            NULL                                            // destroy
+            );
+    tp_base_client_take_handler_filter( pImpl->mpFileTransferClient,
+            tp_asv_new(
+                TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
+                TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
+                TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME, G_TYPE_STRING, getFullServiceName().getStr(),
+                NULL));
+
+    if (!tp_base_client_register( pImpl->mpFileTransferClient, &pError))
+    {
+        /* This shouldn't fail if registering the main handler succeeded */
+        SAL_WARN( "tubes", "TeleManager::connect: error registering file transfer handler: " << pError->message);
+        g_error_free( pError);
+        return false;
+    }
+
     return true;
 }
 
@@ -603,6 +731,12 @@ void TeleManager::sendFile( rtl::OUString &localUri, TeleConference::FileSentCal
     }
 }
 
+void TeleManager::setFileReceivedCallback( TeleManager::FileReceivedCallback callback, void* pUserData )
+{
+    mpFileReceivedCallback = callback;
+    mpFileReceivedCallbackData = pUserData;
+}
+
 void TeleManager::unregisterConference( TeleConferencePtr pConference )
 {
     INFO_LOGGER( "TeleManager::unregisterConference");
@@ -625,6 +759,9 @@ void TeleManager::disconnect()
     tp_base_client_unregister( pImpl->mpClient);
     pImpl->mpClient = NULL;
 
+    tp_base_client_unregister( pImpl->mpFileTransferClient);
+    pImpl->mpFileTransferClient = NULL;
+
     size_t nSize = maConferences.size();
     for (size_t i=0; i < nSize; /*nop*/)
     {
@@ -798,6 +935,7 @@ TeleManagerImpl::TeleManagerImpl()
         mpLoop( NULL),
         mpDBus( NULL),
         mpClient( NULL),
+        mpFileTransferClient( NULL),
         mpAccountManager( NULL),
         meAccountManagerStatus( TeleManager::AMS_UNINITIALIZED),
         mbAccountManagerReadyHandlerInvoked( false)
@@ -809,6 +947,8 @@ TeleManagerImpl::~TeleManagerImpl()
 {
     if (mpClient)
         g_object_unref( mpClient);
+    if (mpFileTransferClient)
+        g_object_unref( mpFileTransferClient);
     if (mpDBus)
         g_object_unref( mpDBus);
     if (mpAccountManager)
commit 50280f414ffac039e225ed2aa4340ae4e1805611
Author: Will Thompson <will.thompson at collabora.co.uk>
Date:   Fri Mar 23 08:50:44 2012 +0000

    tubes test: fix stack corruption on test failure
    
    We can't use CPPUNIT_ASSERT() from a callback called by C code (such as
    the FileSent callback), or we'll trash the stack if it fails.

diff --git a/tubes/qa/test_manager.cxx b/tubes/qa/test_manager.cxx
index ce9a2d0..d08190d 100644
--- a/tubes/qa/test_manager.cxx
+++ b/tubes/qa/test_manager.cxx
@@ -69,6 +69,8 @@ public:
     GMainLoop*                  mpMainLoop;
     void spinMainLoop();
 
+    static void FileSent( bool success, void *user_data);
+
     // Order is significant.
     CPPUNIT_TEST_SUITE( TestTeleTubes );
     CPPUNIT_TEST( testSetupManager1 );
@@ -98,6 +100,8 @@ private:
 
     rtl::OString              maOffererIdentifier;
     rtl::OString              maAccepterIdentifier;
+
+    bool                      maFileSentSuccess;
 };
 
 // static, not members, so they actually survive cppunit test iteration
@@ -287,11 +291,11 @@ void TestTeleTubes::testReceivePacket()
     CPPUNIT_ASSERT( nReceivedPackets == nSentPackets);
 }
 
-static void TestTeleTubes_FileSent( bool success, void *user_data)
+void TestTeleTubes::FileSent( bool success, void *user_data)
 {
     TestTeleTubes *self = reinterpret_cast<TestTeleTubes *>(user_data);
 
-    CPPUNIT_ASSERT( success);
+    self->maFileSentSuccess = success;
     g_main_loop_quit (self->mpMainLoop);
 }
 
@@ -302,8 +306,10 @@ void TestTeleTubes::testSendFile()
     /* This has to run after testContactList has run successfully. */
     CPPUNIT_ASSERT( mpAccepterContact != 0);
     mpManager1->sendFile( maTestConfigIniURL,
-        TestTeleTubes_FileSent, this);
+        &TestTeleTubes::FileSent, this);
     spinMainLoop();
+
+    CPPUNIT_ASSERT( maFileSentSuccess);
 }
 
 void TestTeleTubes::testFlushLoops()


More information about the Libreoffice-commits mailing list