summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2013-02-18 14:40:24 +0000
committerThorsten Behrens <tbehrens@suse.com>2013-02-19 13:00:29 +0100
commit4a7f9c7da446aeb6a5a9010ed7f44ffc40fc67ca (patch)
treeee24f7fec91d8628570b8f99ae9c9e0636705aee
parent25819137fe00afa6ec5cb900a742fa9368a52a16 (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>
-rw-r--r--sd/source/ui/remotecontrol/BluetoothServer.cxx131
-rw-r--r--sd/source/ui/remotecontrol/BluetoothServer.hxx1
-rw-r--r--sd/source/ui/remotecontrol/BufferedStreamSocket.cxx13
-rw-r--r--sd/source/ui/remotecontrol/BufferedStreamSocket.hxx2
-rw-r--r--sd/source/ui/remotecontrol/Communicator.cxx8
-rw-r--r--sd/source/ui/remotecontrol/Communicator.hxx1
-rw-r--r--sd/source/ui/remotecontrol/IBluetoothSocket.hxx2
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() {};
};
}