mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-28 16:49:20 +00:00
Merge branch 'dev_presence_list'
This commit is contained in:
commit
fb6d0dd135
42 changed files with 2050 additions and 538 deletions
|
|
@ -53,6 +53,7 @@ LOCAL_SRC_FILES := \
|
|||
enum.c \
|
||||
event.c \
|
||||
friend.c \
|
||||
friendlist.c \
|
||||
info.c \
|
||||
linphonecall.c \
|
||||
linphonecore.c \
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ set(LINPHONE_HEADER_FILES
|
|||
call_params.h
|
||||
content.h
|
||||
event.h
|
||||
friendlist.h
|
||||
linphonecore.h
|
||||
linphonecore_utils.h
|
||||
linphonefriend.h
|
||||
|
|
@ -82,6 +83,7 @@ set(LINPHONE_SOURCE_FILES_C
|
|||
enum.h
|
||||
event.c
|
||||
friend.c
|
||||
friendlist.c
|
||||
info.c
|
||||
ldap/ldapprovider.c
|
||||
lime.c
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ linphone_include_HEADERS=\
|
|||
call_params.h \
|
||||
content.h \
|
||||
event.h \
|
||||
friendlist.h \
|
||||
linphonecore.h \
|
||||
linphonecore_utils.h \
|
||||
linphonefriend.h \
|
||||
|
|
@ -63,6 +64,7 @@ liblinphone_la_SOURCES=\
|
|||
enum.c enum.h \
|
||||
event.c \
|
||||
friend.c \
|
||||
friendlist.c \
|
||||
info.c \
|
||||
ldap/ldapprovider.c ldap/ldapprovider.h \
|
||||
linphonecall.c \
|
||||
|
|
|
|||
|
|
@ -166,8 +166,7 @@ belle_sip_response_t *sal_create_response_from_request(Sal *sal, belle_sip_reque
|
|||
|
||||
void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming);
|
||||
|
||||
void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body);
|
||||
bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody);
|
||||
SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg);
|
||||
|
||||
SalReason sal_reason_to_sip_code(SalReason r);
|
||||
|
||||
|
|
|
|||
|
|
@ -669,15 +669,19 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
|||
|
||||
}
|
||||
}else{
|
||||
SalBody salbody;
|
||||
if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) {
|
||||
if (sal_body_has_type(&salbody,"application","dtmf-relay")){
|
||||
belle_sip_message_t *msg = BELLE_SIP_MESSAGE(req);
|
||||
belle_sip_body_handler_t *body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, msg));
|
||||
if (body_handler) {
|
||||
belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t);
|
||||
if (content_type
|
||||
&& (strcmp(belle_sip_header_content_type_get_type(content_type), "application") == 0)
|
||||
&& (strcmp(belle_sip_header_content_type_get_subtype(content_type), "dtmf-relay") == 0)) {
|
||||
char tmp[10];
|
||||
if (sal_lines_get_value(salbody.data, "Signal",tmp, sizeof(tmp))){
|
||||
if (sal_lines_get_value(belle_sip_message_get_body(msg), "Signal",tmp, sizeof(tmp))){
|
||||
op->base.root->callbacks.dtmf_received(op,tmp[0]);
|
||||
}
|
||||
}else
|
||||
op->base.root->callbacks.info_received(op,&salbody);
|
||||
op->base.root->callbacks.info_received(op, (SalBodyHandler *)body_handler);
|
||||
} else {
|
||||
op->base.root->callbacks.info_received(op,NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ static void subscribe_process_timeout(void *user_ctx, const belle_sip_timeout_ev
|
|||
static void subscribe_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
|
||||
}
|
||||
|
||||
static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBody * body){
|
||||
static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBodyHandler* body_handler){
|
||||
SalSubscribeStatus sub_state;
|
||||
belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t);
|
||||
belle_sip_response_t* resp;
|
||||
|
|
@ -89,7 +89,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *event
|
|||
} else
|
||||
sub_state=SalSubscribeActive;
|
||||
sal_op_ref(op);
|
||||
op->base.root->callbacks.notify(op,sub_state,eventname,body);
|
||||
op->base.root->callbacks.notify(op,sub_state,eventname,body_handler);
|
||||
resp=sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
sal_op_unref(op);
|
||||
|
|
@ -102,7 +102,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
|
|||
belle_sip_dialog_state_t dialog_state;
|
||||
belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
|
||||
belle_sip_header_t *event_header;
|
||||
SalBody body;
|
||||
belle_sip_body_handler_t *body_handler;
|
||||
belle_sip_response_t* resp;
|
||||
const char *eventname=NULL;
|
||||
const char *method=belle_sip_request_get_method(req);
|
||||
|
|
@ -112,7 +112,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
|
|||
op->pending_server_trans=server_transaction;
|
||||
|
||||
event_header=belle_sip_message_get_header((belle_sip_message_t*)req,"Event");
|
||||
sal_op_get_body(op,(belle_sip_message_t*)req,&body);
|
||||
body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, BELLE_SIP_MESSAGE(req)));
|
||||
|
||||
if (event_header==NULL){
|
||||
ms_warning("No event header in incoming SUBSCRIBE.");
|
||||
|
|
@ -132,7 +132,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
|
|||
belle_sip_dialog_set_application_data(op->dialog, sal_op_ref(op));
|
||||
ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
|
||||
}else{ /*this is a NOTIFY*/
|
||||
handle_notify(op,req,eventname,&body);
|
||||
handle_notify(op, req, eventname, (SalBodyHandler *)body_handler);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -140,7 +140,10 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
|
|||
switch(dialog_state) {
|
||||
|
||||
case BELLE_SIP_DIALOG_NULL: {
|
||||
op->base.root->callbacks.subscribe_received(op,eventname,body.type ? &body : NULL);
|
||||
const char *type = NULL;
|
||||
belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t);
|
||||
if (content_type) type = belle_sip_header_content_type_get_type(content_type);
|
||||
op->base.root->callbacks.subscribe_received(op, eventname, type ? (SalBodyHandler *)body_handler : NULL);
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_EARLY:
|
||||
|
|
@ -149,7 +152,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
|
|||
|
||||
case BELLE_SIP_DIALOG_CONFIRMED:
|
||||
if (strcmp("NOTIFY",method)==0) {
|
||||
handle_notify(op,req,eventname,&body);
|
||||
handle_notify(op, req, eventname, (SalBodyHandler *)body_handler);
|
||||
} else if (strcmp("SUBSCRIBE",method)==0) {
|
||||
/*either a refresh of an unsubscribe*/
|
||||
if (expires && belle_sip_header_expires_get_expires(expires)>0) {
|
||||
|
|
@ -185,7 +188,7 @@ void sal_op_subscribe_fill_cbs(SalOp*op) {
|
|||
}
|
||||
|
||||
|
||||
int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){
|
||||
int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){
|
||||
belle_sip_request_t *req=NULL;
|
||||
|
||||
if (from)
|
||||
|
|
@ -207,24 +210,33 @@ int sal_subscribe(SalOp *op, const char *from, const char *to, const char *event
|
|||
}
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires)));
|
||||
sal_op_add_body(op,(belle_sip_message_t*)req,body);
|
||||
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler));
|
||||
return sal_op_send_and_create_refresher(op,req,expires,subscribe_refresher_listener);
|
||||
}else if (op->refresher){
|
||||
const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher);
|
||||
belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr);
|
||||
/* modify last request to update body*/
|
||||
sal_op_add_body(op,(belle_sip_message_t*)last_req,body);
|
||||
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_req), BELLE_SIP_BODY_HANDLER(body_handler));
|
||||
return belle_sip_refresher_refresh(op->refresher,expires);
|
||||
}
|
||||
ms_warning("sal_subscribe(): no dialog and no refresher ?");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sal_subscribe_refresh(SalOp *op) {
|
||||
if (op->refresher) {
|
||||
belle_sip_refresher_refresh(op->refresher,belle_sip_refresher_get_expires(op->refresher));
|
||||
return 0;
|
||||
}
|
||||
ms_warning("sal_refresh_subscribe(): no refresher");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sal_unsubscribe(SalOp *op){
|
||||
if (op->refresher){
|
||||
const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher);
|
||||
belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr);
|
||||
sal_op_add_body(op,(belle_sip_message_t*)last_req,NULL);
|
||||
belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0);
|
||||
belle_sip_refresher_refresh(op->refresher,0);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -247,7 +259,7 @@ int sal_subscribe_decline(SalOp *op, SalReason reason){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sal_notify(SalOp *op, const SalBody *body){
|
||||
int sal_notify(SalOp *op, const SalBodyHandler *body_handler){
|
||||
belle_sip_request_t* notify;
|
||||
|
||||
if (!op->dialog) return -1;
|
||||
|
|
@ -258,8 +270,7 @@ int sal_notify(SalOp *op, const SalBody *body){
|
|||
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
|
||||
,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600)));
|
||||
|
||||
sal_op_add_body(op,(belle_sip_message_t*)notify, body);
|
||||
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(notify), BELLE_SIP_BODY_HANDLER(body_handler));
|
||||
return sal_op_send_request(op,notify);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -706,50 +706,17 @@ const char *sal_op_get_remote_contact(const SalOp *op){
|
|||
return op->base.remote_contact;
|
||||
}
|
||||
|
||||
void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body){
|
||||
belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-type");
|
||||
belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-length");
|
||||
belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-encoding");
|
||||
belle_sip_message_set_body((belle_sip_message_t*)req,NULL,0);
|
||||
if (body && body->type && body->subtype && body->data){
|
||||
belle_sip_message_add_header((belle_sip_message_t*)req,
|
||||
(belle_sip_header_t*)belle_sip_header_content_type_create(body->type,body->subtype));
|
||||
belle_sip_message_add_header((belle_sip_message_t*)req,
|
||||
(belle_sip_header_t*)belle_sip_header_content_length_create(body->size));
|
||||
belle_sip_message_set_body((belle_sip_message_t*)req,(const char*)body->data,body->size);
|
||||
if (body->encoding){
|
||||
belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)
|
||||
belle_sip_header_create("Content-encoding",body->encoding));
|
||||
}
|
||||
SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg) {
|
||||
belle_sip_body_handler_t *body_handler = belle_sip_message_get_body_handler(msg);
|
||||
if (body_handler != NULL) {
|
||||
belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t);
|
||||
belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_length_t);
|
||||
belle_sip_header_t *content_encoding = belle_sip_message_get_header(msg, "Content-Encoding");
|
||||
if (content_type != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_type));
|
||||
if (content_length != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_length));
|
||||
if (content_encoding != NULL) belle_sip_body_handler_add_header(body_handler, content_encoding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody){
|
||||
const char *body = NULL;
|
||||
belle_sip_header_content_type_t *content_type;
|
||||
belle_sip_header_content_length_t *clen=NULL;
|
||||
belle_sip_header_t *content_encoding;
|
||||
|
||||
content_type=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_type_t);
|
||||
if (content_type){
|
||||
body=belle_sip_message_get_body(msg);
|
||||
clen=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t);
|
||||
}
|
||||
content_encoding=belle_sip_message_get_header(msg,"Content-encoding");
|
||||
|
||||
memset(salbody,0,sizeof(SalBody));
|
||||
|
||||
if (content_type && body && clen) {
|
||||
salbody->type=belle_sip_header_content_type_get_type(content_type);
|
||||
salbody->subtype=belle_sip_header_content_type_get_subtype(content_type);
|
||||
salbody->data=body;
|
||||
salbody->size=belle_sip_header_content_length_get_content_length(clen);
|
||||
if (content_encoding)
|
||||
salbody->encoding=belle_sip_header_get_unparsed_value(content_encoding);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
return (SalBodyHandler *)body_handler;
|
||||
}
|
||||
|
||||
void sal_op_set_privacy(SalOp* op,SalPrivacyMask privacy) {
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "sal_impl.h"
|
||||
|
||||
|
||||
int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body){
|
||||
int sal_send_info(SalOp *op, const char *from, const char *to, const SalBodyHandler *body_handler){
|
||||
if (op->dialog){
|
||||
belle_sip_request_t *req;
|
||||
belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking);
|
||||
req=belle_sip_dialog_create_queued_request(op->dialog,"INFO");
|
||||
sal_op_add_body(op,(belle_sip_message_t*)req,body);
|
||||
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler));
|
||||
return sal_op_send_request(op,req);
|
||||
}
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ int sal_publish_presence(SalOp *op, const char *from, const char *to, int expire
|
|||
}
|
||||
}
|
||||
|
||||
int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){
|
||||
int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){
|
||||
belle_sip_request_t *req=NULL;
|
||||
if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) {
|
||||
if (from)
|
||||
|
|
@ -114,7 +114,7 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna
|
|||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op)));
|
||||
}
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname));
|
||||
sal_op_add_body(op,BELLE_SIP_MESSAGE(req),body);
|
||||
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler));
|
||||
if (expires!=-1)
|
||||
return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener);
|
||||
else return sal_op_send_request(op,req);
|
||||
|
|
@ -123,7 +123,11 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna
|
|||
const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher);
|
||||
belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
|
||||
/*update body*/
|
||||
sal_op_add_body(op,BELLE_SIP_MESSAGE(last_publish),expires!=0 ? body : NULL);
|
||||
if (expires == 0) {
|
||||
belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_publish), NULL, 0);
|
||||
} else {
|
||||
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_publish), BELLE_SIP_BODY_HANDLER(body_handler));
|
||||
}
|
||||
return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,4 +144,4 @@ LINPHONE_PUBLIC bool_t linphone_buffer_is_empty(const LinphoneBuffer *buffer);
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* LINPHONE_CONTENT_H_ */
|
||||
#endif /* LINPHONE_BUFFER_H_ */
|
||||
|
|
|
|||
|
|
@ -1122,7 +1122,7 @@ static void is_composing_received(SalOp *op, const SalIsComposing *is_composing)
|
|||
}
|
||||
|
||||
static void parse_presence_requested(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) {
|
||||
linphone_notify_parse_presence(op, content_type, content_subtype, body, result);
|
||||
linphone_notify_parse_presence(content_type, content_subtype, body, result);
|
||||
}
|
||||
|
||||
static void convert_presence_to_xml_requested(SalOp *op, SalPresenceModel *presence, const char *contact, char **content) {
|
||||
|
|
@ -1276,9 +1276,9 @@ static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){
|
|||
}
|
||||
}
|
||||
|
||||
static void info_received(SalOp *op, const SalBody *body){
|
||||
static void info_received(SalOp *op, SalBodyHandler *body_handler){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
linphone_core_notify_info_message(lc,op,body);
|
||||
linphone_core_notify_info_message(lc,op,body_handler);
|
||||
}
|
||||
|
||||
static void subscribe_response(SalOp *op, SalSubscribeStatus status){
|
||||
|
|
@ -1299,7 +1299,7 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status){
|
|||
}
|
||||
}
|
||||
|
||||
static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, const SalBody *body){
|
||||
static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, SalBodyHandler *body_handler){
|
||||
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
|
||||
|
|
@ -1308,15 +1308,18 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons
|
|||
lev=linphone_event_new_with_out_of_dialog_op(lc,op,LinphoneSubscriptionOutgoing,eventname);
|
||||
}
|
||||
{
|
||||
LinphoneContent *ct=linphone_content_from_sal_body(body);
|
||||
if (ct) linphone_core_notify_notify_received(lc,lev,eventname,ct);
|
||||
LinphoneContent *ct=linphone_content_from_sal_body_handler(body_handler);
|
||||
if (ct) {
|
||||
linphone_core_notify_notify_received(lc,lev,eventname,ct);
|
||||
linphone_content_unref(ct);
|
||||
}
|
||||
}
|
||||
if (st!=SalSubscribeNone){
|
||||
linphone_event_set_state(lev,linphone_subscription_state_from_sal(st));
|
||||
}
|
||||
}
|
||||
|
||||
static void subscribe_received(SalOp *op, const char *eventname, const SalBody *body){
|
||||
static void subscribe_received(SalOp *op, const char *eventname, const SalBodyHandler *body_handler){
|
||||
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
|
||||
|
|
|
|||
|
|
@ -22,23 +22,46 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
|
||||
|
||||
static void linphone_content_set_sal_body_handler(LinphoneContent *content, SalBodyHandler *body_handler) {
|
||||
if (content->body_handler != NULL) {
|
||||
sal_body_handler_unref(content->body_handler);
|
||||
content->body_handler = NULL;
|
||||
}
|
||||
content->body_handler = sal_body_handler_ref(body_handler);
|
||||
}
|
||||
|
||||
static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) {
|
||||
LinphoneContent *content = belle_sip_object_new(LinphoneContent);
|
||||
belle_sip_object_ref(content);
|
||||
content->owned_fields = TRUE;
|
||||
content->cryptoContext = NULL; /* this field is managed externally by encryption/decryption functions so be careful to initialise it to NULL */
|
||||
if (body_handler == NULL) {
|
||||
linphone_content_set_sal_body_handler(content, sal_body_handler_new());
|
||||
} else {
|
||||
linphone_content_set_sal_body_handler(content, body_handler);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
static void linphone_content_destroy(LinphoneContent *content) {
|
||||
if (content->owned_fields == TRUE) {
|
||||
if (content->lcp.type) belle_sip_free(content->lcp.type);
|
||||
if (content->lcp.subtype) belle_sip_free(content->lcp.subtype);
|
||||
if (content->lcp.data) belle_sip_free(content->lcp.data);
|
||||
if (content->lcp.encoding) belle_sip_free(content->lcp.encoding);
|
||||
if (content->lcp.name) belle_sip_free(content->lcp.name);
|
||||
if (content->lcp.key) belle_sip_free(content->lcp.key);
|
||||
if (content->body_handler) sal_body_handler_unref(content->body_handler);
|
||||
if (content->name) belle_sip_free(content->name);
|
||||
if (content->key) belle_sip_free(content->key);
|
||||
/* note : crypto context is allocated/destroyed by the encryption function */
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_content_clone(LinphoneContent *obj, const LinphoneContent *ref) {
|
||||
obj->owned_fields = TRUE;
|
||||
linphone_content_set_type(obj, linphone_content_get_type(ref));
|
||||
linphone_content_set_subtype(obj, linphone_content_get_subtype(ref));
|
||||
linphone_content_set_encoding(obj, linphone_content_get_encoding(ref));
|
||||
linphone_content_set_sal_body_handler(obj, sal_body_handler_new());
|
||||
if ((linphone_content_get_type(ref) != NULL) || (linphone_content_get_subtype(ref) != NULL)) {
|
||||
linphone_content_set_type(obj, linphone_content_get_type(ref));
|
||||
linphone_content_set_subtype(obj, linphone_content_get_subtype(ref));
|
||||
}
|
||||
if (linphone_content_get_encoding(ref) != NULL) {
|
||||
linphone_content_set_encoding(obj, linphone_content_get_encoding(ref));
|
||||
}
|
||||
linphone_content_set_name(obj, linphone_content_get_name(ref));
|
||||
linphone_content_set_key(obj, linphone_content_get_key(ref), linphone_content_get_key_size(ref));
|
||||
if (linphone_content_get_buffer(ref) != NULL) {
|
||||
|
|
@ -81,163 +104,136 @@ void linphone_content_set_user_data(LinphoneContent *content, void *ud) {
|
|||
}
|
||||
|
||||
const char * linphone_content_get_type(const LinphoneContent *content) {
|
||||
return content->lcp.type;
|
||||
return sal_body_handler_get_type(content->body_handler);
|
||||
}
|
||||
|
||||
void linphone_content_set_type(LinphoneContent *content, const char *type) {
|
||||
if (content->lcp.type != NULL) {
|
||||
belle_sip_free(content->lcp.type);
|
||||
content->lcp.type = NULL;
|
||||
}
|
||||
if (type != NULL) {
|
||||
content->lcp.type = belle_sip_strdup(type);
|
||||
}
|
||||
sal_body_handler_set_type(content->body_handler, type);
|
||||
}
|
||||
|
||||
const char * linphone_content_get_subtype(const LinphoneContent *content) {
|
||||
return content->lcp.subtype;
|
||||
return sal_body_handler_get_subtype(content->body_handler);
|
||||
}
|
||||
|
||||
void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) {
|
||||
if (content->lcp.subtype != NULL) {
|
||||
belle_sip_free(content->lcp.subtype);
|
||||
content->lcp.subtype = NULL;
|
||||
}
|
||||
if (subtype != NULL) {
|
||||
content->lcp.subtype = belle_sip_strdup(subtype);
|
||||
}
|
||||
sal_body_handler_set_subtype(content->body_handler, subtype);
|
||||
}
|
||||
|
||||
void * linphone_content_get_buffer(const LinphoneContent *content) {
|
||||
return content->lcp.data;
|
||||
return sal_body_handler_get_data(content->body_handler);
|
||||
}
|
||||
|
||||
void linphone_content_set_buffer(LinphoneContent *content, const void *buffer, size_t size) {
|
||||
content->lcp.size = size;
|
||||
content->lcp.data = belle_sip_malloc(size + 1);
|
||||
memcpy(content->lcp.data, buffer, size);
|
||||
((char *)content->lcp.data)[size] = '\0';
|
||||
void *data;
|
||||
sal_body_handler_set_size(content->body_handler, size);
|
||||
data = belle_sip_malloc(size + 1);
|
||||
memcpy(data, buffer, size);
|
||||
((char *)data)[size] = '\0';
|
||||
sal_body_handler_set_data(content->body_handler, data);
|
||||
}
|
||||
|
||||
const char * linphone_content_get_string_buffer(const LinphoneContent *content) {
|
||||
return (char *)content->lcp.data;
|
||||
return (const char *)linphone_content_get_buffer(content);
|
||||
}
|
||||
|
||||
void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) {
|
||||
content->lcp.size = strlen(buffer);
|
||||
content->lcp.data = belle_sip_strdup(buffer);
|
||||
sal_body_handler_set_size(content->body_handler, strlen(buffer));
|
||||
sal_body_handler_set_data(content->body_handler, belle_sip_strdup(buffer));
|
||||
}
|
||||
|
||||
size_t linphone_content_get_size(const LinphoneContent *content) {
|
||||
return content->lcp.size;
|
||||
return sal_body_handler_get_size(content->body_handler);
|
||||
}
|
||||
|
||||
void linphone_content_set_size(LinphoneContent *content, size_t size) {
|
||||
content->lcp.size = size;
|
||||
sal_body_handler_set_size(content->body_handler, size);
|
||||
}
|
||||
|
||||
const char * linphone_content_get_encoding(const LinphoneContent *content) {
|
||||
return content->lcp.encoding;
|
||||
return sal_body_handler_get_encoding(content->body_handler);
|
||||
}
|
||||
|
||||
void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) {
|
||||
if (content->lcp.encoding != NULL) {
|
||||
belle_sip_free(content->lcp.encoding);
|
||||
content->lcp.encoding = NULL;
|
||||
}
|
||||
if (encoding != NULL) {
|
||||
content->lcp.encoding = belle_sip_strdup(encoding);
|
||||
}
|
||||
sal_body_handler_set_encoding(content->body_handler, encoding);
|
||||
}
|
||||
|
||||
const char * linphone_content_get_name(const LinphoneContent *content) {
|
||||
return content->lcp.name;
|
||||
return content->name;
|
||||
}
|
||||
|
||||
void linphone_content_set_name(LinphoneContent *content, const char *name) {
|
||||
if (content->lcp.name != NULL) {
|
||||
belle_sip_free(content->lcp.name);
|
||||
content->lcp.name = NULL;
|
||||
if (content->name != NULL) {
|
||||
belle_sip_free(content->name);
|
||||
content->name = NULL;
|
||||
}
|
||||
if (name != NULL) {
|
||||
content->lcp.name = belle_sip_strdup(name);
|
||||
content->name = belle_sip_strdup(name);
|
||||
}
|
||||
}
|
||||
|
||||
size_t linphone_content_get_key_size(const LinphoneContent *content) {
|
||||
return content->lcp.keyLength;
|
||||
return content->keyLength;
|
||||
}
|
||||
|
||||
const char * linphone_content_get_key(const LinphoneContent *content) {
|
||||
return content->lcp.key;
|
||||
return content->key;
|
||||
}
|
||||
|
||||
void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) {
|
||||
if (content->lcp.key != NULL) {
|
||||
belle_sip_free(content->lcp.key);
|
||||
content->lcp.key = NULL;
|
||||
if (content->key != NULL) {
|
||||
belle_sip_free(content->key);
|
||||
content->key = NULL;
|
||||
}
|
||||
if (key != NULL) {
|
||||
content->lcp.key = belle_sip_malloc(keyLength);
|
||||
memcpy(content->lcp.key, key, keyLength);
|
||||
content->key = belle_sip_malloc(keyLength);
|
||||
memcpy(content->key, key, keyLength);
|
||||
}
|
||||
}
|
||||
|
||||
/* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */
|
||||
void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) {
|
||||
return &(content->lcp.cryptoContext);
|
||||
return &(content->cryptoContext);
|
||||
}
|
||||
|
||||
bool_t linphone_content_is_multipart(const LinphoneContent *content) {
|
||||
return sal_body_handler_is_multipart(content->body_handler);
|
||||
}
|
||||
|
||||
LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) {
|
||||
SalBodyHandler *part_body_handler;
|
||||
if (!linphone_content_is_multipart(content)) return NULL;
|
||||
part_body_handler = sal_body_handler_get_part(content->body_handler, idx);
|
||||
return linphone_content_from_sal_body_handler(part_body_handler);
|
||||
}
|
||||
|
||||
LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) {
|
||||
SalBodyHandler *part_body_handler;
|
||||
if (!linphone_content_is_multipart(content)) return NULL;
|
||||
part_body_handler = sal_body_handler_find_part_by_header(content->body_handler, header_name, header_value);
|
||||
return linphone_content_from_sal_body_handler(part_body_handler);
|
||||
}
|
||||
|
||||
const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) {
|
||||
return sal_body_handler_get_header(content->body_handler, header_name);
|
||||
}
|
||||
|
||||
|
||||
LinphoneContent * linphone_content_new(void) {
|
||||
LinphoneContent *content = belle_sip_object_new(LinphoneContent);
|
||||
belle_sip_object_ref(content);
|
||||
content->owned_fields = TRUE;
|
||||
content->lcp.cryptoContext = NULL; /* this field is managed externally by encryption/decryption functions so be careful to initialise it to NULL */
|
||||
return content;
|
||||
return linphone_content_new_with_body_handler(NULL);
|
||||
}
|
||||
|
||||
LinphoneContent * linphone_content_copy(const LinphoneContent *ref) {
|
||||
return (LinphoneContent *)belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(ref)));
|
||||
}
|
||||
|
||||
LinphoneContent * linphone_content_from_sal_body(const SalBody *ref) {
|
||||
if (ref && ref->type) {
|
||||
LinphoneContent *content = linphone_content_new();
|
||||
linphone_content_set_type(content, ref->type);
|
||||
linphone_content_set_subtype(content, ref->subtype);
|
||||
linphone_content_set_encoding(content, ref->encoding);
|
||||
if (ref->data != NULL) {
|
||||
linphone_content_set_buffer(content, ref->data, ref->size);
|
||||
} else {
|
||||
linphone_content_set_size(content, ref->size);
|
||||
}
|
||||
return content;
|
||||
LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) {
|
||||
if (body_handler) {
|
||||
return linphone_content_new_with_body_handler(body_handler);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *content) {
|
||||
if (content && linphone_content_get_type(content)) {
|
||||
body->type = linphone_content_get_type(content);
|
||||
body->subtype = linphone_content_get_subtype(content);
|
||||
body->data = linphone_content_get_buffer(content);
|
||||
body->size = linphone_content_get_size(content);
|
||||
body->encoding = linphone_content_get_encoding(content);
|
||||
return body;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LinphoneContent * linphone_content_private_to_linphone_content(const LinphoneContentPrivate *lcp) {
|
||||
LinphoneContent *content = belle_sip_object_new(LinphoneContent);
|
||||
memcpy(&content->lcp, lcp, sizeof(LinphoneContentPrivate));
|
||||
content->owned_fields = FALSE;
|
||||
return content;
|
||||
}
|
||||
|
||||
LinphoneContentPrivate * linphone_content_to_linphone_content_private(const LinphoneContent *content) {
|
||||
return (LinphoneContentPrivate *)&content->lcp;
|
||||
SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) {
|
||||
if (content == NULL) return NULL;
|
||||
return content->body_handler;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,51 +40,6 @@ struct _LinphoneContent;
|
|||
**/
|
||||
typedef struct _LinphoneContent LinphoneContent;
|
||||
|
||||
/**
|
||||
* @deprecated Use LinphoneContent objects instead of this structure.
|
||||
*/
|
||||
struct _LinphoneContentPrivate{
|
||||
char *type; /**<mime type for the data, for example "application"*/
|
||||
char *subtype; /**<mime subtype for the data, for example "html"*/
|
||||
void *data; /**<the actual data buffer, usually a string. Null when provided by callbacks #LinphoneCoreFileTransferSendCb or #LinphoneCoreFileTransferRecvCb*/
|
||||
size_t size; /**<the size of the data buffer, excluding null character despite null character is always set for convenience.
|
||||
When provided by callback #LinphoneCoreFileTransferSendCb or #LinphoneCoreFileTransferRecvCb, it states the total number of bytes of the transfered file*/
|
||||
char *encoding; /**<The encoding of the data buffer, for example "gzip"*/
|
||||
char *name; /**< used by RCS File transfer messages to store the original filename of the file to be downloaded from server */
|
||||
char *key; /**< used by RCS File transfer messages to store the key to encrypt file if needed */
|
||||
size_t keyLength; /**< Length of key in bytes */
|
||||
void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias to the LinphoneContentPrivate struct.
|
||||
* @deprecated
|
||||
**/
|
||||
typedef struct _LinphoneContentPrivate LinphoneContentPrivate;
|
||||
|
||||
/**
|
||||
* Convert a LinphoneContentPrivate structure to a LinphoneContent object.
|
||||
* @deprecated Utility macro to ease porting existing code from LinphoneContentPrivate structure (old LinphoneContent structure) to new LinphoneContent object.
|
||||
*/
|
||||
#define LINPHONE_CONTENT(lcp) linphone_content_private_to_linphone_content(lcp)
|
||||
|
||||
/**
|
||||
* Convert a LinphoneContentPrivate structure to a LinphoneContent object.
|
||||
* @deprecated Utility function to ease porting existing code from LinphoneContentPrivate structure (old LinphoneContent structure) to new LinphoneContent object.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneContent * linphone_content_private_to_linphone_content(const LinphoneContentPrivate *lcp);
|
||||
|
||||
/**
|
||||
* Convert a LinphoneContent object to a LinphoneContentPrivate structure.
|
||||
* @deprecated Utility macro to ease porting existing code from LinphoneContentPrivate structure (old LinphoneContent structure) to new LinphoneContent object.
|
||||
*/
|
||||
#define LINPHONE_CONTENT_PRIVATE(lc) linphone_content_to_linphone_content_private(lc)
|
||||
|
||||
/**
|
||||
* Convert a LinphoneContent object to a LinphoneContentPrivate structure.
|
||||
* @deprecated Utility function to ease porting existing code from LinphoneContentPrivate structure (old LinphoneContent structure) to new LinphoneContent object.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneContentPrivate * linphone_content_to_linphone_content_private(const LinphoneContent *content);
|
||||
|
||||
/**
|
||||
* Create a content with default values from Linphone core.
|
||||
|
|
@ -219,6 +174,38 @@ LINPHONE_PUBLIC const char * linphone_content_get_name(const LinphoneContent *co
|
|||
*/
|
||||
LINPHONE_PUBLIC void linphone_content_set_name(LinphoneContent *content, const char *name);
|
||||
|
||||
/**
|
||||
* Tell whether a content is a multipart content.
|
||||
* @param[in] content LinphoneContent object.
|
||||
* @return A boolean value telling whether the content is multipart or not.
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_content_is_multipart(const LinphoneContent *content);
|
||||
|
||||
/**
|
||||
* Get a part from a multipart content according to its index.
|
||||
* @param[in] content LinphoneContent object.
|
||||
* @param[in] idx The index of the part to get.
|
||||
* @return A LinphoneContent object holding the part if found, NULL otherwise.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx);
|
||||
|
||||
/**
|
||||
* Find a part from a multipart content looking for a part header with a specified value.
|
||||
* @param[in] content LinphoneContent object.
|
||||
* @param[in] header_name The name of the header to look for.
|
||||
* @param[in] header_value The value of the header to look for.
|
||||
* @return A LinphoneContent object object the part if found, NULL otherwise.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value);
|
||||
|
||||
/**
|
||||
* Get a custom header value of a content.
|
||||
* @param[in] content LinphoneContent object.
|
||||
* @param[in] header_name The name of the header to get the value from.
|
||||
* @return The value of the header if found, NULL otherwise.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ LinphoneEvent *linphone_core_subscribe(LinphoneCore *lc, const LinphoneAddress *
|
|||
|
||||
|
||||
int linphone_event_send_subscribe(LinphoneEvent *lev, const LinphoneContent *body){
|
||||
SalBody salbody;
|
||||
SalBodyHandler *body_handler;
|
||||
int err;
|
||||
|
||||
if (lev->dir!=LinphoneSubscriptionOutgoing){
|
||||
|
|
@ -179,7 +179,8 @@ int linphone_event_send_subscribe(LinphoneEvent *lev, const LinphoneContent *bod
|
|||
lev->send_custom_headers=NULL;
|
||||
}else sal_op_set_sent_custom_header(lev->op,NULL);
|
||||
|
||||
err=sal_subscribe(lev->op,NULL,NULL,lev->name,lev->expires,sal_body_from_content(&salbody,body));
|
||||
body_handler = sal_body_handler_from_content(body);
|
||||
err=sal_subscribe(lev->op,NULL,NULL,lev->name,lev->expires,body_handler);
|
||||
if (err==0){
|
||||
if (lev->subscription_state==LinphoneSubscriptionNone)
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionOutgoingInit);
|
||||
|
|
@ -191,6 +192,10 @@ int linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *b
|
|||
return linphone_event_send_subscribe(lev,body);
|
||||
}
|
||||
|
||||
int linphone_event_refresh_subscribe(LinphoneEvent *lev) {
|
||||
return sal_subscribe_refresh(lev->op);
|
||||
}
|
||||
|
||||
int linphone_event_accept_subscription(LinphoneEvent *lev){
|
||||
int err;
|
||||
if (lev->subscription_state!=LinphoneSubscriptionIncomingReceived){
|
||||
|
|
@ -216,7 +221,7 @@ int linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReason reason){
|
|||
}
|
||||
|
||||
int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){
|
||||
SalBody salbody;
|
||||
SalBodyHandler *body_handler;
|
||||
if (lev->subscription_state!=LinphoneSubscriptionActive){
|
||||
ms_error("linphone_event_notify(): cannot notify if subscription is not active.");
|
||||
return -1;
|
||||
|
|
@ -225,7 +230,8 @@ int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){
|
|||
ms_error("linphone_event_notify(): cannot notify if not an incoming subscription.");
|
||||
return -1;
|
||||
}
|
||||
return sal_notify(lev->op,sal_body_from_content(&salbody,body));
|
||||
body_handler = sal_body_handler_from_content(body);
|
||||
return sal_notify(lev->op, body_handler);
|
||||
}
|
||||
|
||||
LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires){
|
||||
|
|
@ -236,7 +242,7 @@ LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddr
|
|||
}
|
||||
|
||||
static int _linphone_event_send_publish(LinphoneEvent *lev, const LinphoneContent *body, bool_t notify_err){
|
||||
SalBody salbody;
|
||||
SalBodyHandler *body_handler;
|
||||
int err;
|
||||
|
||||
if (lev->dir!=LinphoneSubscriptionInvalidDir){
|
||||
|
|
@ -247,7 +253,8 @@ static int _linphone_event_send_publish(LinphoneEvent *lev, const LinphoneConten
|
|||
sal_op_set_sent_custom_header(lev->op,lev->send_custom_headers);
|
||||
lev->send_custom_headers=NULL;
|
||||
}else sal_op_set_sent_custom_header(lev->op,NULL);
|
||||
err=sal_publish(lev->op,NULL,NULL,lev->name,lev->expires,sal_body_from_content(&salbody,body));
|
||||
body_handler = sal_body_handler_from_content(body);
|
||||
err=sal_publish(lev->op,NULL,NULL,lev->name,lev->expires,body_handler);
|
||||
if (err==0){
|
||||
linphone_event_set_publish_state(lev,LinphonePublishProgress);
|
||||
}else if (notify_err){
|
||||
|
|
|
|||
|
|
@ -138,12 +138,19 @@ LINPHONE_PUBLIC LinphoneEvent *linphone_core_create_subscribe(LinphoneCore *lc,
|
|||
LINPHONE_PUBLIC int linphone_event_send_subscribe(LinphoneEvent *ev, const LinphoneContent *body);
|
||||
|
||||
/**
|
||||
* Update (refresh) an outgoing subscription.
|
||||
* Update (refresh) an outgoing subscription, changing the body.
|
||||
* @param lev a LinphoneEvent
|
||||
* @param body an optional body to include in the subscription update, may be NULL.
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *body);
|
||||
|
||||
/**
|
||||
* Refresh an outgoing subscription keeping the same body.
|
||||
* @param lev LinphoneEvent object.
|
||||
* @return 0 if successful, -1 otherwise.
|
||||
*/
|
||||
LINPHONE_PUBLIC int linphone_event_refresh_subscribe(LinphoneEvent *lev);
|
||||
|
||||
|
||||
/**
|
||||
* Accept an incoming subcription.
|
||||
|
|
|
|||
168
coreapi/friend.c
168
coreapi/friend.c
|
|
@ -88,25 +88,6 @@ MSList *linphone_find_friend_by_address(MSList *fl, const LinphoneAddress *addr,
|
|||
return res;
|
||||
}
|
||||
|
||||
LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op){
|
||||
MSList *elem;
|
||||
for (elem=l;elem!=NULL;elem=elem->next){
|
||||
LinphoneFriend *lf=(LinphoneFriend*)elem->data;
|
||||
if (ms_list_find(lf->insubs, op)) return lf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op){
|
||||
MSList *elem;
|
||||
LinphoneFriend *lf;
|
||||
for (elem=l;elem!=NULL;elem=elem->next){
|
||||
lf=(LinphoneFriend*)elem->data;
|
||||
if (lf->outsub && (lf->outsub == op || sal_op_is_forked_of(lf->outsub, op))) return lf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void __linphone_friend_do_subscribe(LinphoneFriend *fr){
|
||||
LinphoneCore *lc=fr->lc;
|
||||
|
||||
|
|
@ -259,19 +240,22 @@ static void linphone_friend_unsubscribe(LinphoneFriend *lf){
|
|||
}
|
||||
}
|
||||
|
||||
static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){
|
||||
void linphone_friend_invalidate_subscription(LinphoneFriend *lf){
|
||||
LinphoneCore *lc=lf->lc;
|
||||
|
||||
if (lf->outsub!=NULL) {
|
||||
LinphoneCore *lc=lf->lc;
|
||||
sal_op_release(lf->outsub);
|
||||
lf->outsub=NULL;
|
||||
lf->subscribe_active=FALSE;
|
||||
/*notify application that we no longer know the presence activity */
|
||||
if (lf->presence != NULL) {
|
||||
linphone_presence_model_unref(lf->presence);
|
||||
}
|
||||
lf->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,"unknown activity");
|
||||
linphone_core_notify_notify_presence_received(lc,lf);
|
||||
}
|
||||
|
||||
/* Notify application that we no longer know the presence activity */
|
||||
if (lf->presence != NULL) {
|
||||
linphone_presence_model_unref(lf->presence);
|
||||
}
|
||||
lf->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,"unknown activity");
|
||||
linphone_core_notify_notify_presence_received(lc,lf);
|
||||
|
||||
lf->initial_subscribes_sent=FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -405,6 +389,17 @@ const LinphonePresenceModel * linphone_friend_get_presence_model(LinphoneFriend
|
|||
return lf->presence;
|
||||
}
|
||||
|
||||
void linphone_friend_set_presence_model(LinphoneFriend *lf, LinphonePresenceModel *presence) {
|
||||
if (lf->presence != NULL) {
|
||||
linphone_presence_model_unref(lf->presence);
|
||||
}
|
||||
lf->presence = presence;
|
||||
}
|
||||
|
||||
bool_t linphone_friend_is_presence_received(const LinphoneFriend *lf) {
|
||||
return lf->presence_received;
|
||||
}
|
||||
|
||||
BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){
|
||||
return lf->info;
|
||||
}
|
||||
|
|
@ -467,8 +462,9 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){
|
|||
}
|
||||
fr->inc_subscribe_pending=FALSE;
|
||||
}
|
||||
if (fr->lc)
|
||||
linphone_friend_update_subscribes(fr,NULL,linphone_core_should_subscribe_friends_only_when_registered(fr->lc));
|
||||
if (fr->lc) {
|
||||
linphone_friend_list_update_subscriptions(fr->lc->friendlist, NULL, linphone_core_should_subscribe_friends_only_when_registered(fr->lc));
|
||||
}
|
||||
ms_message("linphone_friend_apply() done.");
|
||||
lc->bl_refresh=TRUE;
|
||||
fr->commit=FALSE;
|
||||
|
|
@ -491,47 +487,27 @@ LinphoneFriend * linphone_core_create_friend_with_address(LinphoneCore *lc, cons
|
|||
return linphone_friend_new_with_address(address);
|
||||
}
|
||||
|
||||
void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf)
|
||||
{
|
||||
ms_return_if_fail(lf->lc==NULL);
|
||||
ms_return_if_fail(lf->uri!=NULL);
|
||||
if (ms_list_find(lc->friends,lf)!=NULL){
|
||||
char *tmp=NULL;
|
||||
const LinphoneAddress *addr=linphone_friend_get_address(lf);
|
||||
if (addr) tmp=linphone_address_as_string(addr);
|
||||
ms_warning("Friend %s already in list, ignored.", tmp ? tmp : "unknown");
|
||||
if (tmp) ms_free(tmp);
|
||||
return ;
|
||||
}
|
||||
lc->friends=ms_list_append(lc->friends,linphone_friend_ref(lf));
|
||||
if (ms_list_find(lc->subscribers, lf)){
|
||||
void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf) {
|
||||
if ((lc->friendlist == NULL) || (linphone_friend_list_add_friend(lc->friendlist, lf) != LinphoneFriendListOK)) return;
|
||||
if (ms_list_find(lc->subscribers, lf)) {
|
||||
/*if this friend was in the pending subscriber list, now remove it from this list*/
|
||||
lc->subscribers = ms_list_remove(lc->subscribers, lf);
|
||||
linphone_friend_unref(lf);
|
||||
}
|
||||
lf->lc=lc;
|
||||
if ( linphone_core_ready(lc)) linphone_friend_apply(lf,lc);
|
||||
else lf->commit=TRUE;
|
||||
return ;
|
||||
lf->lc = lc;
|
||||
if (linphone_core_ready(lc)) linphone_friend_apply(lf, lc);
|
||||
else lf->commit = TRUE;
|
||||
}
|
||||
|
||||
void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend* fl){
|
||||
MSList *el=ms_list_find(lc->friends,fl);
|
||||
if (el!=NULL){
|
||||
linphone_friend_unref((LinphoneFriend*)el->data);
|
||||
lc->friends=ms_list_remove_link(lc->friends,el);
|
||||
linphone_core_write_friends_config(lc);
|
||||
}else{
|
||||
ms_error("linphone_core_remove_friend(): friend [%p] is not part of core's list.",fl);
|
||||
void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend *lf) {
|
||||
if (linphone_friend_list_remove_friend(lc->friendlist, lf) == LinphoneFriendListNonExistentFriend) {
|
||||
ms_error("linphone_core_remove_friend(): friend [%p] is not part of core's list.", lf);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_core_update_friends_subscriptions(LinphoneCore *lc, LinphoneProxyConfig *cfg, bool_t only_when_registered){
|
||||
const MSList *elem;
|
||||
for(elem=lc->friends;elem!=NULL;elem=elem->next){
|
||||
LinphoneFriend *f=(LinphoneFriend*)elem->data;
|
||||
linphone_friend_update_subscribes(f,cfg,only_when_registered);
|
||||
}
|
||||
if (lc->friendlist != NULL)
|
||||
linphone_friend_list_update_subscriptions(lc->friendlist, cfg, only_when_registered);
|
||||
}
|
||||
|
||||
bool_t linphone_core_should_subscribe_friends_only_when_registered(const LinphoneCore *lc){
|
||||
|
|
@ -539,17 +515,39 @@ bool_t linphone_core_should_subscribe_friends_only_when_registered(const Linphon
|
|||
}
|
||||
|
||||
void linphone_core_send_initial_subscribes(LinphoneCore *lc){
|
||||
bool_t proxy_config_for_rls_presence_uri_domain = FALSE;
|
||||
LinphoneAddress *rls_address = NULL;
|
||||
const MSList *elem;
|
||||
|
||||
if (lc->initial_subscribes_sent) return;
|
||||
lc->initial_subscribes_sent=TRUE;
|
||||
linphone_core_update_friends_subscriptions(lc,NULL,linphone_core_should_subscribe_friends_only_when_registered(lc));
|
||||
if (lc->friendlist->rls_uri != NULL) {
|
||||
rls_address = linphone_core_create_address(lc, lc->friendlist->rls_uri);
|
||||
}
|
||||
if (rls_address != NULL) {
|
||||
const char *rls_domain = linphone_address_get_domain(rls_address);
|
||||
if (rls_domain != NULL) {
|
||||
for (elem = linphone_core_get_proxy_config_list(lc); elem != NULL; elem = elem->next) {
|
||||
LinphoneProxyConfig *cfg = (LinphoneProxyConfig *)elem->data;
|
||||
const char *proxy_domain = linphone_proxy_config_get_domain(cfg);
|
||||
if (strcmp(rls_domain, proxy_domain) == 0) {
|
||||
proxy_config_for_rls_presence_uri_domain = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
linphone_address_unref(rls_address);
|
||||
}
|
||||
if (proxy_config_for_rls_presence_uri_domain == TRUE) {
|
||||
ms_message("Presence list activated so do not send initial subscribes it will be done when registered");
|
||||
} else {
|
||||
linphone_core_update_friends_subscriptions(lc,NULL,linphone_core_should_subscribe_friends_only_when_registered(lc));
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc){
|
||||
const MSList *elem;
|
||||
for(elem=lc->friends;elem!=NULL;elem=elem->next){
|
||||
LinphoneFriend *f=(LinphoneFriend*)elem->data;
|
||||
linphone_friend_invalidate_subscription(f);
|
||||
}
|
||||
if (lc->friendlist != NULL)
|
||||
linphone_friend_list_invalidate_subscriptions(lc->friendlist);
|
||||
lc->initial_subscribes_sent=FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -569,34 +567,15 @@ const char *linphone_friend_get_ref_key(const LinphoneFriend *lf){
|
|||
}
|
||||
|
||||
LinphoneFriend *linphone_core_find_friend(const LinphoneCore *lc, const LinphoneAddress *addr){
|
||||
LinphoneFriend *lf=NULL;
|
||||
MSList *elem;
|
||||
for(elem=lc->friends;elem!=NULL;elem=ms_list_next(elem)){
|
||||
lf=(LinphoneFriend*)elem->data;
|
||||
if (linphone_address_weak_equal(lf->uri,addr))
|
||||
break;
|
||||
lf=NULL;
|
||||
}
|
||||
return lf;
|
||||
return linphone_friend_list_find_friend_by_address(lc->friendlist, addr);
|
||||
}
|
||||
|
||||
LinphoneFriend *linphone_core_get_friend_by_address(const LinphoneCore *lc, const char *uri){
|
||||
LinphoneAddress *puri=linphone_address_new(uri);
|
||||
LinphoneFriend *lf=puri ? linphone_core_find_friend(lc,puri) : NULL;
|
||||
if (puri) linphone_address_unref(puri);
|
||||
return lf;
|
||||
return linphone_friend_list_find_friend_by_uri(lc->friendlist, uri);
|
||||
}
|
||||
|
||||
LinphoneFriend *linphone_core_get_friend_by_ref_key(const LinphoneCore *lc, const char *key){
|
||||
const MSList *elem;
|
||||
if (key==NULL) return NULL;
|
||||
for(elem=linphone_core_get_friend_list(lc);elem!=NULL;elem=elem->next){
|
||||
LinphoneFriend *lf=(LinphoneFriend*)elem->data;
|
||||
if (lf->refkey!=NULL && strcmp(lf->refkey,key)==0){
|
||||
return lf;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return linphone_friend_list_find_friend_by_ref_key(lc->friendlist, key);
|
||||
}
|
||||
|
||||
#define key_compare(s1,s2) strcmp(s1,s2)
|
||||
|
|
@ -648,6 +627,8 @@ LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int inde
|
|||
}
|
||||
a=lp_config_get_int(config,item,"subscribe",0);
|
||||
linphone_friend_send_subscribe(lf,a);
|
||||
a = lp_config_get_int(config, item, "presence_received", 0);
|
||||
lf->presence_received = (bool_t)a;
|
||||
|
||||
linphone_friend_set_ref_key(lf,lp_config_get_string(config,item,"refkey",NULL));
|
||||
return lf;
|
||||
|
|
@ -690,6 +671,7 @@ void linphone_friend_write_to_config_file(LpConfig *config, LinphoneFriend *lf,
|
|||
}
|
||||
lp_config_set_string(config,key,"pol",__policy_enum_to_str(lf->pol));
|
||||
lp_config_set_int(config,key,"subscribe",lf->subscribe);
|
||||
lp_config_set_int(config, key, "presence_received", lf->presence_received);
|
||||
|
||||
refkey=linphone_friend_get_ref_key(lf);
|
||||
if (refkey){
|
||||
|
|
@ -701,11 +683,15 @@ void linphone_core_write_friends_config(LinphoneCore* lc)
|
|||
{
|
||||
MSList *elem;
|
||||
int i;
|
||||
int store_friends;
|
||||
if (! linphone_core_ready(lc)) return; /*dont write config when reading it !*/
|
||||
for (elem=lc->friends,i=0; elem!=NULL; elem=ms_list_next(elem),i++){
|
||||
linphone_friend_write_to_config_file(lc->config,(LinphoneFriend*)elem->data,i);
|
||||
store_friends = lp_config_get_int(lc->config, "misc", "store_friends", 1);
|
||||
if (store_friends) {
|
||||
for (elem=lc->friendlist->friends,i=0; elem!=NULL; elem=ms_list_next(elem),i++){
|
||||
linphone_friend_write_to_config_file(lc->config,(LinphoneFriend*)elem->data,i);
|
||||
}
|
||||
linphone_friend_write_to_config_file(lc->config,NULL,i); /* set the end */
|
||||
}
|
||||
linphone_friend_write_to_config_file(lc->config,NULL,i); /* set the end */
|
||||
}
|
||||
|
||||
LinphoneCore *linphone_friend_get_core(const LinphoneFriend *fr){
|
||||
|
|
|
|||
444
coreapi/friendlist.c
Normal file
444
coreapi/friendlist.c
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2010-2015 Belledonne Communications SARL
|
||||
|
||||
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 2
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
|
||||
|
||||
|
||||
static char * create_resource_list_xml(const LinphoneFriendList *list) {
|
||||
char *xml_content = NULL;
|
||||
MSList *elem;
|
||||
xmlBufferPtr buf;
|
||||
xmlTextWriterPtr writer;
|
||||
int err;
|
||||
|
||||
if (ms_list_size(list->friends) <= 0) return NULL;
|
||||
|
||||
buf = xmlBufferCreate();
|
||||
if (buf == NULL) {
|
||||
ms_error("%s: Error creating the XML buffer", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
writer = xmlNewTextWriterMemory(buf, 0);
|
||||
if (writer == NULL) {
|
||||
ms_error("%s: Error creating the XML writer", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xmlTextWriterSetIndent(writer,1);
|
||||
err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"resource-lists", (const xmlChar *)"urn:ietf:params:xml:ns:resource-lists");
|
||||
}
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"xsi",
|
||||
NULL, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance");
|
||||
}
|
||||
|
||||
if (err>= 0) {
|
||||
err = xmlTextWriterStartElement(writer, (const xmlChar *)"list");
|
||||
}
|
||||
for (elem = list->friends; elem != NULL; elem = elem->next) {
|
||||
LinphoneFriend *friend = (LinphoneFriend *)elem->data;
|
||||
char *uri = linphone_address_as_string_uri_only(friend->uri);
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterStartElement(writer, (const xmlChar *)"entry");
|
||||
}
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"uri", (const xmlChar *)uri);
|
||||
}
|
||||
if (err >= 0) {
|
||||
/* Close the "entry" element. */
|
||||
err = xmlTextWriterEndElement(writer);
|
||||
}
|
||||
if (uri) ms_free(uri);
|
||||
}
|
||||
if (err >= 0) {
|
||||
/* Close the "list" element. */
|
||||
err = xmlTextWriterEndElement(writer);
|
||||
}
|
||||
|
||||
if (err >= 0) {
|
||||
/* Close the "resource-lists" element. */
|
||||
err = xmlTextWriterEndElement(writer);
|
||||
}
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterEndDocument(writer);
|
||||
}
|
||||
if (err > 0) {
|
||||
/* xmlTextWriterEndDocument returns the size of the content. */
|
||||
xml_content = ms_strdup((char *)buf->content);
|
||||
}
|
||||
xmlFreeTextWriter(writer);
|
||||
xmlBufferFree(buf);
|
||||
|
||||
return xml_content;
|
||||
}
|
||||
|
||||
static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList *list, const LinphoneContent *body, const char *first_part_body) {
|
||||
xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new();
|
||||
xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error);
|
||||
xml_ctx->doc = xmlReadDoc((const unsigned char*)first_part_body, 0, NULL, 0);
|
||||
if (xml_ctx->doc != NULL) {
|
||||
char xpath_str[MAX_XPATH_LENGTH];
|
||||
LinphoneFriend *friend;
|
||||
LinphoneContent *presence_part;
|
||||
xmlXPathObjectPtr resource_object;
|
||||
const char *version_str = NULL;
|
||||
const char *full_state_str = NULL;
|
||||
const char *uri = NULL;
|
||||
bool_t full_state = FALSE;
|
||||
int version;
|
||||
int i;
|
||||
|
||||
if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end;
|
||||
xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"rlmi", (const xmlChar *)"urn:ietf:params:xml:ns:rlmi");
|
||||
|
||||
version_str = linphone_get_xml_attribute_text_content(xml_ctx, "/rlmi:list", "version");
|
||||
if (version_str == NULL) {
|
||||
ms_warning("rlmi+xml: No version attribute in list");
|
||||
goto end;
|
||||
}
|
||||
version = atoi(version_str);
|
||||
linphone_free_xml_text_content(version_str);
|
||||
if (version < list->expected_notification_version) {
|
||||
ms_warning("rlmi+xml: Discarding received notification with version %d because %d was expected", version, list->expected_notification_version);
|
||||
linphone_friend_list_update_subscriptions(list, NULL, FALSE); /* Refresh subscription to get new full state notify. */
|
||||
goto end;
|
||||
}
|
||||
|
||||
full_state_str = linphone_get_xml_attribute_text_content(xml_ctx, "/rlmi:list", "fullState");
|
||||
if (full_state_str == NULL) {
|
||||
ms_warning("rlmi+xml: No fullState attribute in list");
|
||||
goto end;
|
||||
}
|
||||
if ((strcmp(full_state_str, "true") == 0) || (strcmp(full_state_str, "1") == 0)) {
|
||||
MSList *l = list->friends;
|
||||
for (; l != NULL; l = l->next) {
|
||||
friend = (LinphoneFriend *)l->data;
|
||||
linphone_friend_set_presence_model(friend, NULL);
|
||||
}
|
||||
full_state = TRUE;
|
||||
}
|
||||
linphone_free_xml_text_content(full_state_str);
|
||||
if ((list->expected_notification_version == 0) && (full_state == FALSE)) {
|
||||
ms_warning("rlmi+xml: Notification with version 0 is not full state, this is not valid");
|
||||
goto end;
|
||||
}
|
||||
list->expected_notification_version = version + 1;
|
||||
|
||||
resource_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/rlmi:list/rlmi:resource");
|
||||
if ((resource_object != NULL) && (resource_object->nodesetval != NULL)) {
|
||||
for (i = 1; i <= resource_object->nodesetval->nodeNr; i++) {
|
||||
snprintf(xpath_str, sizeof(xpath_str), "/rlmi:list/rlmi:resource[%i]/@uri", i);
|
||||
uri = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||
if (uri == NULL) continue;
|
||||
friend = linphone_friend_list_find_friend_by_uri(list, uri);
|
||||
if (friend != NULL) {
|
||||
const char *state = NULL;
|
||||
snprintf(xpath_str, sizeof(xpath_str),"/rlmi:list/rlmi:resource[%i]/rlmi:instance/@state", i);
|
||||
state = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||
if ((state != NULL) && (strcmp(state, "active") == 0)) {
|
||||
const char *cid = NULL;
|
||||
snprintf(xpath_str, sizeof(xpath_str),"/rlmi:list/rlmi:resource[%i]/rlmi:instance/@cid", i);
|
||||
cid = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||
if (cid != NULL) {
|
||||
presence_part = linphone_content_find_part_by_header(body, "Content-Id", cid);
|
||||
if (presence_part == NULL) {
|
||||
ms_warning("rlmi+xml: Cannot find part with Content-Id: %s", cid);
|
||||
} else {
|
||||
SalPresenceModel *presence = NULL;
|
||||
linphone_notify_parse_presence(linphone_content_get_type(presence_part), linphone_content_get_subtype(presence_part), linphone_content_get_string_buffer(presence_part), &presence);
|
||||
if (presence != NULL) {
|
||||
friend->presence_received = TRUE;
|
||||
linphone_friend_set_presence_model(friend, (LinphonePresenceModel *)presence);
|
||||
if (full_state == FALSE) {
|
||||
linphone_core_notify_notify_presence_received(list->lc, friend);
|
||||
}
|
||||
}
|
||||
linphone_content_unref(presence_part);
|
||||
}
|
||||
}
|
||||
if (cid != NULL) linphone_free_xml_text_content(cid);
|
||||
}
|
||||
if (state != NULL) linphone_free_xml_text_content(state);
|
||||
friend->subscribe_active = TRUE;
|
||||
}
|
||||
linphone_free_xml_text_content(uri);
|
||||
}
|
||||
}
|
||||
if (resource_object != NULL) xmlXPathFreeObject(resource_object);
|
||||
|
||||
if (full_state == TRUE) {
|
||||
MSList *l = list->friends;
|
||||
for (; l != NULL; l = l->next) {
|
||||
friend = (LinphoneFriend *)l->data;
|
||||
if (linphone_friend_is_presence_received(friend) == TRUE) {
|
||||
linphone_core_notify_notify_presence_received(list->lc, friend);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ms_warning("Wrongly formatted rlmi+xml body: %s", xml_ctx->errorBuffer);
|
||||
}
|
||||
|
||||
end:
|
||||
linphone_xmlparsing_context_destroy(xml_ctx);
|
||||
}
|
||||
|
||||
static bool_t linphone_friend_list_has_subscribe_inactive(const LinphoneFriendList *list) {
|
||||
MSList *l = list->friends;
|
||||
bool_t has_subscribe_inactive = FALSE;
|
||||
for (; l != NULL; l = l->next) {
|
||||
LinphoneFriend *friend = (LinphoneFriend *)l->data;
|
||||
if (friend->subscribe_active != TRUE) {
|
||||
has_subscribe_inactive = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return has_subscribe_inactive;
|
||||
}
|
||||
|
||||
static LinphoneFriendList * linphone_friend_list_new(void) {
|
||||
LinphoneFriendList *list = belle_sip_object_new(LinphoneFriendList);
|
||||
belle_sip_object_ref(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
static void linphone_friend_list_destroy(LinphoneFriendList *list) {
|
||||
if (list->display_name != NULL) ms_free(list->display_name);
|
||||
if (list->rls_uri != NULL) ms_free(list->rls_uri);
|
||||
if (list->event != NULL) linphone_event_unref(list->event);
|
||||
list->friends = ms_list_free_with_data(list->friends, (void (*)(void *))linphone_friend_unref);
|
||||
}
|
||||
|
||||
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneFriendList);
|
||||
|
||||
BELLE_SIP_INSTANCIATE_VPTR(LinphoneFriendList, belle_sip_object_t,
|
||||
(belle_sip_object_destroy_t)linphone_friend_list_destroy,
|
||||
NULL, // clone
|
||||
NULL, // marshal
|
||||
TRUE
|
||||
);
|
||||
|
||||
|
||||
LinphoneFriendList * linphone_core_create_friend_list(LinphoneCore *lc) {
|
||||
LinphoneFriendList *list = linphone_friend_list_new();
|
||||
list->lc = lc;
|
||||
return list;
|
||||
}
|
||||
|
||||
LinphoneFriendList * linphone_friend_list_ref(LinphoneFriendList *list) {
|
||||
belle_sip_object_ref(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
void linphone_friend_list_unref(LinphoneFriendList *list) {
|
||||
belle_sip_object_unref(list);
|
||||
}
|
||||
|
||||
void * linphone_friend_list_get_user_data(const LinphoneFriendList *list) {
|
||||
return list->user_data;
|
||||
}
|
||||
|
||||
void linphone_friend_list_set_user_data(LinphoneFriendList *list, void *ud) {
|
||||
list->user_data = ud;
|
||||
}
|
||||
|
||||
const char * linphone_friend_list_get_display_name(const LinphoneFriendList *list) {
|
||||
return list->display_name;
|
||||
}
|
||||
|
||||
void linphone_friend_list_set_display_name(LinphoneFriendList *list, const char *display_name) {
|
||||
if (list->display_name != NULL) {
|
||||
ms_free(list->display_name);
|
||||
list->display_name = NULL;
|
||||
}
|
||||
if (display_name != NULL) {
|
||||
list->display_name = ms_strdup(display_name);
|
||||
}
|
||||
}
|
||||
|
||||
const char * linphone_friend_list_get_rls_uri(const LinphoneFriendList *list) {
|
||||
return list->rls_uri;
|
||||
}
|
||||
|
||||
void linphone_friend_list_set_rls_uri(LinphoneFriendList *list, const char *rls_uri) {
|
||||
if (list->rls_uri != NULL) {
|
||||
ms_free(list->rls_uri);
|
||||
list->rls_uri = NULL;
|
||||
}
|
||||
if (rls_uri != NULL) {
|
||||
list->rls_uri = ms_strdup(rls_uri);
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneFriendListStatus linphone_friend_list_add_friend(LinphoneFriendList *list, LinphoneFriend *friend) {
|
||||
if ((friend->lc != NULL) || (friend->uri == NULL)) return LinphoneFriendListInvalidFriend;
|
||||
if (ms_list_find(list->friends, friend) != NULL) {
|
||||
char *tmp = NULL;
|
||||
const LinphoneAddress *addr = linphone_friend_get_address(friend);
|
||||
if (addr) tmp = linphone_address_as_string(addr);
|
||||
ms_warning("Friend %s already in list [%s], ignored.", tmp ? tmp : "unknown", list->display_name);
|
||||
if (tmp) ms_free(tmp);
|
||||
} else {
|
||||
list->friends = ms_list_append(list->friends, linphone_friend_ref(friend));
|
||||
}
|
||||
return LinphoneFriendListOK;
|
||||
}
|
||||
|
||||
LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *friend) {
|
||||
MSList *elem = ms_list_find(list->friends, friend);
|
||||
if (elem == NULL) return LinphoneFriendListNonExistentFriend;
|
||||
linphone_friend_unref((LinphoneFriend *)elem->data);
|
||||
list->friends = ms_list_remove_link(list->friends, elem);
|
||||
return LinphoneFriendListOK;
|
||||
}
|
||||
|
||||
LinphoneFriend * linphone_friend_list_find_friend_by_address(const LinphoneFriendList *list, const LinphoneAddress *address) {
|
||||
LinphoneFriend *friend = NULL;
|
||||
const MSList *elem;
|
||||
for (elem = list->friends; elem != NULL; elem = elem->next) {
|
||||
friend = (LinphoneFriend *)elem->data;
|
||||
if (linphone_address_weak_equal(friend->uri, address))
|
||||
return friend;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LinphoneFriend * linphone_friend_list_find_friend_by_uri(const LinphoneFriendList *list, const char *uri) {
|
||||
LinphoneAddress *address = linphone_address_new(uri);
|
||||
LinphoneFriend *friend = address ? linphone_friend_list_find_friend_by_address(list, address) : NULL;
|
||||
if (address) linphone_address_unref(address);
|
||||
return friend;
|
||||
}
|
||||
|
||||
LinphoneFriend * linphone_friend_list_find_friend_by_ref_key(const LinphoneFriendList *list, const char *ref_key) {
|
||||
const MSList *elem;
|
||||
if (ref_key == NULL) return NULL;
|
||||
for (elem = list->friends; elem != NULL; elem = elem->next) {
|
||||
LinphoneFriend *friend = (LinphoneFriend *)elem->data;
|
||||
if ((friend->refkey != NULL) && (strcmp(friend->refkey, ref_key) == 0)) return friend;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LinphoneFriend * linphone_friend_list_find_friend_by_inc_subscribe(const LinphoneFriendList *list, SalOp *op) {
|
||||
const MSList *elem;
|
||||
for (elem = list->friends; elem != NULL; elem = elem->next) {
|
||||
LinphoneFriend *friend = (LinphoneFriend *)elem->data;
|
||||
if (ms_list_find(friend->insubs, op)) return friend;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LinphoneFriend * linphone_friend_list_find_friend_by_out_subscribe(const LinphoneFriendList *list, SalOp *op) {
|
||||
const MSList *elem;
|
||||
for (elem = list->friends; elem != NULL; elem = elem->next) {
|
||||
LinphoneFriend *friend = (LinphoneFriend *)elem->data;
|
||||
if (friend->outsub && ((friend->outsub == op) || sal_op_is_forked_of(friend->outsub, op))) return friend;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void linphone_friend_list_close_subscriptions(LinphoneFriendList *list) {
|
||||
/* FIXME we should wait until subscription to complete. */
|
||||
if (list->friends)
|
||||
ms_list_for_each(list->friends, (void (*)(void *))linphone_friend_close_subscriptions);
|
||||
}
|
||||
|
||||
void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, LinphoneProxyConfig *cfg, bool_t only_when_registered) {
|
||||
const MSList *elem;
|
||||
if (list->event != NULL) {
|
||||
linphone_event_refresh_subscribe(list->event);
|
||||
} else if (list->rls_uri != NULL) {
|
||||
LinphoneAddress *address = linphone_address_new(list->rls_uri);
|
||||
char *xml_content = create_resource_list_xml(list);
|
||||
if ((address != NULL) && (xml_content != NULL) && (linphone_friend_list_has_subscribe_inactive(list) == TRUE)) {
|
||||
LinphoneContent *content;
|
||||
int expires = lp_config_get_int(list->lc->config, "sip", "rls_presence_expires", 3600);
|
||||
list->expected_notification_version = 0;
|
||||
list->event = linphone_core_create_subscribe(list->lc, address, "presence", expires);
|
||||
linphone_event_add_custom_header(list->event, "Require", "recipient-list-subscribe");
|
||||
linphone_event_add_custom_header(list->event, "Supported", "eventlist");
|
||||
linphone_event_add_custom_header(list->event, "Accept", "multipart/related, application/pidf+xml, application/rlmi+xml");
|
||||
linphone_event_add_custom_header(list->event, "Content-Disposition", "recipient-list");
|
||||
content = linphone_core_create_content(list->lc);
|
||||
linphone_content_set_type(content, "application");
|
||||
linphone_content_set_subtype(content, "resource-lists+xml");
|
||||
linphone_content_set_string_buffer(content, xml_content);
|
||||
linphone_event_send_subscribe(list->event, content);
|
||||
linphone_content_unref(content);
|
||||
}
|
||||
if (address != NULL) linphone_address_unref(address);
|
||||
if (xml_content != NULL) ms_free(xml_content);
|
||||
} else {
|
||||
for (elem = list->friends; elem != NULL; elem = elem->next) {
|
||||
LinphoneFriend *friend = (LinphoneFriend *)elem->data;
|
||||
linphone_friend_update_subscribes(friend, cfg, only_when_registered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list) {
|
||||
const MSList *elem;
|
||||
for (elem = list->friends; elem != NULL; elem = elem->next) {
|
||||
LinphoneFriend *friend = (LinphoneFriend *)elem->data;
|
||||
linphone_friend_invalidate_subscription(friend);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_friend_list_notify_presence(LinphoneFriendList *list, LinphonePresenceModel *presence) {
|
||||
const MSList *elem;
|
||||
for(elem = list->friends; elem != NULL; elem = elem->next) {
|
||||
LinphoneFriend *friend = (LinphoneFriend *)elem->data;
|
||||
linphone_friend_notify(friend, presence);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, LinphoneEvent *lev, const LinphoneContent *body) {
|
||||
if (linphone_content_is_multipart(body)) {
|
||||
LinphoneContent *first_part;
|
||||
const char *type = linphone_content_get_type(body);
|
||||
const char *subtype = linphone_content_get_subtype(body);
|
||||
|
||||
if ((strcmp(type, "multipart") != 0) || (strcmp(subtype, "related") != 0)) {
|
||||
ms_warning("multipart presence notified but it is not 'multipart/related'");
|
||||
return;
|
||||
}
|
||||
|
||||
first_part = linphone_content_get_part(body, 0);
|
||||
if (first_part == NULL) {
|
||||
ms_warning("'multipart/related' presence notified but it doesn't contain any part");
|
||||
return;
|
||||
}
|
||||
|
||||
type = linphone_content_get_type(first_part);
|
||||
subtype = linphone_content_get_subtype(first_part);
|
||||
if ((strcmp(type, "application") != 0) || (strcmp(subtype, "rlmi+xml") != 0)) {
|
||||
ms_warning("multipart presence notified but first part is not 'application/rlmi+xml'");
|
||||
linphone_content_unref(first_part);
|
||||
return;
|
||||
}
|
||||
|
||||
linphone_friend_list_parse_multipart_related_body(list, body, linphone_content_get_string_buffer(first_part));
|
||||
linphone_content_unref(first_part);
|
||||
}
|
||||
}
|
||||
180
coreapi/friendlist.h
Normal file
180
coreapi/friendlist.h
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
friendlist.h
|
||||
Copyright (C) 2010-2015 Belledonne Communications SARL
|
||||
|
||||
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 2
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LINPHONE_FRIENDLIST_H_
|
||||
#define LINPHONE_FRIENDLIST_H_
|
||||
|
||||
|
||||
#include "linphonefriend.h"
|
||||
#include "linphonepresence.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup buddy_list
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enum describing the status of a LinphoneFriendList operation.
|
||||
**/
|
||||
typedef enum _LinphoneFriendListStatus {
|
||||
LinphoneFriendListOK,
|
||||
LinphoneFriendListNonExistentFriend,
|
||||
LinphoneFriendListInvalidFriend
|
||||
} LinphoneFriendListStatus;
|
||||
|
||||
/**
|
||||
* The LinphoneFriendList object representing a list of friends.
|
||||
**/
|
||||
typedef struct _LinphoneFriendList LinphoneFriendList;
|
||||
|
||||
/**
|
||||
* Create a new empty LinphoneFriendList object.
|
||||
* @param[in] lc LinphoneCore object.
|
||||
* @return A new LinphoneFriendList object.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneFriendList * linphone_core_create_friend_list(LinphoneCore *lc);
|
||||
|
||||
/**
|
||||
* Set the friend list.
|
||||
* @param[in] lc LinphoneCore object
|
||||
* @param[in] list LinphoneFriendList object
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_core_set_friend_list(LinphoneCore *lc, LinphoneFriendList *list);
|
||||
|
||||
/**
|
||||
* Acquire a reference to the friend list.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @return The same LinphoneFriendList object.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneFriendList * linphone_friend_list_ref(LinphoneFriendList *list);
|
||||
|
||||
/**
|
||||
* Release reference to the friend list.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_friend_list_unref(LinphoneFriendList *list);
|
||||
|
||||
/**
|
||||
* Retrieve the user pointer associated with the friend list.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @return The user pointer associated with the friend list.
|
||||
**/
|
||||
LINPHONE_PUBLIC void * linphone_friend_list_get_user_data(const LinphoneFriendList *list);
|
||||
|
||||
/**
|
||||
* Assign a user pointer to the friend list.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @param[in] ud The user pointer to associate with the friend list.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_friend_list_set_user_data(LinphoneFriendList *list, void *ud);
|
||||
|
||||
/**
|
||||
* Get the display name of the friend list.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @return The display name of the friend list.
|
||||
**/
|
||||
LINPHONE_PUBLIC const char * linphone_friend_list_get_display_name(const LinphoneFriendList *list);
|
||||
|
||||
/**
|
||||
* Set the display name of the friend list.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @param[in] display_name The new display name of the friend list.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_friend_list_set_display_name(LinphoneFriendList *list, const char *display_name);
|
||||
|
||||
/**
|
||||
* Get the RLS (Resource List Server) URI associated with the friend list to subscribe to these friends presence.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @return The RLS URI associated with the friend list.
|
||||
**/
|
||||
LINPHONE_PUBLIC const char * linphone_friend_list_get_rls_uri(const LinphoneFriendList *list);
|
||||
|
||||
/**
|
||||
* Set the RLS (Resource List Server) URI associated with the friend list to subscribe to these friends presence.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @param[in] rls_uri The RLS URI to associate with the friend list.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_friend_list_set_rls_uri(LinphoneFriendList *list, const char *rls_uri);
|
||||
|
||||
/**
|
||||
* Add a friend to a friend list.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @param[in] friend LinphoneFriend object to add to the friend list.
|
||||
* @return LinphoneFriendListOK if successfully added, LinphoneFriendListInvalidFriend if the friend is not valid.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_add_friend(LinphoneFriendList *list, LinphoneFriend *afriend);
|
||||
|
||||
/**
|
||||
* Remove a friend from a friend list.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @param[in] friend LinphoneFriend object to remove from the friend list.
|
||||
* @return LinphoneFriendListOK if removed successfully, LinphoneFriendListNonExistentFriend if the friend is not in the list.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *afriend);
|
||||
|
||||
/**
|
||||
* Find a friend in the friend list using a LinphoneAddress.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @param[in] address LinphoneAddress object of the friend we want to search for.
|
||||
* @return A LinphoneFriend if found, NULL otherwise.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_address(const LinphoneFriendList *list, const LinphoneAddress *address);
|
||||
|
||||
/**
|
||||
* Find a friend in the friend list using an URI string.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @param[in] uri A string containing the URI of the friend we want to search for.
|
||||
* @return A LinphoneFriend if found, NULL otherwise.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_uri(const LinphoneFriendList *list, const char *uri);
|
||||
|
||||
/**
|
||||
* Find a frient in the friend list using a ref key.
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @param[in] ref_key The ref key string of the friend we want to search for.
|
||||
* @return A LinphoneFriend if found, NULL otherwise.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_ref_key(const LinphoneFriendList *list, const char *ref_key);
|
||||
|
||||
LINPHONE_PUBLIC void linphone_friend_list_close_subscriptions(LinphoneFriendList *list);
|
||||
|
||||
LINPHONE_PUBLIC void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, LinphoneProxyConfig *cfg, bool_t only_when_registered);
|
||||
|
||||
/**
|
||||
* Notify our presence to all the friends in the friend list that have subscribed to our presence directly (not using a RLS).
|
||||
* @param[in] list LinphoneFriendList object.
|
||||
* @param[in] presence LinphonePresenceModel object.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_friend_list_notify_presence(LinphoneFriendList *list, LinphonePresenceModel *presence);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LINPHONE_FRIENDLIST_H_ */
|
||||
|
|
@ -69,10 +69,10 @@ LinphoneInfoMessage *linphone_core_create_info_message(LinphoneCore *lc){
|
|||
* @param call the call
|
||||
* @param info the info message
|
||||
**/
|
||||
int linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info){
|
||||
SalBody body;
|
||||
sal_op_set_sent_custom_header(call->op,info->headers);
|
||||
return sal_send_info(call->op,NULL, NULL, sal_body_from_content(&body,info->content));
|
||||
int linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info) {
|
||||
SalBodyHandler *body_handler = sal_body_handler_from_content(info->content);
|
||||
sal_op_set_sent_custom_header(call->op, info->headers);
|
||||
return sal_send_info(call->op,NULL, NULL, body_handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -112,12 +112,12 @@ const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMess
|
|||
return (im->content && linphone_content_get_type(im->content)) ? im->content : NULL;
|
||||
}
|
||||
|
||||
void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body){
|
||||
void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, SalBodyHandler *body_handler){
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
if (call){
|
||||
LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1);
|
||||
info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op));
|
||||
if (body) info->content=linphone_content_from_sal_body(body);
|
||||
if (body_handler) info->content=linphone_content_from_sal_body_handler(body_handler);
|
||||
linphone_core_notify_info_received(lc,call,info);
|
||||
linphone_info_message_destroy(info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1664,16 +1664,26 @@ static void linphone_core_register_default_codecs(LinphoneCore *lc){
|
|||
linphone_core_register_static_payloads(lc);
|
||||
}
|
||||
|
||||
static void linphone_core_internal_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) {
|
||||
if (strcmp(notified_event, "Presence") == 0) {
|
||||
linphone_friend_list_notify_presence_received(lc->friendlist, lev, body);
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata){
|
||||
const char *remote_provisioning_uri = NULL;
|
||||
LinphoneCoreVTable* local_vtable= linphone_core_v_table_new();
|
||||
LinphoneCoreVTable *internal_vtable = linphone_core_v_table_new();
|
||||
ms_message("Initializing LinphoneCore %s", linphone_core_get_version());
|
||||
|
||||
lc->config=lp_config_ref(config);
|
||||
lc->data=userdata;
|
||||
lc->ringstream_autorelease=TRUE;
|
||||
linphone_core_set_friend_list(lc, NULL);
|
||||
linphone_task_list_init(&lc->hooks);
|
||||
|
||||
internal_vtable->notify_received = linphone_core_internal_notify_received;
|
||||
_linphone_core_add_listener(lc, internal_vtable, TRUE);
|
||||
memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable));
|
||||
_linphone_core_add_listener(lc, local_vtable, TRUE);
|
||||
|
||||
|
|
@ -1906,7 +1916,23 @@ bool_t linphone_core_generic_confort_noise_enabled(const LinphoneCore *lc){
|
|||
|
||||
const MSList * linphone_core_get_friend_list(const LinphoneCore *lc)
|
||||
{
|
||||
return lc->friends;
|
||||
return lc->friendlist->friends;
|
||||
}
|
||||
|
||||
void linphone_core_set_friend_list(LinphoneCore *lc, LinphoneFriendList *list) {
|
||||
if (lc->friendlist != NULL) {
|
||||
linphone_friend_list_unref(lc->friendlist);
|
||||
lc->friendlist = NULL;
|
||||
}
|
||||
if (list != NULL) {
|
||||
lc->friendlist = linphone_friend_list_ref(list);
|
||||
} else {
|
||||
const char *rls_uri = NULL;
|
||||
lc->friendlist = linphone_core_create_friend_list(lc);
|
||||
rls_uri = lp_config_get_string(lc->config, "sip", "rls_uri", NULL);
|
||||
if (rls_uri && lp_config_get_int(lc->config, "sip", "use_rls_presence", 0))
|
||||
linphone_friend_list_set_rls_uri(lc->friendlist, rls_uri);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_core_enable_audio_adaptive_jittcomp(LinphoneCore* lc, bool_t val)
|
||||
|
|
@ -6324,9 +6350,8 @@ static void codecs_config_uninit(LinphoneCore *lc)
|
|||
void ui_config_uninit(LinphoneCore* lc)
|
||||
{
|
||||
ms_message("Destroying friends.");
|
||||
if (lc->friends){
|
||||
lc->friends = ms_list_free_with_data(lc->friends, (void (*)(void *))linphone_friend_unref);
|
||||
}
|
||||
linphone_friend_list_unref(lc->friendlist);
|
||||
lc->friendlist = NULL;
|
||||
if (lc->subscribers){
|
||||
lc->subscribers = ms_list_free_with_data(lc->subscribers, (void (*)(void *))linphone_friend_unref);
|
||||
}
|
||||
|
|
@ -6366,9 +6391,7 @@ static void linphone_core_uninit(LinphoneCore *lc)
|
|||
ms_usleep(50000);
|
||||
}
|
||||
|
||||
if (lc->friends) /* FIXME we should wait until subscription to complete*/
|
||||
ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_close_subscriptions);
|
||||
|
||||
linphone_friend_list_close_subscriptions(lc->friendlist);
|
||||
lc->chatrooms = ms_list_free_with_data(lc->chatrooms, (MSIterateFunc)linphone_chat_room_release);
|
||||
|
||||
linphone_core_set_state(lc,LinphoneGlobalShutdown,"Shutting down");
|
||||
|
|
|
|||
|
|
@ -1939,6 +1939,15 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addFriend(JNIEnv* env
|
|||
) {
|
||||
linphone_core_add_friend((LinphoneCore*)lc,(LinphoneFriend*)aFriend);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setFriendList(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
,jlong friendList
|
||||
) {
|
||||
linphone_core_set_friend_list((LinphoneCore*)lc,(LinphoneFriendList*)friendList);
|
||||
}
|
||||
|
||||
extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getFriendList(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc) {
|
||||
|
|
@ -3054,12 +3063,47 @@ extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNI
|
|||
}
|
||||
return (jlong)lResult;
|
||||
}
|
||||
|
||||
extern "C" jlong Java_org_linphone_core_LinphoneFriendListImpl_newLinphoneFriendList(JNIEnv* env
|
||||
,jobject thiz, jlong lc) {
|
||||
LinphoneFriendList* fl = linphone_core_create_friend_list((LinphoneCore *)lc);
|
||||
linphone_friend_list_set_user_data(fl,env->NewWeakGlobalRef(thiz));
|
||||
return (jlong)fl;
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_setAddress(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr
|
||||
,jlong linphoneAddress) {
|
||||
linphone_friend_set_address((LinphoneFriend*)ptr,(LinphoneAddress*)linphoneAddress);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneFriendListImpl_setRLSUri(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr
|
||||
,jstring jrlsUri) {
|
||||
const char* uri = env->GetStringUTFChars(jrlsUri, NULL);
|
||||
linphone_friend_list_set_rls_uri((LinphoneFriendList*)ptr,uri);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneFriendListImpl_addFriend(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong friendListptr
|
||||
,jlong friendPtr) {
|
||||
linphone_friend_list_add_friend((LinphoneFriendList*)friendListptr,(LinphoneFriend*)friendPtr);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneFriendListImpl_updateSubscriptions(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong friendListptr
|
||||
,jlong proxyConfigPtr
|
||||
,jboolean jonlyWhenRegistered) {
|
||||
linphone_friend_list_update_subscriptions((LinphoneFriendList*)friendListptr,(LinphoneProxyConfig*)proxyConfigPtr,jonlyWhenRegistered);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_getAddress(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr) {
|
||||
|
|
@ -3103,6 +3147,18 @@ extern "C" jobject Java_org_linphone_core_LinphoneFriendImpl_getCore(JNIEnv* en
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C" jobject Java_org_linphone_core_LinphoneFriendListImpl_getCore(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr) {
|
||||
LinphoneCore *lc=linphone_friend_get_core((LinphoneFriend*)ptr);
|
||||
if (lc!=NULL){
|
||||
jobject core = (jobject)linphone_core_get_user_data(lc);
|
||||
return core;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_setRefKey(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr
|
||||
|
|
@ -3127,6 +3183,14 @@ extern "C" void Java_org_linphone_core_LinphoneFriendImpl_finalize(JNIEnv* env
|
|||
linphone_friend_unref(lfriend);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneFriendListImpl_finalize(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr) {
|
||||
LinphoneFriendList *lfriendList=(LinphoneFriendList*)ptr;
|
||||
linphone_friend_list_set_user_data(lfriendList,NULL);
|
||||
linphone_friend_list_unref(lfriendList);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_linphone_core_LinphoneFriendImpl
|
||||
* Method: getPresenceModel
|
||||
|
|
@ -3277,17 +3341,10 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_markAsRead(JNIEnv*
|
|||
|
||||
|
||||
extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferMessage(JNIEnv* env, jobject thiz, jlong ptr, jstring jname, jstring jtype, jstring jsubtype, jint data_size) {
|
||||
LinphoneContentPrivate content = {0};
|
||||
LinphoneContent content = {0};
|
||||
LinphoneChatMessage *message = NULL;
|
||||
|
||||
content.type = (char*)env->GetStringUTFChars(jtype, NULL);
|
||||
content.subtype = (char*)env->GetStringUTFChars(jsubtype, NULL);
|
||||
content.name = (char*)env->GetStringUTFChars(jname, NULL);
|
||||
content.size = data_size;
|
||||
message = linphone_chat_room_create_file_transfer_message((LinphoneChatRoom *)ptr, LINPHONE_CONTENT(&content));
|
||||
env->ReleaseStringUTFChars(jtype, content.type);
|
||||
env->ReleaseStringUTFChars(jsubtype, content.subtype);
|
||||
env->ReleaseStringUTFChars(jname, content.name);
|
||||
message = linphone_chat_room_create_file_transfer_message((LinphoneChatRoom *)ptr, &content);
|
||||
|
||||
return (jlong) message;
|
||||
}
|
||||
|
|
@ -4673,24 +4730,14 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_subscribe(JNIE
|
|||
jstring jevname, jint expires, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){
|
||||
LinphoneCore *lc=(LinphoneCore*)coreptr;
|
||||
LinphoneAddress *addr=(LinphoneAddress*)addrptr;
|
||||
LinphoneContentPrivate content={0};
|
||||
LinphoneContent content={0};
|
||||
LinphoneEvent *ev;
|
||||
jobject jev=NULL;
|
||||
const char *evname=env->GetStringUTFChars(jevname,NULL);
|
||||
|
||||
ev=linphone_core_subscribe(lc,addr,evname,expires,linphone_content_get_type(&content) ? &content : NULL);
|
||||
if (jtype){
|
||||
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
|
||||
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
|
||||
content.encoding=jencoding ? (char*)env->GetStringUTFChars(jencoding,NULL) : NULL;
|
||||
content.data=(void*)env->GetByteArrayElements(jdata,NULL);
|
||||
content.size=env->GetArrayLength(jdata);
|
||||
}
|
||||
ev=linphone_core_subscribe(lc,addr,evname,expires,content.type ? LINPHONE_CONTENT(&content) : NULL);
|
||||
if (jtype){
|
||||
env->ReleaseStringUTFChars(jtype,content.type);
|
||||
env->ReleaseStringUTFChars(jsubtype,content.subtype);
|
||||
if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding);
|
||||
env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT);
|
||||
env->ReleaseByteArrayElements(jdata,(jbyte*)linphone_content_get_user_data(&content),JNI_ABORT);
|
||||
}
|
||||
env->ReleaseStringUTFChars(jevname,evname);
|
||||
if (ev){
|
||||
|
|
@ -4708,24 +4755,16 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_publish(JNIEnv
|
|||
jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){
|
||||
LinphoneCore *lc=(LinphoneCore*)coreptr;
|
||||
LinphoneAddress *addr=(LinphoneAddress*)addrptr;
|
||||
LinphoneContentPrivate content={0};
|
||||
LinphoneContent content={0};
|
||||
LinphoneEvent *ev;
|
||||
jobject jev=NULL;
|
||||
const char *evname=env->GetStringUTFChars(jevname,NULL);
|
||||
|
||||
ev=linphone_core_subscribe(lc,addr,evname,expires,linphone_content_get_type(&content) ? &content : NULL);
|
||||
|
||||
if (jtype){
|
||||
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
|
||||
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
|
||||
content.encoding=jencoding ? (char*)env->GetStringUTFChars(jencoding,NULL) : NULL;
|
||||
content.data=(void*)env->GetByteArrayElements(jdata,NULL);
|
||||
content.size=env->GetArrayLength(jdata);
|
||||
}
|
||||
ev=linphone_core_publish(lc,addr,evname,expires,content.type ? LINPHONE_CONTENT(&content) : NULL);
|
||||
if (jtype){
|
||||
env->ReleaseStringUTFChars(jtype,content.type);
|
||||
env->ReleaseStringUTFChars(jsubtype,content.subtype);
|
||||
if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding);
|
||||
env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT);
|
||||
env->ReleaseByteArrayElements(jdata,(jbyte*)linphone_content_get_user_data(&content),JNI_ABORT);
|
||||
|
||||
}
|
||||
env->ReleaseStringUTFChars(jevname,evname);
|
||||
if (ev){
|
||||
|
|
@ -4868,33 +4907,24 @@ static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent *
|
|||
jstring jtype, jsubtype, jencoding, jname;
|
||||
jbyteArray jdata = NULL;
|
||||
jint jsize = 0;
|
||||
const LinphoneContentPrivate *content = LINPHONE_CONTENT_PRIVATE(icontent);
|
||||
|
||||
contentClass = (jclass)env->FindClass("org/linphone/core/LinphoneContentImpl");
|
||||
ctor = env->GetMethodID(contentClass,"<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;I)V");
|
||||
|
||||
jtype = env->NewStringUTF(content->type);
|
||||
jsubtype = env->NewStringUTF(content->subtype);
|
||||
jencoding = content->encoding ? env->NewStringUTF(content->encoding) : NULL;
|
||||
jname = content->name ? env->NewStringUTF(content->name) : NULL;
|
||||
jsize = (jint) content->size;
|
||||
jtype = env->NewStringUTF(linphone_content_get_type(icontent));
|
||||
jsubtype = env->NewStringUTF(linphone_content_get_subtype(icontent));
|
||||
jencoding = linphone_content_get_encoding(icontent) ? env->NewStringUTF(linphone_content_get_encoding(icontent)) : NULL;
|
||||
jname = linphone_content_get_name(icontent) ? env->NewStringUTF(linphone_content_get_name(icontent)) : NULL;
|
||||
jsize = (jint) linphone_content_get_size(icontent);
|
||||
|
||||
if (content->data){
|
||||
jdata = env->NewByteArray(content->size);
|
||||
env->SetByteArrayRegion(jdata, 0, content->size, (jbyte*)content->data);
|
||||
if (linphone_content_get_user_data(icontent)){
|
||||
jdata = env->NewByteArray(linphone_content_get_size(icontent));
|
||||
env->SetByteArrayRegion(jdata, 0, linphone_content_get_size(icontent), (jbyte*)linphone_content_get_user_data(icontent));
|
||||
}
|
||||
|
||||
jobject jobj = env->NewObject(contentClass, ctor, jname, jtype, jsubtype, jdata, jencoding, jsize);
|
||||
|
||||
env->DeleteLocalRef(contentClass);
|
||||
env->DeleteLocalRef(jtype);
|
||||
env->DeleteLocalRef(jsubtype);
|
||||
if (jencoding) {
|
||||
env->DeleteLocalRef(jencoding);
|
||||
}
|
||||
if (jname) {
|
||||
env->DeleteLocalRef(jname);
|
||||
}
|
||||
|
||||
return jobj;
|
||||
}
|
||||
|
|
@ -4964,16 +4994,9 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getCont
|
|||
* Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_setContent(JNIEnv *env, jobject jobj, jlong infoptr, jstring jtype, jstring jsubtype, jstring jdata){
|
||||
LinphoneContentPrivate content={0};
|
||||
LinphoneContent content={0};
|
||||
|
||||
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
|
||||
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
|
||||
content.data=(void*)env->GetStringUTFChars(jdata,NULL);
|
||||
content.size=strlen((char*)content.data);
|
||||
linphone_info_message_set_content((LinphoneInfoMessage*)infoptr,LINPHONE_CONTENT(&content));
|
||||
env->ReleaseStringUTFChars(jtype,content.type);
|
||||
env->ReleaseStringUTFChars(jsubtype,content.subtype);
|
||||
env->ReleaseStringUTFChars(jdata,(char*)content.data);
|
||||
linphone_info_message_set_content((LinphoneInfoMessage*)infoptr,&content);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -5073,26 +5096,13 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_denySubscription
|
|||
* Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){
|
||||
LinphoneContentPrivate content={0};
|
||||
LinphoneContent content={0};
|
||||
LinphoneEvent *ev=(LinphoneEvent*)evptr;
|
||||
jint err;
|
||||
|
||||
if (jtype){
|
||||
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
|
||||
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
|
||||
content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL;
|
||||
content.data=(void*)env->GetByteArrayElements(jdata,NULL);
|
||||
content.size=env->GetArrayLength(jdata);
|
||||
}
|
||||
|
||||
err=linphone_event_notify(ev,content.type ? LINPHONE_CONTENT(&content) : NULL);
|
||||
err=linphone_event_notify(ev,linphone_content_get_type(&content) ? &content : NULL);
|
||||
|
||||
if (jtype){
|
||||
env->ReleaseStringUTFChars(jtype,content.type);
|
||||
env->ReleaseStringUTFChars(jsubtype,content.subtype);
|
||||
if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding);
|
||||
env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -5102,26 +5112,12 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *e
|
|||
* Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){
|
||||
LinphoneContentPrivate content={0};
|
||||
LinphoneContent content={0};
|
||||
LinphoneEvent *ev=(LinphoneEvent*)evptr;
|
||||
jint err;
|
||||
|
||||
if (jtype){
|
||||
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
|
||||
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
|
||||
content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL;
|
||||
content.data=(void*)env->GetByteArrayElements(jdata,NULL);
|
||||
content.size=env->GetArrayLength(jdata);
|
||||
}
|
||||
err=linphone_event_update_subscribe(ev,linphone_content_get_type(&content) ? &content : NULL);
|
||||
|
||||
err=linphone_event_update_subscribe(ev,content.type ? LINPHONE_CONTENT(&content) : NULL);
|
||||
|
||||
if (jtype){
|
||||
env->ReleaseStringUTFChars(jtype,content.type);
|
||||
env->ReleaseStringUTFChars(jsubtype,content.subtype);
|
||||
if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding);
|
||||
env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -5131,26 +5127,12 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe(
|
|||
* Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updatePublish(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){
|
||||
LinphoneContentPrivate content={0};
|
||||
LinphoneContent content={0};
|
||||
LinphoneEvent *ev=(LinphoneEvent*)evptr;
|
||||
jint err;
|
||||
|
||||
if (jtype){
|
||||
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
|
||||
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
|
||||
content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL;
|
||||
content.data=(void*)env->GetByteArrayElements(jdata,NULL);
|
||||
content.size=env->GetArrayLength(jdata);
|
||||
}
|
||||
err=linphone_event_update_publish(ev,linphone_content_get_type(&content) ? &content : NULL);
|
||||
|
||||
err=linphone_event_update_publish(ev,content.type ? LINPHONE_CONTENT(&content) : NULL);
|
||||
|
||||
if (jtype){
|
||||
env->ReleaseStringUTFChars(jtype,content.type);
|
||||
env->ReleaseStringUTFChars(jsubtype,content.subtype);
|
||||
if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding);
|
||||
env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -5216,21 +5198,8 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createSubscrib
|
|||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_sendSubscribe(JNIEnv *env, jobject thiz, jlong jevent, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding) {
|
||||
LinphoneContentPrivate content = {0};
|
||||
if (jtype) {
|
||||
content.type = (char*) env->GetStringUTFChars(jtype, NULL);
|
||||
content.subtype = (char*) env->GetStringUTFChars(jsubtype, NULL);
|
||||
content.encoding = jencoding ? (char*) env->GetStringUTFChars(jencoding, NULL) : NULL;
|
||||
content.data = (void*) env->GetByteArrayElements(jdata, NULL);
|
||||
content.size = env->GetArrayLength(jdata);
|
||||
}
|
||||
linphone_event_send_subscribe((LinphoneEvent*) jevent, content.type ? LINPHONE_CONTENT(&content) : NULL);
|
||||
if (jtype) {
|
||||
env->ReleaseStringUTFChars(jtype, content.type);
|
||||
env->ReleaseStringUTFChars(jsubtype, content.subtype);
|
||||
if (jencoding) env->ReleaseStringUTFChars(jencoding, content.encoding);
|
||||
env->ReleaseByteArrayElements(jdata, (jbyte*) content.data, JNI_ABORT);
|
||||
}
|
||||
LinphoneContent content = {0};
|
||||
linphone_event_send_subscribe((LinphoneEvent*) jevent, linphone_content_get_type(&content)? &content : NULL);
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createPublish(JNIEnv *env, jobject thiz, jlong jcore, jlong jaddr, jstring jeventname, jint expires) {
|
||||
|
|
@ -5249,21 +5218,10 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createPublish(
|
|||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_sendPublish(JNIEnv *env, jobject thiz, jlong jevent, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding) {
|
||||
LinphoneContentPrivate content = {0};
|
||||
if (jtype) {
|
||||
content.type = (char*) env->GetStringUTFChars(jtype, NULL);
|
||||
content.subtype = (char*) env->GetStringUTFChars(jsubtype, NULL);
|
||||
content.encoding = jencoding ? (char*) env->GetStringUTFChars(jencoding, NULL) : NULL;
|
||||
content.data = (void*) env->GetByteArrayElements(jdata, NULL);
|
||||
content.size = env->GetArrayLength(jdata);
|
||||
}
|
||||
linphone_event_send_publish((LinphoneEvent*) jevent, content.type ? LINPHONE_CONTENT(&content) : NULL);
|
||||
if (jtype) {
|
||||
env->ReleaseStringUTFChars(jtype, content.type);
|
||||
env->ReleaseStringUTFChars(jsubtype, content.subtype);
|
||||
if (jencoding) env->ReleaseStringUTFChars(jencoding, content.encoding);
|
||||
env->ReleaseByteArrayElements(jdata, (jbyte*) content.data, JNI_ABORT);
|
||||
}
|
||||
LinphoneContent content = {0};
|
||||
linphone_event_send_publish((LinphoneEvent*) jevent, linphone_content_get_type(&content)? &content : NULL);
|
||||
|
||||
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_addCustomHeader(JNIEnv *env, jobject thiz, jlong jevent, jstring jname, jstring jvalue) {
|
||||
|
|
|
|||
|
|
@ -240,6 +240,20 @@ LINPHONE_PUBLIC LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFr
|
|||
*/
|
||||
LINPHONE_PUBLIC const LinphonePresenceModel * linphone_friend_get_presence_model(LinphoneFriend *lf);
|
||||
|
||||
/**
|
||||
* Set the presence model of a friend
|
||||
* @param[in] lf A #LinphoneFriend object
|
||||
* @param[in] presence The #LinphonePresenceModel object to set for the friend
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_friend_set_presence_model(LinphoneFriend *lf, LinphonePresenceModel *presence);
|
||||
|
||||
/**
|
||||
* Tells whether we already received presence information for a friend.
|
||||
* @param[in] lf A #LinphoneFriend object
|
||||
* @return TRUE if presence information has been received for the friend, FALSE otherwise.
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_friend_is_presence_received(const LinphoneFriend *lf);
|
||||
|
||||
/**
|
||||
* Store user pointer to friend object.
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -1464,15 +1464,11 @@ void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf){
|
|||
}
|
||||
|
||||
void linphone_core_notify_all_friends(LinphoneCore *lc, LinphonePresenceModel *presence){
|
||||
MSList *elem;
|
||||
LinphonePresenceActivity *activity = linphone_presence_model_get_activity(presence);
|
||||
char *activity_str = linphone_presence_activity_to_string(activity);
|
||||
ms_message("Notifying all friends that we are [%s]", activity_str);
|
||||
if (activity_str != NULL) ms_free(activity_str);
|
||||
for(elem=lc->friends;elem!=NULL;elem=elem->next){
|
||||
LinphoneFriend *lf=(LinphoneFriend *)elem->data;
|
||||
linphone_friend_notify(lf,presence);
|
||||
}
|
||||
linphone_friend_list_notify_presence(lc->friendlist, presence);
|
||||
}
|
||||
|
||||
void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
|
||||
|
|
@ -1486,7 +1482,10 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
|
|||
ms_message("Receiving new subscription from %s.",from);
|
||||
|
||||
/* check if we answer to this subscription */
|
||||
if (linphone_find_friend_by_address(lc->friends,uri,&lf)!=NULL){
|
||||
if (lc->friendlist != NULL) {
|
||||
lf = linphone_friend_list_find_friend_by_address(lc->friendlist, uri);
|
||||
}
|
||||
if (lf!=NULL){
|
||||
linphone_friend_add_incoming_subscription(lf, op);
|
||||
lf->inc_subscribe_pending=TRUE;
|
||||
sal_subscribe_accept(op);
|
||||
|
|
@ -1511,7 +1510,7 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
|
|||
ms_free(tmp);
|
||||
}
|
||||
|
||||
void linphone_notify_parse_presence(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) {
|
||||
void linphone_notify_parse_presence(const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) {
|
||||
xmlparsing_context_t *xml_ctx;
|
||||
LinphonePresenceModel *model = NULL;
|
||||
|
||||
|
|
@ -1850,15 +1849,15 @@ void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presen
|
|||
|
||||
void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model){
|
||||
char *tmp;
|
||||
LinphoneFriend *lf;
|
||||
LinphoneFriend *lf = NULL;
|
||||
LinphoneAddress *friend=NULL;
|
||||
LinphonePresenceModel *presence = model ? (LinphonePresenceModel *)model:linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline, NULL);
|
||||
|
||||
lf=linphone_find_friend_by_out_subscribe(lc->friends,op);
|
||||
if (lc->friendlist != NULL)
|
||||
lf=linphone_friend_list_find_friend_by_out_subscribe(lc->friendlist,op);
|
||||
if (lf==NULL && lp_config_get_int(lc->config,"sip","allow_out_of_subscribe_presence",0)){
|
||||
const SalAddress *addr=sal_op_get_from_address(op);
|
||||
lf=NULL;
|
||||
linphone_find_friend_by_address(lc->friends,(LinphoneAddress*)addr,&lf);
|
||||
lf = linphone_friend_list_find_friend_by_address(lc->friendlist, (LinphoneAddress *)addr);
|
||||
}
|
||||
if (lf!=NULL){
|
||||
LinphonePresenceActivity *activity = NULL;
|
||||
|
|
@ -1869,11 +1868,9 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa
|
|||
activity_str = linphone_presence_activity_to_string(activity);
|
||||
ms_message("We are notified that [%s] has presence [%s]", tmp, activity_str);
|
||||
if (activity_str != NULL) ms_free(activity_str);
|
||||
if (lf->presence != NULL) {
|
||||
linphone_presence_model_unref(lf->presence);
|
||||
}
|
||||
lf->presence = presence;
|
||||
linphone_friend_set_presence_model(lf, presence);
|
||||
lf->subscribe_active=TRUE;
|
||||
lf->presence_received = TRUE;
|
||||
linphone_core_notify_notify_presence_received(lc,(LinphoneFriend*)lf);
|
||||
ms_free(tmp);
|
||||
if (op != lf->outsub){
|
||||
|
|
@ -1904,9 +1901,11 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa
|
|||
}
|
||||
|
||||
void linphone_subscription_closed(LinphoneCore *lc, SalOp *op){
|
||||
LinphoneFriend *lf;
|
||||
lf=linphone_find_friend_by_inc_subscribe(lc->friends,op);
|
||||
|
||||
LinphoneFriend *lf = NULL;
|
||||
|
||||
if (lc->friendlist != NULL)
|
||||
lf=linphone_friend_list_find_friend_by_inc_subscribe(lc->friendlist,op);
|
||||
|
||||
if (lf!=NULL){
|
||||
/*this will release the op*/
|
||||
linphone_friend_remove_incoming_subscription(lf, op);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ extern "C" {
|
|||
#endif
|
||||
#include "linphonecore.h"
|
||||
#include "linphonefriend.h"
|
||||
#include "friendlist.h"
|
||||
#include "linphone_tunnel.h"
|
||||
#include "linphonecore_utils.h"
|
||||
#include "sal/sal.h"
|
||||
|
|
@ -370,7 +371,6 @@ void linphone_core_write_auth_info(LinphoneCore *lc, LinphoneAuthInfo *ai);
|
|||
const LinphoneAuthInfo *_linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain, bool_t ignore_realm);
|
||||
|
||||
void linphone_core_update_proxy_register(LinphoneCore *lc);
|
||||
void linphone_core_refresh_subscribes(LinphoneCore *lc);
|
||||
int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error);
|
||||
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
|
||||
|
||||
|
|
@ -385,13 +385,16 @@ void _linphone_proxy_config_release(LinphoneProxyConfig *cfg);
|
|||
* */
|
||||
const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg);
|
||||
|
||||
void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list);
|
||||
void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, LinphoneEvent *lev, const LinphoneContent *body);
|
||||
void linphone_friend_invalidate_subscription(LinphoneFriend *lf);
|
||||
void linphone_friend_close_subscriptions(LinphoneFriend *lf);
|
||||
void linphone_friend_update_subscribes(LinphoneFriend *fr, LinphoneProxyConfig *cfg, bool_t only_when_registered);
|
||||
void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence);
|
||||
void linphone_friend_add_incoming_subscription(LinphoneFriend *lf, SalOp *op);
|
||||
void linphone_friend_remove_incoming_subscription(LinphoneFriend *lf, SalOp *op);
|
||||
LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op);
|
||||
LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op);
|
||||
LinphoneFriend *linphone_friend_list_find_friend_by_inc_subscribe(const LinphoneFriendList *list, SalOp *op);
|
||||
LinphoneFriend *linphone_friend_list_find_friend_by_out_subscribe(const LinphoneFriendList *list, SalOp *op);
|
||||
MSList *linphone_find_friend_by_address(MSList *fl, const LinphoneAddress *addr, LinphoneFriend **lf);
|
||||
bool_t linphone_core_should_subscribe_friends_only_when_registered(const LinphoneCore *lc);
|
||||
void linphone_core_update_friends_subscriptions(LinphoneCore *lc, LinphoneProxyConfig *cfg, bool_t only_when_registered);
|
||||
|
|
@ -441,7 +444,7 @@ void linphone_process_authentication(LinphoneCore* lc, SalOp *op);
|
|||
void linphone_authentication_ok(LinphoneCore *lc, SalOp *op);
|
||||
void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from);
|
||||
void linphone_core_send_presence(LinphoneCore *lc, LinphonePresenceModel *presence);
|
||||
void linphone_notify_parse_presence(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result);
|
||||
void linphone_notify_parse_presence(const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result);
|
||||
void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presence, const char *contact, char **content);
|
||||
void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model);
|
||||
void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, SalOp *op);
|
||||
|
|
@ -653,11 +656,26 @@ struct _LinphoneFriend{
|
|||
bool_t inc_subscribe_pending;
|
||||
bool_t commit;
|
||||
bool_t initial_subscribes_sent; /*used to know if initial subscribe message was sent or not*/
|
||||
bool_t presence_received;
|
||||
};
|
||||
|
||||
BELLE_SIP_DECLARE_VPTR(LinphoneFriend);
|
||||
|
||||
|
||||
struct _LinphoneFriendList {
|
||||
belle_sip_object_t base;
|
||||
void *user_data;
|
||||
LinphoneCore *lc;
|
||||
LinphoneEvent *event;
|
||||
char *display_name;
|
||||
char *rls_uri;
|
||||
MSList *friends;
|
||||
int expected_notification_version;
|
||||
};
|
||||
|
||||
BELLE_SIP_DECLARE_VPTR(LinphoneFriendList);
|
||||
|
||||
|
||||
typedef struct sip_config
|
||||
{
|
||||
char *contact;
|
||||
|
|
@ -848,7 +866,7 @@ struct _LinphoneCore
|
|||
ui_config_t ui_conf;
|
||||
autoreplier_config_t autoreplier_conf;
|
||||
LinphoneProxyConfig *default_proxy;
|
||||
MSList *friends;
|
||||
LinphoneFriendList *friendlist;
|
||||
MSList *auth_info;
|
||||
struct _RingStream *ringstream;
|
||||
time_t dmfs_playing_start_time;
|
||||
|
|
@ -1067,10 +1085,10 @@ const char *linphone_core_create_uuid(LinphoneCore *lc);
|
|||
void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact);
|
||||
void linphone_call_create_op(LinphoneCall *call);
|
||||
int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer);
|
||||
void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body);
|
||||
void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, SalBodyHandler *body);
|
||||
LinphoneContent * linphone_content_new(void);
|
||||
LinphoneContent * linphone_content_copy(const LinphoneContent *ref);
|
||||
SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *content);
|
||||
SalBodyHandler *sal_body_handler_from_content(const LinphoneContent *content);
|
||||
SalReason linphone_reason_to_sal(LinphoneReason reason);
|
||||
LinphoneReason linphone_reason_from_sal(SalReason reason);
|
||||
LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, int expires);
|
||||
|
|
@ -1082,7 +1100,7 @@ LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp
|
|||
void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state);
|
||||
void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state);
|
||||
LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss);
|
||||
LinphoneContent *linphone_content_from_sal_body(const SalBody *ref);
|
||||
LinphoneContent *linphone_content_from_sal_body_handler(SalBodyHandler *ref);
|
||||
void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc);
|
||||
void linphone_core_register_offer_answer_providers(LinphoneCore *lc);
|
||||
|
||||
|
|
@ -1090,7 +1108,11 @@ void linphone_core_register_offer_answer_providers(LinphoneCore *lc);
|
|||
struct _LinphoneContent {
|
||||
belle_sip_object_t base;
|
||||
void *user_data;
|
||||
struct _LinphoneContentPrivate lcp;
|
||||
SalBodyHandler *body_handler;
|
||||
char *name; /**< used by RCS File transfer messages to store the original filename of the file to be downloaded from server */
|
||||
char *key; /**< used by RCS File transfer messages to store the key to encrypt file if needed */
|
||||
size_t keyLength; /**< Length of key in bytes */
|
||||
void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */
|
||||
bool_t owned_fields;
|
||||
};
|
||||
|
||||
|
|
@ -1237,6 +1259,7 @@ void linphone_xmlparsing_context_destroy(xmlparsing_context_t *ctx);
|
|||
void linphone_xmlparsing_genericxml_error(void *ctx, const char *fmt, ...);
|
||||
int linphone_create_xml_xpath_context(xmlparsing_context_t *xml_ctx);
|
||||
char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression);
|
||||
const char * linphone_get_xml_attribute_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression, const char *attribute_name);
|
||||
void linphone_free_xml_text_content(const char *text);
|
||||
xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression);
|
||||
|
||||
|
|
@ -1290,6 +1313,7 @@ BELLE_SIP_TYPE_ID(LinphoneLDAPContactProvider),
|
|||
BELLE_SIP_TYPE_ID(LinphoneLDAPContactSearch),
|
||||
BELLE_SIP_TYPE_ID(LinphoneProxyConfig),
|
||||
BELLE_SIP_TYPE_ID(LinphoneFriend),
|
||||
BELLE_SIP_TYPE_ID(LinphoneFriendList),
|
||||
BELLE_SIP_TYPE_ID(LinphoneXmlRpcRequest),
|
||||
BELLE_SIP_TYPE_ID(LinphoneXmlRpcRequestCbs),
|
||||
BELLE_SIP_TYPE_ID(LinphoneXmlRpcSession),
|
||||
|
|
|
|||
132
coreapi/sal.c
132
coreapi/sal.c
|
|
@ -855,10 +855,134 @@ int sal_lines_get_value(const char *data, const char *key, char *value, size_t v
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
int sal_body_has_type(const SalBody *body, const char *type, const char *subtype){
|
||||
return body->type && body->subtype
|
||||
&& strcmp(body->type,type)==0
|
||||
&& strcmp(body->subtype,subtype)==0;
|
||||
static belle_sip_header_t * sal_body_handler_find_header(const SalBodyHandler *body_handler, const char *header_name) {
|
||||
belle_sip_body_handler_t *bsbh = BELLE_SIP_BODY_HANDLER(body_handler);
|
||||
const belle_sip_list_t *l = belle_sip_body_handler_get_headers(bsbh);
|
||||
for (; l != NULL; l = l->next) {
|
||||
belle_sip_header_t *header = BELLE_SIP_HEADER(l->data);
|
||||
if (strcmp(belle_sip_header_get_name(header), header_name) == 0) {
|
||||
return header;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SalBodyHandler * sal_body_handler_new(void) {
|
||||
belle_sip_memory_body_handler_t *body_handler = belle_sip_memory_body_handler_new(NULL, NULL);
|
||||
return (SalBodyHandler *)BELLE_SIP_BODY_HANDLER(body_handler);
|
||||
}
|
||||
|
||||
SalBodyHandler * sal_body_handler_ref(SalBodyHandler *body_handler) {
|
||||
return (SalBodyHandler *)belle_sip_object_ref(BELLE_SIP_OBJECT(body_handler));
|
||||
}
|
||||
|
||||
void sal_body_handler_unref(SalBodyHandler *body_handler) {
|
||||
belle_sip_object_unref(BELLE_SIP_OBJECT(body_handler));
|
||||
}
|
||||
|
||||
const char * sal_body_handler_get_type(const SalBodyHandler *body_handler) {
|
||||
belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type"));
|
||||
if (content_type != NULL) {
|
||||
return belle_sip_header_content_type_get_type(content_type);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type) {
|
||||
belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type"));
|
||||
if (content_type == NULL) {
|
||||
content_type = belle_sip_header_content_type_new();
|
||||
belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_type));
|
||||
}
|
||||
belle_sip_header_content_type_set_type(content_type, type);
|
||||
}
|
||||
|
||||
const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler) {
|
||||
belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type"));
|
||||
if (content_type != NULL) {
|
||||
return belle_sip_header_content_type_get_subtype(content_type);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype) {
|
||||
belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type"));
|
||||
if (content_type == NULL) {
|
||||
content_type = belle_sip_header_content_type_new();
|
||||
belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_type));
|
||||
}
|
||||
belle_sip_header_content_type_set_subtype(content_type, subtype);
|
||||
}
|
||||
|
||||
const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler) {
|
||||
belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding");
|
||||
if (content_encoding != NULL) {
|
||||
return belle_sip_header_get_unparsed_value(content_encoding);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding) {
|
||||
belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding");
|
||||
if (content_encoding != NULL) {
|
||||
belle_sip_body_handler_remove_header_from_ptr(BELLE_SIP_BODY_HANDLER(body_handler), content_encoding);
|
||||
}
|
||||
belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), belle_sip_header_create("Content-Encoding", encoding));
|
||||
}
|
||||
|
||||
void * sal_body_handler_get_data(const SalBodyHandler *body_handler) {
|
||||
return belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(body_handler));
|
||||
}
|
||||
|
||||
void sal_body_handler_set_data(SalBodyHandler *body_handler, void *data) {
|
||||
belle_sip_memory_body_handler_set_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(body_handler), data);
|
||||
}
|
||||
|
||||
size_t sal_body_handler_get_size(const SalBodyHandler *body_handler) {
|
||||
return belle_sip_body_handler_get_size(BELLE_SIP_BODY_HANDLER(body_handler));
|
||||
}
|
||||
|
||||
void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size) {
|
||||
belle_sip_header_content_length_t *content_length = BELLE_SIP_HEADER_CONTENT_LENGTH(sal_body_handler_find_header(body_handler, "Content-Length"));
|
||||
if (content_length == NULL) {
|
||||
content_length = belle_sip_header_content_length_new();
|
||||
belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_length));
|
||||
}
|
||||
belle_sip_header_content_length_set_content_length(content_length, size);
|
||||
belle_sip_body_handler_set_size(BELLE_SIP_BODY_HANDLER(body_handler), size);
|
||||
}
|
||||
|
||||
bool_t sal_body_handler_is_multipart(const SalBodyHandler *body_handler) {
|
||||
if (BELLE_SIP_IS_INSTANCE_OF(body_handler, belle_sip_multipart_body_handler_t)) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, int idx) {
|
||||
const belle_sip_list_t *l = belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler));
|
||||
return (SalBodyHandler *)belle_sip_list_nth_data(l, idx);
|
||||
}
|
||||
|
||||
SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value) {
|
||||
const belle_sip_list_t *l = belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler));
|
||||
for (; l != NULL; l = l->next) {
|
||||
belle_sip_body_handler_t *bsbh = BELLE_SIP_BODY_HANDLER(l->data);
|
||||
const belle_sip_list_t *headers = belle_sip_body_handler_get_headers(bsbh);
|
||||
for (; headers != NULL; headers = headers->next) {
|
||||
belle_sip_header_t *header = BELLE_SIP_HEADER(headers->data);
|
||||
if ((strcmp(belle_sip_header_get_name(header), header_name) == 0) && (strcmp(belle_sip_header_get_unparsed_value(header), header_value) == 0)) {
|
||||
return (SalBodyHandler *)bsbh;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, const char *header_name) {
|
||||
belle_sip_header_t *header = sal_body_handler_find_header(body_handler, header_name);
|
||||
if (header != NULL) {
|
||||
return belle_sip_header_get_unparsed_value(header);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal) {
|
||||
|
|
|
|||
|
|
@ -89,6 +89,33 @@ char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char *
|
|||
return (char *)text;
|
||||
}
|
||||
|
||||
const char * linphone_get_xml_attribute_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression, const char *attribute_name) {
|
||||
xmlXPathObjectPtr xpath_obj;
|
||||
xmlChar *text = NULL;
|
||||
|
||||
xpath_obj = xmlXPathEvalExpression((const xmlChar *)xpath_expression, xml_ctx->xpath_ctx);
|
||||
if (xpath_obj != NULL) {
|
||||
if (xpath_obj->nodesetval != NULL) {
|
||||
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
|
||||
if ((nodes != NULL) && (nodes->nodeNr >= 1)) {
|
||||
xmlNodePtr node = nodes->nodeTab[0];
|
||||
xmlAttr *attr = node->properties;
|
||||
while (attr) {
|
||||
if (strcmp((char *)attr->name, attribute_name) == 0) {
|
||||
text = xmlStrcat(text, attr->children->content);
|
||||
attr = NULL;
|
||||
} else {
|
||||
attr = attr->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlXPathFreeObject(xpath_obj);
|
||||
}
|
||||
|
||||
return (const char *)text;
|
||||
}
|
||||
|
||||
void linphone_free_xml_text_content(const char *text) {
|
||||
xmlFree((xmlChar *)text);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ bool_t linphone_gtk_is_friend(LinphoneCore *lc, const char *contact) {
|
|||
char *uri = linphone_address_as_string_uri_only(addr);
|
||||
LinphoneFriend *lf = linphone_core_get_friend_by_address(lc, uri);
|
||||
linphone_address_destroy(addr);
|
||||
if (uri) ms_free(uri);
|
||||
if (lf) return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@ struct SalAddress;
|
|||
|
||||
typedef struct SalAddress SalAddress;
|
||||
|
||||
struct SalBodyHandler;
|
||||
|
||||
typedef struct SalBodyHandler SalBodyHandler;
|
||||
|
||||
struct SalCustomHeader;
|
||||
|
||||
typedef struct SalCustomHeader SalCustomHeader;
|
||||
|
|
@ -455,14 +459,6 @@ typedef struct SalAuthInfo{
|
|||
SalCertificatesChain *certificates;
|
||||
}SalAuthInfo;
|
||||
|
||||
typedef struct SalBody{
|
||||
const char *type;
|
||||
const char *subtype;
|
||||
const void *data;
|
||||
size_t size;
|
||||
const char *encoding;
|
||||
}SalBody;
|
||||
|
||||
typedef void (*SalOnCallReceived)(SalOp *op);
|
||||
typedef void (*SalOnCallRinging)(SalOp *op);
|
||||
typedef void (*SalOnCallAccepted)(SalOp *op);
|
||||
|
|
@ -484,8 +480,8 @@ typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus);
|
|||
typedef void (*SalOnIsComposingReceived)(SalOp *op, const SalIsComposing *is_composing);
|
||||
typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state);
|
||||
typedef void (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status);
|
||||
typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, const SalBody *body);
|
||||
typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBody *body);
|
||||
typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, SalBodyHandler *body);
|
||||
typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBodyHandler *body);
|
||||
typedef void (*SalOnSubscribeClosed)(SalOp *salop);
|
||||
typedef void (*SalOnParsePresenceRequested)(SalOp *salop, const char *content_type, const char *content_subtype, const char *content, SalPresenceModel **result);
|
||||
typedef void (*SalOnConvertPresenceToXMLRequested)(SalOp *salop, SalPresenceModel *presence, const char *contact, char **content);
|
||||
|
|
@ -493,7 +489,7 @@ typedef void (*SalOnNotifyPresence)(SalOp *op, SalSubscribeStatus ss, SalPresenc
|
|||
typedef void (*SalOnSubscribePresenceReceived)(SalOp *salop, const char *from);
|
||||
typedef void (*SalOnSubscribePresenceClosed)(SalOp *salop, const char *from);
|
||||
typedef void (*SalOnPingReply)(SalOp *salop);
|
||||
typedef void (*SalOnInfoReceived)(SalOp *salop, const SalBody *body);
|
||||
typedef void (*SalOnInfoReceived)(SalOp *salop, SalBodyHandler *body);
|
||||
typedef void (*SalOnPublishResponse)(SalOp *salop);
|
||||
typedef void (*SalOnExpire)(SalOp *salop);
|
||||
/*allows sal implementation to access auth info if available, return TRUE if found*/
|
||||
|
|
@ -741,16 +737,17 @@ int sal_publish_presence(SalOp *op, const char *from, const char *to, int expire
|
|||
int sal_ping(SalOp *op, const char *from, const char *to);
|
||||
|
||||
/*info messages*/
|
||||
int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body);
|
||||
int sal_send_info(SalOp *op, const char *from, const char *to, const SalBodyHandler *body);
|
||||
|
||||
/*generic subscribe/notify/publish api*/
|
||||
int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body);
|
||||
int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body);
|
||||
int sal_unsubscribe(SalOp *op);
|
||||
int sal_subscribe_accept(SalOp *op);
|
||||
int sal_subscribe_decline(SalOp *op, SalReason reason);
|
||||
int sal_notify(SalOp *op, const SalBody *body);
|
||||
int sal_subscribe_refresh(SalOp *op);
|
||||
int sal_notify(SalOp *op, const SalBodyHandler *body);
|
||||
int sal_notify_close(SalOp *op);
|
||||
int sal_publish(SalOp *op, const char *from, const char *to, const char*event_name, int expires, const SalBody *body);
|
||||
int sal_publish(SalOp *op, const char *from, const char *to, const char*event_name, int expires, const SalBodyHandler *body);
|
||||
|
||||
/*privacy, must be in sync with LinphonePrivacyMask*/
|
||||
typedef enum _SalPrivacy {
|
||||
|
|
@ -846,7 +843,25 @@ unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size);
|
|||
belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name);
|
||||
void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer);
|
||||
|
||||
int sal_body_has_type(const SalBody *body, const char *type, const char *subtype);
|
||||
//SalBodyHandler * sal_body_handler_new(const char *type, const char *subtype, void *data, size_t size, const char *encoding);
|
||||
SalBodyHandler * sal_body_handler_new(void);
|
||||
SalBodyHandler * sal_body_handler_ref(SalBodyHandler *body_handler);
|
||||
void sal_body_handler_unref(SalBodyHandler *body_handler);
|
||||
const char * sal_body_handler_get_type(const SalBodyHandler *body_handler);
|
||||
void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type);
|
||||
const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler);
|
||||
void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype);
|
||||
const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler);
|
||||
void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding);
|
||||
void * sal_body_handler_get_data(const SalBodyHandler *body_handler);
|
||||
void sal_body_handler_set_data(SalBodyHandler *body_handler, void *data);
|
||||
size_t sal_body_handler_get_size(const SalBodyHandler *body_handler);
|
||||
void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size);
|
||||
bool_t sal_body_handler_is_multipart(const SalBodyHandler *body_handler);
|
||||
SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, int idx);
|
||||
SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value);
|
||||
const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, const char *header_name);
|
||||
|
||||
/*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/
|
||||
int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size);
|
||||
|
||||
|
|
|
|||
|
|
@ -998,6 +998,16 @@ public interface LinphoneCore {
|
|||
* @throws LinphoneCoreException
|
||||
*/
|
||||
void addFriend(LinphoneFriend lf) throws LinphoneCoreException;
|
||||
|
||||
/**
|
||||
* Sets the friend list for the linphone core.
|
||||
*/
|
||||
void setFriendList(LinphoneFriendList friendList) throws LinphoneCoreException;
|
||||
|
||||
/**
|
||||
* Creates a friend list.
|
||||
*/
|
||||
LinphoneFriendList createLinphoneFriendList() throws LinphoneCoreException;
|
||||
|
||||
/**
|
||||
* Get list of LinphoneFriend
|
||||
|
|
|
|||
27
java/common/org/linphone/core/LinphoneFriendList.java
Normal file
27
java/common/org/linphone/core/LinphoneFriendList.java
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
LinphoneFriend.java
|
||||
Copyright (C) 2010 Belledonne Communications, Grenoble, France
|
||||
|
||||
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 2
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
package org.linphone.core;
|
||||
|
||||
|
||||
public interface LinphoneFriendList {
|
||||
public void setRLSUri(String uri);
|
||||
public void addFriend(LinphoneFriend friend);
|
||||
public void updateSubscriptions(LinphoneProxyConfig proxyConfig,boolean onlyWhenRegistered);
|
||||
long getNativePtr();
|
||||
}
|
||||
|
|
@ -94,6 +94,7 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
private native void setPreviewWindowId(long nativePtr, Object wid);
|
||||
private native void setDeviceRotation(long nativePtr, int rotation);
|
||||
private native void addFriend(long nativePtr,long friend);
|
||||
private native void setFriendList(long nativePtr,long friendList);
|
||||
private native LinphoneFriend[] getFriendList(long nativePtr);
|
||||
private native void setPresenceInfo(long nativePtr, int minutes_away, String alternative_contact, int status);
|
||||
private native int getPresenceInfo(long nativePtr);
|
||||
|
|
@ -448,6 +449,15 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
public synchronized void addFriend(LinphoneFriend lf) throws LinphoneCoreException {
|
||||
addFriend(nativePtr,((LinphoneFriendImpl)lf).nativePtr);
|
||||
}
|
||||
|
||||
|
||||
public synchronized LinphoneFriendList createLinphoneFriendList() {
|
||||
return new LinphoneFriendListImpl(this);
|
||||
}
|
||||
|
||||
public synchronized void setFriendList(LinphoneFriendList friendList) throws LinphoneCoreException {
|
||||
setFriendList(nativePtr,((LinphoneFriendListImpl)friendList).nativePtr);
|
||||
}
|
||||
|
||||
public synchronized LinphoneFriend[] getFriendList() {
|
||||
return getFriendList(nativePtr);
|
||||
|
|
|
|||
80
java/impl/org/linphone/core/LinphoneFriendListImpl.java
Normal file
80
java/impl/org/linphone/core/LinphoneFriendListImpl.java
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
LinphoneFriendImpl.java
|
||||
Copyright (C) 2010 Belledonne Communications, Grenoble, France
|
||||
|
||||
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 2
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
package org.linphone.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.linphone.core.LinphoneProxyConfigImpl;
|
||||
|
||||
class LinphoneFriendListImpl implements LinphoneFriendList, Serializable {
|
||||
|
||||
protected final long nativePtr;
|
||||
private native void finalize(long nativePtr);
|
||||
private native long newLinphoneFriendList(long corePtr);
|
||||
private native void setRLSUri(long nativePtr,String uri);
|
||||
private native void addFriend(long nativePtr,long friendPtr);
|
||||
private native void updateSubscriptions(long nativePtr,long proxyConfigPtr,boolean onlyWhenRegistered);
|
||||
private native Object getCore(long ptr);
|
||||
|
||||
|
||||
protected LinphoneFriendListImpl(LinphoneCoreImpl core) {
|
||||
nativePtr = newLinphoneFriendList(core.nativePtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRLSUri(String uri) {
|
||||
synchronized(getSyncObject()){
|
||||
setRLSUri(nativePtr, uri);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFriend(LinphoneFriend friend) {
|
||||
synchronized(getSyncObject()){
|
||||
addFriend(nativePtr, friend.getNativePtr());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSubscriptions(LinphoneProxyConfig proxyConfig,boolean onlyWhenRegistered) {
|
||||
synchronized(getSyncObject()){
|
||||
updateSubscriptions(nativePtr, ((LinphoneProxyConfigImpl)proxyConfig).nativePtr,onlyWhenRegistered);
|
||||
}
|
||||
}
|
||||
|
||||
/*reserved for JNI */
|
||||
protected LinphoneFriendListImpl(long aNativePtr) {
|
||||
nativePtr = aNativePtr;
|
||||
}
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
if (nativePtr != 0) {
|
||||
finalize(nativePtr);
|
||||
}
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNativePtr() {
|
||||
return nativePtr;
|
||||
}
|
||||
private Object getSyncObject(){
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ void check_rtcp(LinphoneCall *call) {
|
|||
linphone_call_unref(call);
|
||||
}
|
||||
|
||||
static FILE *sip_start(const char *senario, const char* dest_username, LinphoneAddress* dest_addres) {
|
||||
FILE *sip_start(const char *senario, const char* dest_username, LinphoneAddress* dest_addres) {
|
||||
#if HAVE_SIPP
|
||||
char *dest;
|
||||
char *command;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,10 @@ const char *liblinphone_tester_get_notify_content(void){
|
|||
void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content){
|
||||
LinphoneCoreManager *mgr;
|
||||
BC_ASSERT_PTR_NOT_NULL_FATAL(content);
|
||||
BC_ASSERT_STRING_EQUAL(notify_content,(const char*)linphone_content_get_buffer(content));
|
||||
if (!linphone_content_is_multipart(content)) {
|
||||
/*hack to disable content checking for list notify */
|
||||
BC_ASSERT_STRING_EQUAL(notify_content,(const char*)linphone_content_get_buffer(content));
|
||||
}
|
||||
mgr=get_manager(lc);
|
||||
mgr->stat.number_of_NotifyReceived++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ aliases=localhost sip2.linphone.org sipopen.example.org sip.example.org auth.exa
|
|||
# Default value: sip:*
|
||||
#transports=sip:192.168.56.101:5060 sips:192.168.56.101:5061
|
||||
|
||||
#note: the ip addresses are explicitely specified here because the machine has several interfaces. In a simple case, using '*' instead of the explicit ip address is sufficient,
|
||||
#note: the ip addresses are explicitely specified here because the machine has several interfaces. In a simple case, using '*' instead of the explicit ip address is sufficient,
|
||||
#and there is no need to specify the ipv6 transport addresses.
|
||||
transports=sip:MacBook-Pro-de-jehan.local:5060 sips:MacBook-Pro-de-jehan.local:5061;tls-certificates-dir=/etc/flexisip/tls/certificates/cn sips:MacBook-Pro-de-jehan.local:5062;tls-certificates-dir=/etc/flexisip/tls/certificates/altname sips:MacBook-Pro-de-jehan.local:5063;require-peer-certificate=1 sip:MacBook-Pro-de-jehan.local:5064 sip:[2001:41d0:2:14b0::1]:5060 sips:[2001:41d0:2:14b0::1]:5061;tls-certificates-dir=/etc/flexisip/tls/certificates/cn sips:[2001:41d0:2:14b0::1]:5062;tls-certificates-dir=/etc/flexisip/tls/certificates/altname sips:[2001:41d0:2:14b0::1]:5063;require-peer-certificate=1 sip:[2001:41d0:2:14b0::1]:5064
|
||||
transports=sip:94.23.19.176:5060 sips:94.23.19.176:5061;tls-certificates-dir=/etc/flexisip/tls/certificates/cn sips:94.23.19.176:5062;tls-certificates-dir=/etc/flexisip/tls/certificates/altname sips:94.23.19.176:5063;require-peer-certificate=1 sip:94.23.19.176:5064 sip:[2001:41d0:2:14b0::1]:5060 sips:[2001:41d0:2:14b0::1]:5061;tls-certificates-dir=/etc/flexisip/tls/certificates/cn sips:[2001:41d0:2:14b0::1]:5062;tls-certificates-dir=/etc/flexisip/tls/certificates/altname sips:[2001:41d0:2:14b0::1]:5063;require-peer-certificate=1 sip:[2001:41d0:2:14b0::1]:5064
|
||||
|
||||
|
||||
# An absolute path of a directory where TLS server certificate and
|
||||
|
|
@ -107,20 +107,19 @@ no-403=user-agent contains 'tester-no-403'
|
|||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter= from.uri.domain contains 'sip.example.org' || from.uri.domain contains 'auth.example.org' || from.uri.domain contains 'auth1.example.org' || from.uri.domain contains 'auth2.example.org' || from.uri.domain contains 'anonymous.invalid'
|
||||
# Default value:
|
||||
filter= from.uri.domain contains 'sip.example.org' || from.uri.domain contains 'auth.example.org' || from.uri.domain contains 'auth1.example.org' || from.uri.domain contains 'auth2.example.org' || from.uri.domain contains 'anonymous.invalid'
|
||||
|
||||
# List of whitespace separated domain names to challenge. Others
|
||||
# are denied.
|
||||
# Default value:
|
||||
# Default value:
|
||||
auth-domains= sip.example.org auth.example.org auth1.example.org auth2.example.org
|
||||
|
||||
client-certificates-domains=client.example.org
|
||||
|
||||
|
||||
# List of whitespace separated IP which will not be challenged.
|
||||
# Default value:
|
||||
trusted-hosts=
|
||||
# Default value:
|
||||
trusted-hosts=127.0.0.1 94.23.19.176
|
||||
|
||||
# Database backend implementation [odbc, file].
|
||||
# Default value: odbc
|
||||
|
|
@ -615,3 +614,11 @@ packet-rate-limit=5
|
|||
# Default value: 2
|
||||
ban-time=1
|
||||
|
||||
[module::Presence]
|
||||
enabled=true
|
||||
presence-server = <sip:127.0.0.1:5065;transport=tcp>
|
||||
|
||||
[presence-server]
|
||||
expires = 600
|
||||
transports = sip:127.0.0.1:5065;transport=tcp
|
||||
|
||||
|
|
|
|||
|
|
@ -884,6 +884,171 @@ static void dos_module_trigger(void) {
|
|||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
|
||||
static void test_subscribe_notify_with_sipp_publisher(void) {
|
||||
char *scen;
|
||||
FILE * sipp_out;
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
/*just to get an identity*/
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
|
||||
LpConfig *pauline_lp = linphone_core_get_config(pauline->lc);
|
||||
char* lf_identity=linphone_address_as_string_uri_only(marie->identity);
|
||||
LinphoneFriend *lf = linphone_core_create_friend_with_address(pauline->lc,lf_identity);
|
||||
ms_free(lf_identity);
|
||||
|
||||
lp_config_set_int(pauline_lp,"sip","subscribe_expires",5);
|
||||
|
||||
linphone_core_add_friend(pauline->lc,lf);
|
||||
|
||||
/*wait for subscribe acknowledgment*/
|
||||
wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyReceived,1,2000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf), int, "%d");
|
||||
|
||||
scen = bc_tester_res("sipp/simple_publish.xml");
|
||||
|
||||
sipp_out = sip_start(scen, linphone_address_get_username(marie->identity), marie->identity);
|
||||
|
||||
if (TRUE/*sipp_out*/) {
|
||||
/*wait for marie status*/
|
||||
wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyReceived,2,3000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf), int, "%d");
|
||||
pclose(sipp_out);
|
||||
}
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
static void test_subscribe_notify_with_sipp_publisher_double_publish(void) {
|
||||
char *scen;
|
||||
FILE * sipp_out;
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
/*just to get an identity*/
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
|
||||
LpConfig *pauline_lp = linphone_core_get_config(pauline->lc);
|
||||
char* lf_identity=linphone_address_as_string_uri_only(marie->identity);
|
||||
LinphoneFriend *lf = linphone_core_create_friend_with_address(pauline->lc,lf_identity);
|
||||
ms_free(lf_identity);
|
||||
lp_config_set_int(pauline_lp,"sip","subscribe_expires",5);
|
||||
|
||||
linphone_core_add_friend(pauline->lc,lf);
|
||||
|
||||
/*wait for subscribe acknowledgment*/
|
||||
wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyReceived,1,2000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf), int, "%d");
|
||||
|
||||
scen = bc_tester_res("sipp/double_publish_with_error.xml");
|
||||
|
||||
sipp_out = sip_start(scen, linphone_address_get_username(marie->identity), marie->identity);
|
||||
|
||||
if (sipp_out) {
|
||||
/*wait for marie status*/
|
||||
wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyReceived,2,3000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf), int, "%d");
|
||||
pclose(sipp_out);
|
||||
BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyReceived,2,int, "%d");
|
||||
}
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void test_publish_unpublish(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneProxyConfig* proxy;
|
||||
|
||||
linphone_core_get_default_proxy(marie->lc,&proxy);
|
||||
linphone_proxy_config_edit(proxy);
|
||||
linphone_proxy_config_enable_publish(proxy,TRUE);
|
||||
linphone_proxy_config_done(proxy);
|
||||
wait_core(marie->lc);
|
||||
linphone_proxy_config_edit(proxy);
|
||||
linphone_proxy_config_enable_publish(proxy,FALSE);
|
||||
linphone_proxy_config_done(proxy);
|
||||
wait_core(marie->lc);
|
||||
linphone_core_manager_destroy(marie);
|
||||
}
|
||||
|
||||
static void test_list_subscribe (void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
|
||||
LinphoneCoreManager* laure = linphone_core_manager_new( "laure_rc");
|
||||
|
||||
char *list = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\"\n"
|
||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
|
||||
"<list>\n"
|
||||
"\t<entry uri=\"%s\" />\n"
|
||||
"\t<entry uri=\"%s\" />\n"
|
||||
"</list>\n"
|
||||
"</resource-lists>\n";
|
||||
|
||||
|
||||
LinphoneEvent *lev;
|
||||
MSList* lcs=ms_list_append(NULL,marie->lc);
|
||||
char * pauline_uri=linphone_address_as_string_uri_only(pauline->identity);
|
||||
char * laure_uri=linphone_address_as_string_uri_only(laure->identity);
|
||||
char * subscribe_content = ms_strdup_printf(list,pauline_uri,laure_uri);
|
||||
LinphoneContent* content = linphone_core_create_content(marie->lc);
|
||||
LinphoneAddress *list_name = linphone_address_new("sip:mescops@sip.example.org");
|
||||
LinphoneProxyConfig* proxy_config;
|
||||
int dummy=0;
|
||||
|
||||
ms_free(pauline_uri);
|
||||
ms_free(laure_uri);
|
||||
|
||||
lcs=ms_list_append(lcs,pauline->lc);
|
||||
lcs=ms_list_append(lcs,laure->lc);
|
||||
|
||||
linphone_content_set_type(content,"application");
|
||||
linphone_content_set_subtype(content,"resource-lists+xml");
|
||||
linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content));
|
||||
|
||||
lev=linphone_core_create_subscribe(marie->lc,list_name,"presence",60);
|
||||
|
||||
linphone_event_add_custom_header(lev,"Supported","eventlist");
|
||||
linphone_event_add_custom_header(lev,"Accept","application/pidf+xml, application/rlmi+xml");
|
||||
linphone_event_add_custom_header(lev,"Content-Disposition", "recipient-list");
|
||||
|
||||
linphone_event_send_subscribe(lev,content);
|
||||
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000));
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,5000));
|
||||
|
||||
/*make sure marie receives first notification before terminating*/
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,1,5000));
|
||||
/*dummy wait to avoid derred notify*/
|
||||
wait_for_list(lcs,&dummy,1,2000);
|
||||
linphone_core_get_default_proxy(pauline->lc,&proxy_config);
|
||||
linphone_proxy_config_edit(proxy_config);
|
||||
linphone_proxy_config_enable_publish(proxy_config,TRUE);
|
||||
linphone_proxy_config_done(proxy_config);
|
||||
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,2,5000));
|
||||
|
||||
linphone_core_get_default_proxy(laure->lc,&proxy_config);
|
||||
linphone_proxy_config_edit(proxy_config);
|
||||
linphone_proxy_config_enable_publish(proxy_config,TRUE);
|
||||
linphone_proxy_config_done(proxy_config);
|
||||
/*make sure notify is not sent "imadiatly but defered*/
|
||||
BC_ASSERT_FALSE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,3,1000));
|
||||
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,3,5000));
|
||||
|
||||
linphone_event_terminate(lev);
|
||||
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionTerminated,1,5000));
|
||||
|
||||
ms_free(subscribe_content);
|
||||
linphone_address_destroy(list_name);
|
||||
linphone_content_unref(content);
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
linphone_core_manager_destroy(laure);
|
||||
}
|
||||
|
||||
|
||||
test_t flexisip_tests[] = {
|
||||
{ "Subscribe forking", subscribe_forking },
|
||||
{ "Message forking", message_forking },
|
||||
|
|
@ -901,6 +1066,10 @@ test_t flexisip_tests[] = {
|
|||
{ "Call with sips", call_with_sips },
|
||||
{ "Call with sips not achievable", call_with_sips_not_achievable },
|
||||
{ "Call with ipv6", call_with_ipv6 },
|
||||
{ "Subscribe Notify with sipp publisher", test_subscribe_notify_with_sipp_publisher },
|
||||
{ "Subscribe Notify with sipp double publish", test_subscribe_notify_with_sipp_publisher_double_publish },
|
||||
{ "Publish/unpublish", test_publish_unpublish },
|
||||
{ "List subscribe", test_list_subscribe },
|
||||
{ "File transfer message rcs to external body client", file_transfer_message_rcs_to_external_body_client },
|
||||
{ "File transfer message external body to rcs client", file_transfer_message_external_body_to_rcs_client },
|
||||
{ "File transfer message external body to external body client", file_transfer_message_external_body_to_external_body_client },
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ typedef struct _stats {
|
|||
|
||||
int number_of_NewSubscriptionRequest;
|
||||
int number_of_NotifyReceived;
|
||||
int number_of_NotifyPresenceReceived;
|
||||
int number_of_LinphonePresenceActivityOffline;
|
||||
int number_of_LinphonePresenceActivityOnline;
|
||||
int number_of_LinphonePresenceActivityAppointment;
|
||||
|
|
@ -351,6 +352,10 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph
|
|||
|
||||
extern const char *liblinphone_tester_mire_id;
|
||||
|
||||
FILE *sip_start(const char *senario, const char* dest_username, LinphoneAddress* dest_addres);
|
||||
|
||||
void wait_core(LinphoneCore *core) ;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,10 +46,10 @@ void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf) {
|
|||
stats* counters;
|
||||
LinphonePresenceActivity *activity = NULL;
|
||||
char* from=linphone_address_as_string(linphone_friend_get_address(lf));
|
||||
ms_message("New Notify request from [%s] ",from);
|
||||
ms_message("New Notify request from [%s] ",from);
|
||||
ms_free(from);
|
||||
counters = get_stats(lc);
|
||||
counters->number_of_NotifyReceived++;
|
||||
counters->number_of_NotifyPresenceReceived++;
|
||||
|
||||
counters->last_received_presence = linphone_friend_get_presence_model(lf);
|
||||
activity = linphone_presence_model_get_activity(counters->last_received_presence);
|
||||
|
|
@ -115,7 +115,7 @@ void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf) {
|
|||
}
|
||||
}
|
||||
|
||||
static void wait_core(LinphoneCore *core) {
|
||||
void wait_core(LinphoneCore *core) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
|
|
@ -173,9 +173,9 @@ static bool_t subscribe_to_callee_presence(LinphoneCoreManager* caller_mgr,Linph
|
|||
|
||||
BC_ASSERT_EQUAL(callee_mgr->stat.number_of_NewSubscriptionRequest,initial_callee.number_of_NewSubscriptionRequest+1, int, "%d");
|
||||
/*without proxy, callee cannot subscribe to caller
|
||||
BC_ASSERT_EQUAL(callee_mgr->stat.number_of_NotifyReceived,initial_callee.number_of_NotifyReceived+1, int, "%d");
|
||||
BC_ASSERT_EQUAL(callee_mgr->stat.number_of_NotifyPresenceReceived,initial_callee.number_of_NotifyPresenceReceived+1, int, "%d");
|
||||
*/
|
||||
BC_ASSERT_EQUAL(caller_mgr->stat.number_of_NotifyReceived,initial_caller.number_of_NotifyReceived+1, int, "%d");
|
||||
BC_ASSERT_EQUAL(caller_mgr->stat.number_of_NotifyPresenceReceived,initial_caller.number_of_NotifyPresenceReceived+1, int, "%d");
|
||||
|
||||
ms_free(identity);
|
||||
return result;
|
||||
|
|
@ -448,7 +448,7 @@ static void test_subscribe_notify_publish(void) {
|
|||
linphone_core_add_friend(pauline->lc,lf);
|
||||
|
||||
/*wait for subscribe acknowledgment*/
|
||||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,1,2000);
|
||||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,1,2000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf), int, "%d");
|
||||
|
||||
/*enable publish*/
|
||||
|
|
@ -461,23 +461,23 @@ static void test_subscribe_notify_publish(void) {
|
|||
linphone_proxy_config_done(proxy);
|
||||
|
||||
/*wait for marie status*/
|
||||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,2,2000);
|
||||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,2,2000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf), int, "%d");
|
||||
|
||||
presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL);
|
||||
linphone_core_set_presence_model(marie->lc,presence);
|
||||
|
||||
/*wait for new status*/
|
||||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,3,2000);
|
||||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,3,2000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d");
|
||||
|
||||
/*wait for refresh*/
|
||||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000);
|
||||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,4,5000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d");
|
||||
|
||||
/*linphone_core_remove_friend(pauline->lc,lf);*/
|
||||
/*wait for final notify*/
|
||||
/*wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000);
|
||||
/*wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,4,5000);
|
||||
BC_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf), int, "%d");
|
||||
*/
|
||||
linphone_core_manager_destroy(marie);
|
||||
|
|
@ -507,7 +507,7 @@ static void test_forked_subscribe_notify_publish(void) {
|
|||
linphone_core_add_friend(pauline->lc,lf);
|
||||
|
||||
/*wait for subscribe acknowledgment*/
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,1,2000);
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyPresenceReceived,1,2000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf), int, "%d");
|
||||
|
||||
/*enable publish*/
|
||||
|
|
@ -526,21 +526,21 @@ static void test_forked_subscribe_notify_publish(void) {
|
|||
|
||||
|
||||
/*wait for marie status*/
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,3,2000);
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyPresenceReceived,3,2000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf), int, "%d");
|
||||
|
||||
presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL);
|
||||
linphone_core_set_presence_model(marie->lc,presence);
|
||||
|
||||
/*wait for new status*/
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,4,2000);
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyPresenceReceived,4,2000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d");
|
||||
|
||||
|
||||
presence =linphone_presence_model_new_with_activity( LinphonePresenceActivityMeeting,NULL);
|
||||
linphone_core_set_presence_model(marie2->lc,presence);
|
||||
/*wait for new status*/
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,5,2000);
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyPresenceReceived,5,2000);
|
||||
BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d"); /*because liblinphone compositor is very simple for now (I.E only take first occurence)*/
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
|
|
@ -551,6 +551,190 @@ static void test_forked_subscribe_notify_publish(void) {
|
|||
|
||||
#endif
|
||||
|
||||
const char * get_identity(LinphoneCoreManager *mgr) {
|
||||
LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(mgr->lc);
|
||||
return linphone_proxy_config_get_identity(cfg);
|
||||
}
|
||||
|
||||
static void enable_publish(LinphoneCoreManager *mgr, bool_t enable) {
|
||||
LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(mgr->lc);
|
||||
linphone_proxy_config_edit(cfg);
|
||||
linphone_proxy_config_enable_publish(cfg, enable);
|
||||
linphone_proxy_config_set_publish_expires(cfg, 60);
|
||||
linphone_proxy_config_done(cfg);
|
||||
}
|
||||
|
||||
static void test_presence_list(void) {
|
||||
LinphoneCoreManager *laure = linphone_core_manager_new("laure_tcp_rc");
|
||||
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
|
||||
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc");
|
||||
const char *rls_uri = "sip:rls@sip.example.org";
|
||||
LinphoneFriendList *lfl;
|
||||
LinphoneFriend *lf;
|
||||
const char *laure_identity;
|
||||
const char *marie_identity;
|
||||
const char *pauline_identity;
|
||||
MSList* lcs = NULL;
|
||||
|
||||
laure_identity = get_identity(laure);
|
||||
marie_identity = get_identity(marie);
|
||||
pauline_identity = get_identity(pauline);
|
||||
enable_publish(marie, TRUE);
|
||||
enable_publish(pauline, TRUE);
|
||||
enable_publish(laure, TRUE);
|
||||
|
||||
linphone_core_set_presence_model(marie->lc, linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityBusy, NULL));
|
||||
linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL));
|
||||
|
||||
lfl = linphone_core_create_friend_list(laure->lc);
|
||||
linphone_friend_list_set_rls_uri(lfl, rls_uri);
|
||||
lf = linphone_core_create_friend_with_address(laure->lc, marie_identity);
|
||||
linphone_friend_list_add_friend(lfl, lf);
|
||||
lf = linphone_core_create_friend_with_address(laure->lc, pauline_identity);
|
||||
linphone_friend_list_add_friend(lfl, lf);
|
||||
lf = linphone_core_create_friend_with_address(laure->lc, "sip:michelle@sip.inexistentdomain.com");
|
||||
linphone_friend_list_add_friend(lfl, lf);
|
||||
linphone_core_set_friend_list(laure->lc, lfl);
|
||||
linphone_friend_list_unref(lfl);
|
||||
linphone_core_set_presence_model(laure->lc, linphone_core_create_presence_model_with_activity(laure->lc, LinphonePresenceActivityOnline, NULL));
|
||||
|
||||
lcs = ms_list_append(lcs, laure->lc);
|
||||
lcs = ms_list_append(lcs, marie->lc);
|
||||
lcs = ms_list_append(lcs, pauline->lc);
|
||||
|
||||
wait_for_list(lcs, &laure->stat.number_of_NotifyReceived, 2, 2000);
|
||||
wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 2, 2000);
|
||||
BC_ASSERT_EQUAL(laure->stat.number_of_NotifyReceived, 2, int, "%d");
|
||||
BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d");
|
||||
BC_ASSERT_EQUAL(laure->lc->friendlist->expected_notification_version, 1, int, "%d");
|
||||
lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, marie_identity);
|
||||
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d");
|
||||
lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, pauline_identity);
|
||||
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d");
|
||||
lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, "sip:michelle@sip.inexistentdomain.com");
|
||||
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->presence_received, FALSE, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d");
|
||||
|
||||
lfl = linphone_core_create_friend_list(marie->lc);
|
||||
linphone_friend_list_set_rls_uri(lfl, rls_uri);
|
||||
lf = linphone_core_create_friend_with_address(marie->lc, laure_identity);
|
||||
linphone_friend_list_add_friend(lfl, lf);
|
||||
linphone_core_set_friend_list(marie->lc, lfl);
|
||||
linphone_friend_list_unref(lfl);
|
||||
linphone_friend_list_update_subscriptions(marie->lc->friendlist, NULL, FALSE);
|
||||
|
||||
wait_for_list(lcs, &marie->stat.number_of_NotifyReceived, 1, 2000);
|
||||
wait_for_list(lcs, &marie->stat.number_of_NotifyPresenceReceived, 1, 2000);
|
||||
BC_ASSERT_EQUAL(marie->stat.number_of_NotifyReceived, 1, int, "%d");
|
||||
BC_ASSERT_EQUAL(marie->stat.number_of_NotifyPresenceReceived, 1, int, "%d");
|
||||
BC_ASSERT_EQUAL(marie->lc->friendlist->expected_notification_version, 1, int, "%d");
|
||||
lf = linphone_friend_list_find_friend_by_uri(marie->lc->friendlist, laure_identity);
|
||||
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnline, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d");
|
||||
|
||||
lfl = linphone_core_create_friend_list(pauline->lc);
|
||||
linphone_friend_list_set_rls_uri(lfl, rls_uri);
|
||||
lf = linphone_core_create_friend_with_address(pauline->lc, marie_identity);
|
||||
linphone_friend_list_add_friend(lfl, lf);
|
||||
linphone_core_set_friend_list(pauline->lc, lfl);
|
||||
linphone_friend_list_unref(lfl);
|
||||
linphone_friend_list_update_subscriptions(pauline->lc->friendlist, NULL, FALSE);
|
||||
|
||||
wait_for_list(lcs, &pauline->stat.number_of_NotifyReceived, 1, 2000);
|
||||
wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 1, 2000);
|
||||
BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyReceived, 1, int, "%d");
|
||||
BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyPresenceReceived, 1, int, "%d");
|
||||
BC_ASSERT_EQUAL(pauline->lc->friendlist->expected_notification_version, 1, int, "%d");
|
||||
lf = linphone_friend_list_find_friend_by_uri(pauline->lc->friendlist, marie_identity);
|
||||
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d");
|
||||
|
||||
linphone_core_set_presence_model(marie->lc, linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityOnThePhone, NULL));
|
||||
|
||||
wait_for_list(lcs, &laure->stat.number_of_NotifyReceived, 3, 2000);
|
||||
wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 4, 2000);
|
||||
BC_ASSERT_EQUAL(laure->stat.number_of_NotifyReceived, 3, int, "%d");
|
||||
BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 4, int, "%d");
|
||||
BC_ASSERT_EQUAL(laure->lc->friendlist->expected_notification_version, 2, int, "%d");
|
||||
lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, marie_identity);
|
||||
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d");
|
||||
|
||||
wait_for_list(lcs, &pauline->stat.number_of_NotifyReceived, 2, 2000);
|
||||
wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 2, 2000);
|
||||
BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyReceived, 2, int, "%d");
|
||||
BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyPresenceReceived, 2, int, "%d");
|
||||
BC_ASSERT_EQUAL(pauline->lc->friendlist->expected_notification_version, 2, int, "%d");
|
||||
lf = linphone_friend_list_find_friend_by_uri(pauline->lc->friendlist, marie_identity);
|
||||
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d");
|
||||
|
||||
enable_publish(laure, FALSE);
|
||||
enable_publish(marie, FALSE);
|
||||
enable_publish(pauline, FALSE);
|
||||
|
||||
linphone_core_manager_destroy(laure);
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void test_presence_list_subscribe_before_publish(void) {
|
||||
LinphoneCoreManager *laure = linphone_core_manager_new("laure_tcp_rc");
|
||||
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc");
|
||||
const char *rls_uri = "sip:rls@sip.example.org";
|
||||
LinphoneFriendList *lfl;
|
||||
LinphoneFriend *lf;
|
||||
const char *pauline_identity;
|
||||
MSList* lcs = NULL;
|
||||
int dummy = 0;
|
||||
|
||||
pauline_identity = get_identity(pauline);
|
||||
|
||||
linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL));
|
||||
|
||||
lfl = linphone_core_create_friend_list(laure->lc);
|
||||
linphone_friend_list_set_rls_uri(lfl, rls_uri);
|
||||
lf = linphone_core_create_friend_with_address(laure->lc, pauline_identity);
|
||||
linphone_friend_list_add_friend(lfl, lf);
|
||||
lf = linphone_core_create_friend_with_address(laure->lc, "sip:michelle@sip.inexistentdomain.com");
|
||||
linphone_friend_list_add_friend(lfl, lf);
|
||||
linphone_core_set_friend_list(laure->lc, lfl);
|
||||
linphone_friend_list_unref(lfl);
|
||||
linphone_core_set_presence_model(laure->lc, linphone_core_create_presence_model_with_activity(laure->lc, LinphonePresenceActivityOnline, NULL));
|
||||
linphone_friend_list_update_subscriptions(laure->lc->friendlist, NULL, FALSE);
|
||||
|
||||
lcs = ms_list_append(lcs, laure->lc);
|
||||
lcs = ms_list_append(lcs, pauline->lc);
|
||||
|
||||
wait_for_list(lcs, &dummy, 1, 2000); /* Wait a little bit for the subscribe to happen */
|
||||
|
||||
enable_publish(pauline, TRUE);
|
||||
wait_for_list(lcs, &pauline->stat.number_of_NotifyReceived, 1, 2000);
|
||||
wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 1, 2000);
|
||||
BC_ASSERT_GREATER(laure->stat.number_of_NotifyReceived, 1, int, "%d");
|
||||
BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 1, int, "%d");
|
||||
BC_ASSERT_GREATER(laure->lc->friendlist->expected_notification_version, 1, int, "%d");
|
||||
lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, pauline_identity);
|
||||
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d");
|
||||
lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, "sip:michelle@sip.inexistentdomain.com");
|
||||
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->presence_received, FALSE, int, "%d");
|
||||
BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d");
|
||||
|
||||
enable_publish(laure, FALSE);
|
||||
enable_publish(pauline, FALSE);
|
||||
|
||||
linphone_core_manager_destroy(laure);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
test_t presence_tests[] = {
|
||||
{ "Simple Subscribe", simple_subscribe },
|
||||
{ "Simple Publish", simple_publish },
|
||||
|
|
@ -565,6 +749,8 @@ test_t presence_tests[] = {
|
|||
{ "Subscribe with late publish", test_subscribe_notify_publish },
|
||||
{ "Forked subscribe with late publish", test_forked_subscribe_notify_publish },
|
||||
#endif
|
||||
{ "Presence list", test_presence_list },
|
||||
{ "Presence list (subscribe before publish)", test_presence_list_subscribe_before_publish }
|
||||
};
|
||||
|
||||
test_suite_t presence_test_suite = {"Presence", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
|
||||
|
|
|
|||
46
tester/rcfiles/laure_tcp_rc
Normal file
46
tester/rcfiles/laure_tcp_rc
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
[sip]
|
||||
sip_port=5092
|
||||
sip_tcp_port=5092
|
||||
sip_tls_port=5093
|
||||
default_proxy=0
|
||||
ping_with_options=0
|
||||
register_only_when_network_is_up=0
|
||||
|
||||
[auth_info_0]
|
||||
username=laure
|
||||
userid=laure
|
||||
passwd=secret
|
||||
realm="sip.example.org"
|
||||
|
||||
|
||||
[proxy_0]
|
||||
reg_proxy=sip.example.org;transport=tcp
|
||||
reg_identity=sip:laure@sip.example.org
|
||||
reg_expires=3600
|
||||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
|
||||
|
||||
[rtp]
|
||||
audio_rtp_port=9010-9390
|
||||
video_rtp_port=9410-9910
|
||||
|
||||
[video]
|
||||
display=0
|
||||
capture=0
|
||||
show_local=0
|
||||
size=qcif
|
||||
enabled=0
|
||||
self_view=0
|
||||
automatically_initiate=0
|
||||
automatically_accept=0
|
||||
device=StaticImage: Static picture
|
||||
|
||||
[sound]
|
||||
echocancellation=0 #to not overload cpu in case of VG
|
||||
|
||||
[net]
|
||||
dns_srv_enabled=0 #no srv needed in general
|
||||
stun_server=stun.linphone.org
|
||||
|
||||
|
|
@ -41,6 +41,8 @@ static void core_init_test(void) {
|
|||
|
||||
static void linphone_address_test(void) {
|
||||
linphone_address_destroy(create_linphone_address(NULL));
|
||||
BC_ASSERT_PTR_NULL(linphone_address_new("sip:@sip.linphone.org"));
|
||||
|
||||
}
|
||||
|
||||
static void core_sip_transport_test(void) {
|
||||
|
|
|
|||
111
tester/sipp/double_publish_with_error.xml
Normal file
111
tester/sipp/double_publish_with_error.xml
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||
|
||||
<!-- 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 2 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., -->
|
||||
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||
<!-- -->
|
||||
<!-- Sipp default 'uac' scenario. -->
|
||||
<!-- -->
|
||||
|
||||
<scenario name="Basic Sipstone publish">
|
||||
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||
<send retrans="500">
|
||||
<![CDATA[
|
||||
|
||||
PUBLISH sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||
From: sipp <sip:[service]@sip.example.org>;tag=[pid]SIPpTag00[call_number]
|
||||
To: sipp <sip:[service]@sip.example.org>
|
||||
Call-ID: [call_id]
|
||||
CSeq: 1 PUBLISH
|
||||
Max-Forwards: 70
|
||||
Expire: 60
|
||||
Event: presence
|
||||
Content-Type: application/pidf+xml
|
||||
Content-Length: [len]
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<presence xmlns:dm="urn:ietf:params:xml:ns:pidf:data-model" xmlns:rpid="urn:ietf:params:xml:ns:pidf:rpid" entity="sip:[service]@sip.example.org" xmlns="urn:ietf:params:xml:ns:pidf">
|
||||
<tuple id="jjlson">
|
||||
<status>
|
||||
<basic>open</basic>
|
||||
</status>
|
||||
<contact priority="0.8">sip:[service]@[local_ip]:[local_port]</contact>
|
||||
<timestamp>2015-09-28T15:49:00Z</timestamp>
|
||||
</tuple>
|
||||
</presence>
|
||||
]]>
|
||||
</send>
|
||||
|
||||
<recv response="100"
|
||||
optional="true">
|
||||
</recv>
|
||||
|
||||
|
||||
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
|
||||
<!-- are saved and used for following messages sent. Useful to test -->
|
||||
<!-- against stateful SIP proxies/B2BUAs. -->
|
||||
<recv response="200" rrs="true">
|
||||
</recv>
|
||||
|
||||
<send retrans="500">
|
||||
<![CDATA[
|
||||
|
||||
PUBLISH sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||
From: sipp <sip:[service]@sip.example.org>;tag=[pid]SIPpTag00[call_number]
|
||||
To: sipp <sip:[service]-2@sip.example.org>
|
||||
Call-ID: [call_id]-2
|
||||
CSeq: 1 PUBLISH
|
||||
Max-Forwards: 70
|
||||
Expire: 60
|
||||
Event: presence
|
||||
Content-Type: application/pidf+xml
|
||||
Content-Length: [len]
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<presence xmlns:dm="urn:ietf:params:xml:ns:pidf:data-model" xmlns:rpid="urn:ietf:params:xml:ns:pidf:rpid" entity="sip:[service]@sip.example.org" xmlns="urn:ietf:params:xml:ns:pidf">
|
||||
<tuple id="jjlson">
|
||||
<status>
|
||||
<basic>open</basic>
|
||||
</status>
|
||||
<contact priority="0.8">sip:[service]@[local_ip]:[local_port]</contact>
|
||||
<timestamp>2015-09-28T15:49:00Z</timestamp>
|
||||
</tuple>
|
||||
</presence>
|
||||
]]>
|
||||
</send>
|
||||
|
||||
<recv response="100"
|
||||
optional="true">
|
||||
</recv>
|
||||
|
||||
|
||||
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
|
||||
<!-- are saved and used for following messages sent. Useful to test -->
|
||||
<!-- against stateful SIP proxies/B2BUAs. -->
|
||||
<recv response="200" rrs="true">
|
||||
</recv>
|
||||
|
||||
<!-- definition of the response time repartition table (unit is ms) -->
|
||||
<!-- definition of the response time repartition table (unit is ms) -->
|
||||
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
|
||||
|
||||
<!-- definition of the call length repartition table (unit is ms) -->
|
||||
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
|
||||
|
||||
</scenario>
|
||||
|
||||
71
tester/sipp/simple_publish.xml
Normal file
71
tester/sipp/simple_publish.xml
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||
|
||||
<!-- 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 2 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., -->
|
||||
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||
<!-- -->
|
||||
<!-- Sipp default 'uac' scenario. -->
|
||||
<!-- -->
|
||||
|
||||
<scenario name="Basic Sipstone publish">
|
||||
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||
<send retrans="500">
|
||||
<![CDATA[
|
||||
|
||||
PUBLISH sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||
From: sipp <sip:[service]@sip.example.org>;tag=[pid]SIPpTag00[call_number]
|
||||
To: sipp <sip:[service]@sip.example.org>
|
||||
Call-ID: [call_id]
|
||||
CSeq: 1 PUBLISH
|
||||
Max-Forwards: 70
|
||||
Expire: 60
|
||||
Event: presence
|
||||
Content-Type: application/pidf+xml
|
||||
Content-Length: [len]
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<presence xmlns:dm="urn:ietf:params:xml:ns:pidf:data-model" xmlns:rpid="urn:ietf:params:xml:ns:pidf:rpid" entity="sip:[service]@sip.example.org" xmlns="urn:ietf:params:xml:ns:pidf">
|
||||
<tuple id="jjlson">
|
||||
<status>
|
||||
<basic>open</basic>
|
||||
</status>
|
||||
<contact priority="0.8">sip:[service]@[local_ip]:[local_port]</contact>
|
||||
<timestamp>2015-09-28T15:49:00Z</timestamp>
|
||||
</tuple>
|
||||
</presence>
|
||||
]]>
|
||||
</send>
|
||||
|
||||
<recv response="100"
|
||||
optional="true">
|
||||
</recv>
|
||||
|
||||
|
||||
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
|
||||
<!-- are saved and used for following messages sent. Useful to test -->
|
||||
<!-- against stateful SIP proxies/B2BUAs. -->
|
||||
<recv response="200" rrs="true">
|
||||
</recv>
|
||||
|
||||
<!-- definition of the response time repartition table (unit is ms) -->
|
||||
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
|
||||
|
||||
<!-- definition of the call length repartition table (unit is ms) -->
|
||||
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
|
||||
|
||||
</scenario>
|
||||
|
||||
Loading…
Add table
Reference in a new issue