Kaydet (Commit) c45e45c5 authored tarafından Michael Meeks's avatar Michael Meeks

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
üst e8f2870b
...@@ -214,15 +214,17 @@ bluezRegisterServiceRecord( DBusConnection *pConnection, DBusObject *pAdapter, ...@@ -214,15 +214,17 @@ bluezRegisterServiceRecord( DBusConnection *pConnection, DBusObject *pAdapter,
return true; return true;
} }
static int static void
bluezCreateListeningSocket() bluezCreateAttachListeningSocket( GMainContext *pContext, GPollFD *pSocketFD )
{ {
int nSocket; int nSocket;
pSocketFD->fd = -1;
if( ( nSocket = socket( AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM ) ) < 0 ) if( ( nSocket = socket( AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM ) ) < 0 )
{ {
SAL_WARN( "sdremote.bluetooth", "failed to open bluetooth socket with error " << nSocket ); SAL_WARN( "sdremote.bluetooth", "failed to open bluetooth socket with error " << nSocket );
return -1; return;
} }
sockaddr_rc aAddr; sockaddr_rc aAddr;
...@@ -235,24 +237,39 @@ bluezCreateListeningSocket() ...@@ -235,24 +237,39 @@ bluezCreateListeningSocket()
if ( ( a = bind( nSocket, (sockaddr*) &aAddr, sizeof(aAddr) ) ) < 0 ) { if ( ( a = bind( nSocket, (sockaddr*) &aAddr, sizeof(aAddr) ) ) < 0 ) {
SAL_WARN( "sdremote.bluetooth", "bind failed with error" << a ); SAL_WARN( "sdremote.bluetooth", "bind failed with error" << a );
close( nSocket ); close( nSocket );
return -1; return;
} }
if ( ( a = listen( nSocket, 1 ) ) < 0 ) if ( ( a = listen( nSocket, 1 ) ) < 0 )
{ {
SAL_WARN( "sdremote.bluetooth", "listen failed with error" << a ); SAL_WARN( "sdremote.bluetooth", "listen failed with error" << a );
close( nSocket ); close( nSocket );
return -1; return;
} }
// set non-blocking behaviour ... // set non-blocking behaviour ...
if( fcntl( nSocket, F_SETFL, O_NONBLOCK) < 0 ) if( fcntl( nSocket, F_SETFL, O_NONBLOCK) < 0 )
{ {
close( nSocket ); 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 #endif // LINUX_BLUETOOTH
...@@ -544,6 +561,24 @@ setDiscoverable( DBusConnection *pConnection, DBusObject *pAdapter, bool bDiscov ...@@ -544,6 +561,24 @@ setDiscoverable( DBusConnection *pConnection, DBusObject *pAdapter, bool bDiscov
dbus_message_unref( pMsg ); 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 #endif // LINUX_BLUETOOTH
BluetoothServer::BluetoothServer( std::vector<Communicator*>* pCommunicators ) BluetoothServer::BluetoothServer( std::vector<Communicator*>* pCommunicators )
...@@ -628,6 +663,17 @@ void BluetoothServer::doRestoreDiscoverable() ...@@ -628,6 +663,17 @@ void BluetoothServer::doRestoreDiscoverable()
spServer->meWasDiscoverable = UNKNOWN; 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() void SAL_CALL BluetoothServer::run()
{ {
SAL_INFO( "sdremote.bluetooth", "BluetoothServer::run called" ); SAL_INFO( "sdremote.bluetooth", "BluetoothServer::run called" );
...@@ -637,33 +683,20 @@ void SAL_CALL BluetoothServer::run() ...@@ -637,33 +683,20 @@ void SAL_CALL BluetoothServer::run()
if( !pConnection ) if( !pConnection )
return; return;
mpImpl->mpService = bluezGetDefaultService( pConnection ); // listen for connection state and power changes - we need to close
if( !mpImpl->mpService ) // and re-create our socket code on suspend / resume, enable/disable
{ DBusError aError;
dbus_connection_unref( pConnection ); dbus_error_init( &aError );
return; dbus_bus_add_match( pConnection, "type='signal',interface='org.bluez.Manager'", &aError );
} dbus_connection_flush( pConnection );
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);
// 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; GPollFD aSocketFD;
aSocketFD.fd = nSocket; if( mpImpl->mpService )
aSocketFD.events = G_IO_IN | G_IO_PRI; bluezCreateAttachListeningSocket( mpImpl->mpContext, &aSocketFD );
g_main_context_add_poll( mpImpl->mpContext, &aSocketFD, G_PRIORITY_DEFAULT );
// also poll on our dbus connection // also poll on our dbus connection
int fd = -1; int fd = -1;
...@@ -688,13 +721,45 @@ void SAL_CALL BluetoothServer::run() ...@@ -688,13 +721,45 @@ void SAL_CALL BluetoothServer::run()
SAL_INFO( "sdremote.bluetooth", "main-loop spin " SAL_INFO( "sdremote.bluetooth", "main-loop spin "
<< aDBusFD.revents << " " << aSocketFD.revents ); << aDBusFD.revents << " " << aSocketFD.revents );
if( aDBusFD.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 ) if( aSocketFD.revents )
{ {
sockaddr_rc aRemoteAddr;
socklen_t aRemoteAddrLen = sizeof(aRemoteAddr);
int nClient; int nClient;
SAL_INFO( "sdremote.bluetooth", "performing accept" ); 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 ) errno != EAGAIN )
{ {
SAL_WARN( "sdremote.bluetooth", "accept failed with errno " << errno ); SAL_WARN( "sdremote.bluetooth", "accept failed with errno " << errno );
......
...@@ -43,6 +43,7 @@ namespace sd ...@@ -43,6 +43,7 @@ namespace sd
BluetoothServerImpl *mpImpl; BluetoothServerImpl *mpImpl;
virtual void SAL_CALL run(); virtual void SAL_CALL run();
void cleanupCommunicators();
std::vector<Communicator*>* mpCommunicators; std::vector<Communicator*>* mpCommunicators;
}; };
} }
......
...@@ -31,7 +31,7 @@ BufferedStreamSocket::BufferedStreamSocket( const osl::StreamSocket &aSocket ): ...@@ -31,7 +31,7 @@ BufferedStreamSocket::BufferedStreamSocket( const osl::StreamSocket &aSocket ):
aRead( 0 ), aRead( 0 ),
aBuffer(), aBuffer(),
mSocket( 0 ), mSocket( 0 ),
usingCSocket( false) usingCSocket( false )
{ {
} }
...@@ -59,6 +59,17 @@ sal_Int32 BufferedStreamSocket::write( const void* pBuffer, sal_uInt32 n ) ...@@ -59,6 +59,17 @@ sal_Int32 BufferedStreamSocket::write( const void* pBuffer, sal_uInt32 n )
return ::send( mSocket, (const char *) pBuffer, (size_t) n, 0 ); 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 ) sal_Int32 BufferedStreamSocket::readLine( OString& aLine )
{ {
while ( true ) while ( true )
......
...@@ -51,6 +51,8 @@ namespace sd ...@@ -51,6 +51,8 @@ namespace sd
virtual sal_Int32 write( const void* pBuffer, sal_uInt32 n ); virtual sal_Int32 write( const void* pBuffer, sal_uInt32 n );
virtual void close();
void getPeerAddr(osl::SocketAddr&); void getPeerAddr(osl::SocketAddr&);
private: private:
sal_Int32 aRet, aRead; sal_Int32 aRet, aRead;
......
...@@ -34,6 +34,14 @@ Communicator::~Communicator() ...@@ -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 // Run as a thread
void Communicator::execute() void Communicator::execute()
{ {
......
...@@ -43,6 +43,7 @@ namespace sd ...@@ -43,6 +43,7 @@ namespace sd
css::presentation::XSlideShowController > &rController ); css::presentation::XSlideShowController > &rController );
void informListenerDestroyed(); void informListenerDestroyed();
void disposeListener(); void disposeListener();
void forceClose();
private: private:
void execute(); void execute();
......
...@@ -33,6 +33,8 @@ namespace sd ...@@ -33,6 +33,8 @@ namespace sd
@return number of bytes actually written @return number of bytes actually written
*/ */
virtual sal_Int32 write( const void* pBuffer, sal_uInt32 n ) = 0; virtual sal_Int32 write( const void* pBuffer, sal_uInt32 n ) = 0;
virtual void close() {};
}; };
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment