LCOV - code coverage report
Current view: top level - sd/source/ui/remotecontrol - Server.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 9 164 5.5 %
Date: 2015-06-13 12:38:46 Functions: 3 19 15.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : #include <stdlib.h>
      10             : #include <algorithm>
      11             : #include <vector>
      12             : 
      13             : #include <officecfg/Office/Common.hxx>
      14             : #include <officecfg/Office/Impress.hxx>
      15             : 
      16             : #include <com/sun/star/container/XNameAccess.hpp>
      17             : #include <com/sun/star/container/XNameContainer.hpp>
      18             : #include <com/sun/star/uno/Sequence.hxx>
      19             : 
      20             : #include <comphelper/processfactory.hxx>
      21             : #include <comphelper/configuration.hxx>
      22             : #include <sal/log.hxx>
      23             : 
      24             : #include "sddll.hxx"
      25             : 
      26             : #include "DiscoveryService.hxx"
      27             : #include "Listener.hxx"
      28             : #include "Receiver.hxx"
      29             : #include "RemoteServer.hxx"
      30             : #include "BluetoothServer.hxx"
      31             : #include "Communicator.hxx"
      32             : #include "BufferedStreamSocket.hxx"
      33             : 
      34             : using namespace std;
      35             : using namespace sd;
      36             : using namespace ::com::sun::star;
      37             : using namespace ::com::sun::star::uno;
      38             : using namespace ::com::sun::star::beans;
      39             : using namespace ::com::sun::star::container;
      40             : using namespace ::com::sun::star::lang;
      41             : using namespace ::osl;
      42             : using namespace ::comphelper;
      43             : 
      44             : namespace sd {
      45             :     /**
      46             :      * Used to keep track of clients that have attempted to connect, but haven't
      47             :      * yet been approved.
      48             :      */
      49           0 :     struct ClientInfoInternal:
      50             :         ClientInfo
      51             :     {
      52             :         BufferedStreamSocket *mpStreamSocket;
      53             :         OUString mPin;
      54             : 
      55           0 :         ClientInfoInternal( const OUString& rName,
      56             :                             const OUString& rAddress,
      57             :                             const bool bIsAlreadyAuthorised,
      58             :                             BufferedStreamSocket *pSocket,
      59             :                             const OUString& rPin ):
      60             :                 ClientInfo( rName, rAddress, bIsAlreadyAuthorised ),
      61             :                 mpStreamSocket( pSocket ),
      62           0 :                 mPin( rPin ) {}
      63             :     };
      64             : }
      65             : 
      66           0 : RemoteServer::RemoteServer() :
      67             :     Thread( "RemoteServerThread" ),
      68             :     mSocket(),
      69           0 :     mAvailableClients()
      70             : {
      71             :     SAL_INFO( "sdremote", "Instantiated RemoteServer" );
      72           0 : }
      73             : 
      74           0 : RemoteServer::~RemoteServer()
      75             : {
      76           0 : }
      77             : 
      78           0 : void RemoteServer::execute()
      79             : {
      80             :     SAL_INFO( "sdremote", "RemoteServer::execute called" );
      81           0 :     uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
      82           0 :     if (!xContext.is()/* || !officecfg::Office::Common::Misc::ExperimentalMode::get(xContext)*/)
      83             :     {
      84             :         // SAL_INFO("sdremote", "not in experimental mode, disabling TCP server");
      85           0 :         spServer = NULL;
      86           0 :         return;
      87             :     }
      88           0 :     osl::SocketAddr aAddr( "0", PORT );
      89           0 :     if ( !mSocket.bind( aAddr ) )
      90             :     {
      91             :         SAL_WARN( "sdremote", "bind failed" << mSocket.getErrorAsString() );
      92           0 :         spServer = NULL;
      93           0 :         return;
      94             :     }
      95             : 
      96           0 :     if ( !mSocket.listen(3) )
      97             :     {
      98             :         SAL_WARN( "sdremote", "listen failed" << mSocket.getErrorAsString() );
      99           0 :         spServer = NULL;
     100           0 :         return;
     101             :     }
     102             :     while ( true )
     103             :     {
     104           0 :         StreamSocket aSocket;
     105             :         SAL_INFO( "sdremote", "waiting on accept" );
     106           0 :         if ( mSocket.acceptConnection( aSocket ) == osl_Socket_Error )
     107             :         {
     108             :             SAL_WARN( "sdremote", "accept failed" << mSocket.getErrorAsString() );
     109           0 :             spServer = NULL;
     110           0 :             return; // Closed, or other issue.
     111             :         }
     112           0 :         BufferedStreamSocket *pSocket = new BufferedStreamSocket( aSocket);
     113           0 :         OString aLine;
     114           0 :         if ( pSocket->readLine( aLine)
     115           0 :             && aLine.equals( "LO_SERVER_CLIENT_PAIR" ) &&
     116           0 :             pSocket->readLine( aLine ) )
     117             :         {
     118           0 :             OString aName( aLine );
     119             : 
     120           0 :             if ( ! pSocket->readLine( aLine ) )
     121             :             {
     122           0 :                 delete pSocket;
     123           0 :                 continue;
     124             :             }
     125           0 :             OString aPin( aLine );
     126             : 
     127           0 :             SocketAddr aClientAddr;
     128           0 :             pSocket->getPeerAddr( aClientAddr );
     129           0 :             OUString aAddress = aClientAddr.getHostname();
     130             : 
     131           0 :             MutexGuard aGuard( sDataMutex );
     132             :             ::boost::shared_ptr< ClientInfoInternal > pClient(
     133             :                 new ClientInfoInternal(
     134             :                     OStringToOUString( aName, RTL_TEXTENCODING_UTF8 ),
     135             :                     aAddress, false, pSocket, OStringToOUString( aPin,
     136           0 :                                                                  RTL_TEXTENCODING_UTF8 ) ) );
     137           0 :             mAvailableClients.push_back( pClient );
     138             : 
     139             :             // Read off any additional non-empty lines
     140             :             // We know that we at least have the empty termination line to read.
     141           0 :             do
     142             :             {
     143           0 :                 pSocket->readLine( aLine );
     144             :             }
     145           0 :             while ( aLine.getLength() > 0 );
     146             : 
     147             :             // Check if we already have this server.
     148           0 :             Reference< XNameAccess > const xConfig = officecfg::Office::Impress::Misc::AuthorisedRemotes::get();
     149           0 :             Sequence< OUString > aNames = xConfig->getElementNames();
     150           0 :             bool aFound = false;
     151           0 :             for ( int i = 0; i < aNames.getLength(); i++ )
     152             :             {
     153           0 :                 if ( aNames[i].equals( pClient->mName ) )
     154             :                 {
     155           0 :                     Reference<XNameAccess> xSetItem( xConfig->getByName(aNames[i]), UNO_QUERY );
     156           0 :                     Any axPin(xSetItem->getByName("PIN"));
     157           0 :                     OUString sPin;
     158           0 :                     axPin >>= sPin;
     159             : 
     160           0 :                     if ( sPin.equals( pClient->mPin ) ) {
     161             :                         SAL_INFO( "sdremote", "client found on validated list -- connecting" );
     162           0 :                         connectClient( pClient, sPin );
     163           0 :                         aFound = true;
     164           0 :                         break;
     165           0 :                     }
     166             :                 }
     167             : 
     168             :             }
     169             :             // Pin not found so inform the client.
     170           0 :             if ( !aFound )
     171             :             {
     172             :                 SAL_INFO( "sdremote", "client not found on validated list" );
     173             :                 pSocket->write( "LO_SERVER_VALIDATING_PIN\n\n",
     174           0 :                             strlen( "LO_SERVER_VALIDATING_PIN\n\n" ) );
     175           0 :             }
     176             :         } else {
     177             :             SAL_INFO( "sdremote", "client failed to send LO_SERVER_CLIENT_PAIR, ignoring" );
     178           0 :             delete pSocket;
     179             :         }
     180           0 :     }
     181             :     SAL_INFO( "sdremote", "shutting down RemoteServer" );
     182           0 :     spServer = NULL; // Object is destroyed when Thread::execute() ends.
     183             : }
     184             : 
     185             : RemoteServer *sd::RemoteServer::spServer = NULL;
     186          22 : ::osl::Mutex sd::RemoteServer::sDataMutex;
     187          22 : ::std::vector<Communicator*> sd::RemoteServer::sCommunicators;
     188             : 
     189           0 : void RemoteServer::setup()
     190             : {
     191           0 :     if (spServer)
     192           0 :         return;
     193             : 
     194           0 :     spServer = new RemoteServer();
     195           0 :     spServer->launch();
     196             : 
     197             : #ifdef ENABLE_SDREMOTE_BLUETOOTH
     198           0 :     sd::BluetoothServer::setup( &sCommunicators );
     199             : #endif
     200             : }
     201             : 
     202           0 : void RemoteServer::presentationStarted( const css::uno::Reference<
     203             :                 css::presentation::XSlideShowController > &rController )
     204             : {
     205           0 :     if ( !spServer )
     206           0 :         return;
     207           0 :     MutexGuard aGuard( sDataMutex );
     208           0 :     for ( vector<Communicator*>::const_iterator aIt = sCommunicators.begin();
     209           0 :          aIt != sCommunicators.end(); ++aIt )
     210             :     {
     211           0 :         (*aIt)->presentationStarted( rController );
     212           0 :     }
     213             : }
     214           0 : void RemoteServer::presentationStopped()
     215             : {
     216           0 :     if ( !spServer )
     217           0 :         return;
     218           0 :     MutexGuard aGuard( sDataMutex );
     219           0 :     for ( vector<Communicator*>::const_iterator aIt = sCommunicators.begin();
     220           0 :          aIt != sCommunicators.end(); ++aIt )
     221             :     {
     222           0 :         (*aIt)->disposeListener();
     223           0 :     }
     224             : }
     225             : 
     226           0 : void RemoteServer::removeCommunicator( Communicator* mCommunicator )
     227             : {
     228           0 :     if ( !spServer )
     229           0 :         return;
     230           0 :     MutexGuard aGuard( sDataMutex );
     231           0 :     for ( vector<Communicator*>::iterator aIt = sCommunicators.begin();
     232           0 :          aIt != sCommunicators.end(); ++aIt )
     233             :     {
     234           0 :         if ( mCommunicator == *aIt )
     235             :         {
     236           0 :             sCommunicators.erase( aIt );
     237           0 :             break;
     238             :         }
     239           0 :     }
     240             : }
     241             : 
     242           0 : std::vector< ::boost::shared_ptr< ClientInfo > > RemoteServer::getClients()
     243             : {
     244             :     SAL_INFO( "sdremote", "RemoteServer::getClients() called" );
     245           0 :     std::vector< ::boost::shared_ptr< ClientInfo > > aClients;
     246           0 :     if ( spServer )
     247             :     {
     248           0 :         MutexGuard aGuard( sDataMutex );
     249             :         aClients.assign( spServer->mAvailableClients.begin(),
     250           0 :                          spServer->mAvailableClients.end() );
     251             :     }
     252             :     else
     253             :     {
     254             :         SAL_INFO( "sdremote", "No remote server instance => no remote clients" );
     255             :     }
     256             :     // We also need to provide authorised clients (no matter whether or not
     257             :     // they are actually available), so that they can be de-authorised if
     258             :     // necessary. We specifically want these to be at the end of the list
     259             :     // since the user is more likely to be trying to connect a new remote
     260             :     // than removing an existing remote.
     261             :     // We can also be sure that pre-authorised clients will not be on the
     262             :     // available clients list, as they get automatially connected if seen.
     263             :     // TODO: we should probably add some sort of extra labelling to mark
     264             :     // authorised AND connected client.
     265           0 :     Reference< XNameAccess > const xConfig = officecfg::Office::Impress::Misc::AuthorisedRemotes::get();
     266           0 :     Sequence< OUString > aNames = xConfig->getElementNames();
     267           0 :     for ( int i = 0; i < aNames.getLength(); i++ )
     268             :     {
     269           0 :         aClients.push_back( ::boost::shared_ptr< ClientInfo > ( new ClientInfo( aNames[i], "", true ) ) );
     270             :     }
     271             : 
     272           0 :     return aClients;
     273             : }
     274             : 
     275           0 : bool RemoteServer::connectClient( ::boost::shared_ptr< ClientInfo > pClient, const OUString& aPin )
     276             : {
     277             :     SAL_INFO( "sdremote", "RemoteServer::connectClient called" );
     278           0 :     if ( !spServer )
     279           0 :         return false;
     280             : 
     281           0 :     ClientInfoInternal* apClient = dynamic_cast< ClientInfoInternal* >( pClient.get() );
     282           0 :     if ( !apClient )
     283             :     // could happen if we try to "connect" an already authorised client
     284             :     {
     285           0 :         return false;
     286             :     }
     287             : 
     288           0 :     if ( apClient->mPin.equals( aPin ) )
     289             :     {
     290             :         // Save in settings first
     291           0 :         std::shared_ptr< ConfigurationChanges > aChanges = ConfigurationChanges::create();
     292           0 :         Reference< XNameContainer > const xConfig = officecfg::Office::Impress::Misc::AuthorisedRemotes::get( aChanges );
     293             : 
     294             :         Reference<XSingleServiceFactory> xChildFactory (
     295           0 :             xConfig, UNO_QUERY);
     296           0 :         Reference<XNameReplace> xChild( xChildFactory->createInstance(), UNO_QUERY);
     297           0 :                 Any aValue;
     298           0 :         if (xChild.is())
     299             :         {
     300             :             // Check whether the client is already saved
     301           0 :             bool aSaved = false;
     302           0 :             Sequence< OUString > aNames = xConfig->getElementNames();
     303           0 :             for ( int i = 0; i < aNames.getLength(); i++ )
     304             :             {
     305           0 :                 if ( aNames[i].equals( apClient->mName ) )
     306             :                 {
     307           0 :                     xConfig->replaceByName( apClient->mName, makeAny( xChild ) );
     308           0 :                     aSaved = true;
     309           0 :                     break;
     310             :                 }
     311             :             }
     312           0 :             if ( !aSaved )
     313           0 :                 xConfig->insertByName( apClient->mName, makeAny( xChild ) );
     314           0 :             aValue <<= OUString( apClient->mPin );
     315           0 :             xChild->replaceByName("PIN", aValue);
     316           0 :             aChanges->commit();
     317             :         }
     318             : 
     319           0 :         Communicator* pCommunicator = new Communicator( apClient->mpStreamSocket );
     320           0 :         MutexGuard aGuard( sDataMutex );
     321             : 
     322           0 :         sCommunicators.push_back( pCommunicator );
     323             : 
     324           0 :         for ( vector< ::boost::shared_ptr< ClientInfoInternal > >::iterator aIt = spServer->mAvailableClients.begin();
     325           0 :             aIt != spServer->mAvailableClients.end(); ++aIt )
     326             :         {
     327           0 :             if ( pClient == *aIt )
     328             :             {
     329           0 :                 spServer->mAvailableClients.erase( aIt );
     330           0 :                 break;
     331             :             }
     332             :         }
     333           0 :         pCommunicator->launch();
     334           0 :         return true;
     335             :     }
     336             :     else
     337             :     {
     338           0 :         return false;
     339             :     }
     340             : }
     341             : 
     342           0 : void RemoteServer::deauthoriseClient( ::boost::shared_ptr< ClientInfo > pClient )
     343             : {
     344             :     // TODO: we probably want to forcefully disconnect at this point too?
     345             :     // But possibly via a separate function to allow just disconnecting from
     346             :     // the UI.
     347             : 
     348             :     SAL_INFO( "sdremote", "RemoteServer::deauthoriseClient called" );
     349             : 
     350           0 :     if ( !pClient->mbIsAlreadyAuthorised )
     351             :     // We can't remove unauthorised clients from the authorised list...
     352             :     {
     353           0 :         return;
     354             :     }
     355             : 
     356           0 :     std::shared_ptr< ConfigurationChanges > aChanges = ConfigurationChanges::create();
     357             :     Reference< XNameContainer > const xConfig =
     358           0 :         officecfg::Office::Impress::Misc::AuthorisedRemotes::get( aChanges );
     359             : 
     360           0 :     xConfig->removeByName( pClient->mName );
     361           0 :     aChanges->commit();
     362             : }
     363             : 
     364           2 : void SdDLL::RegisterRemotes()
     365             : {
     366             :     SAL_INFO( "sdremote", "SdDLL::RegisterRemotes called" );
     367             : 
     368             :     // The remote server is likely of no use in headless mode. And as only
     369             :     // one instance of the server can actually own the appropriate ports its
     370             :     // probably best to not even try to do so from our headless instance
     371             :     // (i.e. as to avoid blocking expected usage).
     372             :     // It could perhaps be argued that we would still need the remote
     373             :     // server for tiled rendering of presentations, but even then this
     374             :     // implementation would not be of much use, i.e. would be controlling
     375             :     // the purely imaginary headless presentation -- instead we'd need
     376             :     // to have some sort of mechanism of plugging in our tiled rendering
     377             :     // client to be controlled by the remote server, or provide an
     378             :     // alternative implementation.
     379           2 :     if ( Application::IsHeadlessModeEnabled() )
     380           2 :         return;
     381             : 
     382           2 :     uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
     383           2 :     if ( xContext.is()  && !officecfg::Office::Impress::Misc::Start::EnableSdremote::get( xContext ) )
     384           2 :         return;
     385             : 
     386           0 :     sd::RemoteServer::setup();
     387           0 :     sd::DiscoveryService::setup();
     388             : }
     389             : 
     390           0 : void RemoteServer::ensureDiscoverable()
     391             : {
     392             :     // FIXME: we could also enable listening on our WiFi
     393             :     // socket here to significantly reduce the attack surface.
     394             : #ifdef ENABLE_SDREMOTE_BLUETOOTH
     395           0 :     BluetoothServer::ensureDiscoverable();
     396             : #endif
     397           0 : }
     398             : 
     399           0 : void RemoteServer::restoreDiscoverable()
     400             : {
     401             : #ifdef ENABLE_SDREMOTE_BLUETOOTH
     402           0 :     BluetoothServer::restoreDiscoverable();
     403             : #endif
     404          66 : }
     405             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11