Commit 093d8afe authored by Patrick Keroulas's avatar Patrick Keroulas
Browse files

* #28472 : Rename all subscribers/buddies related variables. Limit the

* size of these lists. Add a tmp fake status for IP2IP subscription.
* Change loops to fit c++ 11. Remove code from Manager class.
parent 6b9c5e25
...@@ -181,10 +181,10 @@ class CallManager ...@@ -181,10 +181,10 @@ class CallManager
#endif // __ANDROID__ #endif // __ANDROID__
/* Presence subscription/Notification. */ /* Presence subscription/Notification. */
void subscribePresence(const std::string& accountID, const std::string& buddySipUri); void enablePresence(const std::string& accountID, const bool& flag);
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 sendPresence(const std::string& accountID, const std::string& status, const std::string& note);
void approvePresenceSubscription(const bool& flag, const std::string& uri); void approvePresSubServer(const bool& flag, const std::string& uri);
void subscribePresSubClient(const std::string& accountID, const std::string& uri, const bool& flag);
private: private:
#if HAVE_ZRTP #if HAVE_ZRTP
......
...@@ -820,16 +820,17 @@ ...@@ -820,16 +820,17 @@
<arg type="b" name="accepted" direction="in"/> <arg type="b" name="accepted" direction="in"/>
</method> </method>
<method name="subscribePresence" tp:name-for-bindings="subscribePresence"> <method name="subscribePresSubClient" tp:name-for-bindings="subscribePresSubClient">
<tp:added version="0.9.7"/> <tp:added version="0.9.7"/>
<arg type="s" name="accountID" direction="in"/> <arg type="s" name="accountID" direction="in"/>
<arg type="s" name="buddySipUri" direction="in"/> <arg type="s" name="uri" direction="in"/>
<arg type="b" name="flag" direction="in"/>
</method> </method>
<method name="unsubscribePresence" tp:name-for-bindings="unsubscribePresence"> <method name="enablePresence" tp:name-for-bindings="enablePresence">
<tp:added version="0.9.7"/> <tp:added version="0.9.7"/>
<arg type="s" name="accountID" direction="in"/> <arg type="s" name="accountID" direction="in"/>
<arg type="s" name="buddySipUri" direction="in"/> <arg type="b" name="flag" direction="in"/>
</method> </method>
<method name="sendPresence" tp:name-for-bindings="sendPresence"> <method name="sendPresence" tp:name-for-bindings="sendPresence">
...@@ -839,20 +840,20 @@ ...@@ -839,20 +840,20 @@
<arg type="s" name="note" direction="in"/> <arg type="s" name="note" direction="in"/>
</method> </method>
<method name="approvePresenceSubscription" tp:name-for-bindings="approvePresenceSubscription"> <method name="approvePresSubServer" tp:name-for-bindings="approvePresSubServer">
<tp:added version="0.9.7"/> <tp:added version="0.9.7"/>
<arg type="b" name="flag" direction="in"/> <arg type="b" name="flag" direction="in"/>
<arg type="s" name="uri" direction="in"/> <arg type="s" name="uri" direction="in"/>
</method> </method>
<signal name="newPresenceNotification" tp:name-for-bindings="newPresenceNotification"> <signal name="newPresSubClientNotification" tp:name-for-bindings="newPresSubClientNotification">
<tp:added version="0.9.7"/> <tp:added version="0.9.7"/>
<arg type="s" name="buddyUri"/> <arg type="s" name="buddyUri"/>
<arg type="s" name="status"/> <arg type="s" name="status"/>
<arg type="s" name="lineStatus"/> <arg type="s" name="lineStatus"/>
</signal> </signal>
<signal name="newPresenceSubscription" tp:name-for-bindings="newPresenceSubscription"> <signal name="newPresSubServerRequest" tp:name-for-bindings="newPresSubServerRequest">
<arg type="s" name="buddyUri"/> <arg type="s" name="buddyUri"/>
</signal> </signal>
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#include "sip/sipcall.h" #include "sip/sipcall.h"
#include "sip/sipvoiplink.h" #include "sip/sipvoiplink.h"
#include "sip/sipaccount.h"
#include "sip/sippresence.h"
#include "audio/audiolayer.h" #include "audio/audiolayer.h"
#include "audio/audiortp/audio_rtp_factory.h" #include "audio/audiortp/audio_rtp_factory.h"
#if HAVE_ZRTP #if HAVE_ZRTP
...@@ -423,30 +425,64 @@ CallManager::sendTextMessage(const std::string& callID, const std::string& messa ...@@ -423,30 +425,64 @@ CallManager::sendTextMessage(const std::string& callID, const std::string& messa
#endif #endif
} }
/**
* Un/subscribe to buddySipUri for an accountID
*/
void void
CallManager::subscribePresence(const std::string& accountID, const std::string& buddySipUri) CallManager::subscribePresSubClient(const std::string& accountID, const std::string& uri, const bool& flag)
{ {
DEBUG("subscribePresence (acc:%s, buddy:%s)",accountID.c_str(), buddySipUri.c_str());
Manager::instance().subscribePresence(accountID,buddySipUri); SIPAccount *sipaccount = Manager::instance().getSipAccount(accountID);
if (!sipaccount)
ERROR("Could not find account %s",accountID.c_str());
else{
DEBUG("%subscribePresence (acc:%s, buddy:%s)",flag? "S":"Uns", accountID.c_str(), uri.c_str());
sipaccount->getPresence()->subscribePresSubClient(uri,flag);
}
} }
/**
* Enable the presence module (PUBLISH/SUBSCRIBE)
*/
void void
CallManager::unsubscribePresence(const std::string& accountID, const std::string& buddySipUri) CallManager::enablePresence(const std::string& accountID, const bool& flag){
{ SIPAccount *sipaccount = Manager::instance().getSipAccount(accountID);
DEBUG("unsubscribePresence (acc:%s, buddy:%s)",accountID.c_str(), buddySipUri.c_str()); if (!sipaccount)
Manager::instance().unsubscribePresence(accountID,buddySipUri); ERROR("Could not find account %s",accountID.c_str());
else{
DEBUG("Enable Presence (acc:%s : %s)",accountID.c_str(), flag? "yes":"no");
sipaccount->getPresence()->enable(flag);
}
} }
/**
* push a presence for a account
* Notify for IP2IP account and publish for PBX account
*/
void void
CallManager::sendPresence(const std::string& accountID, const std::string& status, const std::string& note) CallManager::sendPresence(const std::string& accountID, const std::string& status, const std::string& note)
{ {
DEBUG("sendPresence (acc:%s, status:%s).",accountID.c_str(),status.c_str()); SIPAccount *sipaccount = Manager::instance().getSipAccount(accountID);
Manager::instance().sendPresence(accountID,status,note); if (!sipaccount)
ERROR("Could not find account %s",accountID.c_str());
else{
DEBUG("Send Presence (acc:%s)",accountID.c_str());
sipaccount->getPresence()->sendPresence(status,note);
}
} }
/**
* Accept or not a PresSubServer request for IP2IP account
*/
void void
CallManager::approvePresenceSubscription(const bool& flag, const std::string& uri) CallManager::approvePresSubServer(const bool& flag, const std::string& buddySipUri)
{ {
DEBUG("approvePresenceSubscription %s : %s.",uri.c_str(), flag? "yes":"no"); SIPAccount *sipaccount = Manager::instance().getIP2IPAccount();
Manager::instance().approvePresenceSubscription(flag, uri); if (!sipaccount)
ERROR("Could not find account IP2IP");
else{
DEBUG("Approve presence (acc:IP2IP, buddy:%s)", buddySipUri.c_str());
sipaccount->getPresence()->approvePresSubServer(flag, buddySipUri);
}
} }
...@@ -2932,30 +2932,6 @@ void ManagerImpl::startAudioDriverStream() ...@@ -2932,30 +2932,6 @@ void ManagerImpl::startAudioDriverStream()
audiodriver_->startStream(); audiodriver_->startStream();
} }
void ManagerImpl::subscribePresence(const std::string& accountID, const std::string& buddySipUri)
{
SIPAccount *account = Manager::instance().getSipAccount(accountID);
account->getPresence()->subscribeBuddy(buddySipUri);
}
void ManagerImpl::unsubscribePresence(const std::string& accountID, const std::string& buddySipUri)
{
SIPAccount *account = Manager::instance().getSipAccount(accountID);
account->getPresence()->unsubscribeBuddy(buddySipUri);
}
void ManagerImpl::sendPresence(const std::string& accountID, const std::string& status, const std::string& note)
{
SIPAccount *account = Manager::instance().getSipAccount(accountID);
account->getPresence()->sendPresence(status,note);
}
void ManagerImpl::approvePresenceSubscription(const bool& flag, const std::string& uri)
{
SIPAccount *account = Manager::instance().getSipAccount("IP2IP");
account->getPresence()->approveServerSubscription(flag, uri);
}
void void
ManagerImpl::registerAccounts() ManagerImpl::registerAccounts()
{ {
......
...@@ -1035,22 +1035,6 @@ class ManagerImpl { ...@@ -1035,22 +1035,6 @@ class ManagerImpl {
void void
checkAudio(); checkAudio();
/**
* 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
* 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 approvePresenceSubscription(const bool& flag, const std::string& uri);
private: private:
NON_COPYABLE(ManagerImpl); NON_COPYABLE(ManagerImpl);
......
...@@ -17,10 +17,10 @@ libsiplink_la_SOURCES = \ ...@@ -17,10 +17,10 @@ libsiplink_la_SOURCES = \
sip_utils.h \ sip_utils.h \
sippresence.cpp \ sippresence.cpp \
sippresence.h \ sippresence.h \
sipbuddy.cpp \ pres_sub_server.cpp\
sipbuddy.h \ pres_sub_server.h\
presence_subscription.cpp\ pres_sub_client.cpp\
presence_subscription.h\ pres_sub_client.h\
sippublish.cpp\ sippublish.cpp\
sippublish.h sippublish.h
if BUILD_SDES if BUILD_SDES
......
/*
* Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
*
* Author: Patrick Keroulas <patrick.keroulas@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#include "pjsip/sip_multipart.h"
#include "sipvoiplink.h"
#include "manager.h"
#include "sippresence.h"
#include "logger.h"
#include "presence_subscription.h"
/* Callback called when *server* subscription state has changed. */
void pres_evsub_on_srv_state(pjsip_evsub *sub, pjsip_event *event) {
pjsip_rx_data *rdata = event->body.rx_msg.rdata;
if(!rdata) {
DEBUG("Presence server state has changed but no rdata.");
return;
}
PJ_UNUSED_ARG(event);
SIPPresence * pres = Manager::instance().getSipAccount("IP2IP")->getPresence();
pres->lock();
PresenceSubscription *presenceSub = (PresenceSubscription *) pjsip_evsub_get_mod_data(sub,pres->getModId());
DEBUG("Presence server subscription to %s is %s", presenceSub->remote, pjsip_evsub_get_state_name(sub));
if (presenceSub) {
pjsip_evsub_state state;
state = pjsip_evsub_get_state(sub);
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) {
pjsip_method *method = &rdata->msg_info.msg->line.req.method;
pj_str_t *str = &method->name;
std::string request(str->ptr, str->slen);
// pj_str_t contact;
pj_status_t status;
pjsip_dialog *dlg;
pjsip_evsub *sub;
pjsip_evsub_user pres_cb;
pjsip_tx_data *tdata;
pjsip_expires_hdr *expires_hdr;
pjsip_status_code st_code;
pj_str_t reason;
pres_msg_data msg_data;
pjsip_evsub_state ev_state;
/* 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;
/* debug msg */
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, name:%s, server:%s."
, request.c_str()
, name.c_str()
, server.c_str());
/* get parents*/
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();
/* Create UAS dialog: */
std::string c(acc->getContactHeader());
const pj_str_t contact = pj_str((char*) c.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;
}
/* Init callback: */
pj_bzero(&pres_cb, sizeof(pres_cb));
pres_cb.on_evsub_state = &pres_evsub_on_srv_state;
/* Create server presence subscription: */
status = pjsip_pres_create_uas(dlg, &pres_cb, rdata, &sub);
if (status != PJ_SUCCESS) {
int code = PJSIP_ERRNO_TO_SIP_STATUS(status);
pjsip_tx_data *tdata;
WARN("Unable to create server subscription %d", status);
if (code == 599 || code > 699 || code < 300) {
code = 400;
}
status = pjsip_dlg_create_response(dlg, rdata, code, NULL, &tdata);
if (status == PJ_SUCCESS) {
status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), tdata);
}
pres->unlock();
return PJ_FALSE;
}
/* Attach our data to the subscription: */
char* remote = (char*) pj_pool_alloc(dlg->pool, PJSIP_MAX_URL_SIZE);
status = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->remote.info->uri, remote, PJSIP_MAX_URL_SIZE);
if (status < 1)
pj_ansi_strcpy(remote, "<-- url is too long-->");
else
remote[status] = '\0';
//pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, dlg->local.info->uri, contact.ptr, PJSIP_MAX_URL_SIZE);
/* Create a new PresenceSubription server and wait for client approve */
PresenceSubscription *presenceSub = new PresenceSubscription(pres, sub, remote, dlg);
pjsip_evsub_set_mod_data(sub, pres->getModId(), presenceSub);
pres->reportNewServerSubscription(presenceSub); /* Notify the client.*/
pres->addServerSubscription(presenceSub);
/* Capture the value of Expires header. */
expires_hdr = (pjsip_expires_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
if (expires_hdr)
presenceSub->setExpires(expires_hdr->ivalue);
else
presenceSub->setExpires(-1);
st_code = (pjsip_status_code) 200;
reason = pj_str("OK");
pj_bzero(&msg_data, sizeof(msg_data));
pj_list_init(&msg_data.hdr_list);
pjsip_media_type_init(&msg_data.multipart_ctype, NULL, NULL);
pj_list_init(&msg_data.multipart_parts);
/* Create and send 2xx response to the SUBSCRIBE request: */
status = pjsip_pres_accept(sub, rdata, st_code, &msg_data.hdr_list);
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
// -------------------------------------------------------------------------------V
// presenceSub->init();
// return PJ_TRUE;
/*Send notify immediatly*/
pjsip_pres_set_status(sub, pres->getStatus());
ev_state = PJSIP_EVSUB_STATE_ACTIVE;
if (presenceSub->getExpires() == 0)
ev_state = PJSIP_EVSUB_STATE_TERMINATED;
/* Create and send the the first NOTIFY to active subscription: */
pj_str_t stateStr = pj_str("");
tdata = NULL;
status = pjsip_pres_notify(sub, ev_state, &stateStr, &reason, &tdata);
if (status == PJ_SUCCESS) {
pres->fillDoc(tdata, &msg_data);
status = pjsip_pres_send_request(sub, tdata);
}
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;
}
PresenceSubscription::PresenceSubscription(SIPPresence * pres, pjsip_evsub *evsub, char *r, pjsip_dialog *d)
: pres_(pres)
, sub(evsub)
, remote(r)
, dlg(d)
, expires(-1)
, approved(false)
{}
void PresenceSubscription::setExpires(int ms) {
expires = ms;
}
int PresenceSubscription::getExpires(){
return expires;
}
/*SIPPresence * PresenceSubscription::getPresence(){
return pres_;
}*/
bool PresenceSubscription::matches(char *s){
// servers match if they have the same remote uri and the account ID.
return (!(strcmp(remote,s))) ;
}
void PresenceSubscription::approve(const bool& flag){
approved = flag;
}
/**
* Send the tirst notification.
* FIXME : pjsip_pres_notify crash because the header can't be cloned
* So far, the first notify is sent in sipvoip_pres.c instead.
*/
void PresenceSubscription::init(){
pjsip_tx_data *tdata = NULL;
pres_msg_data msg_data;
pj_str_t reason = pj_str("OK");
pjsip_evsub_state ev_state = PJSIP_EVSUB_STATE_ACTIVE;
pjsip_pres_set_status(sub, pres_->getStatus());
if (expires == 0)
ev_state = PJSIP_EVSUB_STATE_TERMINATED;
/* Create and send the the first NOTIFY to active subscription: */
pj_str_t stateStr = pj_str("");
pj_status_t status = pjsip_pres_notify(sub, ev_state, &stateStr, &reason, &tdata);
if (status == PJ_SUCCESS) {
pres_->fillDoc(tdata, &msg_data);
status = pjsip_pres_send_request(sub, tdata);
}
if (status != PJ_SUCCESS) {
WARN("Unable to create/send NOTIFY %d", status);
pjsip_pres_terminate(sub, PJ_FALSE);
}
}
void PresenceSubscription::notify() {
/* Only send NOTIFY once subscription is active. Some subscriptions
* may still be in NULL (when app is adding a new buddy while in the
* on_incoming_subscribe() callback) or PENDING (when user approval is
* being requested) state and we don't send NOTIFY to these subs until
* the user accepted the request.
*/
if ((pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACTIVE) && (approved)) {
DEBUG("Notifying %s.", remote);
pjsip_tx_data *tdata;
pjsip_pres_set_status(sub, pres_->getStatus());
if (pjsip_pres_current_notify(sub, &tdata) == PJ_SUCCESS) {
// add msg header and send
pres_->fillDoc(tdata, NULL);
pjsip_pres_send_request(sub, tdata);
}
else{
WARN("Unable to create/send NOTIFY");
pjsip_pres_terminate(sub, PJ_FALSE);
}
}
}
/*
* Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
*
* Author: Patrick Keroulas <patrick.keroulas@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the