LCOV - code coverage report
Current view: top level - libreoffice/sd/source/ui/remotecontrol - Server.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 7 135 5.2 %
Date: 2012-12-27 Functions: 3 16 18.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             : 
      33             : using namespace std;
      34             : using namespace sd;
      35             : using namespace ::com::sun::star;
      36             : using namespace ::com::sun::star::uno;
      37             : using namespace ::com::sun::star::beans;
      38             : using namespace ::com::sun::star::container;
      39             : using namespace ::com::sun::star::lang;
      40             : using rtl::OString;
      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             :     struct ClientInfoInternal:
      50             :         ClientInfo
      51             :     {
      52             :         BufferedStreamSocket *mpStreamSocket;
      53             :         rtl::OUString mPin;
      54             : 
      55           0 :         ClientInfoInternal( const rtl::OUString rName,
      56             :                             const rtl::OUString rAddress,
      57             :                             BufferedStreamSocket *pSocket, rtl::OUString rPin ):
      58             :                 ClientInfo( rName, rAddress ),
      59             :                 mpStreamSocket( pSocket ),
      60           0 :                 mPin( rPin ) {}
      61             :     };
      62             : }
      63             : 
      64           0 : RemoteServer::RemoteServer() :
      65             :     Thread( "RemoteServerThread" ),
      66             :     mSocket(),
      67           0 :     mAvailableClients()
      68             : {
      69           0 : }
      70             : 
      71           0 : RemoteServer::~RemoteServer()
      72             : {
      73           0 : }
      74             : 
      75           0 : void RemoteServer::execute()
      76             : {
      77             :     SAL_INFO( "sdremote", "RemoteServer::execute called" );
      78           0 :     uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
      79           0 :     if (!xContext.is() || !officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
      80             :     {
      81             :         SAL_INFO("sdremote", "not in experimental mode, disabling TCP server");
      82             :         return;
      83             :     }
      84           0 :     osl::SocketAddr aAddr( "0", PORT );
      85           0 :     if ( !mSocket.bind( aAddr ) )
      86             :     {
      87             :         SAL_WARN( "sdremote", "bind failed" << mSocket.getErrorAsString() );
      88             :         return;
      89             :     }
      90             : 
      91           0 :     if ( !mSocket.listen(3) )
      92             :     {
      93             :         SAL_WARN( "sdremote", "listen failed" << mSocket.getErrorAsString() );
      94             :         return;
      95             :     }
      96           0 :     while ( true )
      97             :     {
      98           0 :         StreamSocket aSocket;
      99             :         SAL_INFO( "sdremote", "waiting on accept" );
     100           0 :         if ( mSocket.acceptConnection( aSocket ) == osl_Socket_Error )
     101             :         {
     102             :             SAL_WARN( "sdremote", "accept failed" << mSocket.getErrorAsString() );
     103             :             return; // Closed, or other issue.
     104             :         }
     105           0 :         BufferedStreamSocket *pSocket = new BufferedStreamSocket( aSocket);
     106           0 :         OString aLine;
     107           0 :         if ( pSocket->readLine( aLine)
     108           0 :             && aLine.equals( "LO_SERVER_CLIENT_PAIR" ) &&
     109           0 :             pSocket->readLine( aLine ) )
     110             :         {
     111           0 :             OString aName( aLine );
     112             : 
     113           0 :             if ( ! pSocket->readLine( aLine ) ) delete pSocket;
     114           0 :             OString aPin( aLine );
     115             : 
     116           0 :             SocketAddr aClientAddr;
     117           0 :             pSocket->getPeerAddr( aClientAddr );
     118           0 :             OUString aAddress = aClientAddr.getHostname();
     119             : 
     120           0 :             MutexGuard aGuard( sDataMutex );
     121             :             ClientInfoInternal* pClient = new ClientInfoInternal(
     122             :                     OStringToOUString( aName, RTL_TEXTENCODING_UTF8 ),
     123             :                     aAddress, pSocket, OStringToOUString( aPin,
     124           0 :                     RTL_TEXTENCODING_UTF8 ) );
     125           0 :             mAvailableClients.push_back( pClient );
     126             : 
     127             :             // Read off any additional non-empty lines
     128             :             // We know that we at least have the empty termination line to read.
     129           0 :             do
     130             :             {
     131           0 :                 pSocket->readLine( aLine );
     132             :             }
     133           0 :             while ( aLine.getLength() > 0 );
     134             : 
     135             :             // Check if we already have this server.
     136             :             Reference< XNameAccess > const xConfig = officecfg::Office::Impress::Misc::AuthorisedRemotes::get();
     137           0 :             Sequence< OUString > aNames = xConfig->getElementNames();
     138           0 :             bool aFound = false;
     139           0 :             for ( int i = 0; i < aNames.getLength(); i++ )
     140             :             {
     141           0 :                 if ( aNames[i].equals( pClient->mName ) )
     142             :                 {
     143           0 :                     Reference<XNameAccess> xSetItem( xConfig->getByName(aNames[i]), UNO_QUERY );
     144           0 :                     Any axPin(xSetItem->getByName("PIN"));
     145           0 :                     OUString sPin;
     146           0 :                     axPin >>= sPin;
     147             : 
     148           0 :                     if ( sPin.equals( pClient->mPin ) ) {
     149             :                         SAL_INFO( "sdremote", "client found on validated list -- connecting" );
     150           0 :                         connectClient( pClient, sPin );
     151           0 :                         aFound = true;
     152             :                         break;
     153           0 :                     }
     154             :                 }
     155             : 
     156             :             }
     157             :             // Pin not found so inform the client.
     158           0 :             if ( !aFound )
     159             :             {
     160             :                 SAL_INFO( "sdremote", "client not found on validated list" );
     161             :                 pSocket->write( "LO_SERVER_VALIDATING_PIN\n\n",
     162           0 :                             strlen( "LO_SERVER_VALIDATING_PIN\n\n" ) );
     163           0 :             }
     164             :         } else {
     165             :             SAL_INFO( "sdremote", "client failed to send LO_SERVER_CLIENT_PAIR, ignoring" );
     166           0 :             delete pSocket;
     167             :         }
     168           0 :     }
     169           0 :     spServer = NULL; // Object is destroyed when Thread::execute() ends.
     170             : }
     171             : 
     172             : RemoteServer *sd::RemoteServer::spServer = NULL;
     173           3 : ::osl::Mutex sd::RemoteServer::sDataMutex;
     174           3 : ::std::vector<Communicator*> sd::RemoteServer::sCommunicators;
     175             : 
     176           0 : void RemoteServer::setup()
     177             : {
     178           0 :     if (spServer)
     179           0 :         return;
     180             : 
     181           0 :     spServer = new RemoteServer();
     182           0 :     spServer->launch();
     183             : 
     184             : #ifdef ENABLE_SDREMOTE_BLUETOOTH
     185           0 :     sd::BluetoothServer::setup( &sCommunicators );
     186             : #endif
     187             : }
     188             : 
     189             : 
     190           0 : void RemoteServer::presentationStarted( const css::uno::Reference<
     191             :                 css::presentation::XSlideShowController > &rController )
     192             : {
     193           0 :     if ( !spServer )
     194           0 :         return;
     195           0 :     MutexGuard aGuard( sDataMutex );
     196           0 :     for ( vector<Communicator*>::const_iterator aIt = sCommunicators.begin();
     197           0 :          aIt != sCommunicators.end(); ++aIt )
     198             :     {
     199           0 :         (*aIt)->presentationStarted( rController );
     200           0 :     }
     201             : }
     202           0 : void RemoteServer::presentationStopped()
     203             : {
     204           0 :     if ( !spServer )
     205           0 :         return;
     206           0 :     MutexGuard aGuard( sDataMutex );
     207           0 :     for ( vector<Communicator*>::const_iterator aIt = sCommunicators.begin();
     208           0 :          aIt != sCommunicators.end(); ++aIt )
     209             :     {
     210           0 :         (*aIt)->disposeListener();
     211           0 :     }
     212             : }
     213             : 
     214           0 : void RemoteServer::removeCommunicator( Communicator* mCommunicator )
     215             : {
     216           0 :     if ( !spServer )
     217           0 :         return;
     218           0 :     MutexGuard aGuard( sDataMutex );
     219           0 :     for ( vector<Communicator*>::iterator aIt = sCommunicators.begin();
     220           0 :          aIt != sCommunicators.end(); ++aIt )
     221             :     {
     222           0 :         if ( mCommunicator == *aIt )
     223             :         {
     224           0 :             sCommunicators.erase( aIt );
     225           0 :             break;
     226             :         }
     227           0 :     }
     228             : }
     229             : 
     230           0 : std::vector<ClientInfo*> RemoteServer::getClients()
     231             : {
     232           0 :     std::vector<ClientInfo*> aClients;
     233           0 :     if ( !spServer )
     234             :         return aClients;
     235             : 
     236           0 :     MutexGuard aGuard( sDataMutex );
     237             :     aClients.assign( spServer->mAvailableClients.begin(),
     238           0 :                      spServer->mAvailableClients.end() );
     239           0 :     return aClients;
     240             : }
     241             : 
     242           0 : sal_Bool RemoteServer::connectClient( ClientInfo* pClient, rtl::OUString aPin )
     243             : {
     244             :     SAL_INFO( "sdremote", "RemoteServer::connectClient called" );
     245           0 :     if ( !spServer )
     246           0 :         return false;
     247             : 
     248           0 :     ClientInfoInternal *apClient = (ClientInfoInternal*) pClient;
     249           0 :     if ( apClient->mPin.equals( aPin ) )
     250             :     {
     251             :         // Save in settings first
     252           0 :         boost::shared_ptr< ConfigurationChanges > aChanges = ConfigurationChanges::create();
     253             :         Reference< XNameContainer > const xConfig = officecfg::Office::Impress::Misc::AuthorisedRemotes::get( aChanges );
     254             : 
     255             :         Reference<XSingleServiceFactory> xChildFactory (
     256           0 :             xConfig, UNO_QUERY);
     257           0 :         Reference<XNameReplace> xChild( xChildFactory->createInstance(), UNO_QUERY);
     258           0 :                 Any aValue;
     259           0 :         if (xChild.is())
     260             :         {
     261             :             // Check whether the client is already saved
     262           0 :             bool aSaved = false;
     263           0 :             Sequence< OUString > aNames = xConfig->getElementNames();
     264           0 :             for ( int i = 0; i < aNames.getLength(); i++ )
     265             :             {
     266           0 :                 if ( aNames[i].equals( apClient->mName ) )
     267             :                 {
     268           0 :                     xConfig->replaceByName( apClient->mName, makeAny( xChild ) );
     269           0 :                     aSaved = true;
     270           0 :                     break;
     271             :                 }
     272             :             }
     273           0 :             if ( !aSaved )
     274           0 :                 xConfig->insertByName( apClient->mName, makeAny( xChild ) );
     275           0 :             aValue <<= OUString( apClient->mPin );
     276           0 :             xChild->replaceByName("PIN", aValue);
     277           0 :             aChanges->commit();
     278             :         }
     279             : 
     280           0 :         Communicator* pCommunicator = new Communicator( apClient->mpStreamSocket );
     281           0 :         MutexGuard aGuard( sDataMutex );
     282             : 
     283           0 :         sCommunicators.push_back( pCommunicator );
     284             : 
     285           0 :         for ( vector<ClientInfoInternal*>::iterator aIt = spServer->mAvailableClients.begin();
     286           0 :             aIt != spServer->mAvailableClients.end(); ++aIt )
     287             :         {
     288           0 :             if ( pClient == *aIt )
     289             :             {
     290           0 :                 spServer->mAvailableClients.erase( aIt );
     291           0 :             break;
     292             :             }
     293             :         }
     294           0 :         pCommunicator->launch();
     295           0 :         return true;
     296             :     }
     297             :     else
     298             :     {
     299           0 :         return false;
     300             :     }
     301             : }
     302             : 
     303           3 : void SdDLL::RegisterRemotes()
     304             : {
     305             :     // Disable unless in experimental mode for now
     306             :     SAL_INFO( "sdremote", "SdDLL::RegisterRemotes called" );
     307           3 :     uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
     308           3 :     if (!xContext.is() || !officecfg::Office::Impress::Misc::Start::EnableSdremote::get(xContext))
     309           3 :         return;
     310             : 
     311           0 :     sd::RemoteServer::setup();
     312           0 :     sd::DiscoveryService::setup();
     313             : 
     314             : }
     315             : 
     316           0 : bool RemoteServer::isBluetoothDiscoverable()
     317             : {
     318             : #ifdef ENABLE_SDREMOTE_BLUETOOTH
     319           0 :     return BluetoothServer::isDiscoverable();
     320             : #else
     321             :     return false;
     322             : #endif
     323             : }
     324             : 
     325           0 : void RemoteServer::setBluetoothDiscoverable( bool aDiscoverable )
     326             : {
     327             : #ifdef ENABLE_SDREMOTE_BLUETOOTH
     328           0 :     BluetoothServer::setDiscoverable( aDiscoverable );
     329             : #else
     330             :     (void) aDiscoverable;
     331             : #endif
     332           9 : }
     333             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10