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