summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2013-02-18 11:30:54 +0000
committerThorsten Behrens <tbehrens@suse.com>2013-02-19 13:00:19 +0100
commit7848b97462a088521986ba200ee2fd55982667bb (patch)
tree64fd42b9f275560c808a0935c1833c8464e8cd44
parent84f1c87936fa13ea937cd02ec79a3b29ed26c5d1 (diff)
sdremote: switch to a non-blocking socket, and polling glib mainloop.
Conflicts: sd/source/ui/remotecontrol/BluetoothServer.cxx Change-Id: I84c0a522fe16fbc8fc86a8e4bccb84aec0a1acd1 (cherry picked from commit 0d89d814055d5c267a2cc57e302a23e9f0b521e3) Signed-off-by: Thorsten Behrens <tbehrens@suse.com>
-rw-r--r--sd/source/ui/remotecontrol/BluetoothServer.cxx94
-rw-r--r--sd/source/ui/remotecontrol/BluetoothServer.hxx3
2 files changed, 77 insertions, 20 deletions
diff --git a/sd/source/ui/remotecontrol/BluetoothServer.cxx b/sd/source/ui/remotecontrol/BluetoothServer.cxx
index 2ccfc8738195..5229e9d56723 100644
--- a/sd/source/ui/remotecontrol/BluetoothServer.cxx
+++ b/sd/source/ui/remotecontrol/BluetoothServer.cxx
@@ -15,9 +15,15 @@
#include <sal/log.hxx>
#if (defined(LINUX) && !defined(__FreeBSD_kernel__)) && defined(ENABLE_DBUS)
+# define LINUX_BLUETOOTH
+#endif
+
+#ifdef LINUX_BLUETOOTH
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
+ #include <errno.h>
+ #include <fcntl.h>
#include <sys/unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
@@ -75,7 +81,13 @@
using namespace sd;
-#if (defined(LINUX) && !defined(__FreeBSD_kernel__)) && defined(ENABLE_DBUS)
+#ifdef LINUX_BLUETOOTH
+
+struct sd::BluetoothServerImpl {
+ // the glib mainloop running in the thread
+ GMainContext *mpContext;
+ volatile bool mbExitMainloop;
+};
struct DBusObject {
OString maBusName;
@@ -230,6 +242,13 @@ bluezCreateListeningSocket()
return -1;
}
+ // set non-blocking behaviour ...
+ if( fcntl( nSocket, F_SETFL, O_NONBLOCK) < 0 )
+ {
+ close( nSocket );
+ return -1;
+ }
+
return nSocket;
}
@@ -386,8 +405,15 @@ void incomingCallback( void *userRefCon,
BluetoothServer::BluetoothServer( std::vector<Communicator*>* pCommunicators )
: meWasDiscoverable( UNKNOWN ),
+ mpImpl( NULL ),
mpCommunicators( pCommunicators )
{
+#ifdef LINUX_BLUETOOTH
+ g_type_init();
+ mpImpl = new BluetoothServerImpl();
+ mpImpl->mpContext = g_main_context_new();
+ mpImpl->mbExitMainloop = false;
+#endif
}
BluetoothServer::~BluetoothServer()
@@ -569,10 +595,9 @@ void BluetoothServer::addCommunicator( Communicator* pCommunicator )
void SAL_CALL BluetoothServer::run()
{
- SAL_INFO( "sdremote.bluetooth", "BluetoothServer::execute called" );
-#if (defined(LINUX) && !defined(__FreeBSD_kernel__)) && defined(ENABLE_DBUS)
- g_type_init();
+ SAL_INFO( "sdremote.bluetooth", "BluetoothServer::run called" );
+#ifdef LINUX_BLUETOOTH
DBusConnection *pConnection = dbusConnectToNameOnBus();
if( !pConnection )
return;
@@ -587,8 +612,8 @@ void SAL_CALL BluetoothServer::run()
if( !bluezRegisterServiceRecord( pConnection, pService, bluetooth_service_record ) )
return;
- int aSocket = bluezCreateListeningSocket();
- if( aSocket < 0 )
+ int nSocket = bluezCreateListeningSocket();
+ if( nSocket < 0 )
return;
// ---------------- Socket code ----------------
@@ -596,22 +621,51 @@ void SAL_CALL BluetoothServer::run()
sockaddr_rc aRemoteAddr;
socklen_t aRemoteAddrLen = sizeof(aRemoteAddr);
- // FIXME: use a glib main-loop [!] ...
- // FIXME: fixme ! ...
- while ( true )
+ // Avoid using GSources where we can
+
+ // poll on our socket
+ GPollFD aSocketFD;
+ aSocketFD.fd = nSocket;
+ aSocketFD.events = G_IO_IN | G_IO_PRI;
+ g_main_context_add_poll( mpImpl->mpContext, &aSocketFD, G_PRIORITY_DEFAULT );
+
+ // also poll on our dbus connection
+ int fd = -1;
+ GPollFD aDBusFD;
+ if( dbus_connection_get_unix_fd( pConnection, &fd ) && fd >= 0 )
{
- int bSocket;
- SAL_INFO( "sdremote.bluetooth", "waiting on accept" );
- if ( (bSocket = accept(aSocket, (sockaddr*) &aRemoteAddr, &aRemoteAddrLen)) < 0 )
+ aDBusFD.fd = fd;
+ aDBusFD.events = G_IO_IN | G_IO_PRI;
+ g_main_context_add_poll( mpImpl->mpContext, &aDBusFD, G_PRIORITY_DEFAULT );
+ }
+ else
+ SAL_WARN( "sdremote.bluetooth", "failed to poll for incoming dbus signals" );
+
+ while( !mpImpl->mbExitMainloop )
+ {
+ aDBusFD.revents = 0;
+ aSocketFD.revents = 0;
+ g_main_context_iteration( mpImpl->mpContext, TRUE );
+
+ SAL_INFO( "sdremote.bluetooth", "main-loop spin "
+ << aDBusFD.revents << " " << aSocketFD.revents );
+ if( aDBusFD.revents )
+ dbus_connection_read_write_dispatch( pConnection, 0 );
+
+ if( aSocketFD.revents )
{
- SAL_WARN( "sdremote.bluetooth", "accept failed with error" << bSocket );
- close( aSocket );
- return;
- } else {
- SAL_INFO( "sdremote.bluetooth", "connection accepted" );
- Communicator* pCommunicator = new Communicator( new BufferedStreamSocket( bSocket) );
- mpCommunicators->push_back( pCommunicator );
- pCommunicator->launch();
+ int nClient;
+ SAL_INFO( "sdremote.bluetooth", "performing accept" );
+ if ( ( nClient = accept( nSocket, (sockaddr*) &aRemoteAddr, &aRemoteAddrLen)) < 0 &&
+ errno != EAGAIN )
+ {
+ SAL_WARN( "sdremote.bluetooth", "accept failed with errno " << errno );
+ } else {
+ SAL_INFO( "sdremote.bluetooth", "connection accepted " << nClient );
+ Communicator* pCommunicator = new Communicator( new BufferedStreamSocket( nClient ) );
+ mpCommunicators->push_back( pCommunicator );
+ pCommunicator->launch();
+ }
}
}
diff --git a/sd/source/ui/remotecontrol/BluetoothServer.hxx b/sd/source/ui/remotecontrol/BluetoothServer.hxx
index 5b986fae210c..b922d6094901 100644
--- a/sd/source/ui/remotecontrol/BluetoothServer.hxx
+++ b/sd/source/ui/remotecontrol/BluetoothServer.hxx
@@ -16,6 +16,7 @@ namespace sd
{
class Communicator;
+ struct BluetoothServerImpl;
class BluetoothServer:
public osl::Thread
{
@@ -39,7 +40,9 @@ namespace sd
enum { UNKNOWN, DISCOVERABLE, NOT_DISCOVERABLE } meWasDiscoverable;
static BluetoothServer *spServer;
+ BluetoothServerImpl *mpImpl;
virtual void SAL_CALL run();
+
std::vector<Communicator*>* mpCommunicators;
};
}