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: */
|