Presence Detection: listen connman signals instead of polling (mb#10438)
This commit is contained in:
parent
82465b359b
commit
5ec64c4504
|
@ -877,9 +877,14 @@ class PresenceStatus {
|
|||
:m_httpPresence (false), m_btPresence (false), m_initiated (false), m_server (server),
|
||||
m_httpTimer(), m_btTimer()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
enum TransportType{
|
||||
HTTP_TRANSPORT,
|
||||
BT_TRANSPORT,
|
||||
INVALID_TRANSPORT
|
||||
};
|
||||
|
||||
void init();
|
||||
|
||||
/* Implement DBusServer::checkPresence*/
|
||||
|
@ -888,6 +893,7 @@ class PresenceStatus {
|
|||
void updateConfigPeers (const std::string &peer, const ReadOperations::Config_t &config);
|
||||
|
||||
void updatePresenceStatus (bool httpPresence, bool btPresence);
|
||||
void updatePresenceStatus (bool newStatus, TransportType type);
|
||||
|
||||
bool getHttpPresence() { return m_httpPresence; }
|
||||
bool getBtPresence() { return m_btPresence; }
|
||||
|
@ -895,6 +901,32 @@ class PresenceStatus {
|
|||
Timer& getBtTimer() { return m_btTimer; }
|
||||
};
|
||||
|
||||
/*
|
||||
* Implements org.moblin.connman.Manager
|
||||
* GetProperty : getPropCb
|
||||
* PropertyChanged: propertyChanged
|
||||
**/
|
||||
class ConnmanClient : public DBusRemoteObject
|
||||
{
|
||||
public:
|
||||
ConnmanClient (DBusServer &server);
|
||||
virtual const char *getDestination() const {return "org.moblin.connman";}
|
||||
virtual const char *getPath() const {return "/";}
|
||||
virtual const char *getInterface() const {return "org.moblin.connman.Manager";}
|
||||
virtual DBusConnection *getConnection() const {return m_connmanConn.get();}
|
||||
|
||||
void propertyChanged(const string &name,
|
||||
const boost::variant<vector<string>, string> &prop);
|
||||
|
||||
void getPropCb(const std::map <std::string, boost::variant <std::vector <std::string> > >& props, const string &error);
|
||||
|
||||
private:
|
||||
DBusServer &m_server;
|
||||
DBusConnectionPtr m_connmanConn;
|
||||
|
||||
SignalWatch2 <string,boost::variant<vector<string>, string> > m_propertyChanged;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements the main org.syncevolution.Server interface.
|
||||
*
|
||||
|
@ -1107,12 +1139,10 @@ class DBusServer : public DBusObjectHelper,
|
|||
string,
|
||||
const std::string &> logOutput;
|
||||
|
||||
static gboolean connmanPoll (gpointer dbus_server);
|
||||
DBusConnectionPtr m_connmanConn;
|
||||
|
||||
friend class Session;
|
||||
|
||||
PresenceStatus m_presence;
|
||||
ConnmanClient m_connman;
|
||||
|
||||
/** manager to automatic sync */
|
||||
AutoSyncManager m_autoSync;
|
||||
|
@ -1193,8 +1223,6 @@ public:
|
|||
|
||||
PresenceStatus& getPresenceStatus() {return m_presence;}
|
||||
|
||||
DBusConnectionPtr getConnmanConnection() {return m_connmanConn;}
|
||||
|
||||
void clearPeerTempls() { m_matchedTempls.clear(); }
|
||||
void addPeerTempl(const string &templName, const boost::shared_ptr<SyncConfig::TemplateDescription> peerTempl);
|
||||
|
||||
|
@ -4331,6 +4359,15 @@ void PresenceStatus::updateConfigPeers (const std::string &peer, const ReadOpera
|
|||
}
|
||||
}
|
||||
|
||||
void PresenceStatus::updatePresenceStatus (bool newStatus, PresenceStatus::TransportType type) {
|
||||
if (type == PresenceStatus::HTTP_TRANSPORT) {
|
||||
updatePresenceStatus (newStatus, m_btPresence);
|
||||
} else if (type == PresenceStatus::BT_TRANSPORT) {
|
||||
updatePresenceStatus (m_httpPresence, newStatus);
|
||||
}else {
|
||||
}
|
||||
}
|
||||
|
||||
void PresenceStatus::updatePresenceStatus (bool httpPresence, bool btPresence) {
|
||||
bool httpChanged = (m_httpPresence != httpPresence);
|
||||
bool btChanged = (m_btPresence != btPresence);
|
||||
|
@ -4380,6 +4417,99 @@ void PresenceStatus::updatePresenceStatus (bool httpPresence, bool btPresence) {
|
|||
}
|
||||
}
|
||||
|
||||
/********************** Connman Client implementation **************/
|
||||
ConnmanClient::ConnmanClient(DBusServer &server):
|
||||
m_server(server),
|
||||
m_propertyChanged(*this, "PropertyChanged")
|
||||
{
|
||||
const char *connmanTest = getenv ("DBUS_TEST_CONNMAN");
|
||||
m_connmanConn = g_dbus_setup_bus (connmanTest ? DBUS_BUS_SESSION: DBUS_BUS_SYSTEM, NULL, true, NULL);
|
||||
if (m_connmanConn){
|
||||
typedef std::map <std::string, boost::variant <std::vector <std::string> > > PropDict;
|
||||
DBusClientCall1<PropDict> getProp(*this,"GetProperties");
|
||||
getProp (boost::bind(&ConnmanClient::getPropCb, this, _1, _2));
|
||||
m_propertyChanged.activate(boost::bind(&ConnmanClient::propertyChanged, this, _1, _2));
|
||||
}else{
|
||||
SE_LOG_ERROR (NULL, NULL, "DBus connection setup for connman failed");
|
||||
}
|
||||
}
|
||||
|
||||
void ConnmanClient::getPropCb (const std::map <std::string,
|
||||
boost::variant <std::vector <std::string> > >& props, const string &error){
|
||||
if (!error.empty()) {
|
||||
if (error == "org.freedesktop.DBus.Error.ServiceUnknown") {
|
||||
// ensure there is still first set of singal set in case of no
|
||||
// connman available
|
||||
m_server.getPresenceStatus().updatePresenceStatus (true, true);
|
||||
SE_LOG_DEBUG (NULL, NULL, "No connman service available %s", error.c_str());
|
||||
return;
|
||||
}
|
||||
SE_LOG_DEBUG (NULL, NULL, "error in connmanCallback %s", error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
typedef std::pair <std::string, boost::variant <std::vector <std::string> > > element;
|
||||
bool httpPresence = false, btPresence = false;
|
||||
BOOST_FOREACH (element entry, props) {
|
||||
//match connected for HTTP based peers (wifi/wimax/ethernet)
|
||||
if (entry.first == "ConnectedTechnologies") {
|
||||
std::vector <std::string> connected = boost::get <std::vector <std::string> > (entry.second);
|
||||
BOOST_FOREACH (std::string tech, connected) {
|
||||
if (boost::iequals (tech, "wifi") || boost::iequals (tech, "ethernet")
|
||||
|| boost::iequals (tech, "wimax")) {
|
||||
httpPresence = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (entry.first == "AvailableTechnologies") {
|
||||
std::vector <std::string> enabled = boost::get <std::vector <std::string> > (entry.second);
|
||||
BOOST_FOREACH (std::string tech, enabled){
|
||||
if (boost::iequals (tech, "bluetooth")) {
|
||||
btPresence = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//now delivering the signals
|
||||
m_server.getPresenceStatus().updatePresenceStatus (httpPresence, btPresence);
|
||||
}
|
||||
|
||||
void ConnmanClient::propertyChanged(const string &name,
|
||||
const boost::variant<vector<string>, string> &prop)
|
||||
{
|
||||
bool httpPresence=false, btPresence=false;
|
||||
bool httpChanged=false, btChanged=false;
|
||||
if (boost::iequals(name, "ConnectedTechnologies")) {
|
||||
httpChanged=true;
|
||||
vector<string> connected = boost::get<vector<string> >(prop);
|
||||
BOOST_FOREACH (std::string tech, connected) {
|
||||
if (boost::iequals (tech, "wifi") || boost::iequals (tech, "ethernet")
|
||||
|| boost::iequals (tech, "wimax")) {
|
||||
httpPresence=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (boost::iequals (name, "AvailableTechnologies")){
|
||||
btChanged=true;
|
||||
vector<string> enabled = boost::get<vector<string> >(prop);
|
||||
BOOST_FOREACH (std::string tech, enabled){
|
||||
if (boost::iequals (tech, "bluetooth")) {
|
||||
btPresence = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(httpChanged) {
|
||||
m_server.getPresenceStatus().updatePresenceStatus (httpPresence, PresenceStatus::HTTP_TRANSPORT);
|
||||
} else if (btChanged) {
|
||||
m_server.getPresenceStatus().updatePresenceStatus (btPresence, PresenceStatus::BT_TRANSPORT);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
/********************** DBusServer implementation ******************/
|
||||
|
||||
void DBusServer::clientGone(Client *c)
|
||||
|
@ -4545,6 +4675,7 @@ DBusServer::DBusServer(GMainLoop *loop, const DBusConnectionPtr &conn, int durat
|
|||
infoRequest(*this, "InfoRequest"),
|
||||
logOutput(*this, "LogOutput"),
|
||||
m_presence(*this),
|
||||
m_connman(*this),
|
||||
m_autoSync(*this),
|
||||
m_autoTerm(m_autoSync.preventTerm() ? -1 : duration), //if there is any task in auto sync, prevent auto termination
|
||||
m_parentLogger(LoggerBase::instance())
|
||||
|
@ -4572,12 +4703,6 @@ DBusServer::DBusServer(GMainLoop *loop, const DBusConnectionPtr &conn, int durat
|
|||
|
||||
LoggerBase::pushLogger(this);
|
||||
setLevel(LoggerBase::DEBUG);
|
||||
|
||||
const char *connmanTest = getenv ("DBUS_TEST_CONNMAN");
|
||||
m_connmanConn = g_dbus_setup_bus (connmanTest ? DBUS_BUS_SESSION: DBUS_BUS_SYSTEM, NULL, true, NULL);
|
||||
if (m_connmanConn) {
|
||||
m_pollConnman = g_timeout_add_seconds (10, connmanPoll, static_cast <gpointer> (this));
|
||||
}
|
||||
}
|
||||
|
||||
DBusServer::~DBusServer()
|
||||
|
@ -4838,74 +4963,6 @@ void DBusServer::removeInfoReq(const InfoReq &req)
|
|||
}
|
||||
}
|
||||
|
||||
gboolean DBusServer::connmanPoll (gpointer dbusserver)
|
||||
{
|
||||
DBusServer *me = static_cast<DBusServer *>(dbusserver);
|
||||
DBusConnectionPtr conn = me->getConnmanConnection();
|
||||
struct ConnmanClient : public DBusCallObject
|
||||
{
|
||||
DBusConnectionPtr m_connection;
|
||||
ConnmanClient (DBusConnectionPtr conn ) : m_connection (conn) {}
|
||||
virtual const char *getDestination() const {return "org.moblin.connman";}
|
||||
virtual const char *getPath() const {return "/";}
|
||||
virtual const char *getInterface() const {return "org.moblin.connman.Manager";}
|
||||
virtual const char *getMethod() const {return "GetProperties"; }
|
||||
virtual DBusConnection *getConnection() const {return m_connection.get();}
|
||||
}connman (conn);
|
||||
|
||||
typedef std::map <std::string, boost::variant <std::vector <std::string> > > PropDict;
|
||||
DBusClientCall1<PropDict> getProp(connman);
|
||||
getProp (boost::bind(&DBusServer::connmanCallback, me, _1, _2));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void DBusServer::connmanCallback (const std::map <std::string, boost::variant <std::vector <std::string> > >& props, const string &error)
|
||||
{
|
||||
if (!error.empty()) {
|
||||
if (error == "org.freedesktop.DBus.Error.ServiceUnknown") {
|
||||
// no connman available, remove connmanPoll.
|
||||
m_pollConnman.set(0);
|
||||
// ensure there is still first set of singal set in case of no
|
||||
// connman available
|
||||
m_presence.updatePresenceStatus (true, true);
|
||||
SE_LOG_DEBUG (NULL, NULL, "No connman service available %s", error.c_str());
|
||||
return;
|
||||
}
|
||||
SE_LOG_DEBUG (NULL, NULL, "error in connmanCallback %s", error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
typedef std::pair <std::string, boost::variant <std::vector <std::string> > > element;
|
||||
bool httpPresence = false, btPresence = false;
|
||||
BOOST_FOREACH (element entry, props) {
|
||||
//match connected for HTTP based peers (wifi/wimax/ethernet)
|
||||
if (entry.first == "ConnectedTechnologies") {
|
||||
std::vector <std::string> connected = boost::get <std::vector <std::string> > (entry.second);
|
||||
BOOST_FOREACH (std::string tech, connected) {
|
||||
if (boost::iequals (tech, "wifi") || boost::iequals (tech, "ethernet")
|
||||
|| boost::iequals (tech, "wimax")) {
|
||||
httpPresence = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (entry.first == "EnabledTechnologies") {
|
||||
std::vector <std::string> enabled = boost::get <std::vector <std::string> > (entry.second);
|
||||
BOOST_FOREACH (std::string tech, enabled){
|
||||
if (boost::iequals (tech, "bluetooth")) {
|
||||
btPresence = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//now delivering the signals
|
||||
m_presence.updatePresenceStatus (httpPresence, btPresence);
|
||||
|
||||
}
|
||||
|
||||
void DBusServer::getDeviceList(SyncConfig::DeviceList &devices)
|
||||
{
|
||||
//wait bluez or other device managers
|
||||
|
|
|
@ -666,27 +666,53 @@ class Connman (dbus.service.Object):
|
|||
if (self.count == 1):
|
||||
loop.quit()
|
||||
return {"ConnectedTechnologies":["ethernet", "some other stuff"],
|
||||
"EnabledTechnologies": ["bluetooth"]}
|
||||
"AvailableTechnologies": ["bluetooth"]}
|
||||
elif (self.count == 2):
|
||||
""" unplug the ethernet cable """
|
||||
loop.quit()
|
||||
return {"ConnectedTechnologies":["some other stuff"],
|
||||
"EnabledTechnologies": ["bluetooth"]}
|
||||
"AvailableTechnologies": ["bluetooth"]}
|
||||
elif (self.count == 3):
|
||||
""" replug the ethernet cable """
|
||||
loop.quit()
|
||||
return {"ConnectedTechnologies":["ethernet", "some other stuff"],
|
||||
"EnabledTechnologies": ["bluetooth"]}
|
||||
"AvailableTechnologies": ["bluetooth"]}
|
||||
elif (self.count == 4):
|
||||
""" nothing presence """
|
||||
loop.quit()
|
||||
return {"ConnectedTechnologies":[""],
|
||||
"EnabledTechnologies": [""]}
|
||||
"AvailableTechnologies": [""]}
|
||||
elif (self.count == 5):
|
||||
""" come back the same time """
|
||||
loop.quit()
|
||||
return {"ConnectedTechnologies":["ethernet", "some other stuff"],
|
||||
"EnabledTechnologies": ["bluetooth"]}
|
||||
"AvailableTechnologies": ["bluetooth"]}
|
||||
|
||||
@dbus.service.signal(dbus_interface='org.moblin.connman.Manager', signature='sv')
|
||||
def PropertyChanged(self, key, value):
|
||||
pass
|
||||
|
||||
def emitSignal(self):
|
||||
self.count = self.count+1
|
||||
if (self.count == 2):
|
||||
""" unplug the ethernet cable """
|
||||
self.PropertyChanged("ConnectedTechnologies",["some other stuff"])
|
||||
return
|
||||
elif (self.count == 3):
|
||||
""" replug the ethernet cable """
|
||||
self.PropertyChanged("ConnectedTechnologies", ["ethernet", "some other stuff"])
|
||||
return
|
||||
elif (self.count == 4):
|
||||
""" nothing presence """
|
||||
self.PropertyChanged("ConnectedTechnologies", [""])
|
||||
self.PropertyChanged("AvailableTechnologies", [""])
|
||||
return
|
||||
elif (self.count == 5):
|
||||
""" come back the same time """
|
||||
self.PropertyChanged("ConnectedTechnologies", ["ethernet", "some other stuff"])
|
||||
self.PropertyChanged("AvailableTechnologies", ["bluetooth"])
|
||||
return
|
||||
|
||||
def reset(self):
|
||||
self.count = 0
|
||||
|
||||
|
@ -709,6 +735,7 @@ class TestDBusServerPresence(unittest.TestCase, DBusUtil):
|
|||
self.failUnlessEqual (status, "")
|
||||
self.failUnlessEqual (server, "foo")
|
||||
self.failUnlessEqual (transport, "http://http-only-1")
|
||||
loop.quit()
|
||||
|
||||
match = bus.add_signal_receiver(cb_http_presence,
|
||||
'Presence',
|
||||
|
@ -720,13 +747,14 @@ class TestDBusServerPresence(unittest.TestCase, DBusUtil):
|
|||
loop.run()
|
||||
time.sleep(1)
|
||||
self.setUpSession("foo")
|
||||
self.session.SetConfig(True, True, {"" : {"syncURL":
|
||||
self.session.SetConfig(True, False, {"" : {"syncURL":
|
||||
"obex-bt://temp-bluetooth-peer-changed-from-http"}})
|
||||
def cb_bt_presence(server, status, transport):
|
||||
self.failUnlessEqual (status, "")
|
||||
self.failUnlessEqual (server, "foo")
|
||||
self.failUnlessEqual (transport,
|
||||
"obex-bt://temp-bluetooth-peer-changed-from-http")
|
||||
loop.quit()
|
||||
match.remove()
|
||||
match = bus.add_signal_receiver(cb_bt_presence,
|
||||
'Presence',
|
||||
|
@ -735,6 +763,7 @@ class TestDBusServerPresence(unittest.TestCase, DBusUtil):
|
|||
None,
|
||||
byte_arrays=True,
|
||||
utf8_strings=True)
|
||||
self.conn.emitSignal()
|
||||
loop.run()
|
||||
time.sleep(1)
|
||||
self.session.Detach()
|
||||
|
@ -744,6 +773,9 @@ class TestDBusServerPresence(unittest.TestCase, DBusUtil):
|
|||
self.session.Detach()
|
||||
self.foo = "random string"
|
||||
self.bar = "random string"
|
||||
match.remove()
|
||||
self.conn.emitSignal()
|
||||
self.conn.emitSignal()
|
||||
def cb_bt_http_presence(server, status, transport):
|
||||
if (server == "foo"):
|
||||
self.foo = status
|
||||
|
@ -751,8 +783,8 @@ class TestDBusServerPresence(unittest.TestCase, DBusUtil):
|
|||
self.bar = status
|
||||
else:
|
||||
self.fail("wrong server config")
|
||||
loop.quit()
|
||||
|
||||
match.remove()
|
||||
match = bus.add_signal_receiver(cb_bt_http_presence,
|
||||
'Presence',
|
||||
'org.syncevolution.Server',
|
||||
|
@ -760,6 +792,8 @@ class TestDBusServerPresence(unittest.TestCase, DBusUtil):
|
|||
None,
|
||||
byte_arrays=True,
|
||||
utf8_strings=True)
|
||||
#count=5, 2 signals recevied
|
||||
self.conn.emitSignal()
|
||||
loop.run()
|
||||
loop.run()
|
||||
time.sleep(1)
|
||||
|
@ -798,7 +832,7 @@ class TestDBusServerPresence(unittest.TestCase, DBusUtil):
|
|||
"http://http-client-mixed"])
|
||||
|
||||
#count = 2
|
||||
loop.run()
|
||||
self.conn.emitSignal()
|
||||
time.sleep(1)
|
||||
(status, transports) = self.server.CheckPresence ("foo")
|
||||
self.failUnlessEqual (status, "no transport")
|
||||
|
@ -819,9 +853,9 @@ class TestDBusServerPresence(unittest.TestCase, DBusUtil):
|
|||
time.sleep(1)
|
||||
status = self.session.checkPresence()
|
||||
self.failUnlessEqual (status, "")
|
||||
loop.run()
|
||||
loop.run()
|
||||
loop.run()
|
||||
self.conn.emitSignal()
|
||||
self.conn.emitSignal()
|
||||
self.conn.emitSignal()
|
||||
#count = 4
|
||||
time.sleep(1)
|
||||
status = self.session.checkPresence()
|
||||
|
|
Loading…
Reference in New Issue