diff options
author | Michael Meeks <michael.meeks@suse.com> | 2013-02-18 14:40:24 +0000 |
---|---|---|
committer | Thorsten Behrens <tbehrens@suse.com> | 2013-02-19 13:00:29 +0100 |
commit | 4a7f9c7da446aeb6a5a9010ed7f44ffc40fc67ca (patch) | |
tree | ee24f7fec91d8628570b8f99ae9c9e0636705aee /sd/source/ui | |
parent | 25819137fe00afa6ec5cb900a742fa9368a52a16 (diff) |
sdremote: listening to dynamic changes to adapters.
Allows LibreOffice to start with no bluetooth, and for it to
appear and disappear dynamically at run-time, cleaning up stale
bluetooth sockets, and re-binding successfully each time.
Change-Id: Ifa04c8cc1859c98adca94ac0e57c7ebd85f2f31f
(cherry picked from commit 93abe8688a4700c04b5ab045eb296298e1b49031)
Signed-off-by: Thorsten Behrens <tbehrens@suse.com>
Diffstat (limited to 'sd/source/ui')
-rw-r--r-- | sd/source/ui/remotecontrol/BluetoothServer.cxx | 131 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/BluetoothServer.hxx | 1 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/BufferedStreamSocket.cxx | 13 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/BufferedStreamSocket.hxx | 2 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/Communicator.cxx | 8 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/Communicator.hxx | 1 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/IBluetoothSocket.hxx | 2 |
7 files changed, 124 insertions, 34 deletions
diff --git a/sd/source/ui/remotecontrol/BluetoothServer.cxx b/sd/source/ui/remotecontrol/BluetoothServer.cxx index a4cad7b2b7aa..69cc5934a54b 100644 --- a/sd/source/ui/remotecontrol/BluetoothServer.cxx +++ b/sd/source/ui/remotecontrol/BluetoothServer.cxx @@ -222,15 +222,17 @@ bluezRegisterServiceRecord( DBusConnection *pConnection, DBusObject *pAdapter, return true; } -static int -bluezCreateListeningSocket() +static void +bluezCreateAttachListeningSocket( GMainContext *pContext, GPollFD *pSocketFD ) { int nSocket; + pSocketFD->fd = -1; + if( ( nSocket = socket( AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM ) ) < 0 ) { SAL_WARN( "sdremote.bluetooth", "failed to open bluetooth socket with error " << nSocket ); - return -1; + return; } sockaddr_rc aAddr; @@ -243,24 +245,39 @@ bluezCreateListeningSocket() if ( ( a = bind( nSocket, (sockaddr*) &aAddr, sizeof(aAddr) ) ) < 0 ) { SAL_WARN( "sdremote.bluetooth", "bind failed with error" << a ); close( nSocket ); - return -1; + return; } if ( ( a = listen( nSocket, 1 ) ) < 0 ) { SAL_WARN( "sdremote.bluetooth", "listen failed with error" << a ); close( nSocket ); - return -1; + return; } // set non-blocking behaviour ... if( fcntl( nSocket, F_SETFL, O_NONBLOCK) < 0 ) { close( nSocket ); - return -1; + return; } - return nSocket; + pSocketFD->fd = nSocket; + pSocketFD->events = G_IO_IN | G_IO_PRI; + pSocketFD->revents = 0; + + g_main_context_add_poll( pContext, pSocketFD, G_PRIORITY_DEFAULT ); +} + +static void +bluezDetachCloseSocket( GMainContext *pContext, GPollFD *pSocketFD ) +{ + if( pSocketFD->fd >= 0 ) + { + close( pSocketFD->fd ); + g_main_context_remove_poll( pContext, pSocketFD ); + pSocketFD->fd = -1; + } } #endif // LINUX_BLUETOOTH @@ -552,6 +569,24 @@ setDiscoverable( DBusConnection *pConnection, DBusObject *pAdapter, bool bDiscov dbus_message_unref( pMsg ); } +static DBusObject * +registerWithDefaultAdapter( DBusConnection *pConnection ) +{ + DBusObject *pService; + pService = bluezGetDefaultService( pConnection ); + if( !pService ) + return NULL; + + if( !bluezRegisterServiceRecord( pConnection, pService, + bluetooth_service_record ) ) + { + delete pService; + return NULL; + } + + return pService; +} + #endif // LINUX_BLUETOOTH BluetoothServer::BluetoothServer( std::vector<Communicator*>* pCommunicators ) @@ -636,6 +671,17 @@ void BluetoothServer::doRestoreDiscoverable() spServer->meWasDiscoverable = UNKNOWN; } +// We have to have all our clients shut otherwise we can't +// re-bind to the same port number it appears. +void BluetoothServer::cleanupCommunicators() +{ + for (std::vector<Communicator *>::iterator it = mpCommunicators->begin(); + it != mpCommunicators->end(); it++) + (*it)->forceClose(); + // the hope is that all the threads then terminate cleanly and + // clean themselves up. +} + void SAL_CALL BluetoothServer::run() { SAL_INFO( "sdremote.bluetooth", "BluetoothServer::run called" ); @@ -645,33 +691,20 @@ void SAL_CALL BluetoothServer::run() if( !pConnection ) return; - mpImpl->mpService = bluezGetDefaultService( pConnection ); - if( !mpImpl->mpService ) - { - dbus_connection_unref( pConnection ); - return; - } - - if( !bluezRegisterServiceRecord( pConnection, mpImpl->mpService, - bluetooth_service_record ) ) - return; - - int nSocket = bluezCreateListeningSocket(); - if( nSocket < 0 ) - return; - - // ---------------- Socket code ---------------- - - sockaddr_rc aRemoteAddr; - socklen_t aRemoteAddrLen = sizeof(aRemoteAddr); + // listen for connection state and power changes - we need to close + // and re-create our socket code on suspend / resume, enable/disable + DBusError aError; + dbus_error_init( &aError ); + dbus_bus_add_match( pConnection, "type='signal',interface='org.bluez.Manager'", &aError ); + dbus_connection_flush( pConnection ); - // Avoid using GSources where we can + // Try to setup the default adapter, otherwise wait for add/remove signal + mpImpl->mpService = registerWithDefaultAdapter( pConnection ); - // poll on our socket + // poll on our bluetooth socket - if we can. GPollFD aSocketFD; - aSocketFD.fd = nSocket; - aSocketFD.events = G_IO_IN | G_IO_PRI; - g_main_context_add_poll( mpImpl->mpContext, &aSocketFD, G_PRIORITY_DEFAULT ); + if( mpImpl->mpService ) + bluezCreateAttachListeningSocket( mpImpl->mpContext, &aSocketFD ); // also poll on our dbus connection int fd = -1; @@ -696,13 +729,45 @@ void SAL_CALL BluetoothServer::run() SAL_INFO( "sdremote.bluetooth", "main-loop spin " << aDBusFD.revents << " " << aSocketFD.revents ); if( aDBusFD.revents ) - dbus_connection_read_write_dispatch( pConnection, 0 ); + { + dbus_connection_read_write( pConnection, 0 ); + DBusMessage *pMsg = dbus_connection_pop_message( pConnection ); + if( pMsg ) + { + if( dbus_message_is_signal( pMsg, "org.bluez.Manager", "AdapterRemoved" ) ) + { + SAL_WARN( "sdremote.bluetooth", "lost adapter - cleaning up sockets" ); + bluezDetachCloseSocket( mpImpl->mpContext, &aSocketFD ); + cleanupCommunicators(); + } + else if( dbus_message_is_signal( pMsg, "org.bluez.Manager", "AdapterAdded" ) || + dbus_message_is_signal( pMsg, "org.bluez.Manager", "DefaultAdapterChanged" ) ) + { + SAL_WARN( "sdremote.bluetooth", "gained adapter - re-generating sockets" ); + bluezDetachCloseSocket( mpImpl->mpContext, &aSocketFD ); + cleanupCommunicators(); + mpImpl->mpService = registerWithDefaultAdapter( pConnection ); + if( mpImpl->mpService ) + bluezCreateAttachListeningSocket( mpImpl->mpContext, &aSocketFD ); + } + else + SAL_INFO( "sdremote.bluetooth", "unknown incoming dbus message, " + << " type: " << dbus_message_get_type( pMsg ) + << " path: '" << dbus_message_get_path( pMsg ) + << "' interface: '" << dbus_message_get_interface( pMsg ) + << "' member: '" << dbus_message_get_member( pMsg ) ); + } + dbus_message_unref( pMsg ); + } if( aSocketFD.revents ) { + sockaddr_rc aRemoteAddr; + socklen_t aRemoteAddrLen = sizeof(aRemoteAddr); + int nClient; SAL_INFO( "sdremote.bluetooth", "performing accept" ); - if ( ( nClient = accept( nSocket, (sockaddr*) &aRemoteAddr, &aRemoteAddrLen)) < 0 && + if ( ( nClient = accept( aSocketFD.fd, (sockaddr*) &aRemoteAddr, &aRemoteAddrLen)) < 0 && errno != EAGAIN ) { SAL_WARN( "sdremote.bluetooth", "accept failed with errno " << errno ); diff --git a/sd/source/ui/remotecontrol/BluetoothServer.hxx b/sd/source/ui/remotecontrol/BluetoothServer.hxx index 24b8dec36ba2..8078edeb6b81 100644 --- a/sd/source/ui/remotecontrol/BluetoothServer.hxx +++ b/sd/source/ui/remotecontrol/BluetoothServer.hxx @@ -43,6 +43,7 @@ namespace sd BluetoothServerImpl *mpImpl; virtual void SAL_CALL run(); + void cleanupCommunicators(); std::vector<Communicator*>* mpCommunicators; }; } diff --git a/sd/source/ui/remotecontrol/BufferedStreamSocket.cxx b/sd/source/ui/remotecontrol/BufferedStreamSocket.cxx index d35b6065523d..c4f7f611f665 100644 --- a/sd/source/ui/remotecontrol/BufferedStreamSocket.cxx +++ b/sd/source/ui/remotecontrol/BufferedStreamSocket.cxx @@ -27,7 +27,7 @@ BufferedStreamSocket::BufferedStreamSocket( const osl::StreamSocket &aSocket ): aRead( 0 ), aBuffer(), mSocket( 0 ), - usingCSocket( false) + usingCSocket( false ) { } @@ -55,6 +55,17 @@ sal_Int32 BufferedStreamSocket::write( const void* pBuffer, sal_uInt32 n ) return ::send( mSocket, (const char *) pBuffer, (size_t) n, 0 ); } +void BufferedStreamSocket::close() +{ + if( usingCSocket ) + { + ::close( mSocket ); + mSocket = -1; + } + else + close(); +} + sal_Int32 BufferedStreamSocket::readLine( OString& aLine ) { while ( true ) diff --git a/sd/source/ui/remotecontrol/BufferedStreamSocket.hxx b/sd/source/ui/remotecontrol/BufferedStreamSocket.hxx index 0e6b99aa5f22..005cc7342a63 100644 --- a/sd/source/ui/remotecontrol/BufferedStreamSocket.hxx +++ b/sd/source/ui/remotecontrol/BufferedStreamSocket.hxx @@ -51,6 +51,8 @@ namespace sd virtual sal_Int32 write( const void* pBuffer, sal_uInt32 n ); + virtual void close(); + void getPeerAddr(osl::SocketAddr&); private: sal_Int32 aRet, aRead; diff --git a/sd/source/ui/remotecontrol/Communicator.cxx b/sd/source/ui/remotecontrol/Communicator.cxx index 7f013349153e..de73dcce9338 100644 --- a/sd/source/ui/remotecontrol/Communicator.cxx +++ b/sd/source/ui/remotecontrol/Communicator.cxx @@ -33,6 +33,14 @@ Communicator::~Communicator() { } +/// Close the underlying socket from another thread to force +/// an early exit / termination +void Communicator::forceClose() +{ + if( mpSocket ) + mpSocket->close(); +} + // Run as a thread void Communicator::execute() { diff --git a/sd/source/ui/remotecontrol/Communicator.hxx b/sd/source/ui/remotecontrol/Communicator.hxx index a783bacb7672..7883401eff65 100644 --- a/sd/source/ui/remotecontrol/Communicator.hxx +++ b/sd/source/ui/remotecontrol/Communicator.hxx @@ -43,6 +43,7 @@ namespace sd css::presentation::XSlideShowController > &rController ); void informListenerDestroyed(); void disposeListener(); + void forceClose(); private: void execute(); diff --git a/sd/source/ui/remotecontrol/IBluetoothSocket.hxx b/sd/source/ui/remotecontrol/IBluetoothSocket.hxx index 194936730058..0359807d549f 100644 --- a/sd/source/ui/remotecontrol/IBluetoothSocket.hxx +++ b/sd/source/ui/remotecontrol/IBluetoothSocket.hxx @@ -33,6 +33,8 @@ namespace sd @return number of bytes actually written */ virtual sal_Int32 write( const void* pBuffer, sal_uInt32 n ) = 0; + + virtual void close() {}; }; } |