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

Generated by: LCOV version 1.10