summaryrefslogtreecommitdiff
path: root/sd/source/ui
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2013-02-18 14:40:24 +0000
committerMichael Meeks <michael.meeks@suse.com>2013-02-19 09:12:20 +0000
commitc45e45c5c3d1570cc8fe688c715d3fd9795abbe1 (patch)
tree19f4c935686bb68bf4b0e92d37e6b831d96aba32 /sd/source/ui
parente8f2870be12b8886cb58f5c35f607c00ebe96ea3 (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
Diffstat (limited to 'sd/source/ui')
-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 164b81322cff..5692406b1a67 100644
--- a/sd/source/ui/remotecontrol/BluetoothServer.cxx
+++ b/sd/source/ui/remotecontrol/BluetoothServer.cxx
@@ -214,15 +214,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;
@@ -235,24 +237,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
@@ -544,6 +561,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 )
@@ -628,6 +663,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" );
@@ -637,33 +683,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;
@@ -688,13 +721,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 01c79720310d..30022d6c526a 100644
--- a/sd/source/ui/remotecontrol/BufferedStreamSocket.cxx
+++ b/sd/source/ui/remotecontrol/BufferedStreamSocket.cxx
@@ -31,7 +31,7 @@ BufferedStreamSocket::BufferedStreamSocket( const osl::StreamSocket &aSocket ):
aRead( 0 ),
aBuffer(),
mSocket( 0 ),
- usingCSocket( false)
+ usingCSocket( false )
{
}
@@ -59,6 +59,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 908f732d0a07..e5459fb39166 100644
--- a/sd/source/ui/remotecontrol/Communicator.cxx
+++ b/sd/source/ui/remotecontrol/Communicator.cxx
@@ -34,6 +34,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() {};
};
}