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