diff --git a/daemon/src/dbus/callmanager-introspec.xml b/daemon/src/dbus/callmanager-introspec.xml index c86062e82a331a9f052063557685d6cb4fe8b64e..ad062f2e7e31d374d13ac2c404d3061562cdf492 100644 --- a/daemon/src/dbus/callmanager-introspec.xml +++ b/daemon/src/dbus/callmanager-introspec.xml @@ -819,14 +819,23 @@ <arg type="s" name="accountID" direction="in"/> <arg type="s" name="buddySipUri" direction="in"/> </method> - <method name="setPresenceOnline" tp:name-for-bindings="setPresenceOnline"> + + <method name="unsubscribePresence" tp:name-for-bindings="unsubscribePresence"> + <tp:added version="0.9.7"/> + <arg type="s" name="accountID" direction="in"/> + <arg type="s" name="buddySipUri" direction="in"/> + </method> + + <method name="setPresenceOnline" tp:name-for-bindings="setPresenceOnline"> <tp:added version="0.9.7"/> <arg type="s" name="accountID" direction="in"/> </method> + <method name="setPresenceOffline" tp:name-for-bindings="setPresenceOffline"> <tp:added version="0.9.7"/> <arg type="s" name="accountID" direction="in"/> </method> + <signal name="newPresenceNotification" tp:name-for-bindings="newPresenceNotification"> <arg type="s" name="buddyUri"/> <arg type="s" name="status"/> diff --git a/daemon/src/dbus/callmanager.cpp b/daemon/src/dbus/callmanager.cpp index 08c24e1be95f525eb84acf418df7f3300f5c7686..108fc356257836a44a2f77364abbe4f02f43bd86 100644 --- a/daemon/src/dbus/callmanager.cpp +++ b/daemon/src/dbus/callmanager.cpp @@ -403,18 +403,28 @@ CallManager::sendTextMessage(const std::string& callID, const std::string& messa ERROR("Could not send \"%s\" text message to %s since SFLphone daemon does not support it, please recompile with instant messaging support", message.c_str(), callID.c_str()); #endif } + void CallManager::subscribePresence(const std::string& accountID, const std::string& buddySipUri) { DEBUG("subscribePresence"); Manager::instance().subscribePresence(accountID,buddySipUri); } + +void +CallManager::unsubscribePresence(const std::string& accountID, const std::string& buddySipUri) +{ + DEBUG("unsubscribePresence"); + Manager::instance().unsubscribePresence(accountID,buddySipUri); +} + void CallManager::setPresenceOnline(const std::string& accountID) { DEBUG("setPresenceOnline"); Manager::instance().setPresenceOnline(accountID); } + void CallManager::setPresenceOffline(const std::string& accountID) { diff --git a/daemon/src/dbus/callmanager.h b/daemon/src/dbus/callmanager.h index 0e7c94a59d4361d6304af4f1b0c1f5d0a7a739a5..9dc59048ee0ec6af642bb704fd54acbc32e7a785 100644 --- a/daemon/src/dbus/callmanager.h +++ b/daemon/src/dbus/callmanager.h @@ -129,6 +129,7 @@ class CallManager /* Presence subscription */ void subscribePresence(const std::string& accountID, const std::string& buddySipUri); + void unsubscribePresence(const std::string& accountID, const std::string& buddySipUri); /* Presence Publication for IP2IP */ void setPresenceOnline(const std::string& accountID); void setPresenceOffline(const std::string& accountID); diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index eb7b8fe8eaec6bc59567ea573d70cd8211b3f783..e25f509e6bc02d8164e4a2aa0581b6e600b128e8 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -85,8 +85,6 @@ #include <sys/types.h> // mkdir(2) #include <sys/stat.h> // mkdir(2) -#include "sip/sipbuddy.h" - ManagerImpl::ManagerImpl() : preferences(), voipPreferences(), hookPreference(), audioPreference(), shortcutPreferences(), @@ -2899,16 +2897,23 @@ void ManagerImpl::startAudioDriverStream() void ManagerImpl::subscribePresence(const std::string& accountID, const std::string& buddySipUri) { SIPAccount *account = Manager::instance().getSipAccount(accountID); - SIPBuddy *b = new SIPBuddy(buddySipUri, account); - b->subscribe(); + account->addBuddy(buddySipUri); } + +void ManagerImpl::unsubscribePresence(const std::string& accountID, const std::string& buddySipUri) +{ + SIPAccount *account = Manager::instance().getSipAccount(accountID); + account->removeBuddy(buddySipUri); +} + void ManagerImpl::setPresenceOnline(const std::string& accountID) { SIPAccount *account = Manager::instance().getSipAccount(accountID); - account->notifyServers("open",""); + account->notifyServerSubscription("open",""); } + void ManagerImpl::setPresenceOffline(const std::string& accountID) { SIPAccount *account = Manager::instance().getSipAccount(accountID); - account->notifyServers("close",""); + account->notifyServerSubscription ("close",""); } diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h index 6bf5d2377369ca765d057943f4802fd3abed549d..03a994a3ad46164e9d52a0eeea85ecfdaa3e94af 100644 --- a/daemon/src/managerimpl.h +++ b/daemon/src/managerimpl.h @@ -1045,8 +1045,9 @@ class ManagerImpl { * Subscribe to buddySipUri for an accountID */ void subscribePresence(const std::string& accountID, const std::string& buddySipUri); + void unsubscribePresence(const std::string& accountID, const std::string& buddySipUri); - /** + /** * push a presence for a account * only used for IP2IP accounts */ diff --git a/daemon/src/sip/presence_subscription.h b/daemon/src/sip/presence_subscription.h index 2d71875af943ac08dc34ef57c409b4c723cb6cc4..32483b68cb5ce0a9d24fc5a554c5ba9bb1ee5ac7 100644 --- a/daemon/src/sip/presence_subscription.h +++ b/daemon/src/sip/presence_subscription.h @@ -8,6 +8,7 @@ #ifndef SERVERPRESENCESUB_H #define SERVERPRESENCESUB_H +#include <string> #include "logger.h" #include <pjsip-simple/evsub.h> #include"pjsip-simple/presence.h" @@ -22,17 +23,25 @@ public: , dlg(d) , expires (-1) {}; + char *remote; /**< Remote URI. */ + std::string accId; /**< Account ID. */ + void setExpires(int ms) { expires = ms; } - inline void notify(const std::string &newPresenceState, const std::string &newChannelState) { - DEBUG("notifying %s", remote); + /*bool operator==(const PresenceSubscription & s) const { + return (!(strcmp(remote,s.remote))); + }*/ + bool match(PresenceSubscription * s){ + // servers match if they have the same remote uri and the account ID. + return ((!(strcmp(remote,s->remote))) && (accId==s->accId)); + } + - pjsip_pres_status pres_status; - pjsip_tx_data *tdata; + inline void notify(const std::string &newPresenceState, const std::string &newChannelState) { + DEBUG("################################################notifying %s", remote); - pjsip_pres_get_status(sub, &pres_status); /* Only send NOTIFY once subscription is active. Some subscriptions * may still be in NULL (when app is adding a new buddy while in the @@ -42,6 +51,11 @@ public: */ if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACTIVE /* && (pres_status.info[0].basic_open != getStatus()) */) { + DEBUG("Active"); + + pjsip_tx_data *tdata; + pjsip_pres_status pres_status; + pjsip_pres_get_status(sub, &pres_status); pres_status.info[0].basic_open = newPresenceState == "open"? true: false; @@ -59,6 +73,10 @@ public: pjsip_pres_send_request(sub, tdata); } } + else{ + DEBUG("Inactive"); + + } } friend void pres_evsub_on_srv_state( pjsip_evsub *sub, pjsip_event *event); @@ -67,10 +85,9 @@ public: private: NON_COPYABLE(PresenceSubscription); pjsip_evsub *sub; /**< The evsub. */ - char *remote; /**< Remote URI. */ - std::string accId; /**< Account ID. */ pjsip_dialog *dlg; /**< Dialog. */ int expires; /**< "expires" value in the request. */ }; + #endif /* SERVERPRESENCESUB_H */ diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp index 1bbcdcbfe9d36f895808d80d6d1c063212e8dd8f..9b0f3f9b9ef606ceae3c8222c751c3f3b65cddbc 100644 --- a/daemon/src/sip/sipaccount.cpp +++ b/daemon/src/sip/sipaccount.cpp @@ -47,10 +47,12 @@ #include <algorithm> #include <cstdlib> + #ifdef SFL_VIDEO #include "video/libav_utils.h" #endif + const char * const SIPAccount::IP2IP_PROFILE = "IP2IP"; const char * const SIPAccount::OVERRTP_STR = "overrtp"; const char * const SIPAccount::SIPINFO_STR = "sipinfo"; @@ -111,7 +113,8 @@ SIPAccount::SIPAccount(const std::string& accountID) , keepAliveTimer_() , keepAliveTimerActive_(false) , link_(SIPVoIPLink::instance()) - , serverSubscriptions () + , serverSubscriptions_ () + , buddies_ () , receivedParameter_("") , rPort_(-1) , via_addr_() @@ -1206,6 +1209,39 @@ VoIPLink* SIPAccount::getVoIPLink() return link_; } + +/* + * Buddy list management + * + */ +void SIPAccount::addBuddy(const std::string& buddySipUri){ + std::list< SIPBuddy *>::iterator buddyIt; + + for (buddyIt = buddies_.begin(); buddyIt != buddies_.end(); buddyIt++) + if((*buddyIt)->getURI()==buddySipUri){ + DEBUG("Buddy:%s exist in the list, Resubscribe.",buddySipUri.c_str()); + (*buddyIt)->subscribe(); // The buddy won't add the subscription if it allready exists. + return; + } + + DEBUG("New buddy subscription added."); + SIPBuddy *b = new SIPBuddy(buddySipUri, this); + b->subscribe(); + buddies_.push_back(b); +} + +void SIPAccount::removeBuddy(const std::string& buddySipUri){ + std::list< SIPBuddy *>::iterator buddyIt; + + for (buddyIt = buddies_.begin(); buddyIt != buddies_.end(); buddyIt++) + if((*buddyIt)->getURI()==buddySipUri){ + DEBUG("Found buddy:%s in list. Unsubscribe.",buddySipUri.c_str()); + (*buddyIt)->unsubscribe(); + return; + } +} + + bool SIPAccount::isIP2IP() const { return accountID_ == IP2IP_PROFILE; @@ -1220,23 +1256,32 @@ bool SIPAccount::isIP2IP() const /* Presence : Method used to add serverSubscription to PresenceSubscription list in case of IP2IP accounts */ void SIPAccount::addServerSubscription(PresenceSubscription *s) { - serverSubscriptions.push_back(s); - DEBUG("server subscription added"); + std::list< PresenceSubscription *>::iterator serverIt; + for (serverIt = serverSubscriptions_.begin(); serverIt != serverSubscriptions_.end(); serverIt++) + if((*serverIt)->match(s)){ + DEBUG("Server already subscribed. Replace it with a new fresh uas."); + serverSubscriptions_.remove(*serverIt); + } + DEBUG("Server subscription added."); + serverSubscriptions_.push_back(s); } -/* Presence : Method used to remove serverSubscription to PresenceSubscription list in case of IP2IP accounts */ -void SIPAccount::removerServerSubscription(PresenceSubscription *s) { - serverSubscriptions.remove(s); +/* Presence : Method used to remove serverSubscription to PresenceSubscription list in: case of IP2IP accounts */ +void SIPAccount::removeServerSubscription(PresenceSubscription *s) { + serverSubscriptions_.remove(s); + delete s; DEBUG("server subscription removed"); } /* Presence : Method used to notify each serverSubscription of a new presencein case of IP2IP accounts */ -void SIPAccount::notifyServers(const std::string &newPresenceStatus, const std::string &newChannelStatus) { +void SIPAccount::notifyServerSubscription(const std::string &newPresenceStatus, const std::string &newChannelStatus) { std::list< PresenceSubscription *>::iterator serverIt; DEBUG("iterating through servers"); - for (serverIt = serverSubscriptions.begin(); serverIt != serverSubscriptions.end(); serverIt++) + for (serverIt = serverSubscriptions_.begin(); serverIt != serverSubscriptions_.end(); serverIt++) (*serverIt)->notify(newPresenceStatus, newChannelStatus); } + + /* * Presence Management for IP2IP accounts * diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h index af031db29efbc5a701f95cd5059d80c1bd9fe995..1df0b17153dafc7f80374fbd4b07712bd301f927 100644 --- a/daemon/src/sip/sipaccount.h +++ b/daemon/src/sip/sipaccount.h @@ -43,6 +43,7 @@ #include "pjsip-ua/sip_regc.h" #include "noncopyable.h" +#include "sipbuddy.h" #include "presence_subscription.h" typedef std::vector<pj_ssl_cipher> CipherArray; @@ -516,12 +517,14 @@ class SIPAccount : public Account { /* Returns true if the username and/or hostname match this account */ bool matches(const std::string &username, const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const; - //void addBuddy(const std::string &uri, bool subscribe); - //void removeBuddy(const std::string &uri); + //int getBuddy(const std::string& buddySipUri, SIPBuddy *b); + void addBuddy(const std::string& buddySipUri); + void removeBuddy(const std::string& buddySipUri); void addServerSubscription(PresenceSubscription *s); - void removerServerSubscription(PresenceSubscription *s); - void notifyServers(const std::string &newPresenceStatus, const std::string &newChannelStatus); - private: + void removeServerSubscription(PresenceSubscription *s); + void notifyServerSubscription(const std::string &newPresenceStatus, const std::string &newChannelStatus); + bool compareServerSubscription(PresenceSubscription *first, PresenceSubscription *second); +private: NON_COPYABLE(SIPAccount); bool fullMatch(const std::string &username, const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const; @@ -768,11 +771,15 @@ class SIPAccount : public Account { */ pjsip_host_port via_addr_; + /** + * server subscription + */ + std::list< PresenceSubscription *> serverSubscriptions_; /** - * Server subscription (added by ELOI) + * buddies */ - std::list< PresenceSubscription *> serverSubscriptions; + std::list< SIPBuddy *> buddies_; }; diff --git a/daemon/src/sip/sipbuddy.cpp b/daemon/src/sip/sipbuddy.cpp index 2316b4e352e5209ee8165ddc44be54046de820f5..6b383125ab46e96d36eb07ae645824955a9c8e00 100644 --- a/daemon/src/sip/sipbuddy.cpp +++ b/daemon/src/sip/sipbuddy.cpp @@ -367,16 +367,17 @@ pj_status_t SIPBuddy::updatePresence() { pj_status_t retStatus; if (sub == NULL) { + DEBUG("Buddy already unsubscribed sub=NULL."); return PJ_SUCCESS; } if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { + DEBUG("Buddy already unsubscribed sub=TERMINATED."); pjsip_evsub_terminate(sub, PJ_FALSE); // = NULL; return PJ_SUCCESS; } DEBUG("Buddy %s: unsubscribing..", uri.ptr); - retStatus = pjsip_pres_initiate(sub, 300, &tdata); if (retStatus == PJ_SUCCESS) { // pjsua_process_msg_data(tdata, NULL); @@ -554,3 +555,8 @@ void SIPBuddy::unsubscribe() { monitor = false; updatePresence(); } + +bool SIPBuddy::match(SIPBuddy *b){ + //return !(strcmp(b->getURI(),getURI())); + return (b->getURI()==getURI()); +} diff --git a/daemon/src/sip/sipbuddy.h b/daemon/src/sip/sipbuddy.h index 0a385c9c7921e78751d5ac9ce55b710abc4d03ca..5035ade267973a92905195898eb1196f0abb259d 100644 --- a/daemon/src/sip/sipbuddy.h +++ b/daemon/src/sip/sipbuddy.h @@ -61,6 +61,7 @@ class SIPBuddy { public: SIPBuddy(const std::string &uri, SIPAccount *acc); ~SIPBuddy(); + bool match(SIPBuddy *b); void subscribe(); void unsubscribe(); bool isSubscribed(); diff --git a/daemon/src/sip/sipvoip_pres.cpp b/daemon/src/sip/sipvoip_pres.cpp index 3c558613bcca6fd3269eace5c8248aa732901126..3f5d650c797d2b95b12765f4ada1140c6c7be9ac 100644 --- a/daemon/src/sip/sipvoip_pres.cpp +++ b/daemon/src/sip/sipvoip_pres.cpp @@ -29,7 +29,7 @@ * as that of the covered work. */ -#ifdef HAVE_CONFIG_H +#ifdef have_config_h #include "config.h" #endif @@ -71,13 +71,11 @@ void pres_evsub_on_srv_state(pjsip_evsub *sub, pjsip_event *event) { // PJSUA_LOCK(); /* ebail : FIXME figure out if locking is necessary or not */ presenceSub = (PresenceSubscription *) pjsip_evsub_get_mod_data(sub, ((SIPVoIPLink*) (acc->getVoIPLink()))->getModId() /*my_mod_pres.id*/); - WARN("Presence subscription to %s is %s", presenceSub->remote, pjsip_evsub_get_state_name(sub)); + WARN("Presence server subscription to %s is %s", presenceSub->remote, pjsip_evsub_get_state_name(sub)); if (presenceSub) { pjsip_evsub_state state; - WARN("Server subscription to %s is %s", presenceSub->remote, pjsip_evsub_get_state_name(sub)); - state = pjsip_evsub_get_state(sub); /* ebail : FIXME check if ths code is usefull */ @@ -95,6 +93,7 @@ void pres_evsub_on_srv_state(pjsip_evsub *sub, pjsip_event *event) { if (state == PJSIP_EVSUB_STATE_TERMINATED) { pjsip_evsub_set_mod_data(sub, ((SIPVoIPLink*) (acc->getVoIPLink()))->getModId(), NULL); // pj_list_erase(uapres); + acc->removeServerSubscription(presenceSub); } } // PJSUA_UNLOCK(); /* ebail : FIXME figure out if unlocking is necessary or not */ @@ -194,6 +193,7 @@ pj_bool_t my_pres_on_rx_request(pjsip_rx_data *rdata) { // pjsip_evsub_add_header(sub, &acc->cfg.sub_hdr_list); int modId = ((SIPVoIPLink*) (acc->getVoIPLink()))->getModId(); pjsip_evsub_set_mod_data(sub, modId/*my_mod_pres.id*/, presenceSub); + //DEBUG("***************** presenceSub.name:%s",sub->mod_name); acc->addServerSubscription(presenceSub); /* Add server subscription to the list: */ // pj_list_push_back(&pjsua_var.acc[acc_id].pres_srv_list, uapres); @@ -293,7 +293,6 @@ pj_bool_t my_pres_on_rx_request(pjsip_rx_data *rdata) { tdata->msg->body = body; } // process_msg_data - status = pjsip_pres_send_request(sub, tdata); } diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 860db2af03e29dfbbbb6f2db6f2d721f770bedb4..a5b85e7130e4ca5b1d61909795513fbcccf471d6 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -2313,7 +2313,7 @@ void setCallMediaLocal(SIPCall* call, const std::string &localIP) return; // Reference: http://www.cs.columbia.edu/~hgs/rtp/faq.html#ports - // We only want to set ports to new values if they haven't been set + // We only want to set ports to new values if they haven't been set if (call->getLocalAudioPort() == 0) { const unsigned callLocalAudioPort = getRandomEvenNumber(16384, 32766); call->setLocalAudioPort(callLocalAudioPort); @@ -2344,7 +2344,7 @@ void SIPVoIPLink::setPresenceState(const std::string &accId, const std::string& #else SIPAccount *acc = Manager::instance().getSipAccount(accId); /*no need of channelStatte. We put it to NULL */ - acc->notifyServers(presenceState, NULL); + acc->notifyServerSubscription(presenceState, NULL); #endif } std::string SIPVoIPLink::getPresenceState() {