Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
savoirfairelinux
jami-daemon
Commits
77b017ca
Commit
77b017ca
authored
Sep 13, 2013
by
Tristan Matthews
Browse files
* #29736: presence: merge sippublish into sippresence
parent
f03f5101
Changes
5
Hide whitespace changes
Inline
Side-by-side
daemon/src/sip/Makefile.am
View file @
77b017ca
...
...
@@ -20,9 +20,8 @@ libsiplink_la_SOURCES = \
pres_sub_server.cpp
\
pres_sub_server.h
\
pres_sub_client.cpp
\
pres_sub_client.h
\
sippublish.cpp
\
sippublish.h
pres_sub_client.h
if
BUILD_SDES
libsiplink_la_SOURCES
+=
sdes_negotiator.cpp
\
sdes_negotiator.h
\
...
...
daemon/src/sip/sippresence.cpp
View file @
77b017ca
...
...
@@ -30,14 +30,14 @@
*/
#include
"sippresence.h"
#include
"logger.h"
#include
"manager.h"
#include
"client/client.h"
#include
"client/callmanager.h"
#include
"client/presencemanager.h"
#include
"sipaccount.h"
#include
"sippublish.h"
#include
"sippresence.h"
#include
"sip_utils.h"
#include
"pres_sub_server.h"
#include
"pres_sub_client.h"
#include
"sipvoiplink.h"
...
...
@@ -46,7 +46,7 @@
#define MAX_N_PRES_SUB_CLIENT 20
SIPPresence
::
SIPPresence
(
SIPAccount
*
acc
)
:
publish_sess
()
:
publish_sess
_
()
,
pres_status_data_
()
,
enabled_
(
true
)
,
acc_
(
acc
)
...
...
@@ -74,10 +74,10 @@ SIPPresence::SIPPresence(SIPAccount *acc)
SIPPresence
::~
SIPPresence
()
{
/* Flush the lists */
for
(
const
auto
&
c
:
pres_sub_client_list_
)
for
(
const
auto
&
c
:
pres_sub_client_list_
)
removePresSubClient
(
c
)
;
for
(
const
auto
&
s
:
pres_sub_server_list_
)
for
(
const
auto
&
s
:
pres_sub_server_list_
)
removePresSubServer
(
s
);
}
...
...
@@ -160,13 +160,14 @@ void SIPPresence::reportPresSubClientNotification(const std::string& uri, pjsip_
void
SIPPresence
::
subscribeClient
(
const
std
::
string
&
uri
,
bool
flag
)
{
/* Check if the buddy was already subscribed */
for
(
const
auto
&
c
:
pres_sub_client_list_
)
for
(
const
auto
&
c
:
pres_sub_client_list_
)
{
if
(
c
->
getURI
()
==
uri
)
{
DEBUG
(
"-PresSubClient:%s exists in the list. Replace it."
,
uri
.
c_str
());
delete
c
;
removePresSubClient
(
c
);
break
;
}
}
if
(
pres_sub_client_list_
.
size
()
>=
MAX_N_PRES_SUB_CLIENT
)
{
WARN
(
"Can't add PresSubClient, max number reached."
);
...
...
@@ -210,12 +211,13 @@ void SIPPresence::reportnewServerSubscriptionRequest(PresSubServer *s)
void
SIPPresence
::
approvePresSubServer
(
const
std
::
string
&
uri
,
bool
flag
)
{
for
(
const
auto
&
s
:
pres_sub_server_list_
)
for
(
const
auto
&
s
:
pres_sub_server_list_
)
{
if
(
s
->
matches
((
char
*
)
uri
.
c_str
()))
{
DEBUG
(
"Approve Presence_subscription_server for %s: %s."
,
s
->
remote
,
flag
?
"true"
:
"false"
);
s
->
approve
(
flag
);
// return; // 'return' would prevent multiple-time subscribers from spam
}
}
}
...
...
@@ -240,7 +242,7 @@ void SIPPresence::notifyPresSubServer()
{
DEBUG
(
"Iterating through Presence_subscription_server:"
);
for
(
const
auto
&
s
:
pres_sub_server_list_
)
for
(
const
auto
&
s
:
pres_sub_server_list_
)
s
->
notify
();
}
...
...
@@ -292,3 +294,190 @@ void SIPPresence::fillDoc(pjsip_tx_data *tdata, const pres_msg_data *msg_data)
tdata
->
msg
->
body
=
body
;
}
}
static
const
pjsip_publishc_opt
my_publish_opt
=
{
true
};
// this is queue_request
/*
* Client presence publication callback.
*/
void
SIPPresence
::
pres_publish_cb
(
struct
pjsip_publishc_cbparam
*
param
)
{
SIPPresence
*
pres
=
(
SIPPresence
*
)
param
->
token
;
if
(
param
->
code
/
100
!=
2
||
param
->
status
!=
PJ_SUCCESS
)
{
pjsip_publishc_destroy
(
param
->
pubc
);
pres
->
publish_sess_
=
NULL
;
if
(
param
->
status
!=
PJ_SUCCESS
)
{
char
errmsg
[
PJ_ERR_MSG_SIZE
];
pj_strerror
(
param
->
status
,
errmsg
,
sizeof
(
errmsg
));
ERROR
(
"Client publication (PUBLISH) failed, status=%d, msg=%s"
,
param
->
status
,
errmsg
);
}
else
if
(
param
->
code
==
412
)
{
/* 412 (Conditional Request Failed)
* The PUBLISH refresh has failed, retry with new one.
*/
WARN
(
"Publish retry."
);
pres_publish
(
pres
);
}
else
{
ERROR
(
"Client publication (PUBLISH) failed (%u/%.*s)"
,
param
->
code
,
param
->
reason
.
slen
,
param
->
reason
.
ptr
);
}
}
else
{
if
(
param
->
expiration
<
1
)
{
/* Could happen if server "forgot" to include Expires header
* in the response. We will not renew, so destroy the pubc.
*/
pjsip_publishc_destroy
(
param
->
pubc
);
pres
->
publish_sess_
=
NULL
;
}
}
}
/*
* Send PUBLISH request.
*/
pj_status_t
SIPPresence
::
pres_send_publish
(
SIPPresence
*
pres
,
pj_bool_t
active
)
{
pjsip_tx_data
*
tdata
;
pj_status_t
status
;
DEBUG
(
"Send presence %sPUBLISH.."
,
(
active
?
""
:
"un-"
));
SIPAccount
*
acc
=
pres
->
getAccount
();
std
::
string
contactWithAngles
=
acc
->
getFromUri
();
contactWithAngles
.
erase
(
contactWithAngles
.
find
(
'>'
));
int
semicolon
=
contactWithAngles
.
find_first_of
(
":"
);
std
::
string
contactWithoutAngles
=
contactWithAngles
.
substr
(
semicolon
+
1
);
// pj_str_t contact = pj_str(strdup(contactWithoutAngles.c_str()));
// pj_memcpy(&pres_status_data.info[0].contact, &contt, sizeof(pj_str_t));;
/* Create PUBLISH request */
if
(
active
)
{
char
*
bpos
;
pj_str_t
entity
;
status
=
pjsip_publishc_publish
(
pres
->
publish_sess_
,
PJ_TRUE
,
&
tdata
);
if
(
status
!=
PJ_SUCCESS
)
{
ERROR
(
"Error creating PUBLISH request"
,
status
);
goto
on_error
;
}
pj_str_t
from
=
pj_str
(
strdup
(
acc
->
getFromUri
().
c_str
()));
if
((
bpos
=
pj_strchr
(
&
from
,
'<'
))
!=
NULL
)
{
char
*
epos
=
pj_strchr
(
&
from
,
'>'
);
if
(
epos
-
bpos
<
2
)
{
pj_assert
(
!
"Unexpected invalid URI"
);
status
=
PJSIP_EINVALIDURI
;
goto
on_error
;
}
entity
.
ptr
=
bpos
+
1
;
entity
.
slen
=
epos
-
bpos
-
1
;
}
else
{
entity
=
from
;
}
/* Create and add PIDF message body */
status
=
pjsip_pres_create_pidf
(
tdata
->
pool
,
pres
->
getStatus
(),
&
entity
,
&
tdata
->
msg
->
body
);
if
(
status
!=
PJ_SUCCESS
)
{
ERROR
(
"Error creating PIDF for PUBLISH request"
);
pjsip_tx_data_dec_ref
(
tdata
);
goto
on_error
;
}
}
else
{
WARN
(
"Unpublish is not implemented."
);
}
pres_msg_data
msg_data
;
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
);
pres
->
fillDoc
(
tdata
,
&
msg_data
);
/* Send the PUBLISH request */
status
=
pjsip_publishc_send
(
pres
->
publish_sess_
,
tdata
);
if
(
status
==
PJ_EPENDING
)
{
WARN
(
"Previous request is in progress, "
);
}
else
if
(
status
!=
PJ_SUCCESS
)
{
ERROR
(
"Error sending PUBLISH request"
);
goto
on_error
;
}
return
PJ_SUCCESS
;
on_error:
if
(
pres
->
publish_sess_
)
{
pjsip_publishc_destroy
(
pres
->
publish_sess_
);
pres
->
publish_sess_
=
NULL
;
}
return
status
;
}
/* Create client publish session */
pj_status_t
SIPPresence
::
pres_publish
(
SIPPresence
*
pres
)
{
pj_status_t
status
;
const
pj_str_t
STR_PRESENCE
=
pj_str
(
"presence"
);
SIPAccount
*
acc
=
pres
->
getAccount
();
pjsip_endpoint
*
endpt
=
((
SIPVoIPLink
*
)
acc
->
getVoIPLink
())
->
getEndpoint
();
/* Create and init client publication session */
/* Create client publication */
status
=
pjsip_publishc_create
(
endpt
,
&
my_publish_opt
,
pres
,
&
pres_publish_cb
,
&
pres
->
publish_sess_
);
if
(
status
!=
PJ_SUCCESS
)
{
pres
->
publish_sess_
=
NULL
;
ERROR
(
"Failed to create a publish seesion."
);
return
status
;
}
/* Initialize client publication */
pj_str_t
from
=
pj_str
(
strdup
(
acc
->
getFromUri
().
c_str
()));
status
=
pjsip_publishc_init
(
pres
->
publish_sess_
,
&
STR_PRESENCE
,
&
from
,
&
from
,
&
from
,
0xFFFF
);
if
(
status
!=
PJ_SUCCESS
)
{
ERROR
(
"Failed to init a publish session"
);
pres
->
publish_sess_
=
NULL
;
return
status
;
}
/* Add credential for authentication */
if
(
acc
->
hasCredentials
()
and
pjsip_publishc_set_credentials
(
pres
->
publish_sess_
,
acc
->
getCredentialCount
(),
acc
->
getCredInfo
())
!=
PJ_SUCCESS
)
{
ERROR
(
"Could not initialize credentials for invite session authentication"
);
return
status
;
}
/* Set route-set */
if
(
acc
->
hasServiceRoute
())
pjsip_regc_set_route_set
(
acc
->
getRegistrationInfo
(),
sip_utils
::
createRouteSet
(
acc
->
getServiceRoute
(),
pres
->
getPool
()));
/* Send initial PUBLISH request */
status
=
pres_send_publish
(
pres
,
PJ_TRUE
);
if
(
status
!=
PJ_SUCCESS
)
return
status
;
return
PJ_SUCCESS
;
}
daemon/src/sip/sippresence.h
View file @
77b017ca
...
...
@@ -44,26 +44,25 @@
#include
"pjsip-simple/rpid.h"
#include
<pj/pool.h>
struct
pres_msg_data
{
struct
pres_msg_data
{
/**
* Additional message headers as linked list. Application can add
* headers to the list by creating the header, either from the heap/pool
* or from temporary local variable, and add the header using
* linked list operation. See pjsip_apps.c for some sample codes.
*/
pjsip_hdr
hdr_list
;
pjsip_hdr
hdr_list
;
/**
* MIME type of optional message body.
*/
pj_str_t
content_type
;
pj_str_t
content_type
;
/**
* Optional message body to be added to the message, only when the
* message doesn't have a body.
*/
pj_str_t
msg_body
;
pj_str_t
msg_body
;
/**
* Content type of the multipart body. If application wants to send
...
...
@@ -102,133 +101,136 @@ struct pj_caching_pool;
class
SIPPresence
{
public:
/**
* Constructor
* @param acc the associated sipaccount
*/
SIPPresence
(
SIPAccount
*
acc
);
/**
* Destructor
*/
~
SIPPresence
();
/**
* Return associated sipaccount
*/
SIPAccount
*
getAccount
()
const
;
/**
* Return presence data.
*/
pjsip_pres_status
*
getStatus
();
/**
* Return presence module ID which is actually the same as the VOIP link
*/
int
getModId
()
const
;
/**
* Return a pool for generic functions.
*/
pj_pool_t
*
getPool
()
const
;
/**
* Activate the module (PUBLISH/SUBSCRIBE)
*/
void
enable
(
bool
flag
);
/**
* Fill xml document, the header and the body
*/
void
fillDoc
(
pjsip_tx_data
*
tdata
,
const
pres_msg_data
*
msg_data
);
/**
* Modify the presence data
* @param status is basically "open" or "close"
*/
void
updateStatus
(
bool
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
(
bool
status
,
const
std
::
string
&
note
);
/**
* Send a signal to the client on DBus. The signal contain the status
* of a remote user.
*/
void
reportPresSubClientNotification
(
const
std
::
string
&
uri
,
pjsip_pres_status
*
status
);
/**
* Send a SUBSCRIBE request to PBX/IP2IP
* @param buddyUri Remote user that we want to subscribe
*/
void
subscribeClient
(
const
std
::
string
&
uri
,
bool
flag
);
/**
* Add a buddy in the buddy list.
* @param b PresSubClient pointer
*/
void
addPresSubClient
(
PresSubClient
*
b
);
/**
* Remove a buddy from the list.
* @param b PresSubClient pointer
*/
void
removePresSubClient
(
PresSubClient
*
b
);
/**
* IP2IP context.
* Report new Subscription to the client, waiting for approval.
* @param s PresenceSubcription pointer.
*/
void
reportnewServerSubscriptionRequest
(
PresSubServer
*
s
);
/**
* IP2IP context.
* Process new subscription based on client decision.
* @param flag client decision.
* @param uri uri of the remote subscriber
*/
void
approvePresSubServer
(
const
std
::
string
&
uri
,
bool
flag
);
/**
* IP2IP context.
* Add a server associated to a subscriber in the list.
* @param s PresenceSubcription pointer.
*/
void
addPresSubServer
(
PresSubServer
*
s
);
/**
* IP2IP context.
* Remove a server associated to a subscriber from the list.
* @param s PresenceSubcription pointer.
*/
void
removePresSubServer
(
PresSubServer
*
s
);
/**
* IP2IP context.
* Iterate through the subscriber list and send NOTIFY to each.
*/
void
notifyPresSubServer
();
bool
isEnabled
()
const
{
return
enabled_
;
}
const
std
::
list
<
PresSubClient
*>
getClientSubscriptions
()
{
return
pres_sub_client_list_
;
}
void
lock
();
void
unlock
();
pjsip_publishc
*
publish_sess
;
/**< Client publication session.*/
private:
pjsip_pres_status
pres_status_data_
;
/**< Presence Data.*/
pj_bool_t
enabled_
;
/**< Allow for status publish,*/
NON_COPYABLE
(
SIPPresence
);
SIPAccount
*
acc_
;
/**< Associated SIP account. */
std
::
list
<
PresSubServer
*>
pres_sub_server_list_
;
/**< Subscribers list.*/
std
::
list
<
PresSubClient
*>
pres_sub_client_list_
;
/**< Subcribed buddy list.*/
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. */
public:
/**
* Constructor
* @param acc the associated sipaccount
*/
SIPPresence
(
SIPAccount
*
acc
);
/**
* Destructor
*/
~
SIPPresence
();
/**
* Return associated sipaccount
*/
SIPAccount
*
getAccount
()
const
;
/**
* Return presence data.
*/
pjsip_pres_status
*
getStatus
();
/**
* Return presence module ID which is actually the same as the VOIP link
*/
int
getModId
()
const
;
/**
* Return a pool for generic functions.
*/
pj_pool_t
*
getPool
()
const
;
/**
* Activate the module (PUBLISH/SUBSCRIBE)
*/
void
enable
(
bool
flag
);
/**
* Fill xml document, the header and the body
*/
void
fillDoc
(
pjsip_tx_data
*
tdata
,
const
pres_msg_data
*
msg_data
);
/**
* Modify the presence data
* @param status is basically "open" or "close"
*/
void
updateStatus
(
bool
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
(
bool
status
,
const
std
::
string
&
note
);
/**
* Send a signal to the client on DBus. The signal contain the status
* of a remote user.
*/
void
reportPresSubClientNotification
(
const
std
::
string
&
uri
,
pjsip_pres_status
*
status
);
/**
* Send a SUBSCRIBE request to PBX/IP2IP
* @param buddyUri Remote user that we want to subscribe
*/
void
subscribeClient
(
const
std
::
string
&
uri
,
bool
flag
);
/**
* Add a buddy in the buddy list.
* @param b PresSubClient pointer
*/
void
addPresSubClient
(
PresSubClient
*
b
);
/**
* Remove a buddy from the list.
* @param b PresSubClient pointer
*/
void
removePresSubClient
(
PresSubClient
*
b
);
/**
* IP2IP context.
* Report new Subscription to the client, waiting for approval.
* @param s PresenceSubcription pointer.
*/
void
reportnewServerSubscriptionRequest
(
PresSubServer
*
s
);
/**
* IP2IP context.
* Process new subscription based on client decision.
* @param flag client decision.
* @param uri uri of the remote subscriber
*/
void
approvePresSubServer
(
const
std
::
string
&
uri
,
bool
flag
);
/**
* IP2IP context.
* Add a server associated to a subscriber in the list.
* @param s PresenceSubcription pointer.
*/
void
addPresSubServer
(
PresSubServer
*
s
);
/**
* IP2IP context.
* Remove a server associated to a subscriber from the list.
* @param s PresenceSubcription pointer.
*/
void
removePresSubServer
(
PresSubServer
*
s
);
/**
* IP2IP context.
* Iterate through the subscriber list and send NOTIFY to each.
*/
void
notifyPresSubServer
();
bool
isEnabled
()
const
{
return
enabled_
;
}
const
std
::
list
<
PresSubClient
*>
getClientSubscriptions
()
{
return
pres_sub_client_list_
;
}
void
lock
();
void
unlock
();
private:
NON_COPYABLE
(
SIPPresence
);
static
pj_status_t
pres_publish
(
SIPPresence
*
pres
);
static
void
pres_publish_cb
(
struct
pjsip_publishc_cbparam
*
param
);
static
pj_status_t
pres_send_publish
(
SIPPresence
*
pres
,
pj_bool_t
active
);
pjsip_publishc
*
publish_sess_
;
/**< Client publication session.*/
pjsip_pres_status
pres_status_data_
;
/**< Presence Data.*/
pj_bool_t
enabled_
;
/**< Allow for status publish,*/
SIPAccount
*
acc_
;
/**< Associated SIP account. */
std
::
list
<
PresSubServer
*>
pres_sub_server_list_
;
/**< Subscribers list.*/
std
::
list
<
PresSubClient
*>
pres_sub_client_list_
;
/**< Subcribed buddy list.*/
pj_mutex_t
*
mutex_
;
unsigned
mutex_nesting_level_
;
pj_thread_t
*
mutex_owner_
;
pj_caching_pool
cp_
;
pj_pool_t
*
pool_
;
};
#endif
daemon/src/sip/sippublish.cpp
deleted
100644 → 0
View file @
f03f5101
/*
* 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_endpoint.h>
#include
"sippresence.h"
#include
"sip_utils.h"
#include
"sippublish.h"
#include
"logger.h"
#include
"sipvoiplink.h"
void
pres_publish_cb
(
struct
pjsip_publishc_cbparam
*
param
);
pj_status_t
pres_send_publish
(
SIPPresence
*
pres
,
pj_bool_t
active
);
const
pjsip_publishc_opt
my_publish_opt
=
{
true
};
// this is queue_request
/*
* Client presence publication callback.
*/
void
pres_publish_cb
(
struct
pjsip_publishc_cbparam
*
param
)
{
SIPPresence
*
pres
=
(
SIPPresence
*
)
param
->
token
;