Commit 0ba34215 authored by PatrickKeroulas's avatar PatrickKeroulas
Browse files

Add comments, delete obsolete files.

parent 445d9972
......@@ -59,7 +59,7 @@ int modId;
static void buddy_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry) {
(void) th;
SIPBuddy *b = (SIPBuddy *) entry->user_data;
b->updatePresence();
b->reportPresence();
}
/* Callback called when *client* subscription state has changed. */
......@@ -255,7 +255,7 @@ static void buddy_evsub_on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int
return;
pjsip_pres_get_status(sub, &buddy->status);
buddy->updatePresence();
buddy->reportPresence();
/* The default is to send 200 response to NOTIFY.
* Just leave it there..
......@@ -345,7 +345,7 @@ void SIPBuddy::accept() {
acc->getPresence()->addBuddy(this);
}
pj_status_t SIPBuddy::updatePresence() {
pj_status_t SIPBuddy::reportPresence() {
//incLock();
/* callback*/
......
/*
* Copyright (C) 2012, 2013 LOTES TM LLC
* Author : Andrey Loukhnov <aol.nnov@gmail.com>
*
* Author : Patrick Keroulas <patrick.keroulas@savoirfairelinux.com>
* This file is a part of pult5-voip
*
* pult5-voip is free software; you can redistribute it and/or modify
......@@ -43,8 +43,11 @@
#include <pjsip/sip_transport.h>
class SIPAccount;
class SIPAccount; // dummy prototype
/**
* Transaction functions of event subscription client side.
*/
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,
......@@ -57,17 +60,48 @@ static void buddy_evsub_on_rx_notify(pjsip_evsub *sub,
pjsip_msg_body **p_body);
static void buddy_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry);
class SIPBuddy {
public:
/**
* Constructor
* @param uri SIP uri of remote user that we want to subscribe,
*/
SIPBuddy(const std::string &uri, SIPAccount *acc);
/**
* Destructor.
* Process the the unsubscription before the destruction.
*/
~SIPBuddy();
/**
* Compare with another buddy's uris.
* @param b Other buddy pointer
*/
bool match(SIPBuddy *b);
/**
* The PBX must approve the subrciption before the buddy is added in the buddy list.
*/
void accept();
/**
* Send a SUBCRIBE to the PXB or directly to a buddy in the IP2IP context.
*/
bool subscribe();
/**
* Send a SUBCRIBE to the PXB or directly to a buddy in the IP2IP context but
* the 0s timeout make the dialog expire immediatly.
*/
bool unsubscribe();
/**
* Return the monitor variable.
*/
bool isSubscribed();
/**
* Return the buddy URI
*/
std::string getURI();
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,
......@@ -88,14 +122,31 @@ public:
private:
/**
* Plan a retry or a renew a subscription.
* @param reschedule Allow for reschedule.
* @param msec Delay value in milliseconds.
*/
void rescheduleTimer(bool reschedule, unsigned msec);
pj_status_t updatePresence();
/**
* Callback after a presence notification was received.
* Tranfert info to the SIP account.
*/
pj_status_t reportPresence();
/**
* Process the un/subscribe request transmission.
*/
pj_status_t updateSubscription();
/*
* Compare the reason of a transaction end with the given string.
*/
bool isTermReason(std::string);
/**
* return the code after a transaction is terminated.
*/
unsigned getTermCode();
SIPAccount *acc;
SIPAccount *acc; /**< Associated SIP account pointer */
pj_str_t uri; /**< Buddy URI. */
pj_str_t contact; /**< Contact learned from subscrp. */
pj_str_t display; /**< Buddy display name. */
......
......@@ -101,54 +101,98 @@ class PresenceSubscription;
class SIPPresence {
public:
/**
* Constructor
* @param acc the associated sipaccount
*/
SIPPresence(SIPAccount * acc);
/**
* Destructor
*/
~SIPPresence();
SIPAccount * getAccount();
pjsip_pres_status * getStatus();
int getModId();
void updateStatus(const std::string &status, const std::string &note);
void sendPresence(const std::string &status, const std::string &note);
void reportBuddy(const std::string& buddySipUri, pjsip_pres_status * status);
void subscribeBuddy(const std::string& buddySipUri);
void unsubscribeBuddy(const std::string& buddySipUri);
/*TODO : is that supposed to be private ?*/
void addBuddy(SIPBuddy *b);
void removeBuddy(SIPBuddy *b);
/**
* IP2IP context:
* remote subscriber management
*/
void addServerSubscription(PresenceSubscription *s);
void removeServerSubscription(PresenceSubscription *s);
void notifyServerSubscription();
pjsip_pres_status pres_status_data;
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,*/
/**
* Return associated sipaccount
*/
SIPAccount * getAccount();
/**
* Return presence data.
*/
pjsip_pres_status * getStatus();
/**
* Return presence module ID which is actually the same as the VOIP link
*/
int getModId();
/**
* Modify the presence data
* @param status is basically "open" or "close"
*/
void updateStatus(const std::string &status, const std::string &note);
/**
* Send the presence data in a PUBLISH to the PBX or in a NOTIFY
* to a remote subscriber (IP2IP)
*/
void sendPresence(const std::string &status, const std::string &note);
/**
* Send a signal to the client on DBus. The signal contain the status
* of a remote user.
*/
void reportBuddy(const std::string& buddySipUri, pjsip_pres_status * status);
/**
* Send a SUBSCRIBE request to PBX/IP2IP
* @param buddyUri Remote user that we want to subscribe
*/
void subscribeBuddy(const std::string& buddySipUri);
/**
* Send a SUBSCRIBE request to PBX/IP2IP but the the 0s timeout makes
* the dialog expire immediatly.
* @param buddyUri Remote user that we want to unsubscribe
*/
void unsubscribeBuddy(const std::string& buddySipUri);
/**
* Add a buddy in the buddy list.
* @param b Buddy pointer
*/
void addBuddy(SIPBuddy *b);
/**
* Remove a buddy from the list.
* @param b Buddy pointer
*/
void removeBuddy(SIPBuddy *b);
private:
SIPAccount * acc_;
/**
* server subscription
* IP2IP context.
* Add a server associated to a subscriber in the list.
* @param s PresenceSubcription pointer.
*/
std::list< PresenceSubscription *> serverSubscriptions_;
void addServerSubscription(PresenceSubscription *s);
/**
* buddies
* IP2IP context.
* Remove a server associated to a subscriber from the list.
* @param s PresenceSubcription pointer.
*/
std::list< SIPBuddy *> buddies_;
void removeServerSubscription(PresenceSubscription *s);
/**
* IP2IP context.
* Iterate through the subscriber list and send NOTIFY to each.
*/
void notifyServerSubscription();
pjsip_pres_status pres_status_data; /**< Presence Data.*/
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,*/
private:
SIPAccount * acc_; /**< Associated SIP account. */
std::list< PresenceSubscription *> serverSubscriptions_; /**< Subscribers list.*/
std::list< SIPBuddy *> buddies_; /**< Subcribed buddy list.*/
};
......
......@@ -33,7 +33,6 @@
#include "sippresence.h"
#include "sippublish.h"
#include "sipvoip_pres.h"
#include "logger.h"
#include "sipvoiplink.h"
......@@ -195,7 +194,7 @@ on_error:
pj_status_t pres_publish(SIPPresence *pres)
{
pj_status_t status;
const pj_str_t STR_PRESENCE = { "presence", 8 };
const pj_str_t STR_PRESENCE = pj_str("presence");
SIPAccount * acc = pres->getAccount();
pjsip_endpoint *endpt = ((SIPVoIPLink*) acc->getVoIPLink())->getEndpoint();
......
/*
* Copyright (C) 2012б 2013 LOTES TM LLC
* Author : Andrey Loukhnov <aol.nnov@gmail.com>
*
* This file is a part of pult5-voip
*
* pult5-voip 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.
*
* pult5-voip 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 programm. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify pult5-voip, 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, LOTES-TM LLC
* 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.
*/
#ifdef have_config_h
#include "config.h"
#endif
#include <string>
#include <bits/stringfwd.h>
#include <bits/basic_string.h>
#include "pjsip/sip_dialog.h"
#include "pjsip/sip_msg.h"
#include "pjsip/sip_ua_layer.h"
#include "pjsip/sip_transaction.h"
#include"pjsip-simple/evsub.h"
#include"pjsip-simple/presence.h"
#include <pj/log.h>
#include <pj/pool.h>
#include <pj/string.h>
#include <pj/compat/string.h>
#include "sipvoip_pres.h"
#include "logger.h"
#include "sipaccount.h"
#include "sipcall.h"
#include "sipvoiplink.h"
#include "manager.h"
#include "sippresence.h"
#include "presence_subscription.h"
/*
pjsip_pres_status pres_status_data;
pjsip_pres_status * pres_get_data(){
return &pres_status_data;
}
void pres_update(const std::string &status, const std::string &note){
pjrpid_element rpid = {pjrpid_element_type_person,
pj_str("20"),
pjrpid_activity_unknown,
pj_str(strdup(note.c_str()))};
if(note=="away")
rpid.activity = pjrpid_activity_away;
else if (note=="busy")
rpid.activity = pjrpid_activity_busy;
else
warn("presence : unkown activity");
pj_bzero(&pres_status_data, sizeof(pres_status_data));
pres_status_data.info_cnt = 1;
pres_status_data.info[0].basic_open = (status == "open")? true: false;
pres_status_data.info[0].id = pj_str("0");
pj_memcpy(&pres_status_data.info[0].rpid, &rpid,sizeof(pjrpid_element));
}
void pres_process_msg_data(pjsip_tx_data *tdata, const pres_msg_data *msg_data){
if (tdata->msg->type == PJSIP_REQUEST_MSG) {
const pj_str_t STR_USER_AGENT = {"User-Agent", 10 };
pjsip_hdr *h;
pj_str_t ua = pj_str("SFLPhone");
h = (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool, &STR_USER_AGENT, &ua);
pjsip_msg_add_hdr(tdata->msg, h);
}
if(msg_data == NULL)
return;
const pjsip_hdr *hdr;
hdr = msg_data->hdr_list.next;
while (hdr && hdr != &msg_data->hdr_list) {
pjsip_hdr *new_hdr;
new_hdr = (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, hdr);
WARN("adding header", new_hdr->name.ptr);
pjsip_msg_add_hdr(tdata->msg, new_hdr);
hdr = hdr->next;
}
if (msg_data->content_type.slen && msg_data->msg_body.slen) {
pjsip_msg_body *body;
pj_str_t type = pj_str("application");
pj_str_t subtype = pj_str("pidf+xml");
body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &msg_data->msg_body);
tdata->msg->body = body;
}
}
*/
/* 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("no rdata in presence");
return;
}
std::string accountId = "IP2IP";/* ebail : this code is only used for IP2IP accounts */
SIPAccount *acc = Manager::instance().getSipAccount(accountId);
PJ_UNUSED_ARG(event);
PresenceSubscription *presenceSub;
presenceSub = (PresenceSubscription *) pjsip_evsub_get_mod_data(sub,
((SIPVoIPLink*) (acc->getVoIPLink()))->getModId() /*my_mod_pres.id*/);
WARN("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);
/* 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, ((SIPVoIPLink*) (acc->getVoIPLink()))->getModId(), NULL);
acc->getPresence()->removeServerSubscription(presenceSub);
}
}
}
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;
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;
/* 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){
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);
std::string accountId = "IP2IP"; /* ebail : this code is only used for IP2IP accounts */
SIPAccount *acc = (SIPAccount *) Manager::instance().getSipAccount(accountId);
pjsip_endpoint *endpt = ((SIPVoIPLink*) acc->getVoIPLink())->getEndpoint();
contact = pj_str(strdup(acc->getContactHeader().c_str()));
/* Create UAS dialog: */
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);
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);
}
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);
pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, dlg->local.info->uri, contact.ptr, PJSIP_MAX_URL_SIZE);
PresenceSubscription *presenceSub = new PresenceSubscription(acc->getPresence(), sub, remote, dlg);
if (status < 1)
pj_ansi_strcpy(remote, "<-- url is too long-->");
else
remote[status] = '\0';
int modId = ((SIPVoIPLink*) (acc->getVoIPLink()))->getModId();
pjsip_evsub_set_mod_data(sub, modId/*my_mod_pres.id*/, presenceSub);
/* Add server subscription to the list: */
acc->getPresence()->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);
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, acc->getPresence()->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_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);
return status;
}
return PJ_TRUE;
}
/*
* Copyright (C) 2012б 2013 LOTES TM LLC
* Author : Andrey Loukhnov <aol.nnov@gmail.com>
*
* This file is a part of pult5-voip
*
* pult5-voip 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.
*
* pult5-voip 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 programm. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify pult5-voip, 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, LOTES-TM LLC
* 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 SIPVOIP_PRES_H
#define SIPVOIP_PRES_H
#include "pjsip/sip_types.h"
#include "pjsip/sip_module.h"
#include "pjsip/sip_msg.h"
#include "pjsip/sip_multipart.h"
#include "pjsip-simple/presence.h"
//PJ_BEGIN_DECL
//extern void pres_process_msg_data(pjsip_tx_data *tdata, const pres_msg_data *msg_data);
//PJ_END_DECL
#endif /* SIPVOIP_PRES_H */
Supports Markdown
0%