diff --git a/daemon/src/client/callmanager.h b/daemon/src/client/callmanager.h index c2189a6dfe69b98afba904e2926d931d65bee2a3..57eea4c93804fbdec8d6fa2fdb803de643a11353 100644 --- a/daemon/src/client/callmanager.h +++ b/daemon/src/client/callmanager.h @@ -184,6 +184,7 @@ class CallManager void subscribePresence(const std::string& accountID, const std::string& buddySipUri); void unsubscribePresence(const std::string& accountID, const std::string& buddySipUri); void sendPresence(const std::string& accountID, const std::string& status, const std::string& note); + void confirmPresenceSubscription(const bool& confirm); private: #if HAVE_ZRTP diff --git a/daemon/src/client/dbus/callmanager-introspec.xml b/daemon/src/client/dbus/callmanager-introspec.xml index b0e9954dc0cadd00d811ebe09f9b07e5bdcffefd..47a22e47f7ffb43b1b8525c4c02d708f2fd7231a 100644 --- a/daemon/src/client/dbus/callmanager-introspec.xml +++ b/daemon/src/client/dbus/callmanager-introspec.xml @@ -832,18 +832,26 @@ <arg type="s" name="buddySipUri" direction="in"/> </method> - <method name="sendPresence" tp:name-for-bindings="sendPresence"> + <method name="sendPresence" tp:name-for-bindings="sendPresence"> <tp:added version="0.9.7"/> <arg type="s" name="accountID" direction="in"/> <arg type="s" name="status" direction="in"/> <arg type="s" name="note" direction="in"/> </method> + <method name="confirmPresenceSubscription" tp:name-for-bindings="confirmPresenceSubscription"> + <arg type="b" name="confirm"/> + </method> + <signal name="newPresenceNotification" tp:name-for-bindings="newPresenceNotification"> <arg type="s" name="buddyUri"/> <arg type="s" name="status"/> <arg type="s" name="lineStatus"/> - </signal>D + </signal> + + <signal name="newPresenceSubscription" tp:name-for-bindings="newPresenceSubscription"> + <arg type="s" name="buddyUri"/> + </signal> </interface> </node> diff --git a/daemon/src/client/dbus/callmanager.cpp b/daemon/src/client/dbus/callmanager.cpp index 3dc6e0757caef877bbf87049228ecb8237231852..4178ada940d5b033e48e38424732044c19d9bf9c 100644 --- a/daemon/src/client/dbus/callmanager.cpp +++ b/daemon/src/client/dbus/callmanager.cpp @@ -426,14 +426,14 @@ CallManager::sendTextMessage(const std::string& callID, const std::string& messa void CallManager::subscribePresence(const std::string& accountID, const std::string& buddySipUri) { - DEBUG("subscribePresence"); + DEBUG("subscribePresence (acc:%s, buddy:%)",accountID.c_str(), buddySipUri.c_str()); Manager::instance().subscribePresence(accountID,buddySipUri); } void CallManager::unsubscribePresence(const std::string& accountID, const std::string& buddySipUri) { - DEBUG("unsubscribePresence"); + DEBUG("unsubscribePresence (acc:%s, buddy:%)",accountID.c_str(), buddySipUri.c_str()); Manager::instance().unsubscribePresence(accountID,buddySipUri); } @@ -441,6 +441,14 @@ void CallManager::sendPresence(const std::string& accountID, const std::string& status, const std::string& note) { - DEBUG("sendPresence"); + DEBUG("sendPresence (acc:%s, status:%s).",accountID.c_str(),status.c_str()); Manager::instance().sendPresence(accountID,status,note); } + +void + +CallManager::confirmPresenceSubscription(const bool& confirm) +{ + DEBUG("confirmPresenceSubscription : %s",confirm); + Manager::instance().confirmPresenceSubscription(confirm); +} diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index 0570709039d7d68da815ffcc004ff9c4eea97fe4..87bfd451c5d0418c94f57d85d6f38cd3aaa26813 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -2950,7 +2950,13 @@ void ManagerImpl::sendPresence(const std::string& accountID, const std::string& account->getPresence()->sendPresence(status,note); } -void +void ManagerImpl::confirmPresenceSubscription(const bool& confirm) +{ + SIPAccount *account = Manager::instance().getSipAccount("IP2IP"); + account->getPresence()->confirmNewServerSubscription(confirm); +} + + void ManagerImpl::registerAccounts() { AccountMap allAccounts(getAllAccounts()); diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h index db78baec8ca6aa8ada62b2fd081406cbae5c2055..246754405180c38b077391f7b5fc84f090a6fb36 100644 --- a/daemon/src/managerimpl.h +++ b/daemon/src/managerimpl.h @@ -1041,11 +1041,15 @@ class ManagerImpl { 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 - * Notify for IP2IP accounts and publish for PBX account + * Notify for IP2IP account and publish for PBX account */ void sendPresence(const std::string& accountID, const std::string& status, const std::string& note); + /** + * Accept or not a PresenceSubscription request for IP2IP account + */ + void confirmPresenceSubscription(const bool& confirm); private: NON_COPYABLE(ManagerImpl); diff --git a/daemon/src/sip/presence_subscription.cpp b/daemon/src/sip/presence_subscription.cpp index fbdd96ab24f135f7fab39cf3c9500cbb49914461..d568de280479f138be8e29f4b178ab3d8b81367a 100644 --- a/daemon/src/sip/presence_subscription.cpp +++ b/daemon/src/sip/presence_subscription.cpp @@ -42,14 +42,13 @@ void pres_evsub_on_srv_state(pjsip_evsub *sub, pjsip_event *event) { pjsip_rx_data *rdata = event->body.rx_msg.rdata; if(!rdata) { - DEBUG("no rdata in presence"); + DEBUG("Presence server state has changed but no rdata."); return; } - /*std::string accountId = "IP2IP"; - SIPAccount *acc = Manager::instance().getSipAccount(accountId);*/ + PJ_UNUSED_ARG(event); SIPPresence * pres = Manager::instance().getSipAccount("IP2IP")->getPresence(); - + pres->lock(); PresenceSubscription *presenceSub = (PresenceSubscription *) pjsip_evsub_get_mod_data(sub,pres->getModId()); WARN("Presence server subscription to %s is %s", presenceSub->remote, pjsip_evsub_get_state_name(sub)); @@ -58,23 +57,13 @@ void pres_evsub_on_srv_state(pjsip_evsub *sub, pjsip_event *event) { state = pjsip_evsub_get_state(sub); - /* ebail : FIXME check if ths code is usefull */ -#if 0 - if (false pjsua_var.ua_cfg.cb.on_srv_subscribe_state) { - pj_str_t from; - - from = server->dlg->remote.info_str; - (*pjsua_var.ua_cfg.cb.on_srv_subscribe_state)(uapres->acc_id, - uapres, &from, - state, event); - } -#endif - if (state == PJSIP_EVSUB_STATE_TERMINATED) { pjsip_evsub_set_mod_data(sub, pres->getModId(), NULL); pres->removeServerSubscription(presenceSub); } + /* TODO check if other cases should be handled*/ } + pres->unlock(); } pj_bool_t pres_on_rx_subscribe_request(pjsip_rx_data *rdata) { @@ -82,7 +71,6 @@ pj_bool_t pres_on_rx_subscribe_request(pjsip_rx_data *rdata) { pjsip_method *method = &rdata->msg_info.msg->line.req.method; pj_str_t *str = &method->name; std::string request(str->ptr, str->slen); - DEBUG("pres_on_rx_subscribe_request for %s.", request.c_str()); pj_str_t contact; pj_status_t status; pjsip_dialog *dlg; @@ -95,27 +83,32 @@ pj_bool_t pres_on_rx_subscribe_request(pjsip_rx_data *rdata) { pres_msg_data msg_data; pjsip_evsub_state ev_state; - /* ebail this code only hande incoming subscribe messages. Otherwise we return FALSE to let other modules handle it */ - if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, pjsip_get_subscribe_method()) != 0){ + + /* Only hande incoming subscribe messages should be processed here. + * Otherwise we return FALSE to let other modules handle it */ + if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, pjsip_get_subscribe_method()) != 0) return PJ_FALSE; - } - std::string name(rdata->msg_info.to->name.ptr, rdata->msg_info.to->name.slen); - std::string server(rdata->msg_info.from->name.ptr, rdata->msg_info.from->name.slen); + DEBUG("Incomming pres_on_rx_subscribe_request for %s.", request.c_str()); + + //std::string name(rdata->msg_info.to->name.ptr, rdata->msg_info.to->name.slen); + //std::string server(rdata->msg_info.from->name.ptr, rdata->msg_info.from->name.slen); - std::string accountId = "IP2IP"; /* ebail : this code is only used for IP2IP accounts */ + std::string accountId = "IP2IP"; /* this code is only used for IP2IP accounts */ SIPAccount *acc = (SIPAccount *) Manager::instance().getSipAccount(accountId); pjsip_endpoint *endpt = ((SIPVoIPLink*) acc->getVoIPLink())->getEndpoint(); SIPPresence * pres = acc->getPresence(); + pres->lock(); - contact = pj_str(strdup(acc->getContactHeader().c_str())); /* Create UAS dialog: */ + contact = pj_str(strdup(acc->getContactHeader().c_str())); status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, &contact, &dlg); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; pj_strerror(status, errmsg, sizeof(errmsg)); WARN("Unable to create UAS dialog for subscription: %s [status=%d]", errmsg, status); + pres->unlock(); pjsip_endpt_respond_stateless(endpt, rdata, 400, NULL, NULL, NULL); return PJ_TRUE; } @@ -141,6 +134,7 @@ pj_bool_t pres_on_rx_subscribe_request(pjsip_rx_data *rdata) { status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), tdata); } + pres->unlock(); return PJ_FALSE; } @@ -157,8 +151,8 @@ pj_bool_t pres_on_rx_subscribe_request(pjsip_rx_data *rdata) { pjsip_evsub_set_mod_data(sub, pres->getModId(), presenceSub); - /* Add server subscription to the list: */ - pres->addServerSubscription(presenceSub); + /* Need client approvement.*/ + pres->reportNewServerSubscription(presenceSub); /* Capture the value of Expires header. */ expires_hdr = (pjsip_expires_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL); @@ -179,6 +173,7 @@ pj_bool_t pres_on_rx_subscribe_request(pjsip_rx_data *rdata) { if (status != PJ_SUCCESS) { WARN("Unable to accept presence subscription %d", status); pjsip_pres_terminate(sub, PJ_FALSE); + pres->unlock(); return PJ_FALSE; } //TODO: handle rejection case pjsua_pers.c:956 @@ -207,8 +202,10 @@ pj_bool_t pres_on_rx_subscribe_request(pjsip_rx_data *rdata) { if (status != PJ_SUCCESS) { WARN("Unable to create/send NOTIFY %d", status); pjsip_pres_terminate(sub, PJ_FALSE); + pres->unlock(); return status; } + pres->unlock(); return PJ_TRUE; } diff --git a/daemon/src/sip/presence_subscription.h b/daemon/src/sip/presence_subscription.h index c70d41a00da3c5af6f1a4edb5e7b74b816fef63f..f9860e48f3bf5807a646c62274217099b37df224 100644 --- a/daemon/src/sip/presence_subscription.h +++ b/daemon/src/sip/presence_subscription.h @@ -45,7 +45,7 @@ extern pj_bool_t pres_on_rx_subscribe_request(pjsip_rx_data *rdata); static pjsip_module mod_presence_server = { NULL, NULL, /* prev, next. */ - pj_str("mod-presence-server"), //{ "mod-lotes-presence", 18}, /* Name. */ + pj_str("mod-presence-server"), /* Name. */ -1, /* Id */ PJSIP_MOD_PRIORITY_DIALOG_USAGE, NULL, /* load() */ diff --git a/daemon/src/sip/sipbuddy.h b/daemon/src/sip/sipbuddy.h index d0dda6c93ac5684fdf15df1fdf4d6b995656460e..ace2903028c80a192507431dcdbbb91c57515209 100644 --- a/daemon/src/sip/sipbuddy.h +++ b/daemon/src/sip/sipbuddy.h @@ -113,6 +113,10 @@ class SIPBuddy { pjsip_hdr *res_hdr, pjsip_msg_body **p_body); friend void buddy_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry); + + /** + * TODO: explain this: + */ void incLock() { lock_count++; } diff --git a/daemon/src/sip/sippresence.cpp b/daemon/src/sip/sippresence.cpp index a44cf11e10ea44fc4f75d20d1be496177a6c947f..ee3ddca8599c1b8bd4f0c5dea6c98cccc1ede379 100644 --- a/daemon/src/sip/sippresence.cpp +++ b/daemon/src/sip/sippresence.cpp @@ -76,6 +76,7 @@ void pres_process_msg_data(pjsip_tx_data *tdata, const pres_msg_data *msg_data){ } } +static pj_caching_pool cp; SIPPresence::SIPPresence(SIPAccount *acc) : acc_(acc) @@ -88,11 +89,24 @@ SIPPresence::SIPPresence(SIPAccount *acc) , publish_sess() , publish_state() , publish_enabled(true) + , newPresenceSubscription_(NULL) , serverSubscriptions_ () , buddies_ () + , mutex_() + , mutex_nesting_level_() + , mutex_owner_() + , pool_() + , cp_() { // init default status updateStatus("open","Available"); + + cp_ = &cp; + pj_caching_pool_init(cp_, NULL, 0); + pool_ = pj_pool_create(&(cp_->factory), "pres", 1000, 1000, NULL); + /* Create mutex */ + if(pj_mutex_create_recursive(pool_, "pres",&mutex_) != PJ_SUCCESS) + ERROR("Unable to create mutex"); } @@ -186,6 +200,27 @@ void SIPPresence::removeBuddy(SIPBuddy *b){ buddies_.remove(b); } + +void SIPPresence::reportNewServerSubscription(PresenceSubscription *s){ + newPresenceSubscription_ = s; + Manager::instance().getClient()->getCallManager()->newPresenceSubscription(s->remote); +} + +void SIPPresence::confirmNewServerSubscription(const bool& confirm){ + if(newPresenceSubscription_!=NULL) + return; + + if(confirm){ + DEBUG("-Confirm new PresenceSubscription for %s",newPresenceSubscription_->remote); + addServerSubscription(newPresenceSubscription_); + } + else{ + DEBUG("-Refused new PresenceSubscription for %s",newPresenceSubscription_->remote); + newPresenceSubscription_ = NULL; + } +} + + void SIPPresence::addServerSubscription(PresenceSubscription *s) { DEBUG("-PresenceServer subscription added."); serverSubscriptions_.push_back(s); @@ -202,3 +237,34 @@ void SIPPresence::notifyServerSubscription() { for (serverIt = serverSubscriptions_.begin(); serverIt != serverSubscriptions_.end(); serverIt++) (*serverIt)->notify(); } + + +void SIPPresence::lock() +{ + pj_mutex_lock(mutex_); + mutex_owner_ = pj_thread_this(); + ++mutex_nesting_level_; +} + +void SIPPresence::unlock() +{ + if (--mutex_nesting_level_ == 0) + mutex_owner_ = NULL; + pj_mutex_unlock(mutex_); +} + +bool SIPPresence::tryLock() +{ + pj_status_t status; + status = pj_mutex_trylock(mutex_); + if (status == PJ_SUCCESS) { + mutex_owner_ = pj_thread_this(); + ++mutex_nesting_level_; + } + return status; +} + +bool SIPPresence::isLocked() +{ + return mutex_owner_ == pj_thread_this(); +} diff --git a/daemon/src/sip/sippresence.h b/daemon/src/sip/sippresence.h index e05e49076c0d894f2fab5eea328026669c6b1b8a..98b8978da13b643000c595c902e86a8d24498590 100644 --- a/daemon/src/sip/sippresence.h +++ b/daemon/src/sip/sippresence.h @@ -87,12 +87,14 @@ struct pres_msg_data extern void pres_process_msg_data(pjsip_tx_data *tdata, const pres_msg_data *msg_data); - - - class SIPAccount; class SIPBuddy; class PresenceSubscription; +/** + * TODO Clean this: + */ +struct pj_caching_pool; + /** * @file sippresence.h @@ -163,6 +165,18 @@ public: */ void removeBuddy(SIPBuddy *b); + /** + * IP2IP context. + * Report new Subscription to the client, waiting for approval. + * @param s PresenceSubcription pointer. + */ + void reportNewServerSubscription(PresenceSubscription *s); + /** + * IP2IP context. + * Process new subscription based on client decision. + * @param s PresenceSubcription pointer. + */ + void confirmNewServerSubscription(const bool& confirm); /** * IP2IP context. * Add a server associated to a subscriber in the list. @@ -181,6 +195,14 @@ public: */ void notifyServerSubscription(); + /** + * Lock methods + */ + void lock(); + void unlock(); + bool tryLock(); + bool isLocked(); + pjsip_pres_status pres_status_data; /**< Presence Data.*/ pj_bool_t online_status; /**< Our online status. */ pjrpid_element rpid; /**< RPID element information.*/ @@ -190,7 +212,15 @@ public: private: NON_COPYABLE(SIPPresence); + + pj_mutex_t *mutex_; /**< Mutex protection for this data */ + unsigned mutex_nesting_level_; /**< Mutex nesting level. */ + pj_thread_t *mutex_owner_; /**< Mutex owner. */ + pj_caching_pool *cp_; /**< Global pool factory. */ + pj_pool_t *pool_; /**< pjsua's private pool. */ + SIPAccount * acc_; /**< Associated SIP account. */ + PresenceSubscription *newPresenceSubscription_; /**< Latest Subscribers waiting for approval */ std::list< PresenceSubscription *> serverSubscriptions_; /**< Subscribers list.*/ std::list< SIPBuddy *> buddies_; /**< Subcribed buddy list.*/ };