1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
13 #include <officecfg/Office/Common.hxx>
14 #include <officecfg/Office/Impress.hxx>
16 #include <com/sun/star/container/XNameAccess.hpp>
17 #include <com/sun/star/container/XNameContainer.hpp>
18 #include <com/sun/star/uno/Sequence.hxx>
20 #include <comphelper/processfactory.hxx>
21 #include <comphelper/configuration.hxx>
22 #include <sal/log.hxx>
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"
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
;
46 * Used to keep track of clients that have attempted to connect, but haven't
49 struct ClientInfoInternal
:
52 BufferedStreamSocket
*mpStreamSocket
;
55 ClientInfoInternal( const OUString rName
,
56 const OUString rAddress
,
57 BufferedStreamSocket
*pSocket
, OUString rPin
):
58 ClientInfo( rName
, rAddress
),
59 mpStreamSocket( pSocket
),
64 RemoteServer::RemoteServer() :
65 Thread( "RemoteServerThread" ),
69 SAL_INFO( "sdremote", "Instantiated RemoteServer" );
72 RemoteServer::~RemoteServer()
76 void RemoteServer::execute()
78 SAL_INFO( "sdremote", "RemoteServer::execute called" );
79 uno::Reference
< uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
80 if (!xContext
.is() || !officecfg::Office::Common::Misc::ExperimentalMode::get(xContext
))
82 SAL_INFO("sdremote", "not in experimental mode, disabling TCP server");
86 osl::SocketAddr
aAddr( "0", PORT
);
87 if ( !mSocket
.bind( aAddr
) )
89 SAL_WARN( "sdremote", "bind failed" << mSocket
.getErrorAsString() );
94 if ( !mSocket
.listen(3) )
96 SAL_WARN( "sdremote", "listen failed" << mSocket
.getErrorAsString() );
102 StreamSocket aSocket
;
103 SAL_INFO( "sdremote", "waiting on accept" );
104 if ( mSocket
.acceptConnection( aSocket
) == osl_Socket_Error
)
106 SAL_WARN( "sdremote", "accept failed" << mSocket
.getErrorAsString() );
108 return; // Closed, or other issue.
110 BufferedStreamSocket
*pSocket
= new BufferedStreamSocket( aSocket
);
112 if ( pSocket
->readLine( aLine
)
113 && aLine
.equals( "LO_SERVER_CLIENT_PAIR" ) &&
114 pSocket
->readLine( aLine
) )
116 OString
aName( aLine
);
118 if ( ! pSocket
->readLine( aLine
) ) delete pSocket
;
119 OString
aPin( aLine
);
121 SocketAddr aClientAddr
;
122 pSocket
->getPeerAddr( aClientAddr
);
123 OUString aAddress
= aClientAddr
.getHostname();
125 MutexGuard
aGuard( sDataMutex
);
126 ClientInfoInternal
* pClient
= new ClientInfoInternal(
127 OStringToOUString( aName
, RTL_TEXTENCODING_UTF8
),
128 aAddress
, pSocket
, OStringToOUString( aPin
,
129 RTL_TEXTENCODING_UTF8
) );
130 mAvailableClients
.push_back( pClient
);
132 // Read off any additional non-empty lines
133 // We know that we at least have the empty termination line to read.
136 pSocket
->readLine( aLine
);
138 while ( aLine
.getLength() > 0 );
140 // Check if we already have this server.
141 Reference
< XNameAccess
> const xConfig
= officecfg::Office::Impress::Misc::AuthorisedRemotes::get();
142 Sequence
< OUString
> aNames
= xConfig
->getElementNames();
144 for ( int i
= 0; i
< aNames
.getLength(); i
++ )
146 if ( aNames
[i
].equals( pClient
->mName
) )
148 Reference
<XNameAccess
> xSetItem( xConfig
->getByName(aNames
[i
]), UNO_QUERY
);
149 Any
axPin(xSetItem
->getByName("PIN"));
153 if ( sPin
.equals( pClient
->mPin
) ) {
154 SAL_INFO( "sdremote", "client found on validated list -- connecting" );
155 connectClient( pClient
, sPin
);
162 // Pin not found so inform the client.
165 SAL_INFO( "sdremote", "client not found on validated list" );
166 pSocket
->write( "LO_SERVER_VALIDATING_PIN\n\n",
167 strlen( "LO_SERVER_VALIDATING_PIN\n\n" ) );
170 SAL_INFO( "sdremote", "client failed to send LO_SERVER_CLIENT_PAIR, ignoring" );
174 spServer
= NULL
; // Object is destroyed when Thread::execute() ends.
177 RemoteServer
*sd::RemoteServer::spServer
= NULL
;
178 ::osl::Mutex
sd::RemoteServer::sDataMutex
;
179 ::std::vector
<Communicator
*> sd::RemoteServer::sCommunicators
;
181 void RemoteServer::setup()
186 spServer
= new RemoteServer();
189 #ifdef ENABLE_SDREMOTE_BLUETOOTH
190 sd::BluetoothServer::setup( &sCommunicators
);
195 void RemoteServer::presentationStarted( const css::uno::Reference
<
196 css::presentation::XSlideShowController
> &rController
)
200 MutexGuard
aGuard( sDataMutex
);
201 for ( vector
<Communicator
*>::const_iterator aIt
= sCommunicators
.begin();
202 aIt
!= sCommunicators
.end(); ++aIt
)
204 (*aIt
)->presentationStarted( rController
);
207 void RemoteServer::presentationStopped()
211 MutexGuard
aGuard( sDataMutex
);
212 for ( vector
<Communicator
*>::const_iterator aIt
= sCommunicators
.begin();
213 aIt
!= sCommunicators
.end(); ++aIt
)
215 (*aIt
)->disposeListener();
219 void RemoteServer::removeCommunicator( Communicator
* mCommunicator
)
223 MutexGuard
aGuard( sDataMutex
);
224 for ( vector
<Communicator
*>::iterator aIt
= sCommunicators
.begin();
225 aIt
!= sCommunicators
.end(); ++aIt
)
227 if ( mCommunicator
== *aIt
)
229 sCommunicators
.erase( aIt
);
235 std::vector
<ClientInfo
*> RemoteServer::getClients()
237 SAL_INFO( "sdremote", "RemoteServer::getClients() called" );
238 std::vector
<ClientInfo
*> aClients
;
241 SAL_INFO( "sdremote", "No remote server instance => no clients" );
245 MutexGuard
aGuard( sDataMutex
);
246 aClients
.assign( spServer
->mAvailableClients
.begin(),
247 spServer
->mAvailableClients
.end() );
251 sal_Bool
RemoteServer::connectClient( ClientInfo
* pClient
, OUString aPin
)
253 SAL_INFO( "sdremote", "RemoteServer::connectClient called" );
257 ClientInfoInternal
*apClient
= (ClientInfoInternal
*) pClient
;
258 if ( apClient
->mPin
.equals( aPin
) )
260 // Save in settings first
261 boost::shared_ptr
< ConfigurationChanges
> aChanges
= ConfigurationChanges::create();
262 Reference
< XNameContainer
> const xConfig
= officecfg::Office::Impress::Misc::AuthorisedRemotes::get( aChanges
);
264 Reference
<XSingleServiceFactory
> xChildFactory (
266 Reference
<XNameReplace
> xChild( xChildFactory
->createInstance(), UNO_QUERY
);
270 // Check whether the client is already saved
272 Sequence
< OUString
> aNames
= xConfig
->getElementNames();
273 for ( int i
= 0; i
< aNames
.getLength(); i
++ )
275 if ( aNames
[i
].equals( apClient
->mName
) )
277 xConfig
->replaceByName( apClient
->mName
, makeAny( xChild
) );
283 xConfig
->insertByName( apClient
->mName
, makeAny( xChild
) );
284 aValue
<<= OUString( apClient
->mPin
);
285 xChild
->replaceByName("PIN", aValue
);
289 Communicator
* pCommunicator
= new Communicator( apClient
->mpStreamSocket
);
290 MutexGuard
aGuard( sDataMutex
);
292 sCommunicators
.push_back( pCommunicator
);
294 for ( vector
<ClientInfoInternal
*>::iterator aIt
= spServer
->mAvailableClients
.begin();
295 aIt
!= spServer
->mAvailableClients
.end(); ++aIt
)
297 if ( pClient
== *aIt
)
299 spServer
->mAvailableClients
.erase( aIt
);
303 pCommunicator
->launch();
312 void SdDLL::RegisterRemotes()
314 // Disable unless in experimental mode for now
315 SAL_INFO( "sdremote", "SdDLL::RegisterRemotes called" );
316 uno::Reference
< uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
317 if ( xContext
.is() && !officecfg::Office::Impress::Misc::Start::EnableSdremote::get( xContext
) )
320 sd::RemoteServer::setup();
321 sd::DiscoveryService::setup();
324 void RemoteServer::ensureDiscoverable()
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 BluetoothServer::ensureDiscoverable();
333 void RemoteServer::restoreDiscoverable()
335 #ifdef ENABLE_SDREMOTE_BLUETOOTH
336 BluetoothServer::restoreDiscoverable();
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */