diff --git a/apps/telepathy/Connection.cxx b/apps/telepathy/Connection.cxx index 43b57f4d3f..be19938931 100644 --- a/apps/telepathy/Connection.cxx +++ b/apps/telepathy/Connection.cxx @@ -5,7 +5,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -22,7 +22,13 @@ #include #include - +#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 "MyConversationManager.hxx" @@ -36,11 +42,14 @@ using namespace std; #define RESIPROCATE_SUBSYSTEM ReconSubsystem::RECON +static const QString c_fileWithContacts = QLatin1String("data.txt"); + tr::Connection::Connection(const QDBusConnection &dbusConnection, const QString &cmName, const QString &protocolName, const QVariantMap ¶meters) : Tp::BaseConnection(dbusConnection, cmName, protocolName, parameters), mUAProfile(new TelepathyMasterProfile(parameters)), mConversationProfile(new TelepathyConversationProfile(mUAProfile, parameters)), ua(0), + mProfile(new TelepathyMasterProfile(parameters)), nextHandleId(1) { std::vector _codecIds; @@ -77,13 +86,13 @@ tr::Connection::Connection(const QDBusConnection &dbusConnection, const QString mContactsInterface = Tp::BaseConnectionContactsInterface::create(); mContactsInterface->setGetContactAttributesCallback(Tp::memFun(this, &Connection::getContactAttributes)); mContactsInterface->setContactAttributeInterfaces(QStringList() - << TP_QT_IFACE_CONNECTION - << TP_QT_IFACE_CONNECTION_INTERFACE_CONTACT_LIST - << TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE - //<< TP_QT_IFACE_CONNECTION_INTERFACE_ALIASING - << TP_QT_IFACE_CONNECTION_INTERFACE_REQUESTS - //<< TP_QT_IFACE_CONNECTION_INTERFACE_AVATARS - ); + << TP_QT_IFACE_CONNECTION + << TP_QT_IFACE_CONNECTION_INTERFACE_CONTACT_LIST + << TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE + << TP_QT_IFACE_CONNECTION_INTERFACE_ALIASING + << TP_QT_IFACE_CONNECTION_INTERFACE_REQUESTS + //<< TP_QT_IFACE_CONNECTION_INTERFACE_AVATARS + ); plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(mContactsInterface)); /* Connection.Interface.SimplePresence */ @@ -92,19 +101,25 @@ tr::Connection::Connection(const QDBusConnection &dbusConnection, const QString mSimplePresenceInterface->setSetPresenceCallback(Tp::memFun(this, &Connection::setPresence)); plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(mSimplePresenceInterface)); - /* Connection.Interface.ContactList */ - mContactListInterface = Tp::BaseConnectionContactListInterface::create(); - mContactListInterface->setContactListPersists(true); - mContactListInterface->setCanChangeContactList(true); - mContactListInterface->setDownloadAtConnection(true); - //mContactListInterface->setGetContactListAttributesCallback(Tp::memFun(this, &Connection::getContactListAttributes)); - //mContactListInterface->setRequestSubscriptionCallback(Tp::memFun(this, &Connection::requestSubscription)); - //mContactListInterface->setAuthorizePublicationCallback(Tp::memFun(this, &Connection::authorizePublication)); - //mContactListInterface->setRemoveContactsCallback(Tp::memFun(this, &Connection::removeContacts)); - //mContactListInterface->setUnsubscribeCallback(Tp::memFun(this, &Connection::unsubscribe)); - //mContactListInterface->setUnpublishCallback(Tp::memFun(this, &Connection::unpublish)); - plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(mContactListInterface)); - + /* Connection.Interface.ContactList */ + mContactListInterface = Tp::BaseConnectionContactListInterface::create(); + mContactListInterface->setContactListPersists(true); + mContactListInterface->setCanChangeContactList(true); + mContactListInterface->setDownloadAtConnection(true); + mContactListInterface->setGetContactListAttributesCallback(Tp::memFun(this, &Connection::getContactListAttributes)); + mContactListInterface->setRequestSubscriptionCallback(Tp::memFun(this, &Connection::requestSubscription)); + // mContactListInterface->setAuthorizePublicationCallback(Tp::memFun(this, &Connection::authorizePublication)); + mContactListInterface->setRemoveContactsCallback(Tp::memFun(this, &Connection::removeContacts)); + //mContactListInterface->setUnsubscribeCallback(Tp::memFun(this, &Connection::unsubscribe)); + //mContactListInterface->setUnpublishCallback(Tp::memFun(this, &Connection::unpublish)); + plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(mContactListInterface)); + + /* Connection.Interface.Aliasing */ + mAliasingInterface = Tp::BaseConnectionAliasingInterface::create(); + mAliasingInterface->setGetAliasesCallback(Tp::memFun(this, &Connection::getAliases)); + mAliasingInterface->setSetAliasesCallback(Tp::memFun(this, &Connection::setAliases)); + plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(mAliasingInterface)); + /* Connection.Interface.Requests */ mRequestsInterface = Tp::BaseConnectionRequestsInterface::create(this); /* Fill requestableChannelClasses */ @@ -142,6 +157,219 @@ tr::Connection::Connection(const QDBusConnection &dbusConnection, const QString setCreateChannelCallback(Tp::memFun(this, &Connection::createChannel)); setRequestHandlesCallback(Tp::memFun(this, &Connection::requestHandles)); connect(this, SIGNAL(disconnected()), SLOT(doDisconnect())); + connect(ua, SIGNAL(setContactStatus(const QString&, const QString&)), + this, SLOT(setContactStatus(const QString&, const QString&))); + + // This should be static but I could only initialize a map at declaration in c++11 + // mTpStatus["offline"] = "Offline"; + // mTpStatus["available"] = QString("Online"); + // mTpStatus["away"] = QString("Away"); + // mTpStatus["xa"] = QString("In a meeting"); + // mTpStatus["dnd"] = QString("Busy (DND)"); + // mTpStatus["hidden"] = QString("Invisible"); + + // Q_FOREACH (QString tpStatus, mTpStatus.keys()) + // { + // mResipStatus[mTpStatus.value(tpStatus)] = tpStatus; + // } + +} + +// QString +// tr::Connection::ensureStatus(const QString& tpStatus) +// { +// if(mTpStatus.find(tpStatus) == mTpStatus.end()) +// { +// mTpStatus[tpStatus] = "Offline"; +// mResipStatus["Offline"] = tpStatus; +// } +// return mTpStatus[tpStatus]; +// } + +void +tr::Connection::getContactsFromFile(Tp::DBusError *error) +{ + if (error->isValid()) + { + return; + } + + QFile file(c_fileWithContacts); + + if ( file.open(QFile::ReadOnly) ) + { + QTextStream in(&file); + QString line = in.readLine(); + Tp::AliasMap aliases; + while ( !line.isNull() ) + { + QString identifier = line.split(" ").at(0); + uint handle = ensureHandle(identifier); + aliases[handle] = line.split(" ").at(1); + + string strIdentifier = identifier.toUtf8().constData(); + string uri = "sip:" + strIdentifier; + ua->createSubscription(Data("presence"), NameAddr(uri.c_str()), 3600, Mime("application", "pidf+xml")); + + line = in.readLine(); + } + setAliases(aliases, error); + } + + else + { + file.open(QFile::WriteOnly); + } + + mContactListInterface->setContactListState(Tp::ContactListStateSuccess); +} + +void +tr::Connection::setContactsInFile() +{ + QFile file(c_fileWithContacts); + + if( file.open(QIODevice::ReadWrite | QIODevice::Truncate) ) + { + QTextStream stream(&file); + QMap::iterator it; + for ( it = mHandles.begin(); it != mHandles.end(); it++ ) + { + if ( it.key() != selfHandle() ) + { + stream << it.value() << " " << mAliases[it.key()] << endl; + } + } + file.close(); + } + + else + { + ErrLog(<<"couldn't write contacts to file" << endl); + } +} + +Tp::AliasMap +tr::Connection::getAliases(const Tp::UIntList& handles, Tp::DBusError *error) +{ + if ( error->isValid() ) + { + return Tp::AliasMap(); + } + + qDebug() << Q_FUNC_INFO << handles; + + Tp::AliasMap aliases; + Q_FOREACH ( uint handle, handles ) + { + if ( mAliases.find(handle) == mAliases.end() ) + { + error->set(TP_QT_ERROR_INVALID_HANDLE, QLatin1String("Invalid handle(s)")); + } + aliases[handle] = mAliases[handle]; + } + + return aliases; +} + +void +tr::Connection::setAliases(const Tp::AliasMap &aliases, Tp::DBusError *error) +{ + if ( error->isValid() ) + { + return; + } + + qDebug() << Q_FUNC_INFO << aliases; + + for ( Tp::AliasMap::const_iterator it = aliases.begin(); it != aliases.end(); it++ ) + { + mAliases[it.key()] = it.value(); + } + +} + +void +tr::Connection::deleteContacts(const QStringList& contacts) +{ + + Tp::ContactSubscriptionMap changes; + Tp::HandleIdentifierMap identifiers; + Tp::HandleIdentifierMap removals; + Q_FOREACH ( const QString &contact, contacts ) + { + uint id = mIdentifiers[contact]; + removals[id] = contact; + } + mContactListInterface->contactsChangedWithID(changes, identifiers, removals); + + setContactsInFile(); +} + +Tp::ContactAttributesMap +tr::Connection::getContactListAttributes(const QStringList &interfaces, bool hold, Tp::DBusError *error) +{ + Tp::UIntList handles = mHandles.keys(); + handles.removeOne(selfHandle()); + + StackLog(<<"getContactListAttributes()"); + qDebug() << handles; + + return getContactAttributes(handles, interfaces, error); +} + +void +tr::Connection::requestSubscription(const Tp::UIntList &handles, const QString &message, Tp::DBusError *error) +{ + + QStringList contacts = inspectHandles(Tp::HandleTypeContact, handles, error); + + if ( error->isValid() ) + { + return; + } + + if ( contacts.isEmpty() ) + { + error->set(TP_QT_ERROR_INVALID_HANDLE, QLatin1String("Invalid handle(s)")); + } + + Tp::ContactSubscriptionMap changes; + Tp::HandleIdentifierMap identifiers; + Tp::HandleIdentifierMap removals; + Q_FOREACH ( const QString &contact, contacts ) + { + uint handle = ensureHandle(contact); + + Tp::ContactSubscriptions change; + change.publish = Tp::SubscriptionStateYes; + change.publishRequest = QString(); + change.subscribe = Tp::SubscriptionStateUnknown; + + changes[handle] = change; + identifiers[handle] = contact; + } + mContactListInterface->contactsChangedWithID(changes, identifiers, removals); + + setContactsInFile(); +} + +void +tr::Connection::removeContacts(const Tp::UIntList &handles, Tp::DBusError *error) +{ + QStringList contacts = inspectHandles(Tp::HandleTypeContact, handles, error); + + if ( error->isValid() ) + { + return; + } + + if ( contacts.isEmpty() ) + { + error->set(TP_QT_ERROR_INVALID_HANDLE, QLatin1String("Invalid handle(s)")); + } + + deleteContacts(contacts); } void @@ -153,8 +381,11 @@ tr::Connection::doConnect(Tp::DBusError *error) ua->startup(); myConversationManager->startup(); ua->run(); + statusMap = tr::Common::getSimpleStatusSpecMap(); mContactListInterface->setContactListState(Tp::ContactListStateWaiting); + + getContactsFromFile(error); } void @@ -163,19 +394,93 @@ tr::Connection::onConnected() setStatus(Tp::ConnectionStatusConnected, Tp::ConnectionStatusReasonRequested); Tp::SimpleContactPresences presences; - mSelfPresence.type = Tp::ConnectionPresenceTypeAvailable; - mSelfPresence.status = QLatin1String("available"); + Tp::DBusError error; + setPresence(QLatin1String("available"), QLatin1String(""), &error); + presences[selfHandle()] = mSelfPresence; mSimplePresenceInterface->setPresences(presences); } + +void +tr::Connection::setContactStatus(const QString& identifier, const QString& status) +{ + qDebug() << "setContactStatus() of " << identifier << " to " << status; + + Tp::SimpleContactPresences newPresences; + uint handle = ensureHandle(identifier); + + if( handle == selfHandle() ) + { + return; + } + + Tp::SimplePresence presence; + presence.status = status; + presence.type = statusMap[status].type; + + newPresences[handle] = presence; + + mSimplePresenceInterface->setPresences(newPresences); +} + uint tr::Connection::setPresence(const QString &status, const QString &message, Tp::DBusError *error) { - //FIXME + // TODO: find out why message is always getting here empty + + StackLog(<<"setPresence()"); + // qDebug() << mTpStatus; + // qDebug() << mResipStatus; + + mSelfPresence.type = statusMap[status].type; + mSelfPresence.status = status; + if ( statusMap[status].canHaveMessage ) + { + mSelfPresence.statusMessage = message; + } + + + QString identifier = mHandles[selfHandle()]; + string strIdentifier = identifier.toUtf8().constData(); + string uri = "sip:" + strIdentifier; + // QString resipStatusQt = ensureStatus(status); + // Data resipStatus(resipStatusQt.toUtf8().data()); + Data resipStatus(status.toUtf8().data()); + + qDebug() << "status = " << mSelfPresence.status << " type = " << mSelfPresence.type << " message = " << message; + + ua->createPublication(Data("presence"), NameAddr(uri.c_str()), resipStatus, 3600, Mime("application", "pidf+xml")); + return selfHandle(); } +Tp::SimpleContactPresences +tr::Connection::getPresences(const Tp::UIntList &handles) +{ + StackLog(<<"getPresences()"); + + Tp::SimpleContactPresences presences; + Q_FOREACH ( uint handle, handles ) + { + presences[handle] = getPresence(handle); + } + + return presences; +} + +Tp::SimplePresence +tr::Connection::getPresence(uint handle) +{ + StackLog(<<"getPresence()"); + if ( !mPresences.contains(handle) ) + { + return Tp::SimplePresence(); + } + qDebug() << "presence = " << mPresences.value(handle).status; + + return mPresences.value(handle); +} void tr::Connection::doDisconnect() @@ -195,7 +500,8 @@ tr::Connection::setStatusSlot(uint newStatus, uint reason) uint tr::Connection::ensureHandle(const QString& identifier) { - if(!mIdentifiers.contains(identifier)) { + if ( !mIdentifiers.contains(identifier) ) + { long id = nextHandleId++; mHandles[id] = identifier; mIdentifiers[identifier] = id; @@ -223,9 +529,10 @@ tr::Connection::onIncomingCall(const QString & caller, uint callHandle) Tp::DBusError error; Tp::BaseChannelPtr channel = ensureChannel(request, yours, false, &error); - if (error.isValid() || channel.isNull()) { - qWarning() << "error creating the channel " << error.name() << error.message(); - return; + if ( error.isValid() || channel.isNull() ) + { + qWarning() << "error creating the channel " << error.name() << error.message(); + return; } } @@ -234,16 +541,19 @@ tr::Connection::inspectHandles(uint handleType, const Tp::UIntList &handles, Tp: { StackLog(<<"inspectHandles()"); - if(handleType != Tp::HandleTypeContact) { + if ( handleType != Tp::HandleTypeContact ) + { error->set(TP_QT_ERROR_INVALID_ARGUMENT, QLatin1String("Unsupported handle type")); return QStringList(); } QStringList result; - foreach (uint handle, handles) { - if(!mHandles.contains(handle)) { - return QStringList(); + Q_FOREACH ( uint handle, handles ) + { + if ( !mHandles.contains(handle) ) + { + return QStringList(); } result.append(mHandles.value(handle)); @@ -257,15 +567,16 @@ tr::Connection::requestHandles(uint handleType, const QStringList &identifiers, DebugLog(<<"requestHandles() "); Tp::UIntList result; - if(handleType != Tp::HandleTypeContact) { + if ( handleType != Tp::HandleTypeContact ) + { ErrLog(<<"requestHandles() unsupported handleType == " << handleType); error->set(TP_QT_ERROR_INVALID_ARGUMENT, QLatin1String("Connection::requestHandles - Handle Type unknown")); return result; } - Q_FOREACH(const QString &identifier, identifiers) { - ensureHandle(identifier); - result.append(mIdentifiers[identifier]); + Q_FOREACH ( const QString &identifier, identifiers ) + { + result.append(ensureHandle(identifier)); } return result; @@ -281,27 +592,40 @@ tr::Connection::createChannel(const QVariantMap &request, Tp::DBusError *error) uint targetHandle = 0; QString targetID; - switch (targetHandleType) { - case Tp::HandleTypeContact: - if (request.contains(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle"))) { - targetHandle = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")).toUInt(); - targetID = mHandles[targetHandle]; - } else if (request.contains(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetID"))) { - targetID = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetID")).toString(); - targetHandle = ensureHandle(targetID); + switch ( targetHandleType ) + { + case Tp::HandleTypeContact: + { + if ( request.contains(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")) ) + { + targetHandle = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")).toUInt(); + targetID = mHandles[targetHandle]; + } + + else if ( request.contains(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetID")) ) + { + targetID = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetID")).toString(); + targetHandle = ensureHandle(targetID); + } + break; } - break; - default: - if (error) { - error->set(TP_QT_ERROR_INVALID_ARGUMENT, QLatin1String("Unknown target handle type")); + + default: + { + if ( error ) + { + error->set(TP_QT_ERROR_INVALID_ARGUMENT, QLatin1String("Unknown target handle type")); + } + return Tp::BaseChannelPtr(); + break; } - return Tp::BaseChannelPtr(); - break; } - if (targetID.isEmpty()) { - if (error) { - error->set(TP_QT_ERROR_INVALID_HANDLE, QLatin1String("Target handle is empty.")); + if ( targetID.isEmpty() ) + { + if ( error ) + { + error->set(TP_QT_ERROR_INVALID_HANDLE, QLatin1String("Target handle is empty.")); } return Tp::BaseChannelPtr(); } @@ -309,30 +633,32 @@ tr::Connection::createChannel(const QVariantMap &request, Tp::DBusError *error) uint initiatorHandle = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".InitiatorHandle")).toUInt(); /*Tp::BaseChannelPtr baseChannel = Tp::BaseChannel::create(this, channelType, Tp::HandleType(targetHandleType), targetHandle); - baseChannel->setTargetID(targetID); - baseChannel->setInitiatorHandle(initiatorHandle); */ + baseChannel->setTargetID(targetID); + baseChannel->setInitiatorHandle(initiatorHandle); */ ParticipantHandle participantHandle = -1; bool incoming = false; StackLog(<<"createChannel - channelType = " << channelType.toUtf8().constData() << " and contact = " << targetID.toUtf8().constData()); - if(channelType == TP_QT_IFACE_CHANNEL_TYPE_CALL) { + if ( channelType == TP_QT_IFACE_CHANNEL_TYPE_CALL ) + { recon::ConversationHandle cHandle = 1; // FIXME - hardcoded default value, should create new Conversation //recon::ConversationHandle cHandle = myConversationManager->createConversation(); //myConversationManager->createLocalParticipant(); - if(!request.contains("participantHandle")) + if ( !request.contains("participantHandle") ) { - // Outgoing call - DebugLog(<<"outoing call"); - NameAddr callee(targetID.toUtf8().constData()); - participantHandle = myConversationManager->createRemoteParticipant(cHandle, callee); - myConversationManager->addParticipant(cHandle, participantHandle); + // Outgoing call + DebugLog(<<"outoing call"); + NameAddr callee(targetID.toUtf8().constData()); + participantHandle = myConversationManager->createRemoteParticipant(cHandle, callee); + myConversationManager->addParticipant(cHandle, participantHandle); } + else { - // Incoming call - DebugLog(<<"incoming call"); - incoming = true; - participantHandle = (ParticipantHandle)request["participantHandle"].toUInt(); + // Incoming call + DebugLog(<<"incoming call"); + incoming = true; + participantHandle = (ParticipantHandle)request["participantHandle"].toUInt(); } } @@ -346,23 +672,35 @@ tr::Connection::createChannel(const QVariantMap &request, Tp::DBusError *error) Tp::ContactAttributesMap tr::Connection::getContactAttributes(const Tp::UIntList &handles, const QStringList &ifaces, Tp::DBusError *error) { - StackLog(<<"getContactAttributes"); - qDebug() << "getContactAttributes" << handles << ifaces; - Tp::ContactAttributesMap attributesMap; - Q_FOREACH(uint handle, handles) { - QVariantMap attributes; - QStringList inspectedHandles = inspectHandles(Tp::HandleTypeContact, Tp::UIntList() << handle, error); - if (inspectedHandles.size() > 0) { - attributes[TP_QT_IFACE_CONNECTION+"/contact-id"] = inspectedHandles.at(0); - } else { - continue; - } - if (ifaces.contains(TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE)) { - attributes[TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE+"/presence"] = QVariant::fromValue(mSelfPresence); - } - attributesMap[handle] = attributes; - } - return attributesMap; -} + StackLog(<<"getContactAttributes"); + Tp::ContactAttributesMap attributesMap; + Q_FOREACH ( uint handle, handles ) + { + QVariantMap attributes; + QStringList inspectedHandle = inspectHandles(Tp::HandleTypeContact, Tp::UIntList() << handle, error); + if ( inspectedHandle.size() > 0 ) + { + attributes[TP_QT_IFACE_CONNECTION+"/contact-id"] = inspectedHandle.at(0); + } + else + { + continue; + } + qDebug() << "handle = " << handle << " inspectedHandle = " << inspectedHandle; + if ( ifaces.contains(TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE) ) + { + attributes[TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE+"/presence"] = QVariant::fromValue(getPresence(handle)); + } + + if ( ifaces.contains(TP_QT_IFACE_CONNECTION_INTERFACE_ALIASING) ) + { + attributes[TP_QT_IFACE_CONNECTION_INTERFACE_ALIASING + QLatin1String("/alias")] = QVariant::fromValue(mAliases[handle]); + } + + attributesMap[handle] = attributes; + } + + return attributesMap; +} diff --git a/apps/telepathy/Connection.hxx b/apps/telepathy/Connection.hxx index 9de94ad197..67a8c5c535 100644 --- a/apps/telepathy/Connection.hxx +++ b/apps/telepathy/Connection.hxx @@ -19,7 +19,7 @@ #define CONNECTION_HXX #if defined(HAVE_CONFIG_H) - #include "config.h" +#include "config.h" #endif @@ -28,6 +28,7 @@ #include #include + #include #include @@ -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 ¶meters); - - 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 mUAProfile; - resip::SharedPtr mConversationProfile; - tr::MyUserAgent* ua; - std::auto_ptr myConversationManager; - - Tp::BaseConnectionContactsInterfacePtr mContactsInterface; - Tp::BaseConnectionSimplePresenceInterfacePtr mSimplePresenceInterface; - Tp::BaseConnectionContactListInterfacePtr mContactListInterface; - Tp::BaseConnectionRequestsInterfacePtr mRequestsInterface; - - long nextHandleId; - QMap mHandles; - QMap 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 ¶meters); + + 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 mUAProfile; + resip::SharedPtr mConversationProfile; + tr::MyUserAgent* ua; + std::auto_ptr myConversationManager; + resip::SharedPtr mProfile; + + Tp::BaseConnectionContactsInterfacePtr mContactsInterface; + Tp::BaseConnectionAliasingInterfacePtr mAliasingInterface; + Tp::BaseConnectionSimplePresenceInterfacePtr mSimplePresenceInterface; + Tp::BaseConnectionContactListInterfacePtr mContactListInterface; + Tp::BaseConnectionRequestsInterfacePtr mRequestsInterface; + + long nextHandleId; + QMap mHandles; + QMap mIdentifiers; + Tp::AliasMap mAliases; + + // QMap mTpStatus; + // QMap mResipStatus; + + Tp::SimpleStatusSpecMap statusMap; + Tp::SimplePresence mSelfPresence; + Tp::SimpleContactPresences mPresences; + }; } #endif - - - diff --git a/apps/telepathy/MyUserAgent.cxx b/apps/telepathy/MyUserAgent.cxx index 2933fd9c36..f0fd4f38ac 100644 --- a/apps/telepathy/MyUserAgent.cxx +++ b/apps/telepathy/MyUserAgent.cxx @@ -22,7 +22,17 @@ #include #include #include +#include +#include +#include +#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" @@ -49,10 +59,205 @@ tr::MyUserAgent::onSubscriptionTerminated(SubscriptionHandle handle, unsigned in InfoLog(<< "onSubscriptionTerminated: handle=" << handle << " statusCode=" << statusCode); } +std::vector +tr::MyUserAgent::getTuplesFromXML(const Data& notifyData) +{ + ParseBuffer pb(notifyData.data(), notifyData.size()); + std::string pidf_namespace; + + XMLCursor xml(pb); + std::vector 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 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 diff --git a/apps/telepathy/MyUserAgent.hxx b/apps/telepathy/MyUserAgent.hxx index d6141dc59b..dc2df3ca64 100644 --- a/apps/telepathy/MyUserAgent.hxx +++ b/apps/telepathy/MyUserAgent.hxx @@ -45,6 +45,12 @@ public: virtual void thread(); virtual void setStatus(uint newStatus, uint reason); virtual void stop(); + +private: + std::vector getTuplesFromXML(const resip::Data& notifyData); + +signals: + void setContactStatus(const QString& identifier, const QString& status); private: tr::Connection& mConnection; diff --git a/configure.ac b/configure.ac index 49b00f8320..4d6318a6a0 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/resip/dum/BaseCreator.cxx b/resip/dum/BaseCreator.cxx index 4a38d0d50b..453f60c230 100644 --- a/resip/dum/BaseCreator.cxx +++ b/resip/dum/BaseCreator.cxx @@ -133,6 +133,11 @@ BaseCreator::makeInitialRequest(const NameAddr& target, const NameAddr& from, Me // Add ;ob parm to non-register requests - RFC5626 pg17 mLastRequest->header(h_Contacts).front().uri().param(p_ob); } + + if(method == SUBSCRIBE) + { + mLastRequest->header(h_Accepts).push_back( Mime( "application","pidf+xml") ); + } Via via; mLastRequest->header(h_Vias).push_front(via); @@ -145,7 +150,7 @@ BaseCreator::makeInitialRequest(const NameAddr& target, const NameAddr& from, Me //DumHelper::setOutgoingEncryptionLevel(mLastRequest, mEncryptionLevel); - DebugLog ( << "BaseCreator::makeInitialRequest: " << std::endl << std::endl << mLastRequest); + DebugLog ( << "BaseCreator::makeInitialRequest: " << std::endl << std::endl << *mLastRequest); } diff --git a/resip/recon/HandleTypes.hxx b/resip/recon/HandleTypes.hxx index 36b9530612..c159786911 100644 --- a/resip/recon/HandleTypes.hxx +++ b/resip/recon/HandleTypes.hxx @@ -7,6 +7,7 @@ namespace recon typedef unsigned int ConversationHandle; typedef unsigned int ParticipantHandle; typedef unsigned int SubscriptionHandle; +typedef unsigned int PublicationHandle; } diff --git a/resip/recon/Makefile.am b/resip/recon/Makefile.am index 9127301298..e60be80e5b 100644 --- a/resip/recon/Makefile.am +++ b/resip/recon/Makefile.am @@ -48,6 +48,7 @@ librecon_la_SOURCES = BridgeMixer.cxx \ SipXHelper.cxx \ UserAgent.cxx \ UserAgentClientSubscription.cxx \ + UserAgentClientPublication.cxx \ UserAgentDialogSetFactory.cxx \ UserAgentMasterProfile.cxx \ UserAgentRegistration.cxx \ @@ -84,6 +85,7 @@ nobase_reconinclude_HEADERS = ReconSubsystem.hxx \ DefaultDialogSet.hxx \ Participant.hxx \ UserAgentClientSubscription.hxx \ + UserAgentClientPublication.hxx \ UserAgent.hxx \ ConversationParticipantAssignment.hxx \ RemoteParticipant.hxx \ diff --git a/resip/recon/UserAgent.cxx b/resip/recon/UserAgent.cxx index 35dda3216b..1473c33558 100644 --- a/resip/recon/UserAgent.cxx +++ b/resip/recon/UserAgent.cxx @@ -7,6 +7,7 @@ #include "UserAgentCmds.hxx" #include "UserAgentServerAuthManager.hxx" #include "UserAgentClientSubscription.hxx" +#include "UserAgentClientPublication.hxx" #include "UserAgentRegistration.hxx" #include "ReconSubsystem.hxx" @@ -17,10 +18,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #if defined(USE_SSL) @@ -133,6 +136,26 @@ UserAgent::unregisterSubscription(UserAgentClientSubscription *subscription) mSubscriptions.erase(subscription->getSubscriptionHandle()); } +PublicationHandle +UserAgent::getNewPublicationHandle() +{ + Lock lock(mPublicationHandleMutex); + return mCurrentPublicationHandle++; +} + +void +UserAgent::registerPublication(UserAgentClientPublication *publication) +{ + mPublications[publication->getPublicationHandle()] = publication; +} + +void +UserAgent::unregisterPublication(UserAgentClientPublication *publication) +{ + mPublications.erase(publication->getPublicationHandle()); +} + + ConversationProfileHandle UserAgent::getNewConversationProfileHandle() { @@ -282,6 +305,22 @@ UserAgent::destroySubscription(SubscriptionHandle handle) mDum.post(cmd); } +PublicationHandle +UserAgent::createPublication(const Data& eventType, const NameAddr& target, const Data& status, unsigned int publicationTime, const Mime& mimeType) +{ + PublicationHandle handle = getNewPublicationHandle(); + CreatePublicationCmd* cmd = new CreatePublicationCmd(this, handle, status, eventType, target, publicationTime, mimeType); + mDum.post(cmd); + + return handle; +} + +void +UserAgent::destroyPublication(PublicationHandle handle) +{ + DestroyPublicationCmd* cmd = new DestroyPublicationCmd(this, handle); + mDum.post(cmd); +} SharedPtr UserAgent::getDefaultOutgoingConversationProfile() @@ -569,6 +608,119 @@ UserAgent::destroySubscriptionImpl(SubscriptionHandle handle) } } +class ClientPubHandler : public ClientPublicationHandler { +public: + ClientPubHandler() {} + virtual void onSuccess(ClientPublicationHandle cph, const SipMessage& status) + { + InfoLog(<<"ClientPubHandler::onSuccess\n"); + handle = cph; + } + virtual void onRemove(ClientPublicationHandle cph, const SipMessage& status) + { + InfoLog(<<"ClientPubHandler::onRemove\n"); + handle = ClientPublicationHandle(); + } + virtual int onRequestRetry(ClientPublicationHandle cph, int retrySeconds, const SipMessage& status) + { + handle = cph; + InfoLog(<<"ClientPubHandler::onRequestRetry\n"); + return 30; + } + virtual void onFailure(ClientPublicationHandle cph, const SipMessage& status) + { + InfoLog(<<"ClientPubHandler::onFailure\n"); + handle = ClientPublicationHandle(); + } + ClientPublicationHandle handle; +}; + +void +UserAgent::createPublicationImpl(PublicationHandle handle, const Data& status, const Data& eventType, const NameAddr& target, unsigned int publicationTime, const Mime& mimeType) +{ + // Ensure we have a client publication handler for this event type + if(!mDum.getClientPublicationHandler(eventType)) + { + ClientPubHandler* cph = new ClientPubHandler(); + mDum.addClientPublicationHandler(eventType, cph); + } + // Ensure that the request Mime type is supported in the dum profile + if(!mProfile->isMimeTypeSupported(PUBLISH, mimeType)) + { + mProfile->addSupportedMimeType(PUBLISH, mimeType); + } + + // Adding rpid defined at RFC 4480 https://tools.ietf.org/html/rfc4480#page-7 + resip::GenericPidfContents gPidf; + + resip::GenericPidfContents::Node* dm = new resip::GenericPidfContents::Node(); + dm->mNamespacePrefix = Data("dm:"); + dm->mTag = "person"; + dm->mAttributes["id"] = Random::getRandomHex(3); + + resip::GenericPidfContents::Node* rpid = new resip::GenericPidfContents::Node(); + rpid->mNamespacePrefix = Data("rpid:"); + rpid->mTag = "activities"; + dm->mChildren.push_back(rpid); + + if(status != "available") + { + resip::GenericPidfContents::Node* st = new resip::GenericPidfContents::Node(); + st->mNamespacePrefix = Data("rpid:"); + if(status == "dnd") + { + st->mTag = "busy"; + } + else + { + st->mTag = status; + } + + rpid->mChildren.push_back(st); + } + + + gPidf.getRootNodes().push_back(dm); + + InfoLog( << "generated gPidf : " << endl << gPidf ); + + Data note; + if(status == "dnd") + { + note = Data("Busy (DND)"); + } + else if(status == "available") + { + note = Data("Online"); + } + else if(status == "away") + { + note = Data("Away"); + } + gPidf.setSimplePresenceTupleNode(Random::getRandomHex(3), true, Data::Empty, note, target.uri().getAorNoReally(), Data(1.0)); + gPidf.setEntity(target.uri()); + gPidf.addNamespace(Data("urn:ietf:params:xml:ns:pidf:data-model"), Data("dm")); + gPidf.addNamespace(Data("urn:ietf:params:xml:ns:pidf:rpid"), Data("rpid")); + + HashMap mp = gPidf.getNamespaces(); + for(HashMap::const_iterator kv = mp.begin(); kv != mp.end(); kv++){ + InfoLog(<<" key = " << kv->first << " value = " << kv->second); + } + + UserAgentClientPublication *publication = new UserAgentClientPublication(*this, mDum, handle); + mDum.send(mDum.makePublication(target, getDefaultOutgoingConversationProfile(), gPidf, eventType, publicationTime, publication)); +} + +void +UserAgent::destroyPublicationImpl(PublicationHandle handle) +{ + PublicationMap::iterator it = mPublications.find(handle); + if(it != mPublications.end()) + { + it->second->end(); + } +} + //////////////////////////////////////////////////////////////////////////////// // Registration Handler //////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// diff --git a/resip/recon/UserAgent.hxx b/resip/recon/UserAgent.hxx index 3363c72385..84de18fa5a 100644 --- a/resip/recon/UserAgent.hxx +++ b/resip/recon/UserAgent.hxx @@ -8,16 +8,21 @@ #include "UserAgentMasterProfile.hxx" #include "HandleTypes.hxx" +#include +#include #include #include #include #include #include #include +#include +#include #include #include #include #include +#include namespace recon { @@ -25,6 +30,7 @@ namespace recon class UserAgentShutdownCmd; class SetActiveConversationProfileCmd; class UserAgentClientSubscription; +class UserAgentClientPublication; class UserAgentRegistration; /** @@ -222,6 +228,10 @@ public: */ void destroySubscription(SubscriptionHandle handle); + PublicationHandle createPublication(const resip::Data& eventType, const resip::NameAddr& target, const resip::Data& status, unsigned int publicationTime, const resip::Mime& mimeType); + + void destroyPublication(PublicationHandle handle); + //////////////////////////////////////////////////////////////////// // UserAgent Handlers ////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// @@ -294,7 +304,9 @@ private: friend class CreateSubscriptionCmd; friend class DestroySubscriptionCmd; friend class MediaResourceParticipant; - + friend class CreatePublicationCmd; + friend class DestroyPublicationCmd; + // Note: In general the following fns are not thread safe and must be called from dum process // loop only friend class UserAgentServerAuthManager; @@ -314,6 +326,9 @@ private: void destroyConversationProfileImpl(ConversationProfileHandle handle); void createSubscriptionImpl(SubscriptionHandle handle, const resip::Data& eventType, const resip::NameAddr& target, unsigned int subscriptionTime, const resip::Mime& mimeType); void destroySubscriptionImpl(SubscriptionHandle handle); + void createPublicationImpl(PublicationHandle handle, const resip::Data& status, const resip::Data& eventType, const resip::NameAddr& target, unsigned int publicationTime, const resip::Mime& mimeType); + void destroyPublicationImpl(PublicationHandle handle); + // Subscription storage friend class UserAgentClientSubscription; @@ -325,6 +340,17 @@ private: void registerSubscription(UserAgentClientSubscription *); void unregisterSubscription(UserAgentClientSubscription *); + // Publication storage + friend class UserAgentClientPublication; + typedef std::map PublicationMap; + PublicationMap mPublications; + resip::Mutex mPublicationHandleMutex; + PublicationHandle mCurrentPublicationHandle; + PublicationHandle getNewPublicationHandle(); // thread safe + void registerPublication(UserAgentClientPublication *); + void unregisterPublication(UserAgentClientPublication *); + + // Conversation Profile Storage typedef std::map > ConversationProfileMap; ConversationProfileMap mConversationProfiles; diff --git a/resip/recon/UserAgentClientPublication.cxx b/resip/recon/UserAgentClientPublication.cxx new file mode 100644 index 0000000000..a983af285a --- /dev/null +++ b/resip/recon/UserAgentClientPublication.cxx @@ -0,0 +1,112 @@ +#include "UserAgent.hxx" +#include "ReconSubsystem.hxx" +#include "UserAgentClientPublication.hxx" + +#include +#include +#include +#include + +using namespace recon; +using namespace resip; +using namespace std; + +#define RESIPROCATE_SUBSYSTEM ReconSubsystem::RECON + +UserAgentClientPublication::UserAgentClientPublication(UserAgent& userAgent, DialogUsageManager& dum, unsigned int handle) +: AppDialogSet(dum), + mUserAgent(userAgent), + mDum(dum), + mPublicationHandle(handle), + mEnded(false) +{ + mUserAgent.registerPublication(this); +} + +UserAgentClientPublication::~UserAgentClientPublication() +{ + mUserAgent.unregisterPublication(this); +} + +PublicationHandle +UserAgentClientPublication::getPublicationHandle() +{ + return mPublicationHandle; +} + +void +UserAgentClientPublication::end() +{ + if(!mEnded) + { + mEnded = true; + AppDialogSet::end(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// ClientPublicationHandler /////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void +UserAgentClientPublication::onSuccess(ClientPublicationHandle handle, const SipMessage& status) +{ + +} + +void +UserAgentClientPublication::onRemove(ClientPublicationHandle handle, const SipMessage& status) +{ + +} + +void +UserAgentClientPublication::onFailure(ClientPublicationHandle handle, const SipMessage& status) +{ + +} + +int +UserAgentClientPublication::onRequestRetry(ClientPublicationHandle handle, int retrySeconds, const SipMessage& status) +{ + return 0; +} + +void +UserAgentClientPublication::onStaleUpdate(ClientPublicationHandle handle, const SipMessage& status) +{ + +} + +/* ==================================================================== + + Copyright (c) 2007-2008, Plantronics, Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of Plantronics nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ==================================================================== */ diff --git a/resip/recon/UserAgentClientPublication.hxx b/resip/recon/UserAgentClientPublication.hxx new file mode 100644 index 0000000000..93bcf04cb6 --- /dev/null +++ b/resip/recon/UserAgentClientPublication.hxx @@ -0,0 +1,99 @@ +#if !defined(UserAgentClientPublication_hxx) +#define UserAgentClientPublication_hxx + +#include +#include +#include +#include + +#include "UserAgent.hxx" + +namespace resip +{ +class DialogUsageManager; +class SipMessage; +} + +namespace recon +{ +class UserAgent; + +/** + This class is used to manage active client publications. + +*/ + +class UserAgentClientPublication : public resip::AppDialogSet +{ + public: + UserAgentClientPublication(UserAgent& userAgent, resip::DialogUsageManager& dum, unsigned int handle); + virtual ~UserAgentClientPublication(); + + PublicationHandle getPublicationHandle(); + virtual void end(); + + // ClientPublicationHandler /////////////////////////////////////////////////// + /// Called when the publication succeeds or each time it is sucessfully + /// refreshed. + virtual void onSuccess(resip::ClientPublicationHandle, const resip::SipMessage& status); + + //publication was successfully removed + virtual void onRemove(resip::ClientPublicationHandle, const resip::SipMessage& status); + + //call on failure. The usage will be destroyed. Note that this may not + //necessarily be 4xx...a malformed 200, etc. could also reach here. + virtual void onFailure(resip::ClientPublicationHandle, const resip::SipMessage& status); + + /// call on Retry-After failure. + /// return values: -1 = fail, 0 = retry immediately, N = retry in N seconds + virtual int onRequestRetry(resip::ClientPublicationHandle, int retrySeconds, const resip::SipMessage& status); + + // ?dcm? -- when should this be called + virtual void onStaleUpdate(resip::ClientPublicationHandle, const resip::SipMessage& status); + + + private: + UserAgent &mUserAgent; + resip::DialogUsageManager &mDum; + PublicationHandle mPublicationHandle; + bool mEnded; +}; + +} + +#endif + + +/* ==================================================================== + + Copyright (c) 2007-2008, Plantronics, Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of Plantronics nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ==================================================================== */ diff --git a/resip/recon/UserAgentCmds.hxx b/resip/recon/UserAgentCmds.hxx index 52bb6f1b9f..be856930da 100644 --- a/resip/recon/UserAgentCmds.hxx +++ b/resip/recon/UserAgentCmds.hxx @@ -172,6 +172,59 @@ class DestroySubscriptionCmd : public resip::DumCommand SubscriptionHandle mHandle; }; +class CreatePublicationCmd : public resip::DumCommand +{ + public: + CreatePublicationCmd(UserAgent* userAgent, + PublicationHandle handle, + const resip::Data& status, + const resip::Data& eventType, + const resip::NameAddr& target, + unsigned int publicationTime, + const resip::Mime& mimeType) + : mUserAgent(userAgent), + mHandle(handle), + mStatus(status), + mEventType(eventType), + mTarget(target), + mPublicationTime(publicationTime), + mMimeType(mimeType) {} + virtual void executeCommand() + { + mUserAgent->createPublicationImpl(mHandle, mStatus, mEventType, mTarget, mPublicationTime, mMimeType); + } + resip::Message* clone() const { resip_assert(0); return 0; } + EncodeStream& encode(EncodeStream& strm) const { strm << " CreatePublicationCmd: "; return strm; } + EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); } + private: + UserAgent* mUserAgent; + PublicationHandle mHandle; + resip::Data mStatus; + resip::Data mEventType; + resip::NameAddr mTarget; + unsigned int mPublicationTime; + resip::Mime mMimeType; +}; + +class DestroyPublicationCmd : public resip::DumCommand +{ + public: + DestroyPublicationCmd(UserAgent* userAgent, + PublicationHandle handle) + : mUserAgent(userAgent), + mHandle(handle) {} + virtual void executeCommand() + { + mUserAgent->destroyPublicationImpl(mHandle); + } + resip::Message* clone() const { resip_assert(0); return 0; } + EncodeStream& encode(EncodeStream& strm) const { strm << " DestroyPublicationCmd: "; return strm; } + EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); } + private: + UserAgent* mUserAgent; + PublicationHandle mHandle; +}; + } #endif diff --git a/resip/stack/TransportSelector.cxx b/resip/stack/TransportSelector.cxx index 6bae0490bf..caa6d0541d 100644 --- a/resip/stack/TransportSelector.cxx +++ b/resip/stack/TransportSelector.cxx @@ -62,6 +62,8 @@ #include +#include "resip/stack/UnknownParameterType.hxx" + using namespace resip; #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT @@ -1146,6 +1148,8 @@ TransportSelector::transmit(SipMessage* msg, Tuple& target, SendData* sendData) contact.uri().param(p_transport) = Tuple::toDataLower(transport->transport()); } + // contact.uri().param(UnknownParameterType("registering_acc")) = Data("ws_sip5060_net"); + // Add comp=sigcomp to contact URI // Also, If no +sip.instance on contact HEADER, // add sigcomp-id="" to contact URI.