Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

buddy list contact status clean #46

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
508 changes: 423 additions & 85 deletions apps/telepathy/Connection.cxx

Large diffs are not rendered by default.

122 changes: 71 additions & 51 deletions apps/telepathy/Connection.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#define CONNECTION_HXX

#if defined(HAVE_CONFIG_H)
#include "config.h"
#include "config.h"
#endif


Expand All @@ -28,6 +28,7 @@
#include <rutil/ThreadIf.hxx>
#include <resip/recon/UserAgent.hxx>


#include <TelepathyQt/BaseConnection>
#include <TelepathyQt/BaseChannel>

Expand All @@ -39,57 +40,76 @@

namespace tr {

class MyConversationManager;
class MyUserAgent;

class Connection : public Tp::BaseConnection
{
Q_OBJECT
public:
Connection(const QDBusConnection &dbusConnection,
const QString &cmName, const QString &protocolName,
const QVariantMap &parameters);

MyConversationManager& getConversationManager() { return *myConversationManager.get(); };

private:
uint setPresence(const QString &status, const QString &message, Tp::DBusError *error);
QStringList inspectHandles(uint handleType, const Tp::UIntList &handles, Tp::DBusError *error);
Tp::UIntList requestHandles(uint handleType, const QStringList &identifiers, Tp::DBusError *error);
Tp::BaseChannelPtr createChannel(const QVariantMap &request, Tp::DBusError *error);
Tp::ContactAttributesMap getContactAttributes(const Tp::UIntList &handles, const QStringList &ifaces, Tp::DBusError *error);
uint ensureHandle(const QString& identifier);


private slots:
void doConnect(Tp::DBusError *error);
void onConnected();
void doDisconnect();
void setStatusSlot(uint newStatus, uint reason);
void onIncomingCall(const QString & caller, uint callHandle);


private:
resip::SharedPtr<TelepathyMasterProfile> mUAProfile;
resip::SharedPtr<TelepathyConversationProfile> mConversationProfile;
tr::MyUserAgent* ua;
std::auto_ptr<MyConversationManager> myConversationManager;

Tp::BaseConnectionContactsInterfacePtr mContactsInterface;
Tp::BaseConnectionSimplePresenceInterfacePtr mSimplePresenceInterface;
Tp::BaseConnectionContactListInterfacePtr mContactListInterface;
Tp::BaseConnectionRequestsInterfacePtr mRequestsInterface;

long nextHandleId;
QMap<uint, QString> mHandles;
QMap<QString, uint> mIdentifiers;

Tp::SimplePresence mSelfPresence;
};
class MyConversationManager;
class MyUserAgent;

class Connection : public Tp::BaseConnection
{
Q_OBJECT
public:
Connection(const QDBusConnection &dbusConnection,
const QString &cmName, const QString &protocolName,
const QVariantMap &parameters);

MyConversationManager& getConversationManager() { return *myConversationManager.get(); };

Tp::ContactAttributesMap getContactListAttributes(const QStringList &interfaces, bool hold, Tp::DBusError *error);

void requestSubscription(const Tp::UIntList &handles, const QString &message, Tp::DBusError *error);
void removeContacts(const Tp::UIntList &handles, Tp::DBusError *error);
Tp::AliasMap getAliases(const Tp::UIntList& handles, Tp::DBusError *error);
void setAliases(const Tp::AliasMap &aliases, Tp::DBusError *error);
void getContactsFromFile(Tp::DBusError *error);
void setContactsInFile();
void deleteContacts(const QStringList& contacts);
Tp::SimpleStatusSpecMap getSimpleStatusSpecMap();
Tp::SimpleContactPresences getPresences(const Tp::UIntList &handles);
Tp::SimplePresence getPresence(uint handle);

private:
uint setPresence(const QString &status, const QString &message, Tp::DBusError *error);
QStringList inspectHandles(uint handleType, const Tp::UIntList &handles, Tp::DBusError *error);
Tp::UIntList requestHandles(uint handleType, const QStringList &identifiers, Tp::DBusError *error);
Tp::BaseChannelPtr createChannel(const QVariantMap &request, Tp::DBusError *error);
Tp::ContactAttributesMap getContactAttributes(const Tp::UIntList &handles, const QStringList &ifaces, Tp::DBusError *error);
uint ensureHandle(const QString& identifier);
void sendPresence(const QString& status);
// QString ensureStatus(const QString& tpStatus);

private slots:
void doConnect(Tp::DBusError *error);
void onConnected();
void doDisconnect();
void setStatusSlot(uint newStatus, uint reason);
void onIncomingCall(const QString & caller, uint callHandle);
void setContactStatus(const QString& identifier, const QString& status);

private:
resip::SharedPtr<TelepathyMasterProfile> mUAProfile;
resip::SharedPtr<TelepathyConversationProfile> mConversationProfile;
tr::MyUserAgent* ua;
std::auto_ptr<MyConversationManager> myConversationManager;
resip::SharedPtr<resip::MasterProfile> mProfile;

Tp::BaseConnectionContactsInterfacePtr mContactsInterface;
Tp::BaseConnectionAliasingInterfacePtr mAliasingInterface;
Tp::BaseConnectionSimplePresenceInterfacePtr mSimplePresenceInterface;
Tp::BaseConnectionContactListInterfacePtr mContactListInterface;
Tp::BaseConnectionRequestsInterfacePtr mRequestsInterface;

long nextHandleId;
QMap<uint, QString> mHandles;
QMap<QString, uint> mIdentifiers;
Tp::AliasMap mAliases;

// QMap<QString, QString> mTpStatus;
// QMap<QString, QString> mResipStatus;

Tp::SimpleStatusSpecMap statusMap;
Tp::SimplePresence mSelfPresence;
Tp::SimpleContactPresences mPresences;
};

}

#endif



205 changes: 205 additions & 0 deletions apps/telepathy/MyUserAgent.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,17 @@
#include <rutil/Log.hxx>
#include <rutil/Logger.hxx>
#include <resip/recon/ReconSubsystem.hxx>
#include <rutil/XMLCursor.hxx>

#include <resip/recon/UserAgent.hxx>
#include <resip/recon/ReconSubsystem.hxx>
#include "resip/stack/Pidf.hxx"
#include "resip/stack/GenericPidfContents.hxx"
#include "resip/dum/PublicationHandler.hxx"
#include "resip/dum/ClientPublication.hxx"
#include "resip/dum/ClientAuthManager.hxx"
#include "resip/dum/DialogUsageManager.hxx"
#include "rutil/Random.hxx"

#include "MyUserAgent.hxx"

Expand All @@ -49,10 +59,205 @@ tr::MyUserAgent::onSubscriptionTerminated(SubscriptionHandle handle, unsigned in
InfoLog(<< "onSubscriptionTerminated: handle=" << handle << " statusCode=" << statusCode);
}

std::vector<Pidf::Tuple>
tr::MyUserAgent::getTuplesFromXML(const Data& notifyData)
{
ParseBuffer pb(notifyData.data(), notifyData.size());
std::string pidf_namespace;

XMLCursor xml(pb);
std::vector<Pidf::Tuple> tuples;
Uri entity;
XMLCursor::AttributeMap attr = xml.getAttributes();
XMLCursor::AttributeMap::const_iterator it =
std::find_if(attr.begin(), attr.end(), XMLCursor::AttributeValueEqual("urn:ietf:params:xml:ns:pidf"));

if ( it != attr.end() )
{

std::string key(it->first.data(), it->first.size());

size_t pos = key.find(':');

if ( pos != string::npos)
{
pidf_namespace.assign(key, pos+1, key.size()-pos-1);
pidf_namespace.append(1, ':');
}
}

const std::string presence = pidf_namespace + "presence";

if (xml.getTag() == presence.c_str())
{
XMLCursor::AttributeMap::const_iterator i = xml.getAttributes().find("entity");
if (i != xml.getAttributes().end())
{
entity = Uri(i->second);
}
else
{
DebugLog(<< "no entity!");
}

if (xml.firstChild())
{
do
{
const std::string tuple = pidf_namespace + "tuple";
if (xml.getTag() == tuple.c_str())
{
Pidf::Tuple t;
t.attributes = xml.getAttributes();
XMLCursor::AttributeMap::const_iterator i = xml.getAttributes().find("id");
if (i != xml.getAttributes().end())
{
t.id = i->second;
t.attributes.erase("id");
}

// look for status, contacts, notes -- take last of each for now
if (xml.firstChild())
{
const std::string status = pidf_namespace + "status";
const std::string contact = pidf_namespace + "contact";
const std::string note = pidf_namespace + "note";
const std::string timestamp = pidf_namespace + "timestamp";
do
{
if (xml.getTag() == status.c_str())
{
// look for basic
if (xml.firstChild())
{
do
{
std::string basic = pidf_namespace + "basic";
if (xml.getTag() == basic.c_str())
{
if (xml.firstChild())
{
t.status = (xml.getValue() == "open");

// If status == closed then the contact is considered Offline
if(!t.status)
{
t.note = "Offline";
t.contact = entity.toString();
tuples.push_back(t);
return tuples;
}

xml.parent();
}
}
} while (xml.nextSibling());
xml.parent();
}
}
else if (xml.getTag() == contact.c_str())
{
XMLCursor::AttributeMap::const_iterator i = xml.getAttributes().find("priority");
if (i != xml.getAttributes().end())
{
t.contactPriority.setValue(i->second);
}
if (xml.firstChild())
{
t.contact = xml.getValue();
xml.parent();
}
}
else if (xml.getTag() == note.c_str())
{
if (xml.firstChild())
{
t.note = xml.getValue();
xml.parent();
}
}
else if (xml.getTag() == timestamp.c_str())
{
if (xml.firstChild())
{
t.timeStamp = xml.getValue();
xml.parent();
}
}
} while (xml.nextSibling());
xml.parent();
}

tuples.push_back(t);
}
} while (xml.nextSibling());
xml.parent();
}
}
else
{
DebugLog(<< "no presence tag!");
}

return tuples;
}

void
tr::MyUserAgent::onSubscriptionNotify(SubscriptionHandle handle, const Data& notifyData)
{
InfoLog(<< "onSubscriptionNotify: handle=" << handle << " data=" << endl << notifyData);

std::vector<Pidf::Tuple> tuples = getTuplesFromXML(notifyData);

InfoLog(<< "mbellomo tuple = " << tuples.back());
InfoLog(<< "mbellomo tuple contact = " << tuples.back().contact);
InfoLog(<< "mbellomo tuple note = " << tuples.back().note);
InfoLog(<< "mbellomo tuple status = " << tuples.back().status);

// I'm assuming here that the last Tuple will hold the valid information
QString identifier = QString::fromUtf8(tuples.back().contact.c_str());
// TODO find a better way to do this...maybe use some resiprocate API
// removes the string sip: from identifier
identifier.remove(0,4);
QString note = QString::fromUtf8(tuples.back().note.c_str());

// RFC 3863 doesn't seem to have this definitions. Got this from Jitsi and Empathy UI
QString presence;
if(note == "Offline")
{
presence = "offline";
}
else if(note == "Online")
{
presence = "available";
}
else if(note == "Away")
{
presence = "away";
}
else if(note == "In a meeting")
{
presence = "xa";
}
else if(note == "Busy (DND)")
{
presence = "dnd";
}
else if(note == "Invisible")
{
presence = "hidden";
}
else
{
presence = "unknown";
}

emit setContactStatus(identifier, presence);

// Apparently this is the right way of doing the parse but I'm getting an error when I do this
// ParseBuffer pb(notifyData.data(), notifyData.size());
// NameAddr res;
// res.parse(pb);
}

void
Expand Down
6 changes: 6 additions & 0 deletions apps/telepathy/MyUserAgent.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ public:
virtual void thread();
virtual void setStatus(uint newStatus, uint reason);
virtual void stop();

private:
std::vector<resip::Pidf::Tuple> getTuplesFromXML(const resip::Data& notifyData);

signals:
void setContactStatus(const QString& identifier, const QString& status);

private:
tr::Connection& mConnection;
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ AC_SUBST(LIBTOOL_VERSION_RELEASE)

AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([foreign subdir-objects])
AM_INIT_AUTOMAKE
m4_pattern_forbid([^PKG_])

AC_CANONICAL_HOST
Expand Down