Commit 445d9972 authored by PatrickKeroulas's avatar PatrickKeroulas

[Presence] Create SIPPresence as a wrapper. Factorize.

parent 27128f02
......@@ -48,6 +48,7 @@
#include "sip/sipaccount.h"
#include "sip/sipcall.h"
#include "im/instant_messaging.h"
#include "sip/sippresence.h"
#if HAVE_IAX
#include "iax/iaxaccount.h"
......@@ -2897,17 +2898,17 @@ void ManagerImpl::startAudioDriverStream()
void ManagerImpl::subscribePresence(const std::string& accountID, const std::string& buddySipUri)
{
SIPAccount *account = Manager::instance().getSipAccount(accountID);
account->subscribeBuddy(buddySipUri);
account->getPresence()->subscribeBuddy(buddySipUri);
}
void ManagerImpl::unsubscribePresence(const std::string& accountID, const std::string& buddySipUri)
{
SIPAccount *account = Manager::instance().getSipAccount(accountID);
account->unsubscribeBuddy(buddySipUri);
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->sendPresence(status,note);
account->getPresence()->sendPresence(status,note);
}
......@@ -15,10 +15,11 @@ libsiplink_la_SOURCES = \
siptransport.h \
sip_utils.cpp \
sip_utils.h \
sippresence.cpp \
sippresence.h \
sipbuddy.cpp \
sipbuddy.h \
sipvoip_pres.cpp \
sipvoip_pres.h \
presence_subscription.cpp\
presence_subscription.h\
sippublish.cpp\
sippublish.h
......
/*
* File: PresenceSubscription.h
* Author: aol
* Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
*
* Created on April 24, 2012, 10:13 AM
* 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.
*/
#ifndef SERVERPRESENCESUB_H
#define SERVERPRESENCESUB_H
#include <string>
#include "logger.h"
#include <pj/string.h>
#include <pjsip/sip_types.h>
#include <pjsip-simple/evsub.h>
#include"pjsip-simple/presence.h"
#include <pjsip-simple/presence.h>
#include <pjsip/sip_module.h>
#include "src/noncopyable.h"
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. */
-1, /* Id */
PJSIP_MOD_PRIORITY_DIALOG_USAGE,
NULL, /* load() */
NULL, /* start() */
NULL, /* stop() */
NULL, /* unload() */
&pres_on_rx_subscribe_request, /* on_rx_request() */
NULL, /* on_rx_response() */
NULL, /* on_tx_request. */
NULL, /* on_tx_response() */
NULL, /* on_tsx_state() */
};
#include "manager.h"
#include "sipvoip_pres.h"
class SIPpresence;
class PresenceSubscription {
public:
PresenceSubscription(pjsip_evsub *evsub, char *r, std::string acc_Id, pjsip_dialog *d):
sub(evsub)
, remote(r)
, accId(acc_Id)
, dlg(d)
, expires (-1) {};
char *remote; /**< Remote URI. */
std::string accId; /**< Account ID. */
void setExpires(int ms) {
expires = ms;
}
public:
int getExpires(){
return expires;
}
PresenceSubscription(SIPPresence * pres, pjsip_evsub *evsub, char *r,pjsip_dialog *d);
bool matches(PresenceSubscription * s){
// servers match if they have the same remote uri and the account ID.
return ((!(strcmp(remote,s->remote))) && (accId==s->accId));
}
char *remote; /**< Remote URI. */
bool isActive(){
if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACTIVE )
return true;
return false;
}
void setExpires(int ms);
int getExpires();
bool matches(PresenceSubscription * s);
bool isActive();
//SIPPresence * getPresence();
/**
* 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 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_get_data());
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_process_msg_data(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 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 (isActive()) {
WARN("Notifying %s.", remote);
pjsip_tx_data *tdata;
pjsip_pres_set_status(sub, pres_get_data());
if (pjsip_pres_current_notify(sub, &tdata) == PJ_SUCCESS) {
// add msg header and send
pres_process_msg_data(tdata, NULL);
pjsip_pres_send_request(sub, tdata);
}
else{
WARN("Unable to create/send NOTIFY");
pjsip_pres_terminate(sub, PJ_FALSE);
}
}
}
void init();
void notify();
friend void pres_evsub_on_srv_state( pjsip_evsub *sub, pjsip_event *event);
friend pj_bool_t pres_on_rx_subscribe_request(pjsip_rx_data *rdata);
private:
NON_COPYABLE(PresenceSubscription);
SIPPresence *pres_;
pjsip_evsub *sub; /**< The evsub. */
pjsip_dialog *dlg; /**< Dialog. */
int expires; /**< "expires" value in the request. */
......
......@@ -36,6 +36,7 @@
#include "account_schema.h"
#include "sipaccount.h"
#include "sippresence.h"
#include "sip_utils.h"
#include "sipvoiplink.h"
#include "config/yamlnode.h"
......@@ -112,20 +113,10 @@ SIPAccount::SIPAccount(const std::string& accountID)
, keepAliveEnabled_(false)
, keepAliveTimer_()
, link_(SIPVoIPLink::instance())
, serverSubscriptions_ ()
, buddies_ ()
, presence_(new SIPPresence(this))
, receivedParameter_("")
, rPort_(-1)
, via_addr_()
, online_status()
, rpid({PJRPID_ELEMENT_TYPE_PERSON,
pj_str("20"),
PJRPID_ACTIVITY_BUSY,
pj_str("bla")})
, publish_sess()
, publish_state()
, publish_enabled(true)
{
via_addr_.host.ptr = 0;
via_addr_.host.slen = 0;
......@@ -135,6 +126,11 @@ SIPAccount::SIPAccount(const std::string& accountID)
alias_ = IP2IP_PROFILE;
}
SIPAccount::~SIPAccount()
{
delete presence_;
}
void SIPAccount::serialize(Conf::YamlEmitter &emitter)
{
using namespace Conf;
......@@ -1218,7 +1214,15 @@ VoIPLink* SIPAccount::getVoIPLink()
return link_;
}
bool SIPAccount::isIP2IP() const{
return accountID_ == IP2IP_PROFILE;
}
SIPPresence * SIPAccount::getPresence(){
return presence_;
}
/*
void SIPAccount::sendPresence(const std::string &status, const std::string &note){
pres_update(status,note);
if (isIP2IP())
......@@ -1227,11 +1231,6 @@ void SIPAccount::sendPresence(const std::string &status, const std::string &note
pres_publish(this);
}
/*
* Buddy list management
*
*/
void SIPAccount::subscribeBuddy(const std::string& buddySipUri){
std::list< SIPBuddy *>::iterator buddyIt;
for (buddyIt = buddies_.begin(); buddyIt != buddies_.end(); buddyIt++)
......@@ -1265,11 +1264,7 @@ void SIPAccount::addBuddy(SIPBuddy *b){
void SIPAccount::removeBuddy(SIPBuddy *b){
DEBUG("-Buddy subscription removed from the buddy list.");
buddies_.remove(b);
}
bool SIPAccount::isIP2IP() const{
return accountID_ == IP2IP_PROFILE;
}
}*/
/*
* Presence Management for IP2IP accounts
......@@ -1280,30 +1275,26 @@ bool SIPAccount::isIP2IP() const{
*/
/* Presence : Method used to add serverSubscription to PresenceSubscription list in case of IP2IP accounts */
void SIPAccount::addServerSubscription(PresenceSubscription *s) {
/*void SIPAccount::addServerSubscription(PresenceSubscription *s) {
DEBUG("-PresenceServer subscription added.");
serverSubscriptions_.push_back(s);
}
}*/
/* Presence : Method used to remove serverSubscription to PresenceSubscription list in: case of IP2IP accounts */
void SIPAccount::removeServerSubscription(PresenceSubscription *s) {
/*void SIPAccount::removeServerSubscription(PresenceSubscription *s) {
serverSubscriptions_.remove(s);
DEBUG("-PresenceServer removed");
}
}*/
/* Presence : Method used to notify each serverSubscription of a new presencein case of IP2IP accounts */
void SIPAccount::notifyServerSubscription() {
/*void SIPAccount::notifyServerSubscription() {
std::list< PresenceSubscription *>::iterator serverIt;
DEBUG("-Iterating through PresenceServers:");
for (serverIt = serverSubscriptions_.begin(); serverIt != serverSubscriptions_.end(); serverIt++)
(*serverIt)->notify();
}
}*/
/*
* Presence Management for IP2IP accounts
*
*/
bool SIPAccount::matches(const std::string &userName, const std::string &server,
pjsip_endpoint *endpt, pj_pool_t *pool) const
......
......@@ -37,15 +37,13 @@
#include <vector>
#include <map>
#include "account.h"
#include "pjsip/sip_transport_tls.h"
#include "pjsip/sip_types.h"
#include "pjsip-ua/sip_regc.h"
#include "noncopyable.h"
#include "sipbuddy.h"
#include "presence_subscription.h"
#include "sippublish.h"
#include "noncopyable.h"
#include "account.h"
typedef std::vector<pj_ssl_cipher> CipherArray;
......@@ -97,6 +95,8 @@ namespace Conf {
}
class SIPVoIPLink;
class SIPPresence;
/**
* @file sipaccount.h
......@@ -115,6 +115,7 @@ class SIPAccount : public Account {
* @param accountID The account identifier
*/
SIPAccount(const std::string& accountID);
~SIPAccount();
virtual VoIPLink* getVoIPLink();
......@@ -522,23 +523,7 @@ class SIPAccount : public Account {
/**
* Presence management
*/
void sendPresence(const std::string &status, const std::string &note);
void subscribeBuddy(const std::string& buddySipUri);
void unsubscribeBuddy(const std::string& buddySipUri);
void addBuddy(SIPBuddy *b);
void removeBuddy(SIPBuddy *b);
void addServerSubscription(PresenceSubscription *s);
void removeServerSubscription(PresenceSubscription *s);
void notifyServerSubscription();
//void notifyServerSubscription(const std::string &newPresenceStatus, const std::string &newChannelStatus);
//bool compareServerSubscription(PresenceSubscription *first, PresenceSubscription *second);
pj_bool_t online_status; /**< Our online status. */
pjrpid_element rpid; /**< RPID element information.*/
pjsip_publishc *publish_sess; /**< Client publication session.*/
pj_bool_t publish_state; /**< Last published online status.*/
pj_bool_t publish_enabled; /**< Allow for status publish,*/
SIPPresence * getPresence();
private:
NON_COPYABLE(SIPAccount);
......@@ -787,15 +772,10 @@ private:
*/
pjsip_host_port via_addr_;
/**
* server subscription
*/
std::list< PresenceSubscription *> serverSubscriptions_;
/**
* buddies
* Presence data structure
*/
std::list< SIPBuddy *> buddies_;
SIPPresence * presence_;
};
......
......@@ -31,7 +31,6 @@
#include <pj/log.h>
#include <pj/rand.h>
#include <pj/log.h>
#include <pjsip/sip_module.h>
#include <pjsip/sip_types.h>
#include <pjsip/sip_event.h>
......@@ -45,19 +44,18 @@
#include "sipbuddy.h"
#include "sipaccount.h"
#include "sippresence.h"
#include "sipvoiplink.h"
#define PJSUA_BUDDY_SUB_TERM_REASON_LEN 32
#define PJSUA_PRES_TIMER 300
#include "manager.h"
#include "dbus/dbusmanager.h"
#include "dbus/callmanager.h"
#include "logger.h"
//extern pjsip_module mod_ua_;
//extern pjsip_endpoint *endpt_;
#define BUDDY_SUB_TERM_REASON_LEN 32
#define PRES_TIMER 300
int modId;
static void buddy_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry) {
(void) th;
SIPBuddy *b = (SIPBuddy *) entry->user_data;
......@@ -65,7 +63,7 @@ static void buddy_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry) {
}
/* Callback called when *client* subscription state has changed. */
static void sflphoned_evsub_on_state(pjsip_evsub *sub, pjsip_event *event) {
static void buddy_evsub_on_state(pjsip_evsub *sub, pjsip_event *event) {
SIPBuddy *buddy;
PJ_UNUSED_ARG(event);
......@@ -81,13 +79,18 @@ static void sflphoned_evsub_on_state(pjsip_evsub *sub, pjsip_event *event) {
DEBUG("Presence subscription to '%s' is '%s'", buddy->getURI().c_str(),
pjsip_evsub_get_state_name(sub) ? pjsip_evsub_get_state_name(sub) : "null");
if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
pjsip_evsub_state state = pjsip_evsub_get_state(sub);
if(state == PJSIP_EVSUB_STATE_ACCEPTED){
DEBUG("Accept buddy.");
buddy->accept();
}
else if (state == PJSIP_EVSUB_STATE_TERMINATED) {
int resub_delay = -1;
// const pj_str_t *pjTermReason = pjsip_evsub_get_termination_reason(sub);
// std::string termReason(pjTermReason->ptr,
// pjTermReason->slen > PJSUA_BUDDY_SUB_TERM_REASON_LEN?
// PJSUA_BUDDY_SUB_TERM_REASON_LEN:
// pjTermReason->slen > BUDDY_SUB_TERM_REASON_LEN?
// BUDDY_SUB_TERM_REASON_LEN:
// pjTermReason->slen
// );
pj_strdup_with_null(buddy->pool, &buddy->term_reason, pjsip_evsub_get_termination_reason(sub));
......@@ -118,7 +121,7 @@ static void sflphoned_evsub_on_state(pjsip_evsub *sub, pjsip_event *event) {
}
} else if (pjsip_method_cmp(&tsx->method, &pjsip_notify_method) == 0) {
if (buddy->isTermReason("deactivated") || buddy->isTermReason("timeout")) {
/* deactivated: The subscription has been terminated,
/* deactivated: The subscription has been terminated,
* but the subscriber SHOULD retry immediately with
* a new subscription.
*/
......@@ -164,8 +167,8 @@ static void sflphoned_evsub_on_state(pjsip_evsub *sub, pjsip_event *event) {
* some random value, to avoid sending SUBSCRIBEs all at once)
*/
if (resub_delay == -1) {
// pj_assert(PJSUA_PRES_TIMER >= 3);
resub_delay = PJSUA_PRES_TIMER * 1000;// - 2500 + (pj_rand() % 5000);
// pj_assert(PRES_TIMER >= 3);
resub_delay = PRES_TIMER * 1000;// - 2500 + (pj_rand() % 5000);
}
buddy->sub = sub;
buddy->rescheduleTimer(PJ_TRUE, resub_delay);
......@@ -190,7 +193,7 @@ static void sflphoned_evsub_on_state(pjsip_evsub *sub, pjsip_event *event) {
}
/* Callback when transaction state has changed. */
static void sflphoned_evsub_on_tsx_state(pjsip_evsub *sub, pjsip_transaction *tsx, pjsip_event *event) {
static void buddy_evsub_on_tsx_state(pjsip_evsub *sub, pjsip_transaction *tsx, pjsip_event *event) {
SIPBuddy *buddy;
pjsip_contact_hdr *contact_hdr;
......@@ -239,7 +242,7 @@ static void sflphoned_evsub_on_tsx_state(pjsip_evsub *sub, pjsip_transaction *ts
}
/* Callback called when we receive NOTIFY */
static void sflphoned_evsub_on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str_t **p_st_text,
static void buddy_evsub_on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str_t **p_st_text,
pjsip_hdr *res_hdr, pjsip_msg_body **p_body) {
SIPBuddy *buddy;
......@@ -338,18 +341,16 @@ void SIPBuddy::rescheduleTimer(bool reschedule, unsigned msec) {
}
}
pj_status_t SIPBuddy::updatePresence() {
incLock();
void SIPBuddy::accept() {
acc->getPresence()->addBuddy(this);
}
/* Update our info. See pjsua_buddy_get_info() for additionnal idea*/
const std::string basic(status.info[0].basic_open ? "open" : "closed");
const std::string note(status.info[0].rpid.note.ptr,status.info[0].rpid.note.slen);
DEBUG(" Received presenceStateChange for %s status=%s note=%s",getURI().c_str(),basic.c_str(),note.c_str());
/* Transmit dbus signal */
Manager::instance().getDbusManager()->getCallManager()->newPresenceNotification(getURI(), basic, note);
pj_status_t SIPBuddy::updatePresence() {
decLock();
//incLock();
/* callback*/
acc->getPresence()->reportBuddy(getURI(),&status);
//decLock();
}
......@@ -414,9 +415,9 @@ pj_status_t SIPBuddy::updateSubscription() {
/* Event subscription callback. */
pj_bzero(&pres_callback, sizeof(pres_callback));
pres_callback.on_evsub_state = &sflphoned_evsub_on_state;
pres_callback.on_tsx_state = &sflphoned_evsub_on_tsx_state;
pres_callback.on_rx_notify = &sflphoned_evsub_on_rx_notify;
pres_callback.on_evsub_state = &buddy_evsub_on_state;
pres_callback.on_tsx_state = &buddy_evsub_on_tsx_state;
pres_callback.on_rx_notify = &buddy_evsub_on_rx_notify;
DEBUG("Buddy %s: subscribing presence,using account %s..",
uri.ptr, acc->getAccountID().c_str());
......@@ -510,7 +511,6 @@ pj_status_t SIPBuddy::updateSubscription() {
pjsip_evsub_terminate(sub, PJ_FALSE); // = NULL;
WARN("Unable to create initial SUBSCRIBE", status);
// if (tmp_pool) pj_pool_release(tmp_pool);
// pj_log_pop_indent();
return PJ_SUCCESS;
}
......@@ -527,7 +527,6 @@ pj_status_t SIPBuddy::updateSubscription() {
WARN("Unable to send initial SUBSCRIBE", status);
// if (tmp_pool) pj_pool_release(tmp_pool);
// pj_log_pop_indent();
return PJ_SUCCESS;
}
......@@ -536,14 +535,14 @@ pj_status_t SIPBuddy::updateSubscription() {
return PJ_SUCCESS;
}
void SIPBuddy::subscribe() {
bool SIPBuddy::subscribe() {
monitor = true;
updateSubscription();
return ((updateSubscription() == PJ_SUCCESS))? true : false;
}
void SIPBuddy::unsubscribe() {
bool SIPBuddy::unsubscribe() {
monitor = false;
updateSubscription();
return ((updateSubscription() == PJ_SUCCESS))? true : false;
}
bool SIPBuddy::match(SIPBuddy *b){
......
......@@ -45,11 +45,11 @@
class SIPAccount;
static void sflphoned_evsub_on_state(pjsip_evsub *sub, pjsip_event *event);
static void sflphoned_evsub_on_tsx_state(pjsip_evsub *sub,
static void buddy_evsub_on_state(pjsip_evsub *sub, pjsip_event *event);
static void buddy_evsub_on_tsx_state(pjsip_evsub *sub,
pjsip_transaction *tsx,
pjsip_event *event);
static void sflphoned_evsub_on_rx_notify(pjsip_evsub *sub,
static void buddy_evsub_on_rx_notify(pjsip_evsub *sub,
pjsip_rx_data *rdata,
int *p_st_code,
pj_str_t **p_st_text,
......@@ -62,16 +62,17 @@ public:
SIPBuddy(const std::string &uri, SIPAccount *acc);
~SIPBuddy();
bool match(SIPBuddy *b);
void subscribe();
void unsubscribe();
void accept();
bool subscribe();
bool unsubscribe();
bool isSubscribed();
std::string getURI();
friend void sflphoned_evsub_on_state( pjsip_evsub *sub, pjsip_event *event);
friend void sflphoned_evsub_on_tsx_state(pjsip_evsub *sub,
friend void buddy_evsub_on_state( pjsip_evsub *sub, pjsip_event *event);
friend void buddy_evsub_on_tsx_state(pjsip_evsub *sub,
pjsip_transaction *tsx,
pjsip_event *event);
friend void sflphoned_evsub_on_rx_notify(pjsip_evsub *sub,
friend void buddy_evsub_on_rx_notify(pjsip_evsub *sub