Revert most of Ronan refactoring to avoid to much instability on master.

This commit is contained in:
Jehan Monnier 2017-09-08 15:10:39 +02:00
parent 252925a373
commit 1948fbcb07
92 changed files with 2180 additions and 4948 deletions

View file

@ -45,7 +45,6 @@ list(APPEND LINPHONE_PRIVATE_HEADER_FILES
offeranswer.h
private.h
quality_reporting.h
sal/sal.h
sqlite3_bctbx_vfs.h
vcard_private.h
xml2lpc.h
@ -54,6 +53,7 @@ list(APPEND LINPHONE_PRIVATE_HEADER_FILES
set(LINPHONE_SOURCE_FILES_C
account_creator.c
account_creator_service.c
address.c
authentication.c
bellesip_sal/sal_address_impl.c
bellesip_sal/sal_impl.c
@ -109,7 +109,7 @@ set(LINPHONE_SOURCE_FILES_C
quality_reporting.c
remote_provisioning.c
ringtoneplayer.c
sal/sal.c
sal.c
siplogin.c
sipsetup.c
sqlite3_bctbx_vfs.c

221
coreapi/address.c Normal file
View file

@ -0,0 +1,221 @@
/*
linphone
Copyright (C) 2009 Simon MORLAT (simon.morlat@linphone.org)
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "linphone/core.h"
#include "linphone/lpconfig.h"
#include "private.h"
LinphoneAddress * _linphone_address_new(const char *addr){
SalAddress *saddr=sal_address_new(addr);
if (saddr==NULL)
ms_error("Cannot create LinphoneAddress, bad uri [%s]",addr);
return saddr;
}
LinphoneAddress * linphone_address_new(const char *addr) {
return _linphone_address_new(addr);
}
LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr){
return sal_address_clone(addr);
}
LinphoneAddress * linphone_address_ref(LinphoneAddress *addr){
return sal_address_ref(addr);
}
void linphone_address_unref(LinphoneAddress *addr){
sal_address_unref(addr);
}
const char *linphone_address_get_scheme(const LinphoneAddress *u){
return sal_address_get_scheme(u);
}
const char *linphone_address_get_display_name(const LinphoneAddress* u){
return sal_address_get_display_name(u);
}
const char *linphone_address_get_username(const LinphoneAddress *u){
return sal_address_get_username(u);
}
const char *linphone_address_get_domain(const LinphoneAddress *u){
return sal_address_get_domain(u);
}
int linphone_address_get_port(const LinphoneAddress *u) {
return sal_address_get_port(u);
}
LinphoneStatus linphone_address_set_display_name(LinphoneAddress *u, const char *display_name){
sal_address_set_display_name(u,display_name);
return 0;
}
LinphoneStatus linphone_address_set_username(LinphoneAddress *uri, const char *username) {
sal_address_set_username(uri,username);
return 0;
}
LinphoneStatus linphone_address_set_domain(LinphoneAddress *uri, const char *host){
sal_address_set_domain(uri,host);
return 0;
}
LinphoneStatus linphone_address_set_port(LinphoneAddress *uri, int port){
sal_address_set_port(uri,port);
return 0;
}
LinphoneStatus linphone_address_set_transport(LinphoneAddress *uri, LinphoneTransportType tp){
sal_address_set_transport(uri,(SalTransport)tp);
return 0;
}
LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri){
return (LinphoneTransportType)sal_address_get_transport(uri);
}
void linphone_address_set_method_param(LinphoneAddress *addr, const char *method) {
sal_address_set_method_param(addr, method);
}
const char *linphone_address_get_method_param(const LinphoneAddress *addr) {
return sal_address_get_method_param(addr);
}
void linphone_address_clean(LinphoneAddress *uri){
sal_address_clean(uri);
}
char *linphone_address_as_string(const LinphoneAddress *u){
return sal_address_as_string(u);
}
char *linphone_address_as_string_uri_only(const LinphoneAddress *u){
return sal_address_as_string_uri_only(u);
}
bool_t linphone_address_is_secure(const LinphoneAddress *uri){
return sal_address_is_secure(uri);
}
bool_t linphone_address_get_secure(const LinphoneAddress *uri){
return sal_address_is_secure(uri);
}
void linphone_address_set_secure(LinphoneAddress *addr, bool_t enabled){
sal_address_set_secure(addr, enabled);
}
bool_t linphone_address_is_sip(const LinphoneAddress *uri){
return sal_address_is_sip(uri);
}
static bool_t strings_equals(const char *s1, const char *s2){
if (s1==NULL && s2==NULL) return TRUE;
if (s1!=NULL && s2!=NULL && strcmp(s1,s2)==0) return TRUE;
return FALSE;
}
bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2){
const char *u1,*u2;
const char *h1,*h2;
int p1,p2;
u1=linphone_address_get_username(a1);
u2=linphone_address_get_username(a2);
p1=linphone_address_get_port(a1);
p2=linphone_address_get_port(a2);
h1=linphone_address_get_domain(a1);
h2=linphone_address_get_domain(a2);
return strings_equals(u1,u2) && strings_equals(h1,h2) && p1==p2;
}
bool_t linphone_address_equal(const LinphoneAddress *a1, const LinphoneAddress *a2) {
char *s1;
char *s2;
bool_t res;
if ((a1 == NULL) && (a2 == NULL)) return TRUE;
if ((a1 == NULL) || (a2 == NULL)) return FALSE;
s1 = linphone_address_as_string(a1);
s2 = linphone_address_as_string(a2);
res = (strcmp(s1, s2) == 0) ? TRUE : FALSE;
ms_free(s1);
ms_free(s2);
return res;
}
void linphone_address_destroy(LinphoneAddress *u){
linphone_address_unref(u);
}
void linphone_address_set_password(LinphoneAddress *addr, const char *passwd){
sal_address_set_password(addr,passwd);
}
const char *linphone_address_get_password(const LinphoneAddress *addr){
return sal_address_get_password(addr);
}
void linphone_address_set_header(LinphoneAddress *addr, const char *header_name, const char *header_value){
sal_address_set_header(addr,header_name,header_value);
}
const char *linphone_address_get_header(const LinphoneAddress *addr, const char *name){
return sal_address_get_header(addr,name);
}
bool_t linphone_address_has_param(const LinphoneAddress *addr, const char *name) {
return sal_address_has_param(addr, name);
}
const char * linphone_address_get_param(const LinphoneAddress *addr, const char *name) {
return sal_address_get_param(addr, name);
}
void linphone_address_set_param(LinphoneAddress *addr, const char *name, const char *value) {
sal_address_set_param(addr, name, value);
}
void linphone_address_set_params(LinphoneAddress *addr, const char *params) {
sal_address_set_params(addr, params);
}
void linphone_address_set_uri_param(LinphoneAddress *addr, const char *name, const char *value) {
sal_address_set_uri_param(addr, name, value);
}
void linphone_address_set_uri_params(LinphoneAddress *addr, const char *params) {
sal_address_set_uri_params(addr, params);
}
bool_t linphone_address_has_uri_param(const LinphoneAddress *addr, const char *name) {
return sal_address_has_uri_param(addr, name);
}
const char * linphone_address_get_uri_param(const LinphoneAddress *addr, const char *name) {
return sal_address_get_uri_param(addr, name);
}
LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address) {
return linphone_address_new(address);
}
/** @} */

View file

@ -33,7 +33,7 @@ SalAddress * sal_address_new(const char *uri){
}
SalAddress * sal_address_clone(const SalAddress *addr){
return (SalAddress *) belle_sip_object_ref(belle_sip_header_address_clone(BELLE_SIP_HEADER_ADDRESS(addr)));
return (SalAddress *) belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(addr)));
}
const char *sal_address_get_scheme(const SalAddress *addr){
@ -277,3 +277,4 @@ bool_t sal_address_is_ipv6(const SalAddress *addr){
void sal_address_destroy(SalAddress *addr){
sal_address_unref(addr);
}

View file

@ -1141,9 +1141,6 @@ int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){
* The state is passed to Terminating to remember to terminate later.
*/
op->state=SalOpStateTerminating;
/* However, even if the transaction is kept alive, we can stop sending retransmissions to avoid flowing the network with no longer
* necessary messages and avoid confusion in logs.*/
belle_sip_client_transaction_stop_retransmissions(op->pending_client_trans);
}
}
break;

View file

@ -84,7 +84,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher
}
}
int sal_register(SalOp *op, const char *proxy, const char *from, int expires, const SalAddress* old_contact){
int sal_register(SalOp *op, const char *proxy, const char *from, int expires,SalAddress* old_contact){
belle_sip_request_t *req;
belle_sip_uri_t* req_uri;
belle_sip_header_t* accept_header;
@ -135,3 +135,5 @@ int sal_register_refresh(SalOp *op, int expires){
int sal_unregister(SalOp *op){
return sal_register_refresh(op,0);
}

View file

@ -238,12 +238,6 @@ char * linphone_call_log_to_str(LinphoneCallLog *cl){
case LinphoneCallMissed:
status=_("missed");
break;
case LinphoneCallAcceptedElsewhere:
status=_("answered elsewhere");
break;
case LinphoneCallDeclinedElsewhere:
status=_("declined elsewhere");
break;
default:
status=_("unknown");
}

View file

@ -950,20 +950,19 @@ static void call_failure(SalOp *op){
case SalReasonRedirect:
{
linphone_call_stop_media_streams(call);
if (
call->state == LinphoneCallOutgoingInit ||
call->state == LinphoneCallOutgoingProgress ||
call->state == LinphoneCallOutgoingRinging ||
call->state == LinphoneCallOutgoingEarlyMedia
) {
const SalAddress* redirection_to = sal_op_get_remote_contact_address(call->op);
if (redirection_to) {
char *url = sal_address_as_string(redirection_to);
if ( call->state==LinphoneCallOutgoingInit
|| call->state==LinphoneCallOutgoingProgress
|| call->state==LinphoneCallOutgoingRinging /*push case*/
|| call->state==LinphoneCallOutgoingEarlyMedia){
LinphoneAddress* redirection_to = (LinphoneAddress*)sal_op_get_remote_contact_address(call->op);
if( redirection_to ){
char* url = linphone_address_as_string(redirection_to);
ms_warning("Redirecting call [%p] to %s",call, url);
if (call->log->to)
linphone_address_unref(call->log->to);
call->log->to = linphone_address_new(url);
ms_free(url);
if( call->log->to != NULL ) {
linphone_address_unref(call->log->to);
}
call->log->to = linphone_address_ref(redirection_to);
linphone_call_restart_invite(call);
return;
}

File diff suppressed because it is too large Load diff

View file

@ -26,12 +26,8 @@
#include "private.h"
#include "ortp/b64.h"
#include "chat/chat-room.h"
extern LinphonePrivate::ChatRoom& linphone_chat_room_get_cpp_obj(LinphoneChatRoom *cr);
static bool_t file_transfer_in_progress_and_valid(LinphoneChatMessage* msg) {
return (msg->chat_room && linphone_chat_room_get_core(msg->chat_room) && msg->http_request && !belle_http_request_is_cancelled(msg->http_request));
return (msg->chat_room && msg->chat_room->lc && msg->http_request && !belle_http_request_is_cancelled(msg->http_request));
}
static void _release_http_request(LinphoneChatMessage* msg) {
@ -92,7 +88,7 @@ static void linphone_chat_message_file_transfer_on_progress(belle_sip_body_handl
msg, msg->file_transfer_information, offset, total);
} else {
/* Legacy: call back given by application level */
linphone_core_notify_file_transfer_progress_indication(linphone_chat_room_get_core(msg->chat_room), msg, msg->file_transfer_information,
linphone_core_notify_file_transfer_progress_indication(msg->chat_room->lc, msg, msg->file_transfer_information,
offset, total);
}
}
@ -112,7 +108,7 @@ static int on_send_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *
return BELLE_SIP_STOP;
}
lc = linphone_chat_room_get_core(msg->chat_room);
lc = msg->chat_room->lc;
/* if we've not reach the end of file yet, ask for more data */
/* in case of file body handler, won't be called */
if (msg->file_transfer_filepath == NULL && offset < linphone_content_get_size(msg->file_transfer_information)) {
@ -157,7 +153,7 @@ static int on_send_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *
static void on_send_end(belle_sip_user_body_handler_t *bh, void *data) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
LinphoneCore *lc = linphone_chat_room_get_core(msg->chat_room);
LinphoneCore *lc = msg->chat_room->lc;
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc);
if (imee) {
@ -189,7 +185,8 @@ static void file_upload_begin_background_task(LinphoneChatMessage *obj){
}
}
static void linphone_chat_message_process_response_from_post_file(void *data, const belle_http_response_event_t *event) {
static void linphone_chat_message_process_response_from_post_file(void *data,
const belle_http_response_event_t *event) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
if (msg->http_request && !file_transfer_in_progress_and_valid(msg)) {
@ -208,7 +205,7 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
belle_sip_body_handler_t *first_part_bh;
bool_t is_file_encryption_enabled = FALSE;
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(linphone_chat_room_get_core(msg->chat_room));
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(msg->chat_room->lc);
if (imee) {
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer_cb =
@ -342,7 +339,7 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
linphone_chat_message_ref(msg);
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferDone);
_release_http_request(msg);
linphone_chat_room_get_cpp_obj(msg->chat_room).sendMessage(msg);
_linphone_chat_room_send_message(msg->chat_room, msg);
file_upload_end_background_task(msg);
linphone_chat_message_unref(msg);
} else {
@ -377,7 +374,7 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t
linphone_chat_message_cancel_file_transfer(msg);
return;
}
lc = linphone_chat_room_get_core(msg->chat_room);
lc = msg->chat_room->lc;
if (lc == NULL){
return; /*might happen during linphone_core_destroy()*/
@ -428,7 +425,7 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t
static void on_recv_end(belle_sip_user_body_handler_t *bh, void *data) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
LinphoneCore *lc = linphone_chat_room_get_core(msg->chat_room);
LinphoneCore *lc = msg->chat_room->lc;
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc);
int retval = -1;
@ -539,7 +536,7 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
int _linphone_chat_room_start_http_transfer(LinphoneChatMessage *msg, const char* url, const char* action, const belle_http_request_listener_callbacks_t *cbs) {
belle_generic_uri_t *uri = NULL;
const char* ua = linphone_core_get_user_agent(linphone_chat_room_get_core(msg->chat_room));
const char* ua = linphone_core_get_user_agent(msg->chat_room->lc);
if (url == NULL) {
ms_warning("Cannot process file transfer msg: no file remote URI configured.");
@ -562,7 +559,7 @@ int _linphone_chat_room_start_http_transfer(LinphoneChatMessage *msg, const char
/* give msg to listener to be able to start the actual file upload when server answer a 204 No content */
msg->http_listener = belle_http_request_listener_create_from_callbacks(cbs, linphone_chat_message_ref(msg));
belle_http_provider_send_request(linphone_chat_room_get_core(msg->chat_room)->http_provider, msg->http_request, msg->http_listener);
belle_http_provider_send_request(msg->chat_room->lc->http_provider, msg->http_request, msg->http_listener);
return 0;
error:
if (uri) {
@ -583,7 +580,7 @@ int linphone_chat_room_upload_file(LinphoneChatMessage *msg) {
cbs.process_response = linphone_chat_message_process_response_from_post_file;
cbs.process_io_error = linphone_chat_message_process_io_error_upload;
cbs.process_auth_requested = linphone_chat_message_process_auth_requested_upload;
err = _linphone_chat_room_start_http_transfer(msg, linphone_core_get_file_transfer_server(linphone_chat_room_get_core(msg->chat_room)), "POST", &cbs);
err = _linphone_chat_room_start_http_transfer(msg, linphone_core_get_file_transfer_server(msg->chat_room->lc), "POST", &cbs);
if (err == -1){
linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered);
}
@ -624,10 +621,10 @@ void _linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg, bool_
if (!belle_http_request_is_cancelled(msg->http_request)) {
if (msg->chat_room) {
ms_message("Canceling file transfer %s - msg [%p] chat room[%p]"
, (msg->external_body_url == NULL) ? linphone_core_get_file_transfer_server(linphone_chat_room_get_core(msg->chat_room)) : msg->external_body_url
, (msg->external_body_url == NULL) ? linphone_core_get_file_transfer_server(msg->chat_room->lc) : msg->external_body_url
, msg
, msg->chat_room);
belle_http_provider_cancel_request(linphone_chat_room_get_core(msg->chat_room)->http_provider, msg->http_request);
belle_http_provider_cancel_request(msg->chat_room->lc->http_provider, msg->http_request);
if ((msg->dir == LinphoneChatMessageOutgoing) && unref) {
// must release it
linphone_chat_message_unref(msg);
@ -657,6 +654,20 @@ const char *linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage
return msg->file_transfer_filepath;
}
LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent *initial_content) {
return linphone_chat_room_get_cpp_obj(cr).createFileTransferMessage(initial_content);
LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr,
const LinphoneContent *initial_content) {
LinphoneChatMessage *msg = belle_sip_object_new(LinphoneChatMessage);
msg->callbacks = linphone_chat_message_cbs_new();
msg->chat_room = (LinphoneChatRoom *)cr;
msg->message = NULL;
msg->file_transfer_information = linphone_content_copy(initial_content);
msg->dir = LinphoneChatMessageOutgoing;
linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr));
msg->from = linphone_address_new(linphone_core_get_identity(cr->lc)); /*direct assignment*/
/* this will be set to application/vnd.gsma.rcs-ft-http+xml when we will transfer the xml reply from server to the peers */
msg->content_type = NULL;
/* this will store the http request during file upload to the server */
msg->http_request = NULL;
msg->time = ms_time(0);
return msg;
}

View file

@ -128,14 +128,10 @@ void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState stat
void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state){
if (lev->publish_state!=state){
ms_message("LinphoneEvent [%p] moving from [%s] to publish state %s"
, lev
, linphone_publish_state_to_string(lev->publish_state)
, linphone_publish_state_to_string(state));
ms_message("LinphoneEvent [%p] moving to publish state %s",lev,linphone_publish_state_to_string(state));
lev->publish_state=state;
linphone_core_notify_publish_state_changed(lev->lc,lev,state);
switch(state){
case LinphonePublishNone: /*this state is probably trigered by a network state change to DOWN, we should release the op*/
case LinphonePublishCleared:
linphone_event_release(lev);
break;
@ -145,6 +141,7 @@ void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState s
case LinphonePublishError:
linphone_event_release(lev);
break;
case LinphonePublishNone:
case LinphonePublishProgress:
case LinphonePublishExpiring:
/*nothing special to do*/
@ -278,7 +275,7 @@ LinphoneStatus linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *
static LinphoneEvent *_linphone_core_create_publish(LinphoneCore *core, LinphoneProxyConfig *cfg, const LinphoneAddress *resource, const char *event, int expires){
LinphoneCore *lc = core;
LinphoneEvent *lev;
if (!lc && cfg) {
if (cfg->lc)
lc = cfg->lc;
@ -289,7 +286,7 @@ static LinphoneEvent *_linphone_core_create_publish(LinphoneCore *core, Linphone
}
if (!resource && cfg)
resource = linphone_proxy_config_get_identity_address(cfg);
lev = linphone_event_new(lc,LinphoneSubscriptionInvalidDir, event,expires);
linphone_configure_op_with_proxy(lc,lev->op,resource,NULL,lp_config_get_int(lc->config,"sip","publish_msg_with_contact",0),cfg);
sal_op_set_manual_refresher_mode(lev->op,!lp_config_get_int(lc->config,"sip","refresh_generic_publish",1));
@ -299,10 +296,10 @@ LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddr
return _linphone_core_create_publish(lc, NULL, resource, event, expires);
}
LinphoneEvent *linphone_proxy_config_create_publish(LinphoneProxyConfig *cfg, const char *event, int expires) {
return _linphone_core_create_publish(NULL, cfg,NULL, event, expires);
}
LinphoneEvent *linphone_core_create_one_shot_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event){
LinphoneEvent *lev = linphone_core_create_publish(lc, resource, event, -1);
@ -423,9 +420,6 @@ static void linphone_event_destroy(LinphoneEvent *lev){
if (lev->ei) linphone_error_info_unref(lev->ei);
if (lev->op) sal_op_release(lev->op);
if (lev->send_custom_headers) sal_custom_header_free(lev->send_custom_headers);
if (lev->to_address) linphone_address_unref(lev->to_address);
if (lev->from_address) linphone_address_unref(lev->from_address);
ms_free(lev->name);
}
@ -445,34 +439,20 @@ const char *linphone_event_get_name(const LinphoneEvent *lev){
return lev->name;
}
static const LinphoneAddress *_linphone_event_cache_to (const LinphoneEvent *lev) {
if (lev->to_address)
linphone_address_unref(lev->to_address);
char *buf = sal_address_as_string(sal_op_get_to_address(lev->op));
((LinphoneEvent *)lev)->to_address = linphone_address_new(buf);
ms_free(buf);
return lev->to_address;
}
static const LinphoneAddress *_linphone_event_cache_from (const LinphoneEvent *lev) {
if (lev->from_address)
linphone_address_unref(lev->from_address);
char *buf = sal_address_as_string(sal_op_get_from_address(lev->op));
((LinphoneEvent *)lev)->from_address = linphone_address_new(buf);
ms_free(buf);
return lev->from_address;
}
const LinphoneAddress *linphone_event_get_from (const LinphoneEvent *lev) {
if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing)
return _linphone_event_cache_to(lev);
return _linphone_event_cache_from(lev);
const LinphoneAddress *linphone_event_get_from(const LinphoneEvent *lev){
if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing){
return (LinphoneAddress*)sal_op_get_to_address(lev->op);
}else{
return (LinphoneAddress*)sal_op_get_from_address(lev->op);
}
}
const LinphoneAddress *linphone_event_get_resource(const LinphoneEvent *lev){
if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing)
return _linphone_event_cache_from(lev);
return _linphone_event_cache_to(lev);
if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing){
return (LinphoneAddress*)sal_op_get_from_address(lev->op);
}else{
return (LinphoneAddress*)sal_op_get_to_address(lev->op);
}
}
LinphoneCore *linphone_event_get_core(const LinphoneEvent *lev){
@ -497,3 +477,4 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneEvent, belle_sip_object_t,
_linphone_event_marshall,
FALSE
);

View file

@ -48,7 +48,7 @@ struct _LinphoneFactory {
char *ring_resources_dir;
char *image_resources_dir;
char *msplugins_dir;
/*these are the cached result computed from directories set by the application*/
char *cached_data_resources_dir;
char *cached_sound_resources_dir;
@ -67,7 +67,7 @@ static void linphone_factory_uninit(LinphoneFactory *obj){
STRING_RESET(obj->ring_resources_dir);
STRING_RESET(obj->image_resources_dir);
STRING_RESET(obj->msplugins_dir);
STRING_RESET(obj->cached_data_resources_dir);
STRING_RESET(obj->cached_sound_resources_dir);
STRING_RESET(obj->cached_ring_resources_dir);
@ -94,7 +94,7 @@ static void _linphone_factory_destroying_cb(void) {
#define ADD_SUPPORTED_VIDEO_DEFINITION(factory, width, height, name) \
(factory)->supported_video_definitions = bctbx_list_append((factory)->supported_video_definitions, \
linphone_video_definition_new(width, height, name))
linphone_video_definition_ref(linphone_video_definition_new(width, height, name)))
static void initialize_supported_video_definitions(LinphoneFactory *factory) {
#if !defined(__ANDROID__) && !TARGET_OS_IPHONE
@ -163,7 +163,7 @@ LinphoneCoreCbs *linphone_factory_create_core_cbs(const LinphoneFactory *factory
}
LinphoneAddress *linphone_factory_create_address(const LinphoneFactory *factory, const char *addr) {
return linphone_address_new(addr);
return _linphone_address_new(addr);
}
LinphoneAuthInfo *linphone_factory_create_auth_info(const LinphoneFactory *factory, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain) {
@ -179,8 +179,7 @@ LinphoneVcard *linphone_factory_create_vcard(LinphoneFactory *factory) {
}
LinphoneVideoDefinition * linphone_factory_create_video_definition(const LinphoneFactory *factory, unsigned int width, unsigned int height) {
LinphoneVideoDefinition *supported = linphone_factory_find_supported_video_definition(factory, width, height);
return supported ? linphone_video_definition_clone(supported) : linphone_video_definition_new(width, height, NULL);
return linphone_video_definition_ref(linphone_video_definition_new(width, height, NULL));
}
LinphoneVideoDefinition * linphone_factory_create_video_definition_from_name(const LinphoneFactory *factory, const char *name) {
@ -202,17 +201,16 @@ LinphoneVideoDefinition * linphone_factory_find_supported_video_definition(const
const bctbx_list_t *item;
const bctbx_list_t *supported = linphone_factory_get_supported_video_definitions(factory);
LinphoneVideoDefinition *searched_vdef = linphone_video_definition_new(width, height, NULL);
LinphoneVideoDefinition *found = NULL;
for (item = supported; item != NULL; item = bctbx_list_next(item)) {
LinphoneVideoDefinition *svdef = (LinphoneVideoDefinition *)bctbx_list_get_data(item);
if (linphone_video_definition_equals(svdef, searched_vdef)) {
found = svdef;
break;
linphone_video_definition_unref(searched_vdef);
return linphone_video_definition_clone(svdef);
}
}
linphone_video_definition_unref(searched_vdef);
return found;
return searched_vdef;
}
LinphoneVideoDefinition * linphone_factory_find_supported_video_definition_by_name(const LinphoneFactory *factory, const char *name) {
@ -222,7 +220,7 @@ LinphoneVideoDefinition * linphone_factory_find_supported_video_definition_by_na
for (item = supported; item != NULL; item = bctbx_list_next(item)) {
LinphoneVideoDefinition *svdef = (LinphoneVideoDefinition *)bctbx_list_get_data(item);
if (strcmp(linphone_video_definition_get_name(svdef), name) == 0) {
return svdef;
return linphone_video_definition_clone(svdef);
}
}
return NULL;
@ -303,9 +301,9 @@ void linphone_factory_set_msplugins_dir(LinphoneFactory *factory, const char *pa
}
LinphoneErrorInfo *linphone_factory_create_error_info(LinphoneFactory *factory){
return linphone_error_info_new();
}
LinphoneRange *linphone_factory_create_range(LinphoneFactory *factory) {
@ -318,4 +316,4 @@ LinphoneTransports *linphone_factory_create_transports(LinphoneFactory *factory)
LinphoneVideoActivationPolicy *linphone_factory_create_video_activation_policy(LinphoneFactory *factory) {
return linphone_video_activation_policy_new();
}
}

View file

@ -1,8 +1,8 @@
################################################################################
############################################################################
# CMakeLists.txt
# Copyright (C) 2017 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
@ -18,36 +18,32 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
################################################################################
############################################################################
if (ENABLE_DOC OR ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER)
find_package(Doxygen)
if (DOXYGEN_FOUND)
if (DOXYGEN_DOT_FOUND)
set(DOC_INPUT_FILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
${CMAKE_CURRENT_SOURCE_DIR}/doxygen.dox
${LINPHONE_HEADER_FILES}
)
set(DOXYGEN_INPUT "")
foreach (HEADER_FILE ${LINPHONE_HEADER_FILES})
string(CONCAT DOXYGEN_INPUT ${DOXYGEN_INPUT} " \"${HEADER_FILE}\"")
endforeach ()
string(CONCAT DOXYGEN_INPUT ${DOXYGEN_INPUT} " \"${CMAKE_CURRENT_SOURCE_DIR}\"")
string(CONCAT DOXYGEN_INPUT ${DOXYGEN_INPUT} " \"${PROJECT_SOURCE_DIR}/coreapi/help/examples/C\"")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${CMAKE_CURRENT_BINARY_DIR}/xml/index.xml"
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
DEPENDS ${DOC_INPUT_FILES}
)
add_custom_target(linphone-doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${CMAKE_CURRENT_BINARY_DIR}/xml/index.xml")
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" "${CMAKE_CURRENT_BINARY_DIR}/xml"
DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/linphone-${LINPHONE_VERSION}")
else ()
if (ENABLE_CXX_WRAPPER)
message(FATAL_ERROR "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.")
else ()
message(WARNING "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.")
endif ()
endif ()
endif ()
endif ()
find_package(Doxygen)
if(DOXYGEN_FOUND)
if(DOXYGEN_DOT_FOUND)
set(top_srcdir "${PROJECT_SOURCE_DIR}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
set(DOC_INPUT_FILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
${CMAKE_CURRENT_SOURCE_DIR}/doxygen.dox
${LINPHONE_HEADER_FILES}
)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${CMAKE_CURRENT_BINARY_DIR}/xml/index.xml"
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
DEPENDS ${DOC_INPUT_FILES}
)
add_custom_target(linphone-doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${CMAKE_CURRENT_BINARY_DIR}/xml/index.xml")
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" "${CMAKE_CURRENT_BINARY_DIR}/xml"
DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/linphone-${LINPHONE_VERSION}")
else()
if (ENABLE_CXX_WRAPPER)
message(FATAL_ERROR "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.")
else()
message(WARNING "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.")
endif()
endif()
endif()
endif()

View file

@ -772,7 +772,9 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = @DOXYGEN_INPUT@
INPUT = @top_srcdir@/include/linphone \
@top_srcdir@/coreapi/help/doc/doxygen \
@top_srcdir@/coreapi/help/examples/C
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses

View file

@ -749,11 +749,11 @@ error:
bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr) {
if (cr) {
switch (linphone_core_lime_enabled(linphone_chat_room_get_core(cr))) {
switch (linphone_core_lime_enabled(cr->lc)) {
case LinphoneLimeDisabled: return FALSE;
case LinphoneLimeMandatory:
case LinphoneLimePreferred: {
void *zrtp_cache_db = linphone_core_get_zrtp_cache_db(linphone_chat_room_get_core(cr));
void *zrtp_cache_db = linphone_core_get_zrtp_cache_db(cr->lc);
if (zrtp_cache_db != NULL) {
bool_t res;
limeURIKeys_t associatedKeys;
@ -832,7 +832,7 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn
LinphoneCore *lc = linphone_im_encryption_engine_get_core(engine);
int errcode = -1;
const char *new_content_type = "xml/cipher";
if(linphone_core_lime_enabled(linphone_chat_room_get_core(room))) {
if(linphone_core_lime_enabled(room->lc)) {
if (linphone_chat_room_lime_available(room)) {
void *zrtp_cache_db = NULL; /* use a void * instead of sqlite3 * to avoid problems and ifdef when SQLITE is not available(the get function shall return NULL in that case) */
if (msg->content_type) {
@ -862,7 +862,7 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn
retval = lime_createMultipartMessage(zrtp_cache_db, msg->content_type, (uint8_t *)msg->message, selfUri, peerUri, &crypted_body);
if (retval != 0) { /* fail to encrypt */
ms_warning("Unable to encrypt message for %s : %s", peerUri, lime_error_code_to_string(retval));
ms_warning("Unable to encrypt message for %s : %s", room->peer, lime_error_code_to_string(retval));
if (crypted_body) ms_free(crypted_body);
errcode = 488;
} else { /* encryption ok, swap plain text message body by encrypted one */

View file

@ -43,9 +43,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <bctoolbox/defs.h>
// For migration purpose.
#include "address/address-p.h"
#include "c-wrapper/c-tools.h"
inline OrtpRtcpXrStatSummaryFlag operator|(OrtpRtcpXrStatSummaryFlag a, OrtpRtcpXrStatSummaryFlag b) {
return static_cast<OrtpRtcpXrStatSummaryFlag>(static_cast<int>(a) | static_cast<int>(b));
@ -1202,7 +1199,7 @@ void linphone_call_create_op(LinphoneCall *call){
**/
static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, LinphoneAddress *to, LinphoneProxyConfig *cfg){
if (linphone_core_ipv6_enabled(call->core)){
if (sal_address_is_ipv6(L_GET_PRIVATE_FROM_C_STRUCT(to, Address)->getInternalAddress())) {
if (sal_address_is_ipv6((SalAddress*)to)){
call->af=AF_INET6;
}else if (cfg && cfg->op){
call->af=sal_op_get_address_family(cfg->op);
@ -1365,8 +1362,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
linphone_call_check_ice_session(call, IR_Controlling, FALSE);
if (linphone_nat_policy_stun_enabled(call->nat_policy) && !(linphone_nat_policy_ice_enabled(call->nat_policy)
|| linphone_nat_policy_turn_enabled(call->nat_policy))) {
if (linphone_nat_policy_ice_enabled(call->nat_policy)) {
call->ping_time=linphone_core_run_stun_tests(call->core,call);
}
#ifdef BUILD_UPNP
@ -1723,7 +1719,7 @@ static void linphone_call_set_terminated(LinphoneCall *call){
call->ringing_beep=FALSE;
}
if (call->chat_room){
linphone_chat_room_set_call(call->chat_room, NULL);
call->chat_room->call = NULL;
}
if (lc->calls == NULL){
ms_bandwidth_controller_reset_state(lc->bw_controller);
@ -1868,32 +1864,6 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
call->log->status=LinphoneCallMissed;
}
break;
case LinphoneReasonNone:
if (call->log->dir == LinphoneCallIncoming){
const LinphoneErrorInfo *ei = linphone_call_get_error_info(call);
if (ei) {
int code = linphone_error_info_get_protocol_code(ei);
if((code >= 200 && code < 300)) {
// error between 200-299 means accepted elsewhere
call->log->status=LinphoneCallAcceptedElsewhere;
break;
}
}
}
break;
case LinphoneReasonDoNotDisturb:
if (call->log->dir == LinphoneCallIncoming){
const LinphoneErrorInfo *ei = linphone_call_get_error_info(call);
if (ei) {
int code = linphone_error_info_get_protocol_code(ei);
if(code >= 600 && code < 700) {
// error between 600-699 means declined elsewhere
call->log->status=LinphoneCallDeclinedElsewhere;
break;
}
}
}
break;
default:
break;
}
@ -2070,10 +2040,10 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
if (vstream != NULL) {
call->current_params->sent_vsize = video_stream_get_sent_video_size(vstream);
call->current_params->recv_vsize = video_stream_get_received_video_size(vstream);
call->current_params->sent_vdef = linphone_factory_create_video_definition(
linphone_factory_get(), call->current_params->sent_vsize.width, call->current_params->sent_vsize.height);
call->current_params->recv_vdef = linphone_factory_create_video_definition(
linphone_factory_get(), call->current_params->recv_vsize.width, call->current_params->recv_vsize.height);
call->current_params->sent_vdef = linphone_video_definition_ref(linphone_factory_find_supported_video_definition(
linphone_factory_get(), call->current_params->sent_vsize.width, call->current_params->sent_vsize.height));
call->current_params->recv_vdef = linphone_video_definition_ref(linphone_factory_find_supported_video_definition(
linphone_factory_get(), call->current_params->recv_vsize.width, call->current_params->recv_vsize.height));
call->current_params->sent_fps = video_stream_get_sent_framerate(vstream);
call->current_params->received_fps = video_stream_get_received_framerate(vstream);
}
@ -4989,19 +4959,14 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call ,
/* if already choosed, don't change it */
return NULL;
} else if (call->ping_op && sal_op_get_contact_address(call->ping_op)) {
char *addr = sal_address_as_string(sal_op_get_contact_address(call->ping_op));
/* if the ping OPTIONS request succeeded use the contact guessed from the
received, rport*/
ms_message("Contact has been fixed using OPTIONS"/* to %s",guessed*/);
ret=linphone_address_new(addr);
ms_free(addr);
ret=linphone_address_clone(sal_op_get_contact_address(call->ping_op));;
} else if (dest_proxy && dest_proxy->op && sal_op_get_contact_address(dest_proxy->op)){
char *addr = sal_address_as_string(sal_op_get_contact_address(dest_proxy->op));
/*if using a proxy, use the contact address as guessed with the REGISTERs*/
ms_message("Contact has been fixed using proxy" /*to %s",fixed_contact*/);
ret=linphone_address_new(addr);
ms_free(addr);
ret=linphone_address_clone(sal_op_get_contact_address(dest_proxy->op));
} else {
ctt=linphone_core_get_primary_contact_parsed(lc);
if (ctt!=NULL){
@ -5016,17 +4981,9 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call ,
}
void linphone_call_set_contact_op(LinphoneCall* call) {
SalAddress *sal_address = nullptr;
{
LinphoneAddress *contact = get_fixed_contact(call->core,call,call->dest_proxy);
if (contact) {
sal_address = const_cast<SalAddress *>(L_GET_PRIVATE_FROM_C_STRUCT(contact, Address)->getInternalAddress());
sal_address_ref(sal_address);
linphone_address_unref(contact);
}
}
sal_op_set_and_clean_contact_address(call->op, sal_address);
LinphoneAddress *contact;
contact=get_fixed_contact(call->core,call,call->dest_proxy);
sal_op_set_and_clean_contact_address(call->op, (SalAddress *)contact);
}
LinphonePlayer *linphone_call_get_player(LinphoneCall *call){

View file

@ -46,10 +46,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mediastreamer2/msogl.h"
#include "mediastreamer2/msvolume.h"
// For migration purpose.
#include "address/address-p.h"
#include "c-wrapper/c-tools.h"
#ifdef INET6
#ifndef _WIN32
#include <netdb.h>
@ -3384,7 +3380,7 @@ static bctbx_list_t *make_routes_for_proxy(LinphoneProxyConfig *proxy, const Lin
ret=bctbx_list_append(ret,sal_address_new(local_route));
}
if (srv_route){
ret=bctbx_list_append(ret,sal_address_clone(L_GET_PRIVATE_FROM_C_STRUCT(srv_route, Address)->getInternalAddress()));
ret=bctbx_list_append(ret,sal_address_clone((SalAddress*)srv_route));
}
if (ret==NULL){
/*if the proxy address matches the domain part of the destination, then use the same transport
@ -3411,7 +3407,7 @@ LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const L
/*return default proxy if it is matching the destination uri*/
if (default_cfg){
const char *domain=linphone_proxy_config_get_domain(default_cfg);
if (domain && !strcmp(domain,linphone_address_get_domain(uri))){
if (strcmp(domain,linphone_address_get_domain(uri))==0){
found_cfg=default_cfg;
goto end;
}
@ -3503,9 +3499,7 @@ void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const Linphon
routes=make_routes_for_proxy(proxy,dest);
linphone_transfer_routes_to_op(routes,op);
}
char *addr = linphone_address_as_string(dest);
sal_op_set_to(op,addr);
ms_free(addr);
sal_op_set_to_address(op,dest);
sal_op_set_from(op,identity);
sal_op_set_sent_custom_header(op,headers);
sal_op_set_realm(op,linphone_proxy_config_get_realm(proxy));
@ -6040,10 +6034,6 @@ LinphoneConfig * linphone_core_create_config(LinphoneCore *lc, const char *filen
return lp_config_new(filename);
}
LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address) {
return linphone_address_new(address);
}
static void linphone_core_uninit(LinphoneCore *lc)
{
bctbx_list_t *elem = NULL;
@ -6163,8 +6153,6 @@ static void stop_refreshing_proxy_config(bool_t is_sip_reachable, LinphoneProxyC
linphone_proxy_config_set_state(cfg, LinphoneRegistrationNone,"Registration impossible (network down)");
}else{
cfg->commit=TRUE;
if (linphone_proxy_config_publish_enabled(cfg))
cfg->send_publish=TRUE; /*not sure if really the best place*/
}
}
}

View file

@ -23,7 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifdef SQLITE_STORAGE_ENABLED
#include "chat/chat-room.h"
#ifndef _WIN32
#if !defined(__QNXNTO__) && !defined(__ANDROID__)
@ -43,9 +42,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <assert.h>
extern LinphonePrivate::ChatRoom& linphone_chat_room_get_cpp_obj(LinphoneChatRoom *cr);
static char *utf8_convert(const char *filename){
char db_file_utf8[MAX_PATH_SIZE] = "";
#if defined(_WIN32)
@ -121,6 +117,31 @@ int _linphone_sqlite3_open(const char *db_file, sqlite3 **db) {
#ifdef SQLITE_STORAGE_ENABLED
static LinphoneChatMessage * get_weak_message(LinphoneChatRoom *cr, unsigned int storage_id) {
LinphoneChatMessage *cm;
bctbx_list_t *item;
for (item = cr->weak_messages; item != NULL; item = bctbx_list_next(item)) {
cm = (LinphoneChatMessage *)bctbx_list_get_data(item);
if (linphone_chat_message_get_storage_id(cm) == storage_id)
return linphone_chat_message_ref(cm);
}
return NULL;
}
static ORTP_INLINE LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, unsigned int storage_id){
bctbx_list_t* transients = cr->transient_messages;
LinphoneChatMessage* chat;
while( transients ){
chat = (LinphoneChatMessage*)transients->data;
if(chat->storage_id == storage_id){
return linphone_chat_message_ref(chat);
}
transients = transients->next;
}
return NULL;
}
/* DB layout:
* | 0 | storage_id
* | 1 | type
@ -151,7 +172,7 @@ static int callback_content(void *data, int argc, char **argv, char **colName) {
return 0;
}
void linphone_chat_message_fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id) {
static void fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id) {
char* errmsg = NULL;
int ret;
char * buf;
@ -165,6 +186,8 @@ void linphone_chat_message_fetch_content_from_database(sqlite3 *db, LinphoneChat
sqlite3_free(buf);
}
// Called when fetching all conversations from database
static int callback_all(void *data, int argc, char **argv, char **colName){
LinphoneCore* lc = (LinphoneCore*) data;
@ -177,6 +200,93 @@ static int callback_all(void *data, int argc, char **argv, char **colName){
return 0;
}
/* DB layout:
* | 0 | storage_id
* | 1 | localContact
* | 2 | remoteContact
* | 3 | direction flag (LinphoneChatMessageDir)
* | 4 | message (text content of the message)
* | 5 | time (unused now, used to be string-based timestamp, replaced by the utc timestamp)
* | 6 | read flag (no longer used, replaced by the LinphoneChatMessageStateDisplayed state)
* | 7 | status (LinphoneChatMessageState)
* | 8 | external body url (deprecated file transfer system)
* | 9 | utc timestamp
* | 10 | app data text
* | 11 | linphone content id (LinphoneContent describing a file transfer)
* | 12 | message id (used for IMDN)
* | 13 | content type (of the message field [must be text representable])
* | 14 | secured flag
*/
static int create_chat_message(void *data, int argc, char **argv, char **colName){
LinphoneChatRoom *cr = (LinphoneChatRoom *)data;
unsigned int storage_id = (unsigned int)atoi(argv[0]);
LinphoneChatMessage* new_message;
/* Check if the message exists in the weak messages list, in which case we should return that one. */
new_message = get_weak_message(cr, storage_id);
if (new_message == NULL) {
/* Check if the message exists in the transient list, in which case we should return that one. */
new_message = get_transient_message(cr, storage_id);
}
if (new_message == NULL) {
new_message = linphone_chat_room_create_message(cr, argv[4]);
if(atoi(argv[3])==LinphoneChatMessageIncoming){
new_message->dir=LinphoneChatMessageIncoming;
linphone_chat_message_set_from(new_message,linphone_chat_room_get_peer_address(cr));
new_message->to = NULL; /*will be filled at the end */
} else {
new_message->dir=LinphoneChatMessageOutgoing;
new_message->from = NULL; /*will be filled at the end */
linphone_chat_message_set_to(new_message,linphone_chat_room_get_peer_address(cr));
}
new_message->time = (time_t)atol(argv[9]);
new_message->is_read=atoi(argv[6]);
new_message->state=static_cast<LinphoneChatMessageState>(atoi(argv[7]));
new_message->storage_id=storage_id;
new_message->external_body_url= ms_strdup(argv[8]);
new_message->appdata = ms_strdup(argv[10]);
new_message->message_id = ms_strdup(argv[12]);
linphone_chat_message_set_content_type(new_message, argv[13]);
new_message->is_secured = (bool_t)atoi(argv[14]);
if (argv[11] != NULL) {
int id = atoi(argv[11]);
if (id >= 0) {
fetch_content_from_database(cr->lc->db, new_message, id);
}
}
/* Fix content type for old messages that were stored without it */
if (new_message->content_type == NULL) {
if (new_message->file_transfer_information != NULL) {
new_message->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml");
} else if (new_message->external_body_url != NULL) {
new_message->content_type = ms_strdup("message/external-body");
} else {
new_message->content_type = ms_strdup("text/plain");
}
}
/* Add the new message to the weak messages list. */
linphone_chat_room_add_weak_message(cr, new_message);
}
cr->messages_hist=bctbx_list_prepend(cr->messages_hist,new_message);
return 0;
}
void linphone_sql_request_message(sqlite3 *db,const char *stmt,LinphoneChatRoom *cr){
char* errmsg=NULL;
int ret;
ret=sqlite3_exec(db,stmt,create_chat_message,cr,&errmsg);
if(ret != SQLITE_OK) {
ms_error("Error in creation: %s.", errmsg);
sqlite3_free(errmsg);
}
}
int linphone_sql_request(sqlite3* db,const char *stmt){
char* errmsg=NULL;
int ret;
@ -297,7 +407,7 @@ void linphone_chat_message_store_update(LinphoneChatMessage *msg) {
}
void linphone_chat_message_store_state(LinphoneChatMessage *msg){
LinphoneCore *lc=linphone_chat_room_get_core(msg->chat_room);
LinphoneCore *lc=msg->chat_room->lc;
if (lc->db){
char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (id = %u);",
msg->state,msg->storage_id);
@ -307,7 +417,7 @@ void linphone_chat_message_store_state(LinphoneChatMessage *msg){
}
void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){
LinphoneCore *lc=linphone_chat_room_get_core(msg->chat_room);
LinphoneCore *lc=msg->chat_room->lc;
if (lc->db){
char *buf=sqlite3_mprintf("UPDATE history SET appdata=%Q WHERE id=%u;",
msg->appdata,msg->storage_id);
@ -316,44 +426,251 @@ void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){
}
}
void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr) {
linphone_chat_room_get_cpp_obj(cr).markAsRead();
void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){
LinphoneCore *lc=linphone_chat_room_get_core(cr);
bctbx_list_t *item;
char *peer;
char *buf;
if (lc->db==NULL) return ;
// optimization: do not modify the database if no message is marked as unread
if(linphone_chat_room_get_unread_messages_count(cr) == 0) return;
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND direction = %i AND status != %i", peer, LinphoneChatMessageIncoming, LinphoneChatMessageStateDisplayed);
linphone_sql_request_message(lc->db, buf, cr);
sqlite3_free(buf);
for (item = cr->messages_hist; item != NULL; item = bctbx_list_next(item)) {
LinphoneChatMessage *cm = (LinphoneChatMessage *)bctbx_list_get_data(item);
linphone_chat_message_send_display_notification(cm);
}
bctbx_list_free_with_data(cr->messages_hist, (bctbx_list_free_func)linphone_chat_message_unref);
cr->messages_hist = NULL;
buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE remoteContact=%Q AND direction=%i;",
LinphoneChatMessageStateDisplayed, peer, LinphoneChatMessageIncoming);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
ms_free(peer);
if (cr->pending_message) {
linphone_chat_message_set_state(cr->pending_message, LinphoneChatMessageStateDisplayed);
linphone_chat_message_send_display_notification(cr->pending_message);
}
cr->unread_count = 0;
}
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr) {
return linphone_chat_room_get_cpp_obj(cr).getUnreadMessagesCount();
void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
LinphoneCore *lc=linphone_chat_room_get_core(cr);
char *buf;
if (lc->db==NULL) return ;
buf=sqlite3_mprintf("UPDATE history SET url=%Q WHERE id=%u;",msg->external_body_url,msg->storage_id);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
}
int linphone_chat_room_get_history_size(LinphoneChatRoom *cr) {
return linphone_chat_room_get_cpp_obj(cr).getHistorySize();
static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t unread_only){
LinphoneCore *lc=linphone_chat_room_get_core(cr);
int numrows=0;
char *peer;
char *buf;
char *option = NULL;
sqlite3_stmt *selectStatement;
int returnValue;
if (lc->db==NULL) return 0;
// optimization: do not read database if the count is already available in memory
if(unread_only && cr->unread_count >= 0) return cr->unread_count;
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
if (unread_only) {
option = bctbx_strdup_printf("AND status!=%i AND direction=%i", LinphoneChatMessageStateDisplayed, LinphoneChatMessageIncoming);
}
buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;",peer,unread_only?option:"");
returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL);
if (returnValue == SQLITE_OK){
if(sqlite3_step(selectStatement) == SQLITE_ROW){
numrows= sqlite3_column_int(selectStatement, 0);
}
}
sqlite3_finalize(selectStatement);
sqlite3_free(buf);
ms_free(peer);
/* no need to test the sign of cr->unread_count here
* because it has been tested above */
if(unread_only) {
cr->unread_count = numrows;
if (option) bctbx_free(option);
}
return numrows;
}
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
return linphone_chat_room_get_messages_count(cr, TRUE);
}
int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){
return linphone_chat_room_get_messages_count(cr, FALSE);
}
void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
linphone_chat_room_get_cpp_obj(cr).deleteMessage(msg);
LinphoneCore *lc=cr->lc;
char *buf;
if (lc->db==NULL) return ;
buf=sqlite3_mprintf("DELETE FROM history WHERE id = %u;", msg->storage_id);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
/* Invalidate unread_count when we modify the database, so that next
time we need it it will be recomputed from latest database state */
cr->unread_count = -1;
}
void linphone_chat_room_delete_history(LinphoneChatRoom *cr) {
linphone_chat_room_get_cpp_obj(cr).deleteHistory();
void linphone_chat_room_delete_history(LinphoneChatRoom *cr){
LinphoneCore *lc=cr->lc;
char *peer;
char *buf;
if (lc->db==NULL) return ;
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
buf=sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;",peer);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
ms_free(peer);
if(cr->unread_count > 0) cr->unread_count = 0;
}
bctbx_list_t *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm) {
std::list<LinphoneChatMessage *> l = linphone_chat_room_get_cpp_obj(cr).getHistoryRange(startm, endm);
bctbx_list_t *result = nullptr;
for (auto it = l.begin(); it != l.end(); it++)
result = bctbx_list_append(result, *it);
return result;
bctbx_list_t *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){
LinphoneCore *lc=linphone_chat_room_get_core(cr);
bctbx_list_t *ret;
char *buf,*buf2;
char *peer;
uint64_t begin,end;
int buf_max_size = 512;
if (lc->db==NULL) return NULL;
peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
cr->messages_hist = NULL;
/*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/
buf=reinterpret_cast<char *>(ms_malloc(buf_max_size));
buf=sqlite3_snprintf(buf_max_size-1,buf,"SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC",peer);
if (startm<0) startm=0;
if ((endm>0&&endm>=startm) || (startm == 0 && endm == 0) ){
buf2=ms_strdup_printf("%s LIMIT %i ",buf,endm+1-startm);
ms_free(buf);
buf = buf2;
}else if(startm>0){
ms_message("%s(): end is lower than start (%d < %d). Assuming no end limit.",__FUNCTION__,endm,startm);
buf2=ms_strdup_printf("%s LIMIT -1",buf);
ms_free(buf);
buf = buf2;
}
if (startm>0){
buf2=ms_strdup_printf("%s OFFSET %i ",buf,startm);
ms_free(buf);
buf = buf2;
}
begin=ortp_get_cur_time_ms();
linphone_sql_request_message(lc->db,buf,cr);
end=ortp_get_cur_time_ms();
if (endm+1-startm > 1) {
//display message only if at least 2 messages are loaded
ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin));
}
ms_free(buf);
if (cr->messages_hist) {
//fill local addr with core identity instead of per message
LinphoneAddress* local_addr = linphone_address_new(linphone_core_get_identity(cr->lc));
bctbx_list_t* it = cr->messages_hist;
while (it) {
LinphoneChatMessage* msg = reinterpret_cast<LinphoneChatMessage *>(it->data);
if (msg->dir == LinphoneChatMessageOutgoing) {
if (msg->from != NULL) linphone_address_unref(msg->from);
msg->from = linphone_address_ref(local_addr);
} else {
msg->to = linphone_address_ref(local_addr);
}
it = it->next;
}
linphone_address_unref(local_addr);
}
ret=cr->messages_hist;
cr->messages_hist=NULL;
ms_free(peer);
return ret;
}
bctbx_list_t *linphone_chat_room_get_history(LinphoneChatRoom *cr, int nb_message) {
std::list<LinphoneChatMessage *> l = linphone_chat_room_get_cpp_obj(cr).getHistory(nb_message);
bctbx_list_t *result = nullptr;
for (auto it = l.begin(); it != l.end(); it++)
result = bctbx_list_append(result, *it);
return result;
bctbx_list_t *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
return linphone_chat_room_get_history_range(cr, 0, nb_message-1);
}
bctbx_list_t* linphone_chat_room_find_messages(LinphoneChatRoom *cr, const char *message_id) {
LinphoneCore *lc = linphone_chat_room_get_core(cr);
char *buf;
char *peer;
bctbx_list_t* messages;
if (lc->db == NULL) return NULL;
peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
cr->messages_hist = NULL;
buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND messageId = %Q", peer, message_id);
linphone_sql_request_message(lc->db, buf, cr);
sqlite3_free(buf);
ms_free(peer);
messages = cr->messages_hist;
cr->messages_hist = NULL;
return messages;
}
LinphoneChatMessage * linphone_chat_room_find_message_with_dir(LinphoneChatRoom *cr, const char *message_id, LinphoneChatMessageDir dir) {
bctbx_list_t* messages = linphone_chat_room_find_messages(cr, message_id);
bctbx_list_t* it;
LinphoneChatMessage *ret = NULL;
for (it = messages; it != NULL; it = it->next) {
LinphoneChatMessage * cm = (LinphoneChatMessage*)it->data;
if (cm->dir == dir) {
linphone_chat_message_ref(cm);
ret = cm;
break;
}
}
if (messages)
bctbx_list_free_with_data(messages, (bctbx_list_free_func)linphone_chat_message_unref);
return ret;
}
LinphoneChatMessage * linphone_chat_room_find_message(LinphoneChatRoom *cr, const char *message_id) {
return linphone_chat_room_get_cpp_obj(cr).findMessage(message_id);
bctbx_list_t* messages = linphone_chat_room_find_messages(cr, message_id);
LinphoneChatMessage *cm = NULL;
if (messages) {
cm = (LinphoneChatMessage *)bctbx_list_nth_data(messages, 0);
linphone_chat_message_ref(cm);
bctbx_list_free_with_data(messages, (bctbx_list_free_func)linphone_chat_message_unref);
}
return cm;
}
static void linphone_create_history_table(sqlite3* db){
@ -658,6 +975,9 @@ void linphone_core_message_storage_init(LinphoneCore *lc){
void linphone_core_message_storage_close(LinphoneCore *lc){
}
void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
}
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
return 0;
}

View file

@ -1933,11 +1933,8 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa
if (linphone_core_get_default_friend_list(lc) != NULL)
lf=linphone_core_find_friend_by_out_subscribe(lc, op);
if (lf==NULL && lp_config_get_int(lc->config,"sip","allow_out_of_subscribe_presence",0)){
char *buf = sal_address_as_string_uri_only(sal_op_get_from_address(op));
LinphoneAddress *addr = linphone_address_new(buf);
lf = linphone_core_find_friend(lc, addr);
ms_free(buf);
linphone_address_unref(addr);
const SalAddress *addr=sal_op_get_from_address(op);
lf = linphone_core_find_friend(lc, (LinphoneAddress *)addr);
}
if (lf!=NULL){
LinphonePresenceActivity *activity = NULL;

View file

@ -180,12 +180,6 @@ struct _LinphoneCallParams{
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneCallParams);
typedef enum _ImdnType {
ImdnTypeDelivery,
ImdnTypeDisplay
} ImdnType;
struct _LinphoneQualityReporting{
reporting_session_report_t * reports[3]; /**Store information on audio and video media streams (RFC 6035) */
bool_t was_video_running; /*Keep video state since last check in order to detect its (de)activation*/
@ -285,6 +279,11 @@ struct _LinphoneChatMessage {
#endif
};
/*
*Gets a Message with a given message id and direction.
*/
LINPHONE_PUBLIC LinphoneChatMessage * linphone_chat_room_find_message_with_dir(LinphoneChatRoom *cr, const char *message_id,LinphoneChatMessageDir dir);
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatMessage);
typedef struct StunCandidate{
@ -595,7 +594,7 @@ LINPHONE_PUBLIC void linphone_core_get_local_ip(LinphoneCore *lc, int af, const
LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore *lc, int index);
void linphone_proxy_config_write_to_config_file(LinphoneConfig* config,LinphoneProxyConfig *obj, int index);
int linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg);
LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg);
void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, uint32_t character, LinphoneCall *call);
void linphone_call_init_stats(LinphoneCallStats *stats, LinphoneStreamType type);
@ -651,8 +650,7 @@ void _linphone_proxy_config_release_ops(LinphoneProxyConfig *obj);
/*chat*/
void linphone_chat_room_release(LinphoneChatRoom *cr);
void linphone_chat_room_set_call(LinphoneChatRoom *cr, LinphoneCall *call);
bctbx_list_t * linphone_chat_room_get_transient_messages(const LinphoneChatRoom *cr);
void linphone_chat_room_add_weak_message(LinphoneChatRoom *cr, LinphoneChatMessage *cm);
void linphone_chat_message_destroy(LinphoneChatMessage* msg);
void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMessageState new_state);
void linphone_chat_message_set_state(LinphoneChatMessage *msg, LinphoneChatMessageState state);
@ -661,14 +659,11 @@ void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm, L
void linphone_chat_message_send_display_notification(LinphoneChatMessage *cm);
void _linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg, bool_t unref);
int linphone_chat_room_upload_file(LinphoneChatMessage *msg);
void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
LinphoneChatMessageCbs *linphone_chat_message_cbs_new(void);
LinphoneChatRoom *_linphone_core_create_chat_room_from_call(LinphoneCall *call);
void linphone_chat_room_add_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
void linphone_chat_room_remove_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
void linphone_chat_message_deactivate(LinphoneChatMessage *msg);
void linphone_chat_message_release(LinphoneChatMessage *msg);
void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChatMessage *msg);
void linphone_chat_message_fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id);
void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, ImdnType imdn_type, LinphoneReason reason);
/**/
struct _LinphoneProxyConfig
@ -721,10 +716,6 @@ struct _LinphoneProxyConfig
char *refkey;
char *sip_etag; /*publish context*/
// For migration purpose. (Do not use directly!)
// Cache.
LinphoneAddress *contact_address;
};
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneProxyConfig);
@ -749,11 +740,33 @@ typedef enum _LinphoneIsComposingState {
LinphoneIsComposingActive
} LinphoneIsComposingState;
struct _LinphoneChatRoom{
belle_sip_object_t base;
void *user_data;
struct _LinphoneCore *lc;
char *peer;
LinphoneAddress *peer_url;
MSList *messages_hist;
MSList *transient_messages;
bctbx_list_t *weak_messages;
int unread_count;
LinphoneIsComposingState remote_is_composing;
LinphoneIsComposingState is_composing;
belle_sip_source_t *remote_composing_refresh_timer;
belle_sip_source_t *composing_idle_timer;
belle_sip_source_t *composing_refresh_timer;
LinphoneCall *call;
LinphoneChatMessage *pending_message;
MSList *received_rtt_characters;
};
typedef struct _LinphoneChatMessageCharacter {
uint32_t value;
bool_t has_been_read;
} LinphoneChatMessageCharacter;
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatRoom);
typedef struct _LinphoneFriendPresence {
char *uri_or_tel;
@ -1159,11 +1172,6 @@ struct _LinphoneEvent{
bool_t is_out_of_dialog_op; /*used for out of dialog notify*/
bool_t internal;
bool_t oneshot;
// For migration purpose. (Do not use directly!)
// Cache.
LinphoneAddress *to_address;
LinphoneAddress *from_address;
};
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneEvent);
@ -1833,7 +1841,6 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(linphone,10000)
BELLE_SIP_TYPE_ID(LinphoneAccountCreator),
BELLE_SIP_TYPE_ID(LinphoneAccountCreatorCbs),
BELLE_SIP_TYPE_ID(LinphoneAccountCreatorService),
BELLE_SIP_TYPE_ID(LinphoneAddress),
BELLE_SIP_TYPE_ID(LinphoneBuffer),
BELLE_SIP_TYPE_ID(LinphoneContactProvider),
BELLE_SIP_TYPE_ID(LinphoneContactSearch),

View file

@ -18,20 +18,14 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <ctype.h>
#include "linphone/core_utils.h"
#include "linphone/core.h"
#include "linphone/lpconfig.h"
#include "linphone/core_utils.h"
#include "linphone/sipsetup.h"
#include "mediastreamer2/mediastream.h"
#include "enum.h"
#include "linphone/lpconfig.h"
#include "private.h"
// For migration purpose.
#include "address/address-p.h"
#include "c-wrapper/c-tools.h"
#include "mediastreamer2/mediastream.h"
#include "enum.h"
#include <ctype.h>
/*store current config related to server location*/
static void linphone_proxy_config_store_server_config(LinphoneProxyConfig* cfg) {
@ -246,9 +240,6 @@ void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg){
if (cfg->ei){
linphone_error_info_unref(cfg->ei);
}
if (cfg->contact_address) linphone_address_unref(cfg->contact_address);
_linphone_proxy_config_release_ops(cfg);
}
@ -413,33 +404,26 @@ void linphone_proxy_config_apply(LinphoneProxyConfig *cfg,LinphoneCore *lc){
}
void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig * cfg){
LinphoneAddress *contact_addr = NULL;
{
const SalAddress *sal_addr = cfg->op && cfg->state == LinphoneRegistrationOk
? sal_op_get_contact_address(cfg->op)
: NULL;
if (sal_addr) {
char *buf = sal_address_as_string(sal_addr);
contact_addr = buf ? linphone_address_new(buf) : NULL;
ms_free(buf);
}
}
LinphoneAddress *contact_addr=NULL;
if ( cfg->op
&& cfg->state == LinphoneRegistrationOk
&& (contact_addr = (LinphoneAddress*)sal_op_get_contact_address(cfg->op))
&& linphone_address_get_transport(contact_addr) != LinphoneTransportUdp /*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/) {
/*need to save current contact in order to reset is later*/
linphone_address_ref(contact_addr);
if (cfg->pending_contact)
linphone_address_unref(cfg->pending_contact);
cfg->pending_contact=contact_addr;
/*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/
if (contact_addr) {
if (linphone_address_get_transport(contact_addr) != LinphoneTransportUdp) {
if (cfg->pending_contact)
linphone_address_unref(cfg->pending_contact);
cfg->pending_contact=contact_addr;
} else
linphone_address_unref(contact_addr);
}
if (cfg->presence_publish_event){ /*might probably do better*/
linphone_event_set_publish_state(cfg->presence_publish_event,LinphonePublishNone);
linphone_event_unref(cfg->presence_publish_event); /*probably useless as cfg->long_term_event is already unref in linphone_proxy_config_notify_publish_state_changed. To be check with Ghislain*/
cfg->presence_publish_event=NULL;
linphone_event_terminate(cfg->presence_publish_event);
if (cfg->presence_publish_event) {
linphone_event_unref(cfg->presence_publish_event); /*probably useless as cfg->long_term_event is already unref in linphone_proxy_config_notify_publish_state_changed. To be check with Ghislain*/
cfg->presence_publish_event=NULL;
}
}
if (cfg->op){
sal_op_release(cfg->op);
cfg->op=NULL;
@ -462,10 +446,10 @@ LinphoneAddress *guess_contact_for_register(LinphoneProxyConfig *cfg){
if (cfg->contact_params) {
// We want to add a list of contacts params to the linphone address
linphone_address_set_params(contact,cfg->contact_params);
sal_address_set_params(contact,cfg->contact_params);
}
if (cfg->contact_uri_params){
linphone_address_set_uri_params(contact,cfg->contact_uri_params);
sal_address_set_uri_params(contact,cfg->contact_uri_params);
}
#ifdef BUILD_UPNP
if (cfg->lc->upnp != NULL && linphone_core_get_firewall_policy(cfg->lc)==LinphonePolicyUseUpnp &&
@ -507,19 +491,14 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *cfg){
linphone_configure_op(cfg->lc, cfg->op, cfg->identity_address, cfg->sent_headers, FALSE);
if ((contact=guess_contact_for_register(cfg))) {
sal_op_set_contact_address(cfg->op, L_GET_PRIVATE_FROM_C_STRUCT(contact, Address)->getInternalAddress());
sal_op_set_contact_address(cfg->op,contact);
linphone_address_unref(contact);
}
sal_op_set_user_pointer(cfg->op,cfg);
if (sal_register(
cfg->op,
proxy_string,
cfg->reg_identity,
cfg->expires,
cfg->pending_contact ? L_GET_PRIVATE_FROM_C_STRUCT(cfg->pending_contact, Address)->getInternalAddress() : NULL
)==0) {
if (sal_register(cfg->op,proxy_string, cfg->reg_identity, cfg->expires, cfg->pending_contact)==0) {
if (cfg->pending_contact) {
linphone_address_unref(cfg->pending_contact);
cfg->pending_contact=NULL;
@ -900,7 +879,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese
}
linphone_presence_model_set_presentity(presence,linphone_proxy_config_get_identity_address(proxy));
linphone_presence_model_set_contact(presence,NULL); /*it will be automatically computed*/
}
if (!(presence_body = linphone_presence_model_to_xml(presence))) {
ms_error("Cannot publish presence model [%p] for proxy config [%p] because of xml serialization error",presence,proxy);
@ -927,7 +906,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese
linphone_presence_model_set_contact(presence,contact);
bctbx_free(contact);
}
}else proxy->send_publish=TRUE; /*otherwise do not send publish if registration is in progress, this will be done later*/
return err;
}
@ -1404,11 +1383,9 @@ const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphonePro
const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg) {
const char* addr=NULL;
const char* ret="udp"; /*default value*/
const SalAddress* route_addr=NULL;
bool_t destroy_route_addr = FALSE;
SalAddress* route_addr=NULL;
if (linphone_proxy_config_get_service_route(cfg)) {
route_addr = L_GET_PRIVATE_FROM_C_STRUCT(linphone_proxy_config_get_service_route(cfg), Address)->getInternalAddress();
route_addr=(SalAddress*)linphone_proxy_config_get_service_route(cfg);
} else if (linphone_proxy_config_get_route(cfg)) {
addr=linphone_proxy_config_get_route(cfg);
} else if(linphone_proxy_config_get_addr(cfg)) {
@ -1418,16 +1395,13 @@ const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg)
return NULL;
}
if (!route_addr) {
if (!((*(SalAddress **)&route_addr) = sal_address_new(addr)))
return NULL;
destroy_route_addr = TRUE;
if (route_addr || (route_addr=sal_address_new(addr))) {
ret=sal_transport_to_string(sal_address_get_transport(route_addr));
if (!linphone_proxy_config_get_service_route(cfg)) {
sal_address_destroy(route_addr);
}
}
ret=sal_transport_to_string(sal_address_get_transport(route_addr));
if (destroy_route_addr)
sal_address_destroy((SalAddress *)route_addr);
return ret;
}
void linphone_proxy_config_set_privacy(LinphoneProxyConfig *params, LinphonePrivacyMask privacy) {
@ -1476,15 +1450,7 @@ uint8_t linphone_proxy_config_get_avpf_rr_interval(const LinphoneProxyConfig *cf
}
const LinphoneAddress* linphone_proxy_config_get_contact(const LinphoneProxyConfig *cfg) {
// Workaround for wrapping.
if (cfg->contact_address)
linphone_address_unref(cfg->contact_address);
char *buf = sal_address_as_string(sal_op_get_contact_address(cfg->op));
const_cast<LinphoneProxyConfig *>(cfg)->contact_address = linphone_address_new(buf);
ms_free(buf);
return cfg->contact_address;
return sal_op_get_contact_address(cfg->op);
}
const struct _LinphoneAuthInfo* linphone_proxy_config_find_auth_info(const LinphoneProxyConfig *cfg) {

View file

@ -32,10 +32,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <sys/sysctl.h>
#endif
// For migration purpose.
#include "address/address-p.h"
#include "c-wrapper/c-tools.h"
#define STR_REASSIGN(dest, src) {\
if (dest != NULL) \
ms_free(dest); \
@ -276,7 +272,6 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report,
LinphoneAddress *request_uri;
const char* collector_uri;
char *collector_uri_allocated = NULL;
const SalAddress *salAddress;
/*if we are on a low bandwidth network, do not send reports to not overload it*/
if (linphone_call_params_low_bandwidth_enabled(linphone_call_get_current_params(call))){
@ -367,9 +362,8 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report,
* (port, transport, maddr), then it is sent directly.
* Otherwise it is routed as any LinphoneEvent publish, following proxy config policy.
**/
salAddress = L_GET_PRIVATE_FROM_C_STRUCT(request_uri, Address)->getInternalAddress();
if (sal_address_has_uri_param(salAddress, "transport") ||
sal_address_has_uri_param(salAddress, "maddr") ||
if (sal_address_has_uri_param((SalAddress*)request_uri, "transport") ||
sal_address_has_uri_param((SalAddress*)request_uri, "maddr") ||
linphone_address_get_port(request_uri) != 0) {
ms_message("Publishing report with custom route %s", collector_uri);
sal_op_set_route(lev->op, collector_uri);

View file

@ -1,942 +0,0 @@
/*
linphone
Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr)
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
This file contains SAL API functions that do not depend on the underlying implementation (like belle-sip).
**/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "sal/sal.h"
#include <ctype.h>
const char *sal_multicast_role_to_string(SalMulticastRole role){
switch(role){
case SalMulticastInactive:
return "inactive";
case SalMulticastReceiver:
return "receiver";
case SalMulticastSender:
return "sender";
case SalMulticastSenderReceiver:
return "sender-receiver";
}
return "INVALID";
}
const char* sal_transport_to_string(SalTransport transport) {
switch (transport) {
case SalTransportUDP:return "udp";
case SalTransportTCP: return "tcp";
case SalTransportTLS:return "tls";
case SalTransportDTLS:return "dtls";
default: {
ms_fatal("Unexpected transport [%i]",transport);
return NULL;
}
}
}
SalTransport sal_transport_parse(const char* param) {
if (!param) return SalTransportUDP;
if (strcasecmp("udp",param)==0) return SalTransportUDP;
if (strcasecmp("tcp",param)==0) return SalTransportTCP;
if (strcasecmp("tls",param)==0) return SalTransportTLS;
if (strcasecmp("dtls",param)==0) return SalTransportDTLS;
ms_error("Unknown transport type[%s], returning UDP", param);
return SalTransportUDP;
}
SalMediaDescription *sal_media_description_new(){
SalMediaDescription *md=ms_new0(SalMediaDescription,1);
int i;
md->refcount=1;
for(i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
md->streams[i].dir=SalStreamInactive;
md->streams[i].rtp_port = 0;
md->streams[i].rtcp_port = 0;
md->streams[i].haveZrtpHash = 0;
}
return md;
}
static void sal_media_description_destroy(SalMediaDescription *md){
int i;
for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;i++){
bctbx_list_free_with_data(md->streams[i].payloads,(void (*)(void *))payload_type_destroy);
bctbx_list_free_with_data(md->streams[i].already_assigned_payloads,(void (*)(void *))payload_type_destroy);
md->streams[i].payloads=NULL;
md->streams[i].already_assigned_payloads=NULL;
sal_custom_sdp_attribute_free(md->streams[i].custom_sdp_attributes);
}
sal_custom_sdp_attribute_free(md->custom_sdp_attributes);
ms_free(md);
}
SalMediaDescription * sal_media_description_ref(SalMediaDescription *md){
md->refcount++;
return md;
}
void sal_media_description_unref(SalMediaDescription *md){
md->refcount--;
if (md->refcount==0){
sal_media_description_destroy (md);
}
}
SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md, SalMediaProto proto, SalStreamType type){
int i;
for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;++i){
SalStreamDescription *ss=&md->streams[i];
if (!sal_stream_description_active(ss)) continue;
if (ss->proto==proto && ss->type==type) return ss;
}
return NULL;
}
unsigned int sal_media_description_nb_active_streams_of_type(SalMediaDescription *md, SalStreamType type) {
unsigned int i;
unsigned int nb = 0;
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (md->streams[i].type == type) nb++;
}
return nb;
}
SalStreamDescription * sal_media_description_get_active_stream_of_type(SalMediaDescription *md, SalStreamType type, unsigned int idx) {
unsigned int i;
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (md->streams[i].type == type) {
if (idx-- == 0) return &md->streams[i];
}
}
return NULL;
}
SalStreamDescription * sal_media_description_find_secure_stream_of_type(SalMediaDescription *md, SalStreamType type) {
SalStreamDescription *desc = sal_media_description_find_stream(md, SalProtoRtpSavpf, type);
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpSavp, type);
return desc;
}
SalStreamDescription * sal_media_description_find_best_stream(SalMediaDescription *md, SalStreamType type) {
SalStreamDescription *desc = sal_media_description_find_stream(md, SalProtoUdpTlsRtpSavpf, type);
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoUdpTlsRtpSavp, type);
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpSavpf, type);
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpSavp, type);
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpAvpf, type);
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpAvp, type);
return desc;
}
bool_t sal_media_description_empty(const SalMediaDescription *md){
if (sal_media_description_get_nb_active_streams(md) > 0) return FALSE;
return TRUE;
}
void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){
int i;
for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;++i){
SalStreamDescription *ss=&md->streams[i];
if (!sal_stream_description_active(ss)) continue;
ss->dir=stream_dir;
}
}
int sal_media_description_get_nb_active_streams(const SalMediaDescription *md) {
int i;
int nb = 0;
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
if (sal_stream_description_active(&md->streams[i])) nb++;
}
return nb;
}
static bool_t is_null_address(const char *addr){
return strcmp(addr,"0.0.0.0")==0 || strcmp(addr,"::0")==0;
}
/*check for the presence of at least one stream with requested direction */
static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
int i;
/* we are looking for at least one stream with requested direction, inactive streams are ignored*/
for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;++i){
const SalStreamDescription *ss=&md->streams[i];
if (!sal_stream_description_active(ss)) continue;
if (ss->dir==stream_dir) {
return TRUE;
}
/*compatibility check for phones that only used the null address and no attributes */
if (ss->dir==SalStreamSendRecv && stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->rtp_addr))){
return TRUE;
}
}
return FALSE;
}
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
if (stream_dir==SalStreamRecvOnly){
return has_dir(md, SalStreamRecvOnly) && !(has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv));
}else if (stream_dir==SalStreamSendOnly){
return has_dir(md, SalStreamSendOnly) && !(has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv));
}else if (stream_dir==SalStreamSendRecv){
return has_dir(md,SalStreamSendRecv);
}else{
/*SalStreamInactive*/
if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv) || has_dir(md,SalStreamRecvOnly))
return FALSE;
else return TRUE;
}
return FALSE;
}
bool_t sal_stream_description_active(const SalStreamDescription *sd) {
return (sd->rtp_port > 0);
}
/*these are switch case, so that when a new proto is added we can't forget to modify this function*/
bool_t sal_stream_description_has_avpf(const SalStreamDescription *sd) {
switch (sd->proto){
case SalProtoRtpAvpf:
case SalProtoRtpSavpf:
case SalProtoUdpTlsRtpSavpf:
return TRUE;
case SalProtoRtpAvp:
case SalProtoRtpSavp:
case SalProtoUdpTlsRtpSavp:
case SalProtoOther:
return FALSE;
}
return FALSE;
}
bool_t sal_stream_description_has_ipv6(const SalStreamDescription *sd){
return strchr(sd->rtp_addr,':') != NULL;
}
bool_t sal_stream_description_has_implicit_avpf(const SalStreamDescription *sd){
return sd->implicit_rtcp_fb;
}
/*these are switch case, so that when a new proto is added we can't forget to modify this function*/
bool_t sal_stream_description_has_srtp(const SalStreamDescription *sd) {
switch (sd->proto){
case SalProtoRtpSavp:
case SalProtoRtpSavpf:
return TRUE;
case SalProtoRtpAvp:
case SalProtoRtpAvpf:
case SalProtoUdpTlsRtpSavpf:
case SalProtoUdpTlsRtpSavp:
case SalProtoOther:
return FALSE;
}
return FALSE;
}
bool_t sal_stream_description_has_dtls(const SalStreamDescription *sd) {
switch (sd->proto){
case SalProtoUdpTlsRtpSavpf:
case SalProtoUdpTlsRtpSavp:
return TRUE;
case SalProtoRtpSavp:
case SalProtoRtpSavpf:
case SalProtoRtpAvp:
case SalProtoRtpAvpf:
case SalProtoOther:
return FALSE;
}
return FALSE;
}
bool_t sal_stream_description_has_zrtp(const SalStreamDescription *sd) {
if (sd->haveZrtpHash==1) return TRUE;
return FALSE;
}
bool_t sal_media_description_has_avpf(const SalMediaDescription *md) {
int i;
if (md->nb_streams == 0) return FALSE;
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (sal_stream_description_has_avpf(&md->streams[i]) != TRUE) return FALSE;
}
return TRUE;
}
bool_t sal_media_description_has_implicit_avpf(const SalMediaDescription *md) {
int i;
if (md->nb_streams == 0) return FALSE;
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (sal_stream_description_has_implicit_avpf(&md->streams[i]) != TRUE) return FALSE;
}
return TRUE;
}
bool_t sal_media_description_has_srtp(const SalMediaDescription *md) {
int i;
if (md->nb_streams == 0) return FALSE;
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (sal_stream_description_has_srtp(&md->streams[i]) != TRUE) return FALSE;
}
return TRUE;
}
bool_t sal_media_description_has_dtls(const SalMediaDescription *md) {
int i;
if (md->nb_streams == 0) return FALSE;
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (sal_stream_description_has_dtls(&md->streams[i]) != TRUE) return FALSE;
}
return TRUE;
}
bool_t sal_media_description_has_zrtp(const SalMediaDescription *md) {
int i;
if (md->nb_streams == 0) return FALSE;
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (sal_stream_description_has_zrtp(&md->streams[i]) != TRUE) return FALSE;
}
return TRUE;
}
bool_t sal_media_description_has_ipv6(const SalMediaDescription *md){
int i;
if (md->nb_streams == 0) return FALSE;
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (md->streams[i].rtp_addr[0] != '\0'){
if (!sal_stream_description_has_ipv6(&md->streams[i])) return FALSE;
}else{
if (strchr(md->addr,':') == NULL) return FALSE;
}
}
return TRUE;
}
/*
static bool_t fmtp_equals(const char *p1, const char *p2){
if (p1 && p2 && strcmp(p1,p2)==0) return TRUE;
if (p1==NULL && p2==NULL) return TRUE;
return FALSE;
}
*/
static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){
if (p1->type!=p2->type) return FALSE;
if (strcmp(p1->mime_type,p2->mime_type)!=0) return FALSE;
if (p1->clock_rate!=p2->clock_rate) return FALSE;
if (p1->channels!=p2->channels) return FALSE;
if (payload_type_get_number(p1) != payload_type_get_number(p2)) return FALSE;
/*
Do not compare fmtp right now: they are modified internally when the call is started
*/
/*
if (!fmtp_equals(p1->recv_fmtp,p2->recv_fmtp) ||
!fmtp_equals(p1->send_fmtp,p2->send_fmtp))
return FALSE;
*/
return TRUE;
}
static bool_t is_recv_only(PayloadType *p){
return (p->flags & PAYLOAD_TYPE_FLAG_CAN_RECV) && ! (p->flags & PAYLOAD_TYPE_FLAG_CAN_SEND);
}
static bool_t payload_list_equals(const bctbx_list_t *l1, const bctbx_list_t *l2){
const bctbx_list_t *e1,*e2;
for(e1=l1,e2=l2;e1!=NULL && e2!=NULL; e1=e1->next,e2=e2->next){
PayloadType *p1=(PayloadType*)e1->data;
PayloadType *p2=(PayloadType*)e2->data;
if (!payload_type_equals(p1,p2))
return FALSE;
}
if (e1!=NULL){
/*skip possible recv-only payloads*/
for(;e1!=NULL && is_recv_only((PayloadType*)e1->data);e1=e1->next){
ms_message("Skipping recv-only payload type...");
}
}
if (e1!=NULL || e2!=NULL){
/*means one list is longer than the other*/
return FALSE;
}
return TRUE;
}
int sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2) {
int result = SAL_MEDIA_DESCRIPTION_UNCHANGED;
int i;
/* A different proto should result in SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED but the encryption change
needs a stream restart for now, so use SAL_MEDIA_DESCRIPTION_CODEC_CHANGED */
if (sd1->proto != sd2->proto) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
if ((sd1->crypto[i].tag != sd2->crypto[i].tag)
|| (sd1->crypto[i].algo != sd2->crypto[i].algo)){
result|=SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED;
}
if ((strncmp(sd1->crypto[i].master_key, sd2->crypto[i].master_key, sizeof(sd1->crypto[i].master_key) - 1))) {
result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED;
}
}
if (sd1->type != sd2->type) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
if (strcmp(sd1->rtp_addr, sd2->rtp_addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
if (sd1->rtp_addr[0]!='\0' && sd2->rtp_addr[0]!='\0' && ms_is_multicast(sd1->rtp_addr) != ms_is_multicast(sd2->rtp_addr))
result |= SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED;
if (sd1->rtp_port != sd2->rtp_port) {
if ((sd1->rtp_port == 0) || (sd2->rtp_port == 0)) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
else result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
}
if (strcmp(sd1->rtcp_addr, sd2->rtcp_addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
if (sd1->rtcp_port != sd2->rtcp_port) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
if (!payload_list_equals(sd1->payloads, sd2->payloads)) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
if (sd1->bandwidth != sd2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
if (sd1->ptime != sd2->ptime) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
if (sd1->dir != sd2->dir) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
/* ICE */
if (strcmp(sd1->ice_ufrag, sd2->ice_ufrag) != 0) result |= SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED;
if (strcmp(sd1->ice_pwd, sd2->ice_pwd) != 0) result |= SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED;
/*DTLS*/
if (sd1->dtls_role != sd2->dtls_role) result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED;
if (strcmp(sd1->dtls_fingerprint, sd2->dtls_fingerprint) != 0) result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED;
return result;
}
char * sal_media_description_print_differences(int result){
char *out = NULL;
if (result & SAL_MEDIA_DESCRIPTION_CODEC_CHANGED){
out = ms_strcat_printf(out, "%s ", "CODEC_CHANGED");
result &= ~SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
}
if (result & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED){
out = ms_strcat_printf(out, "%s ", "NETWORK_CHANGED");
result &= ~SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
}
if (result & SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED){
out = ms_strcat_printf(out, "%s ", "ICE_RESTART_DETECTED");
result &= ~SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED;
}
if (result & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED){
out = ms_strcat_printf(out, "%s ", "CRYPTO_KEYS_CHANGED");
result &= ~SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED;
}
if (result & SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED){
out = ms_strcat_printf(out, "%s ", "NETWORK_XXXCAST_CHANGED");
result &= ~SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED;
}
if (result & SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED){
out = ms_strcat_printf(out, "%s ", "STREAMS_CHANGED");
result &= ~SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED;
}
if (result & SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED){
out = ms_strcat_printf(out, "%s ", "CRYPTO_POLICY_CHANGED");
result &= ~SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED;
}
if (result & SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION){
out = ms_strcat_printf(out, "%s ", "FORCE_STREAM_RECONSTRUCTION");
result &= ~SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION;
}
if (result){
ms_fatal("There are unhandled result bitmasks in sal_media_description_print_differences(), fix it");
}
if (!out) out = ms_strdup("NONE");
return out;
}
int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2) {
int result = SAL_MEDIA_DESCRIPTION_UNCHANGED;
int i;
if (strcmp(md1->addr, md2->addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
if (md1->addr[0]!='\0' && md2->addr[0]!='\0' && ms_is_multicast(md1->addr) != ms_is_multicast(md2->addr))
result |= SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED;
if (md1->nb_streams != md2->nb_streams) result |= SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED;
if (md1->bandwidth != md2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
/* ICE */
if (strcmp(md1->ice_ufrag, md2->ice_ufrag) != 0) result |= SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED;
if (strcmp(md1->ice_pwd, md2->ice_pwd) != 0) result |= SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED;
for(i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){
if (!sal_stream_description_active(&md1->streams[i]) && !sal_stream_description_active(&md2->streams[i])) continue;
result |= sal_stream_description_equals(&md1->streams[i], &md2->streams[i]);
}
return result;
}
static void assign_address(SalAddress** address, const char *value){
if (*address){
sal_address_destroy(*address);
*address=NULL;
}
if (value)
*address=sal_address_new(value);
}
static void assign_string(char **str, const char *arg){
if (*str){
ms_free(*str);
*str=NULL;
}
if (arg)
*str=ms_strdup(arg);
}
void sal_op_set_contact_address(SalOp *op, const SalAddress *address){
if (((SalOpBase*)op)->contact_address) sal_address_destroy(((SalOpBase*)op)->contact_address);
((SalOpBase*)op)->contact_address=address?sal_address_clone(address):NULL;
}
void sal_op_set_and_clean_contact_address(SalOp *op, SalAddress *contact) {
if (contact){
SalTransport tport = sal_address_get_transport((SalAddress*)contact);
const char* gruu = bctbx_strdup(sal_address_get_uri_param(contact, "gr"));
sal_address_clean((SalAddress*)contact); /* clean out contact_params that come from proxy config*/
sal_address_set_transport((SalAddress*)contact,tport);
if(gruu)
sal_address_set_uri_param(contact, "gr", gruu);
sal_op_set_contact_address(op, contact);
sal_address_unref(contact);
}
}
const SalAddress* sal_op_get_contact_address(const SalOp *op) {
return ((SalOpBase*)op)->contact_address;
}
const SalAddress*sal_op_get_remote_contact_address(const SalOp* op)
{
return ((SalOpBase*)op)->remote_contact_address;
}
#define SET_PARAM(op,name) \
char* name##_string=NULL; \
assign_address(&((SalOpBase*)op)->name##_address,name); \
if (((SalOpBase*)op)->name##_address) { \
name##_string=sal_address_as_string(((SalOpBase*)op)->name##_address); \
}\
assign_string(&((SalOpBase*)op)->name,name##_string); \
if(name##_string) ms_free(name##_string);
void sal_op_set_route(SalOp *op, const char *route){
char* route_string=NULL;
SalOpBase* op_base = (SalOpBase*)op;
if (op_base->route_addresses) {
bctbx_list_for_each(op_base->route_addresses,(void (*)(void *))sal_address_destroy);
op_base->route_addresses=bctbx_list_free(op_base->route_addresses);
}
if (route) {
op_base->route_addresses=bctbx_list_append(NULL,NULL);
assign_address((SalAddress**)&(op_base->route_addresses->data),route);
route_string=sal_address_as_string((SalAddress*)op_base->route_addresses->data); \
}
assign_string(&op_base->route,route_string); \
if(route_string) ms_free(route_string);
}
const bctbx_list_t* sal_op_get_route_addresses(const SalOp *op) {
return ((SalOpBase*)op)->route_addresses;
}
void sal_op_set_route_address(SalOp *op, const SalAddress *address){
char* address_string=sal_address_as_string(address); /*can probably be optimized*/
sal_op_set_route(op,address_string);
ms_free(address_string);
}
void sal_op_add_route_address(SalOp *op, const SalAddress *address){
SalOpBase* op_base = (SalOpBase*)op;
if (op_base->route_addresses) {
op_base->route_addresses=bctbx_list_append(op_base->route_addresses,(void*)sal_address_clone(address));
} else {
sal_op_set_route_address(op,address);
}
}
void sal_op_set_realm(SalOp *op, const char *realm){
SalOpBase* op_base = (SalOpBase*)op;
if (op_base->realm != NULL){
ms_free(op_base->realm);
}
op_base->realm = ms_strdup(realm);
}
void sal_op_set_from(SalOp *op, const char *from){
SET_PARAM(op,from);
}
void sal_op_set_from_address(SalOp *op, const SalAddress *from){
char* address_string=sal_address_as_string(from); /*can probably be optimized*/
sal_op_set_from(op,address_string);
ms_free(address_string);
}
void sal_op_set_to(SalOp *op, const char *to){
SET_PARAM(op,to);
}
void sal_op_set_to_address(SalOp *op, const SalAddress *to){
char* address_string=sal_address_as_string(to); /*can probably be optimized*/
sal_op_set_to(op,address_string);
ms_free(address_string);
}
void sal_op_set_diversion_address(SalOp *op, const SalAddress *diversion){
if (((SalOpBase*)op)->diversion_address) sal_address_destroy(((SalOpBase*)op)->diversion_address);
((SalOpBase*)op)->diversion_address=diversion?sal_address_clone(diversion):NULL;
}
void sal_op_set_user_pointer(SalOp *op, void *up){
((SalOpBase*)op)->user_pointer=up;
}
Sal *sal_op_get_sal(const SalOp *op){
return ((SalOpBase*)op)->root;
}
const char *sal_op_get_from(const SalOp *op){
return ((SalOpBase*)op)->from;
}
const SalAddress *sal_op_get_from_address(const SalOp *op){
return ((SalOpBase*)op)->from_address;
}
const char *sal_op_get_to(const SalOp *op){
return ((SalOpBase*)op)->to;
}
const SalAddress *sal_op_get_to_address(const SalOp *op){
return ((SalOpBase*)op)->to_address;
}
const SalAddress *sal_op_get_diversion_address(const SalOp *op){
return ((SalOpBase*)op)->diversion_address;
}
const char *sal_op_get_remote_ua(const SalOp *op){
return ((SalOpBase*)op)->remote_ua;
}
void *sal_op_get_user_pointer(const SalOp *op){
return ((SalOpBase*)op)->user_pointer;
}
const char *sal_op_get_proxy(const SalOp *op){
return ((SalOpBase*)op)->route;
}
const char *sal_op_get_network_origin(const SalOp *op){
return ((SalOpBase*)op)->origin;
}
const char* sal_op_get_call_id(const SalOp *op) {
return ((SalOpBase*)op)->call_id;
}
void __sal_op_init(SalOp *b, Sal *sal){
memset(b,0,sizeof(SalOpBase));
((SalOpBase*)b)->root=sal;
}
void __sal_op_set_network_origin(SalOp *op, const char *origin){
SET_PARAM(op,origin);
}
void __sal_op_set_remote_contact(SalOp *op, const char* remote_contact){
assign_address(&((SalOpBase*)op)->remote_contact_address,remote_contact);\
/*to preserve header params*/
assign_string(&((SalOpBase*)op)->remote_contact,remote_contact); \
}
void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin){
char* address_string=sal_address_as_string(origin); /*can probably be optimized*/
__sal_op_set_network_origin(op,address_string);
ms_free(address_string);
}
void __sal_op_free(SalOp *op){
SalOpBase *b=(SalOpBase *)op;
if (b->from_address){
sal_address_destroy(b->from_address);
b->from_address=NULL;
}
if (b->to_address){
sal_address_destroy(b->to_address);
b->to_address=NULL;
}
if (b->service_route){
sal_address_destroy(b->service_route);
b->service_route=NULL;
}
if (b->origin_address){
sal_address_destroy(b->origin_address);
b->origin_address=NULL;
}
if (b->from) {
ms_free(b->from);
b->from=NULL;
}
if (b->to) {
ms_free(b->to);
b->to=NULL;
}
if (b->route) {
ms_free(b->route);
b->route=NULL;
}
if (b->realm) {
ms_free(b->realm);
b->realm=NULL;
}
if (b->contact_address) {
sal_address_destroy(b->contact_address);
}
if (b->origin){
ms_free(b->origin);
b->origin=NULL;
}
if (b->remote_ua){
ms_free(b->remote_ua);
b->remote_ua=NULL;
}
if (b->remote_contact){
ms_free(b->remote_contact);
b->remote_contact=NULL;
}
if (b->remote_contact_address){
sal_address_destroy(b->remote_contact_address);
}
if (b->local_media)
sal_media_description_unref(b->local_media);
if (b->remote_media)
sal_media_description_unref(b->remote_media);
if (b->call_id)
ms_free((void*)b->call_id);
if (b->service_route) {
sal_address_destroy(b->service_route);
}
if (b->route_addresses){
bctbx_list_for_each(b->route_addresses,(void (*)(void*)) sal_address_destroy);
b->route_addresses=bctbx_list_free(b->route_addresses);
}
if (b->recv_custom_headers)
sal_custom_header_free(b->recv_custom_headers);
if (b->sent_custom_headers)
sal_custom_header_free(b->sent_custom_headers);
if (b->entity_tag != NULL){
ms_free(b->entity_tag);
b->entity_tag = NULL;
}
ms_free(op);
}
SalAuthInfo* sal_auth_info_new() {
return ms_new0(SalAuthInfo,1);
}
SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info) {
SalAuthInfo* new_auth_info=sal_auth_info_new();
new_auth_info->username=auth_info->username?ms_strdup(auth_info->username):NULL;
new_auth_info->userid=auth_info->userid?ms_strdup(auth_info->userid):NULL;
new_auth_info->realm=auth_info->realm?ms_strdup(auth_info->realm):NULL;
new_auth_info->domain=auth_info->realm?ms_strdup(auth_info->domain):NULL;
new_auth_info->password=auth_info->password?ms_strdup(auth_info->password):NULL;
return new_auth_info;
}
void sal_auth_info_delete(SalAuthInfo* auth_info) {
if (auth_info->username) ms_free(auth_info->username);
if (auth_info->userid) ms_free(auth_info->userid);
if (auth_info->realm) ms_free(auth_info->realm);
if (auth_info->domain) ms_free(auth_info->domain);
if (auth_info->password) ms_free(auth_info->password);
if (auth_info->ha1) ms_free(auth_info->ha1);
if (auth_info->certificates) sal_certificates_chain_delete(auth_info->certificates);
if (auth_info->key) sal_signing_key_delete(auth_info->key);
ms_free(auth_info);
}
const char* sal_stream_type_to_string(SalStreamType type) {
switch (type) {
case SalAudio: return "audio";
case SalVideo: return "video";
case SalText: return "text";
default: return "other";
}
}
const char *sal_stream_description_get_type_as_string(const SalStreamDescription *desc){
if (desc->type==SalOther) return desc->typeother;
else return sal_stream_type_to_string(desc->type);
}
const char* sal_media_proto_to_string(SalMediaProto type) {
switch (type) {
case SalProtoRtpAvp:return "RTP/AVP";
case SalProtoRtpSavp:return "RTP/SAVP";
case SalProtoUdpTlsRtpSavp:return "UDP/TLS/RTP/SAVP";
case SalProtoRtpAvpf:return "RTP/AVPF";
case SalProtoRtpSavpf:return "RTP/SAVPF";
case SalProtoUdpTlsRtpSavpf:return "UDP/TLS/RTP/SAVPF";
default: return "unknown";
}
}
const char *sal_stream_description_get_proto_as_string(const SalStreamDescription *desc){
if (desc->proto==SalProtoOther) return desc->proto_other;
else return sal_media_proto_to_string(desc->proto);
}
const char* sal_stream_dir_to_string(SalStreamDir type) {
switch (type) {
case SalStreamSendRecv:return "sendrecv";
case SalStreamSendOnly:return "sendonly";
case SalStreamRecvOnly:return "recvonly";
case SalStreamInactive:return "inative";
default: return "unknown";
}
}
const char* sal_reason_to_string(const SalReason reason) {
switch (reason) {
case SalReasonDeclined : return "SalReasonDeclined";
case SalReasonBusy: return "SalReasonBusy";
case SalReasonRedirect: return "SalReasonRedirect";
case SalReasonTemporarilyUnavailable: return "SalReasonTemporarilyUnavailable";
case SalReasonNotFound: return "SalReasonNotFound";
case SalReasonDoNotDisturb: return "SalReasonDoNotDisturb";
case SalReasonUnsupportedContent: return "SalReasonUnsupportedContent";
case SalReasonForbidden: return "SalReasonForbidden";
case SalReasonUnknown: return "SalReasonUnknown";
case SalReasonServiceUnavailable: return "SalReasonServiceUnavailable";
case SalReasonNotAcceptable: return "SalReasonNotAcceptable";
default: return "Unkown reason";
}
}
const SalAddress* sal_op_get_service_route(const SalOp *op) {
return ((SalOpBase*)op)->service_route;
}
void sal_op_set_service_route(SalOp *op,const SalAddress* service_route) {
if (((SalOpBase*)op)->service_route)
sal_address_destroy(((SalOpBase*)op)->service_route);
((SalOpBase*)op)->service_route=service_route?sal_address_clone(service_route):NULL;
}
const char* sal_presence_status_to_string(const SalPresenceStatus status) {
switch (status) {
case SalPresenceOffline: return "SalPresenceOffline";
case SalPresenceOnline: return "SalPresenceOnline";
case SalPresenceBusy: return "SalPresenceBusy";
case SalPresenceBerightback: return "SalPresenceBerightback";
case SalPresenceAway: return "SalPresenceAway";
case SalPresenceOnthephone: return "SalPresenceOnthephone";
case SalPresenceOuttolunch: return "SalPresenceOuttolunch";
case SalPresenceDonotdisturb: return "SalPresenceDonotdisturb";
case SalPresenceMoved: return "SalPresenceMoved";
case SalPresenceAltService: return "SalPresenceAltService";
default : return "unknown";
}
}
const char* sal_privacy_to_string(SalPrivacy privacy) {
switch(privacy) {
case SalPrivacyUser: return "user";
case SalPrivacyHeader: return "header";
case SalPrivacySession: return "session";
case SalPrivacyId: return "id";
case SalPrivacyNone: return "none";
case SalPrivacyCritical: return "critical";
default: return NULL;
}
}
static void remove_trailing_spaces(char *line) {
size_t size = strlen(line);
char *end = line + size - 1;
while (end >= line && isspace(*end)) {
end--;
}
*(end + 1) = '\0';
}
static int line_get_value(const char *input, const char *key, char *value, size_t value_size, size_t *read){
const char *end=strchr(input,'\n');
char line[256]={0};
char key_candidate[256];
char *equal;
size_t len;
if (!end) len=strlen(input);
else len=end +1 -input;
*read=len;
strncpy(line,input,MIN(len,sizeof(line)));
equal=strchr(line,'=');
if (!equal) return FALSE;
*equal='\0';
if (sscanf(line,"%s",key_candidate)!=1) return FALSE;
if (strcasecmp(key,key_candidate)==0){
equal++;
remove_trailing_spaces(equal);
strncpy(value,equal,value_size-1);
value[value_size-1]='\0';
return TRUE;
}
return FALSE;
}
int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size){
size_t read=0;
do{
if (line_get_value(data,key,value,value_size,&read))
return TRUE;
data+=read;
}while(read!=0);
return FALSE;
}
const char *sal_op_get_entity_tag(const SalOp* op) {
SalOpBase* op_base = (SalOpBase*)op;
return op_base->entity_tag;
}
void sal_op_set_entity_tag(SalOp *op, const char* entity_tag) {
SalOpBase* op_base = (SalOpBase*)op;
if (op_base->entity_tag != NULL){
ms_free(op_base->entity_tag);
}
if (entity_tag)
op_base->entity_tag = ms_strdup(entity_tag);
else
op_base->entity_tag = NULL;
}

View file

@ -27,23 +27,13 @@ static void linphone_video_definition_destroy(LinphoneVideoDefinition *vdef) {
if (vdef->name) bctbx_free(vdef->name);
}
static void _linphone_video_definition_clone(LinphoneVideoDefinition *obj, const LinphoneVideoDefinition *orig){
obj->name = bctbx_strdup(orig->name);
obj->width = orig->width;
obj->height = orig->height;
}
belle_sip_error_code _linphone_video_definition_marshal(const LinphoneVideoDefinition* obj, char* buff, size_t buff_size, size_t *offset){
return belle_sip_snprintf(buff,buff_size,offset,"%s",obj->name);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneVideoDefinition);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneVideoDefinition, belle_sip_object_t,
(belle_sip_object_destroy_t)linphone_video_definition_destroy,
(belle_sip_object_clone_t)_linphone_video_definition_clone, // clone
(belle_sip_object_marshal_t)_linphone_video_definition_marshal, // marshal
FALSE
NULL, // clone
NULL, // marshal
TRUE
);
@ -77,7 +67,7 @@ void linphone_video_definition_set_user_data(LinphoneVideoDefinition *vdef, void
}
LinphoneVideoDefinition * linphone_video_definition_clone(const LinphoneVideoDefinition *vdef) {
return (LinphoneVideoDefinition*)belle_sip_object_clone((belle_sip_object_t*)vdef);
return linphone_video_definition_new(linphone_video_definition_get_width(vdef), linphone_video_definition_get_height(vdef), linphone_video_definition_get_name(vdef));
}
unsigned int linphone_video_definition_get_width(const LinphoneVideoDefinition *vdef) {

View file

@ -342,12 +342,6 @@ void linphone_gtk_call_log_update(GtkWidget *w){
case LinphoneCallDeclined:
status=_("Declined");
break;
case LinphoneCallAnsweredElsewhere:
status=_("Answered elsewhere");
break;
case LinphoneCallDeclinedElsewhere:
status=_("Declined elsewhere");
break;
default:
break;
}

View file

@ -1,8 +1,8 @@
################################################################################
############################################################################
# CMakeLists.txt
# Copyright (C) 2017 Belledonne Communications, Grenoble France
# Copyright (C) 2010-2016 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
@ -18,24 +18,25 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
################################################################################
############################################################################
set(ROOT_HEADER_FILES
account_creator_service.h
set(HEADER_FILES
account_creator.h
account_creator_service.h
address.h
auth_info.h
buffer.h
call.h
callbacks.h
call_log.h
call_params.h
call_stats.h
call.h
callbacks.h
chat.h
conference.h
contactprovider.h
content.h
core_utils.h
core.h
core_utils.h
defs.h
dictionary.h
error_info.h
@ -43,7 +44,6 @@ set(ROOT_HEADER_FILES
factory.h
friend.h
friendlist.h
headers.h
im_encryption_engine.h
im_notif_policy.h
info_message.h
@ -63,74 +63,24 @@ set(ROOT_HEADER_FILES
video_definition.h
wrapper_utils.h
xmlrpc.h
headers.h
# Deprecated header files
linphone_proxy_config.h
linphone_tunnel.h
linphonecore_utils.h
linphonecore.h
linphonecore_utils.h
linphonefriend.h
linphonepresence.h
linphone_proxy_config.h
linphone_tunnel.h
)
set(C_API_HEADER_FILES
c-address.h
c-api.h
c-event-log.h
c-types.h
)
set(LINPHONE_HEADER_FILES )
foreach(HEADER_FILE ${HEADER_FILES})
list(APPEND LINPHONE_HEADER_FILES "${CMAKE_CURRENT_LIST_DIR}/linphone/${HEADER_FILE}")
endforeach()
set(LINPHONE_HEADER_FILES ${LINPHONE_HEADER_FILES} PARENT_SCOPE)
set(ENUMS_HEADER_FILES
event-log-enums.h
)
set(UTILS_HEADER_FILES
enum-generator.h
general.h
magic-macros.h
utils.h
)
# ------------------------------------------------------------------------------
function (PREPEND OUT_LIST PREFIX)
set(TMP_LIST )
foreach (FILENAME ${ARGN})
list(APPEND TMP_LIST "${PREFIX}/${FILENAME}")
endforeach ()
set(${OUT_LIST} "${TMP_LIST}" PARENT_SCOPE)
endfunction ()
# ------------------------------------------------------------------------------
set(SRC_ROOT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/linphone")
PREPEND(ROOT_HEADER_FILES "${SRC_ROOT_DIRECTORY}" ${ROOT_HEADER_FILES})
PREPEND(C_API_HEADER_FILES "${SRC_ROOT_DIRECTORY}/api" ${C_API_HEADER_FILES})
PREPEND(ENUMS_HEADER_FILES "${SRC_ROOT_DIRECTORY}/enums" ${ENUMS_HEADER_FILES})
PREPEND(UTILS_HEADER_FILES "${SRC_ROOT_DIRECTORY}/utils" ${UTILS_HEADER_FILES})
set(LINPHONE_HEADER_FILES ${ROOT_HEADER_FILES} ${C_API_HEADER_FILES} ${ENUMS_HEADER_FILES} ${UTILS_HEADER_FILES} PARENT_SCOPE)
# ------------------------------------------------------------------------------
set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_INCLUDEDIR}/linphone")
install(FILES ${ROOT_HEADER_FILES}
DESTINATION "${DEST_ROOT_DIRECTORY}"
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
install(FILES ${C_API_HEADER_FILES}
DESTINATION "${DEST_ROOT_DIRECTORY}/api"
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
install(FILES ${ENUMS_HEADER_FILES}
DESTINATION "${DEST_ROOT_DIRECTORY}/enums"
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
install(FILES ${UTILS_HEADER_FILES}
DESTINATION "${DEST_ROOT_DIRECTORY}/utils"
install(FILES ${LINPHONE_HEADER_FILES}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/linphone
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)

241
include/linphone/address.h Normal file
View file

@ -0,0 +1,241 @@
/*
address.h
Copyright (C) 2010-2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef LINPHONE_ADDRESS_H
#define LINPHONE_ADDRESS_H
#include "linphone/types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup linphone_address
* @{
*/
/**
* Constructs a LinphoneAddress object by parsing the user supplied address,
* given as a string.
**/
LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr);
/**
* Clones a LinphoneAddress object.
**/
LINPHONE_PUBLIC LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr);
/**
* Increment reference count of LinphoneAddress object.
**/
LINPHONE_PUBLIC LinphoneAddress * linphone_address_ref(LinphoneAddress *addr);
/**
* Decrement reference count of LinphoneAddress object. When dropped to zero, memory is freed.
**/
LINPHONE_PUBLIC void linphone_address_unref(LinphoneAddress *addr);
/**
* Returns the address scheme, normally "sip".
**/
LINPHONE_PUBLIC const char *linphone_address_get_scheme(const LinphoneAddress *u);
/**
* Returns the display name.
**/
LINPHONE_PUBLIC const char *linphone_address_get_display_name(const LinphoneAddress* u);
/**
* Returns the username.
**/
LINPHONE_PUBLIC const char *linphone_address_get_username(const LinphoneAddress *u);
/**
* Returns the domain name.
**/
LINPHONE_PUBLIC const char *linphone_address_get_domain(const LinphoneAddress *u);
/**
* Get port number as an integer value, 0 if not present.
*/
LINPHONE_PUBLIC int linphone_address_get_port(const LinphoneAddress *u);
/**
* Sets the display name.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_address_set_display_name(LinphoneAddress *u, const char *display_name);
/**
* Sets the username.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_address_set_username(LinphoneAddress *uri, const char *username);
/**
* Sets the domain.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_address_set_domain(LinphoneAddress *uri, const char *host);
/**
* Sets the port number.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_address_set_port(LinphoneAddress *uri, int port);
/**
* Set a transport.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_address_set_transport(LinphoneAddress *uri,LinphoneTransportType type);
/**
* Removes address's tags and uri headers so that it is displayable to the user.
**/
LINPHONE_PUBLIC void linphone_address_clean(LinphoneAddress *uri);
/**
* Returns true if address refers to a secure location (sips)
* @deprecated use linphone_address_get_secure()
* @donotwrap
**/
LINPHONE_DEPRECATED LINPHONE_PUBLIC bool_t linphone_address_is_secure(const LinphoneAddress *addr);
/**
* Returns true if address refers to a secure location (sips)
**/
LINPHONE_PUBLIC bool_t linphone_address_get_secure(const LinphoneAddress *addr);
/**
* Make the address refer to a secure location (sips scheme)
* @param[in] addr A #LinphoneAddress object
* @param[in] enabled TRUE if address is requested to be secure.
**/
LINPHONE_PUBLIC void linphone_address_set_secure(LinphoneAddress *addr, bool_t enabled);
/**
* returns true if address is a routable sip address
*/
LINPHONE_PUBLIC bool_t linphone_address_is_sip(const LinphoneAddress *uri);
/**
* Get the transport.
**/
LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri);
/**
* Get the value of the method parameter
**/
LINPHONE_PUBLIC const char *linphone_address_get_method_param(const LinphoneAddress *addr);
/**
* Set the value of the method parameter
**/
LINPHONE_PUBLIC void linphone_address_set_method_param(LinphoneAddress *addr, const char *method);
/**
* Returns the address as a string.
* The returned char * must be freed by the application. Use ms_free().
**/
LINPHONE_PUBLIC char *linphone_address_as_string(const LinphoneAddress *u);
/**
* Returns the SIP uri only as a string, that is display name is removed.
* The returned char * must be freed by the application. Use ms_free().
**/
LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u);
/**
* Compare two LinphoneAddress ignoring tags and headers, basically just domain, username, and port.
* @param[in] a1 LinphoneAddress object
* @param[in] a2 LinphoneAddress object
* @return Boolean value telling if the LinphoneAddress objects are equal.
* @see linphone_address_equal()
**/
LINPHONE_PUBLIC bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2);
/**
* Compare two LinphoneAddress taking the tags and headers into account.
* @param[in] a1 LinphoneAddress object
* @param[in] a2 LinphoneAddress object
* @return Boolean value telling if the LinphoneAddress objects are equal.
* @see linphone_address_weak_equal()
*/
LINPHONE_PUBLIC bool_t linphone_address_equal(const LinphoneAddress *a1, const LinphoneAddress *a2);
/**
* Set the password encoded in the address.
* It is used for basic authentication (not recommended).
* @param addr the LinphoneAddress
* @param passwd the password to set.
**/
LINPHONE_PUBLIC void linphone_address_set_password(LinphoneAddress *addr, const char *passwd);
/**
* Get the password encoded in the address.
* It is used for basic authentication (not recommended).
* @param addr the address
* @return the password, if any, NULL otherwise.
**/
LINPHONE_PUBLIC const char *linphone_address_get_password(const LinphoneAddress *addr);
/**
* Set a header into the address.
* Headers appear in the URI with '?', such as \<sip:test@linphone.org?SomeHeader=SomeValue\>.
* @param addr the address
* @param header_name the header name
* @param header_value the header value
**/
LINPHONE_PUBLIC void linphone_address_set_header(LinphoneAddress *addr, const char *header_name, const char *header_value);
/**
* Get the header encoded in the address.
* @param addr the address
**/
LINPHONE_PUBLIC const char * linphone_address_get_header(const LinphoneAddress *addr, const char *name);
LINPHONE_PUBLIC bool_t linphone_address_has_param(const LinphoneAddress *addr, const char *name);
LINPHONE_PUBLIC const char * linphone_address_get_param(const LinphoneAddress *addr, const char *name);
LINPHONE_PUBLIC void linphone_address_set_param(LinphoneAddress *addr, const char *name, const char *value);
LINPHONE_PUBLIC void linphone_address_set_params(LinphoneAddress *addr, const char *params);
LINPHONE_PUBLIC void linphone_address_set_uri_param(LinphoneAddress *addr, const char *name, const char *value);
LINPHONE_PUBLIC void linphone_address_set_uri_params(LinphoneAddress *addr, const char *params);
LINPHONE_PUBLIC bool_t linphone_address_has_uri_param(const LinphoneAddress *addr, const char *name);
LINPHONE_PUBLIC const char * linphone_address_get_uri_param(const LinphoneAddress *addr, const char *name);
/**
* Destroys a LinphoneAddress object (actually calls linphone_address_unref()).
* @deprecated Use linphone_address_unref() instead
* @donotwrap
**/
LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_address_destroy(LinphoneAddress *u);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* LINPHONE_ADDRESS_H */

View file

@ -1,242 +0,0 @@
/*
* c-event-log.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _C_EVENT_LOG_H_
#define _C_EVENT_LOG_H_
#include "linphone/api/c-types.h"
// =============================================================================
#ifdef __cplusplus
extern "C" {
#endif // ifdef __cplusplus
/**
* @addtogroup linphone_address
* @{
*/
/**
* Constructs a LinphoneAddress object by parsing the user supplied address,
* given as a string.
**/
LINPHONE_PUBLIC LinphoneAddress *linphone_address_new (const char *address);
/**
* Clones a LinphoneAddress object.
**/
LINPHONE_PUBLIC LinphoneAddress *linphone_address_clone (const LinphoneAddress *address);
/**
* Increment reference count of LinphoneAddress object.
**/
LINPHONE_PUBLIC LinphoneAddress *linphone_address_ref (LinphoneAddress *address);
/**
* Decrement reference count of LinphoneAddress object. When dropped to zero, memory is freed.
**/
LINPHONE_PUBLIC void linphone_address_unref (LinphoneAddress *address);
/**
* Returns the address scheme, normally "sip".
**/
LINPHONE_PUBLIC const char *linphone_address_get_scheme (const LinphoneAddress *address);
/**
* Returns the display name.
**/
LINPHONE_PUBLIC const char *linphone_address_get_display_name (const LinphoneAddress *address);
/**
* Sets the display name.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_address_set_display_name (LinphoneAddress *address, const char *display_name);
/**
* Returns the username.
**/
LINPHONE_PUBLIC const char *linphone_address_get_username (const LinphoneAddress *address);
/**
* Sets the username.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_address_set_username (LinphoneAddress *address, const char *username);
/**
* Returns the domain name.
**/
LINPHONE_PUBLIC const char *linphone_address_get_domain (const LinphoneAddress *address);
/**
* Sets the domain.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_address_set_domain (LinphoneAddress *address, const char *domain);
/**
* Get port number as an integer value, 0 if not present.
*/
LINPHONE_PUBLIC int linphone_address_get_port (const LinphoneAddress *address);
/**
* Sets the port number.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_address_set_port (LinphoneAddress *address, int port);
/**
* Get the transport.
**/
LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport (const LinphoneAddress *address);
/**
* Set a transport.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_address_set_transport (LinphoneAddress *address, LinphoneTransportType transport);
/**
* Returns true if address refers to a secure location (sips)
**/
LINPHONE_PUBLIC bool_t linphone_address_get_secure (const LinphoneAddress *address);
/**
* Make the address refer to a secure location (sips scheme)
* @param[in] address A #LinphoneAddress object
* @param[in] enabled TRUE if address is requested to be secure.
**/
LINPHONE_PUBLIC void linphone_address_set_secure (LinphoneAddress *address, bool_t enabled);
/**
* returns true if address is a routable sip address
*/
LINPHONE_PUBLIC bool_t linphone_address_is_sip (const LinphoneAddress *address);
/**
* Get the value of the method parameter
**/
LINPHONE_PUBLIC const char *linphone_address_get_method_param (const LinphoneAddress *address);
/**
* Set the value of the method parameter
**/
LINPHONE_PUBLIC void linphone_address_set_method_param (LinphoneAddress *address, const char *method_param);
/**
* Get the password encoded in the address.
* It is used for basic authentication (not recommended).
* @param address the address
* @return the password, if any, NULL otherwise.
**/
LINPHONE_PUBLIC const char *linphone_address_get_password (const LinphoneAddress *address);
/**
* Set the password encoded in the address.
* It is used for basic authentication (not recommended).
* @param address the LinphoneAddress
* @param password the password to set.
**/
LINPHONE_PUBLIC void linphone_address_set_password (LinphoneAddress *address, const char *password);
/**
* Removes address's tags and uri headers so that it is displayable to the user.
**/
LINPHONE_PUBLIC void linphone_address_clean (LinphoneAddress *address);
/**
* Returns the address as a string.
* The returned char * must be freed by the application. Use ms_free().
**/
LINPHONE_PUBLIC char *linphone_address_as_string (const LinphoneAddress *address);
/**
* Returns the SIP uri only as a string, that is display name is removed.
* The returned char * must be freed by the application. Use ms_free().
**/
LINPHONE_PUBLIC char *linphone_address_as_string_uri_only (const LinphoneAddress *address);
/**
* Compare two LinphoneAddress ignoring tags and headers, basically just domain, username, and port.
* @param[in] address1 LinphoneAddress object
* @param[in] address2 LinphoneAddress object
* @return Boolean value telling if the LinphoneAddress objects are equal.
* @see linphone_address_equal()
**/
LINPHONE_PUBLIC bool_t linphone_address_weak_equal (const LinphoneAddress *address1, const LinphoneAddress *address2);
/**
* Compare two LinphoneAddress taking the tags and headers into account.
* @param[in] address1 LinphoneAddress object
* @param[in] address2 LinphoneAddress object
* @return Boolean value telling if the LinphoneAddress objects are equal.
* @see linphone_address_weak_equal()
*/
LINPHONE_PUBLIC bool_t linphone_address_equal (const LinphoneAddress *address1, const LinphoneAddress *address2);
/**
* Get the header encoded in the address.
* @param address the address
**/
LINPHONE_PUBLIC const char *linphone_address_get_header (const LinphoneAddress *address, const char *header_name);
/**
* Set a header into the address.
* Headers appear in the URI with '?', such as \<sip:test@linphone.org?SomeHeader=SomeValue\>.
* @param address the address
* @param header_name the header name
* @param header_value the header value
**/
LINPHONE_PUBLIC void linphone_address_set_header (LinphoneAddress *address, const char *header_name, const char *header_value);
LINPHONE_PUBLIC bool_t linphone_address_has_param (const LinphoneAddress *address, const char *param_name);
LINPHONE_PUBLIC const char *linphone_address_get_param (const LinphoneAddress *address, const char *param_name);
LINPHONE_PUBLIC void linphone_address_set_param (LinphoneAddress *address, const char *param_name, const char *param_value);
LINPHONE_PUBLIC void linphone_address_set_params (LinphoneAddress *address, const char *params);
LINPHONE_PUBLIC bool_t linphone_address_has_uri_param (const LinphoneAddress *address, const char *uri_param_name);
LINPHONE_PUBLIC const char *linphone_address_get_uri_param (const LinphoneAddress *address, const char *uri_param_name);
LINPHONE_PUBLIC void linphone_address_set_uri_param (LinphoneAddress *address, const char *uri_param_name, const char *uri_param_value);
LINPHONE_PUBLIC void linphone_address_set_uri_params (LinphoneAddress *address, const char *params);
/**
* Destroys a LinphoneAddress object (actually calls linphone_address_unref()).
* @deprecated Use linphone_address_unref() instead
* @donotwrap
**/
LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_address_destroy (LinphoneAddress *address);
/**
* Returns true if address refers to a secure location (sips)
* @deprecated use linphone_address_get_secure()
* @donotwrap
**/
LINPHONE_DEPRECATED LINPHONE_PUBLIC bool_t linphone_address_is_secure (const LinphoneAddress *address);
/**
* @}
*/
#ifdef __cplusplus
}
#endif // ifdef __cplusplus
#endif // ifndef _C_EVENT_LOG_H_

View file

@ -1,25 +0,0 @@
/*
* c-api.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _C_API_H_
#define _C_API_H_
#include "linphone/api/c-address.h"
#include "linphone/api/c-event-log.h"
#endif // ifndef _C_API_H_

View file

@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "linphone/account_creator.h"
#include "linphone/account_creator_service.h"
#include "linphone/address.h"
#include "linphone/auth_info.h"
#include "linphone/buffer.h"
#include "linphone/call.h"
@ -65,8 +66,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "linphone/xmlrpc.h"
#include "linphone/headers.h"
// For migration purpose.
#include "linphone/api/c-api.h"
#ifdef __cplusplus
extern "C" {

View file

@ -26,8 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mediastreamer2/msvideo.h"
#include "linphone/defs.h"
// For migration purpose.
#include "linphone/api/c-types.h"
/**
* The LinphoneAccountCreator object used to configure an account on a server via XML-RPC.
@ -171,6 +169,22 @@ typedef enum _LinphoneAccountCreatorStatus {
LinphoneAccountCreatorStatusServerError /**< Error server */
} LinphoneAccountCreatorStatus;
struct SalAddress;
/**
* Object that represents a SIP address.
*
* The LinphoneAddress is an opaque object to represents SIP addresses, ie
* the content of SIP's 'from' and 'to' headers.
* A SIP address is made of display name, username, domain name, port, and various
* uri headers (such as tags). It looks like 'Alice <sip:alice@example.net>'.
* The LinphoneAddress has methods to extract and manipulate all parts of the address.
* When some part of the address (for example the username) is empty, the accessor methods
* return NULL.
* @ingroup linphone_address
*/
typedef struct SalAddress LinphoneAddress;
/**
* Enum describing Ip family.
* @ingroup initializing
@ -329,9 +343,7 @@ typedef enum _LinphoneCallStatus {
LinphoneCallAborted, /**< The call was aborted */
LinphoneCallMissed, /**< The call was missed (unanswered) */
LinphoneCallDeclined, /**< The call was declined, either locally or by remote end */
LinphoneCallEarlyAborted, /**<The call was aborted before being advertised to the application - for protocol reasons*/
LinphoneCallAcceptedElsewhere, /**<The call was answered on another device*/
LinphoneCallDeclinedElsewhere /**<The call was declined on another device*/
LinphoneCallEarlyAborted /**<The call was aborted before being advertised to the application - for protocol reasons*/
} LinphoneCallStatus;
/**

View file

@ -789,7 +789,7 @@ LINPHONE_PUBLIC void sal_default_set_sdp_handling(Sal* h, SalOpSDPHandling handl
LINPHONE_PUBLIC void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) ;
/*Registration*/
int sal_register(SalOp *op, const char *proxy, const char *from, int expires, const SalAddress* old_contact);
int sal_register(SalOp *op, const char *proxy, const char *from, int expires,SalAddress* old_contact);
/*refresh a register, -1 mean use the last known value*/
int sal_register_refresh(SalOp *op, int expires);
int sal_unregister(SalOp *h);

View file

@ -61,16 +61,6 @@ public interface LinphoneCallLog {
*/
public final static CallStatus EarlyAborted = new CallStatus(4,"Early Aborted");
/**
* The call was answered on another device
*/
public final static CallStatus AcceptedElsewhere = new CallStatus(5,"Accepted Elsewhere");
/**
* The call was declined on another device
*/
public final static CallStatus DeclinedElsewhere = new CallStatus(6,"Declined Elsewhere");
private CallStatus(int value,String stringValue) {
mValue = value;

View file

@ -21,14 +21,9 @@
############################################################################
set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES
address/address-p.h
address/address.h
c-wrapper/api/c-event-log.h
c-wrapper/c-tools.h
chat/chat-message.h
chat/chat-room-p.h
chat/chat-room.h
chat/imdn.h
chat/is-composing.h
c-wrapper/c-types.h
content/content.h
core/core.h
cpim/cpim.h
@ -45,31 +40,29 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES
db/provider/db-session-p.h
db/provider/db-session-provider.h
db/provider/db-session.h
enums.h
event-log/call-event.h
event-log/conference-event-p.h
event-log/conference-event.h
event-log/conference-participant-event.h
event-log/event-log-enums.h
event-log/event-log-p.h
event-log/event-log.h
event-log/message-event.h
logger/logger.h
message/message.h
object/clonable-object-p.h
object/clonable-object.h
object/object-p.h
object/object.h
object/singleton.h
utils/content-type.h
utils/enum-generator.h
utils/general.h
utils/magic-macros.h
utils/utils.h
)
set(LINPHONE_CXX_OBJECTS_SOURCE_FILES
address/address.cpp
c-wrapper/api/c-address.cpp
c-wrapper/api/c-event-log.cpp
chat/chat-message.cpp
chat/chat-room.cpp
chat/imdn.cpp
chat/is-composing.cpp
content/content.cpp
core/core.cpp
cpim/header/cpim-core-headers.cpp
@ -88,9 +81,9 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES
event-log/event-log.cpp
event-log/message-event.cpp
logger/logger.cpp
message/message.cpp
object/clonable-object.cpp
object/object.cpp
utils/content-type.cpp
utils/general.cpp
utils/utils.cpp
)

View file

@ -1,59 +0,0 @@
/*
* address-p.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ADDRESS_P_H_
#define _ADDRESS_P_H_
#include "address.h"
#include "object/clonable-object-p.h"
// =============================================================================
struct SalAddress;
LINPHONE_BEGIN_NAMESPACE
class AddressPrivate : public ClonableObjectPrivate {
public:
inline const SalAddress *getInternalAddress () const {
return internalAddress;
}
private:
struct AddressCache {
mutable std::string scheme;
mutable std::string displayName;
mutable std::string username;
mutable std::string domain;
mutable std::string methodParam;
mutable std::string password;
mutable std::unordered_map<std::string, std::string> headers;
mutable std::unordered_map<std::string, std::string> params;
mutable std::unordered_map<std::string, std::string> uriParams;
};
SalAddress *internalAddress = nullptr;
AddressCache cache;
L_DECLARE_PUBLIC(Address);
};
LINPHONE_END_NAMESPACE
#endif

View file

@ -1,354 +0,0 @@
/*
* address.cpp
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY {} without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "linphone/utils/utils.h"
#include "sal/sal.h"
#include "address-p.h"
#include "c-wrapper/c-tools.h"
#include "logger/logger.h"
#include "address.h"
// =============================================================================
using namespace std;
LINPHONE_BEGIN_NAMESPACE
// -----------------------------------------------------------------------------
Address::Address (const string &address) : ClonableObject(*new AddressPrivate) {
L_D(Address);
if (!(d->internalAddress = sal_address_new(L_STRING_TO_C(address)))) {
lWarning() << "Cannot create address, bad uri [" << address << "].";
return;
}
}
Address::Address (const Address &src) : ClonableObject(*new AddressPrivate) {
L_D(Address);
SalAddress *salAddress = src.getPrivate()->internalAddress;
if (salAddress)
d->internalAddress = sal_address_clone(salAddress);
}
Address::~Address () {
L_D(Address);
if (d->internalAddress)
sal_address_destroy(d->internalAddress);
}
Address &Address::operator= (const Address &src) {
L_D(Address);
if (this != &src) {
if (d->internalAddress)
sal_address_destroy(d->internalAddress);
SalAddress *salAddress = src.getPrivate()->internalAddress;
d->internalAddress = salAddress ? sal_address_clone(salAddress) : nullptr;
}
return *this;
}
Address::operator bool () const {
L_D(const Address);
return static_cast<bool>(d->internalAddress);
}
bool Address::operator== (const Address &address) const {
return equal(address);
}
const string &Address::getScheme () const {
L_D(const Address);
d->cache.scheme = L_C_TO_STRING(sal_address_get_scheme(d->internalAddress));
return d->cache.scheme;
}
const string &Address::getDisplayName () const {
L_D(const Address);
d->cache.displayName = L_C_TO_STRING(sal_address_get_display_name(d->internalAddress));
return d->cache.displayName;
}
bool Address::setDisplayName (const string &displayName) {
L_D(Address);
if (!d->internalAddress)
return false;
sal_address_set_display_name(d->internalAddress, L_STRING_TO_C(displayName));
return true;
}
const string &Address::getUsername () const {
L_D(const Address);
d->cache.username = L_C_TO_STRING(sal_address_get_username(d->internalAddress));
return d->cache.username;
}
bool Address::setUsername (const string &username) {
L_D(Address);
if (!d->internalAddress)
return false;
sal_address_set_username(d->internalAddress, L_STRING_TO_C(username));
return true;
}
const string &Address::getDomain () const {
L_D(const Address);
d->cache.domain = L_C_TO_STRING(sal_address_get_domain(d->internalAddress));
return d->cache.domain;
}
bool Address::setDomain (const string &domain) {
L_D(Address);
if (!d->internalAddress)
return false;
sal_address_set_domain(d->internalAddress, L_STRING_TO_C(domain));
return true;
}
int Address::getPort () const {
L_D(const Address);
return d->internalAddress ? sal_address_get_port(d->internalAddress) : 0;
}
bool Address::setPort (int port) {
L_D(const Address);
if (!d->internalAddress)
return false;
sal_address_set_port(d->internalAddress, port);
return true;
}
Transport Address::getTransport () const {
L_D(const Address);
return d->internalAddress ? static_cast<Transport>(sal_address_get_transport(d->internalAddress)) : Transport::Udp;
}
bool Address::setTransport (Transport transport) {
L_D(const Address);
if (!d->internalAddress)
return false;
sal_address_set_transport(d->internalAddress, static_cast<SalTransport>(transport));
return true;
}
bool Address::getSecure () const {
L_D(const Address);
return d->internalAddress ? sal_address_is_secure(d->internalAddress) : false;
}
bool Address::setSecure (bool enabled) {
L_D(const Address);
if (!d->internalAddress)
return false;
sal_address_set_secure(d->internalAddress, enabled);
return true;
}
bool Address::isSip () const {
L_D(const Address);
return d->internalAddress ? sal_address_is_sip(d->internalAddress) : false;
}
const string &Address::getMethodParam () const {
L_D(const Address);
d->cache.methodParam = L_C_TO_STRING(sal_address_get_method_param(d->internalAddress));
return d->cache.methodParam;
}
bool Address::setMethodParam (const string &methodParam) {
L_D(Address);
if (!d->internalAddress)
return false;
sal_address_set_method_param(d->internalAddress, L_STRING_TO_C(methodParam));
return true;
}
const string &Address::getPassword () const {
L_D(const Address);
d->cache.password = L_C_TO_STRING(sal_address_get_password(d->internalAddress));
return d->cache.password;
}
bool Address::setPassword (const string &password) {
L_D(Address);
if (!d->internalAddress)
return false;
sal_address_set_password(d->internalAddress, L_STRING_TO_C(password));
return true;
}
bool Address::clean () {
L_D(const Address);
if (!d->internalAddress)
return false;
sal_address_clean(d->internalAddress);
return true;
}
string Address::asString () const {
L_D(const Address);
if (!d->internalAddress)
return "";
char *buf = sal_address_as_string(d->internalAddress);
string out = buf;
ms_free(buf);
return out;
}
string Address::asStringUriOnly () const {
L_D(const Address);
if (!d->internalAddress)
return "";
char *buf = sal_address_as_string_uri_only(d->internalAddress);
string out = buf;
ms_free(buf);
return out;
}
bool Address::equal (const Address &address) const {
return asString() == address.asString();
}
bool Address::weakEqual (const Address &address) const {
return getUsername() == address.getUsername() &&
getDomain() == address.getDomain() &&
getPort() == address.getPort();
}
const string &Address::getHeaderValue (const string &headerName) const {
L_D(const Address);
const char *value = sal_address_get_header(d->internalAddress, L_STRING_TO_C(headerName));
if (value) {
d->cache.headers[headerName] = value;
return d->cache.headers[headerName];
}
return Utils::getEmptyConstRefObject<string>();
}
bool Address::setHeader (const string &headerName, const string &headerValue) {
L_D(Address);
if (!d->internalAddress)
return false;
sal_address_set_header(d->internalAddress, L_STRING_TO_C(headerName), L_STRING_TO_C(headerValue));
return true;
}
bool Address::hasParam (const string &paramName) const {
L_D(const Address);
return sal_address_has_param(d->internalAddress, L_STRING_TO_C(paramName));
}
const string &Address::getParamValue (const string &paramName) const {
L_D(const Address);
const char *value = sal_address_get_param(d->internalAddress, L_STRING_TO_C(paramName));
if (value) {
d->cache.params[paramName] = value;
return d->cache.params[paramName];
}
return Utils::getEmptyConstRefObject<string>();
}
bool Address::setParam (const string &paramName, const string &paramValue) {
L_D(Address);
if (!d->internalAddress)
return false;
sal_address_set_param(d->internalAddress, L_STRING_TO_C(paramName), L_STRING_TO_C(paramValue));
return true;
}
bool Address::setParams (const string &params) {
L_D(Address);
if (!d->internalAddress)
return false;
sal_address_set_params(d->internalAddress, L_STRING_TO_C(params));
return true;
}
bool Address::hasUriParam (const string &uriParamName) const {
L_D(const Address);
return sal_address_has_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName));
}
const string &Address::getUriParamValue (const string &uriParamName) const {
L_D(const Address);
const char *value = sal_address_get_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName));
if (value) {
d->cache.uriParams[uriParamName] = value;
return d->cache.uriParams[uriParamName];
}
return Utils::getEmptyConstRefObject<string>();
}
bool Address::setUriParam (const string &uriParamName, const string &uriParamValue) {
L_D(Address);
if (!d->internalAddress)
return false;
sal_address_set_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName), L_STRING_TO_C(uriParamValue));
return true;
}
bool Address::setUriParams (const string &uriParams) {
L_D(Address);
if (!d->internalAddress)
return false;
sal_address_set_uri_params(d->internalAddress, L_STRING_TO_C(uriParams));
return true;
}
LINPHONE_END_NAMESPACE

View file

@ -1,100 +0,0 @@
/*
* address.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ADDRESS_H_
#define _ADDRESS_H_
#include <string>
#include "enums.h"
#include "object/clonable-object.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
class AddressPrivate;
class LINPHONE_PUBLIC Address : public ClonableObject {
public:
Address (const std::string &address = "");
Address (const Address &src);
~Address ();
Address &operator= (const Address &src);
operator bool () const;
bool operator== (const Address &address) const;
const std::string &getScheme () const;
const std::string &getDisplayName () const;
bool setDisplayName (const std::string &displayName);
const std::string &getUsername () const;
bool setUsername (const std::string &username);
const std::string &getDomain () const;
bool setDomain (const std::string &domain);
int getPort () const;
bool setPort (int port);
Transport getTransport () const;
bool setTransport (Transport transport);
bool getSecure () const;
bool setSecure (bool enabled);
bool isSip () const;
const std::string &getMethodParam () const;
bool setMethodParam (const std::string &methodParam);
const std::string &getPassword () const;
bool setPassword (const std::string &password);
bool clean ();
std::string asString () const;
std::string asStringUriOnly () const;
bool equal (const Address &address) const;
bool weakEqual (const Address &address) const;
const std::string &getHeaderValue (const std::string &headerName) const;
bool setHeader (const std::string &headerName, const std::string &headerValue);
bool hasParam (const std::string &paramName) const;
const std::string &getParamValue (const std::string &paramName) const;
bool setParam (const std::string &paramName, const std::string &paramValue);
bool setParams (const std::string &params);
bool hasUriParam (const std::string &uriParamName) const;
const std::string &getUriParamValue (const std::string &uriParamName) const;
bool setUriParam (const std::string &uriParamName, const std::string &uriParamValue);
bool setUriParams (const std::string &uriParams);
private:
L_DECLARE_PRIVATE(Address);
};
LINPHONE_END_NAMESPACE
#endif // ifndef _ADDRESS_H_

View file

@ -1,192 +0,0 @@
/*
* c-event-log.cpp
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "linphone/api/c-address.h"
#include "c-wrapper/c-tools.h"
#include "address/address.h"
// =============================================================================
using namespace std;
L_DECLARE_C_STRUCT_IMPL(Address, address);
LinphoneAddress *linphone_address_new (const char *address) {
shared_ptr<LINPHONE_NAMESPACE::Address> cppPtr = make_shared<LINPHONE_NAMESPACE::Address>(L_C_TO_STRING(address));
if (!*cppPtr.get())
return nullptr;
LinphoneAddress *object = _linphone_address_init();
object->cppPtr = cppPtr;
return object;
}
LinphoneAddress *linphone_address_clone (const LinphoneAddress *address) {
return (LinphoneAddress *)belle_sip_object_clone(BELLE_SIP_OBJECT(address));
}
LinphoneAddress *linphone_address_ref (LinphoneAddress *address) {
belle_sip_object_ref(address);
return address;
}
void linphone_address_unref (LinphoneAddress *address) {
belle_sip_object_unref(address);
}
const char *linphone_address_get_scheme (const LinphoneAddress *address) {
return L_STRING_TO_C(address->cppPtr->getScheme());
}
const char *linphone_address_get_display_name (const LinphoneAddress *address) {
return L_STRING_TO_C(address->cppPtr->getDisplayName());
}
LinphoneStatus linphone_address_set_display_name (LinphoneAddress *address, const char *display_name) {
return !address->cppPtr->setDisplayName(L_C_TO_STRING(display_name));
}
const char *linphone_address_get_username (const LinphoneAddress *address) {
return L_STRING_TO_C(address->cppPtr->getUsername());
}
LinphoneStatus linphone_address_set_username (LinphoneAddress *address, const char *username) {
return !address->cppPtr->setUsername(L_C_TO_STRING(username));
}
const char *linphone_address_get_domain (const LinphoneAddress *address) {
return L_STRING_TO_C(address->cppPtr->getDomain());
}
LinphoneStatus linphone_address_set_domain (LinphoneAddress *address, const char *domain) {
return !address->cppPtr->setDomain(L_C_TO_STRING(domain));
}
int linphone_address_get_port (const LinphoneAddress *address) {
return address->cppPtr->getPort();
}
LinphoneStatus linphone_address_set_port (LinphoneAddress *address, int port) {
return !address->cppPtr->setPort(port);
}
LinphoneTransportType linphone_address_get_transport (const LinphoneAddress *address) {
return static_cast<LinphoneTransportType>(address->cppPtr->getTransport());
}
LinphoneStatus linphone_address_set_transport (LinphoneAddress *address, LinphoneTransportType transport) {
return !address->cppPtr->setTransport(static_cast<LINPHONE_NAMESPACE::Transport>(transport));
}
bool_t linphone_address_get_secure (const LinphoneAddress *address) {
return address->cppPtr->getSecure();
}
void linphone_address_set_secure (LinphoneAddress *address, bool_t enabled) {
address->cppPtr->setSecure(enabled);
}
bool_t linphone_address_is_sip (const LinphoneAddress *address) {
return address->cppPtr->isSip();
}
const char *linphone_address_get_method_param (const LinphoneAddress *address) {
return L_STRING_TO_C(address->cppPtr->getMethodParam());
}
void linphone_address_set_method_param (LinphoneAddress *address, const char *method_param) {
address->cppPtr->setMethodParam(L_C_TO_STRING(method_param));
}
const char *linphone_address_get_password (const LinphoneAddress *address) {
return L_STRING_TO_C(address->cppPtr->getPassword());
}
void linphone_address_set_password (LinphoneAddress *address, const char *password) {
address->cppPtr->setPassword(L_C_TO_STRING(password));
}
void linphone_address_clean (LinphoneAddress *address) {
address->cppPtr->clean();
}
char *linphone_address_as_string (const LinphoneAddress *address) {
return ms_strdup(address->cppPtr->asString().c_str());
}
char *linphone_address_as_string_uri_only (const LinphoneAddress *address) {
return ms_strdup(address->cppPtr->asStringUriOnly().c_str());
}
bool_t linphone_address_weak_equal (const LinphoneAddress *address1, const LinphoneAddress *address2) {
return address1->cppPtr->weakEqual(*address2->cppPtr.get());
}
bool_t linphone_address_equal (const LinphoneAddress *address1, const LinphoneAddress *address2) {
return *address1->cppPtr.get() == *address2->cppPtr.get();
}
const char *linphone_address_get_header (const LinphoneAddress *address, const char *header_name) {
return L_STRING_TO_C(address->cppPtr->getHeaderValue(L_C_TO_STRING(header_name)));
}
void linphone_address_set_header (LinphoneAddress *address, const char *header_name, const char *header_value) {
address->cppPtr->setHeader(L_C_TO_STRING(header_name), L_C_TO_STRING(header_value));
}
bool_t linphone_address_has_param (const LinphoneAddress *address, const char *param_name) {
return address->cppPtr->hasParam(L_C_TO_STRING(param_name));
}
const char *linphone_address_get_param (const LinphoneAddress *address, const char *param_name) {
return L_STRING_TO_C(address->cppPtr->getParamValue(L_C_TO_STRING(param_name)));
}
void linphone_address_set_param (LinphoneAddress *address, const char *param_name, const char *param_value) {
address->cppPtr->setParam(L_C_TO_STRING(param_name), L_C_TO_STRING(param_value));
}
void linphone_address_set_params (LinphoneAddress *address, const char *params) {
address->cppPtr->setParams(L_C_TO_STRING(params));
}
bool_t linphone_address_has_uri_param (const LinphoneAddress *address, const char *uri_param_name) {
return address->cppPtr->hasUriParam(L_C_TO_STRING(uri_param_name));
}
const char *linphone_address_get_uri_param (const LinphoneAddress *address, const char *uri_param_name) {
return L_STRING_TO_C(address->cppPtr->getUriParamValue(L_C_TO_STRING(uri_param_name)));
}
void linphone_address_set_uri_param (LinphoneAddress *address, const char *uri_param_name, const char *uri_param_value) {
address->cppPtr->setUriParam(L_C_TO_STRING(uri_param_name), L_C_TO_STRING(uri_param_value));
}
void linphone_address_set_uri_params (LinphoneAddress *address, const char *params) {
address->cppPtr->setUriParams(L_C_TO_STRING(params));
}
void linphone_address_destroy (LinphoneAddress *address) {
belle_sip_object_unref(address);
}
bool_t linphone_address_is_secure (const LinphoneAddress *address) {
return address->cppPtr->getSecure();
}

View file

@ -16,10 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "linphone/api/c-event-log.h"
#include "c-wrapper/c-tools.h"
#include "c-event-log.h"
#include "event-log/call-event.h"
#include "event-log/conference-participant-event.h"
#include "event-log/message-event.h"
@ -28,6 +28,7 @@
using namespace std;
extern "C" {
// -----------------------------------------------------------------------------
// Event log.
// -----------------------------------------------------------------------------
@ -111,3 +112,4 @@ const LinphoneAddress *linphone_conference_participant_event_get_participant_add
// TODO.
return nullptr;
}
}

View file

@ -19,13 +19,13 @@
#ifndef _C_EVENT_LOG_H_
#define _C_EVENT_LOG_H_
#include "linphone/api/c-types.h"
#include "c-wrapper/c-types.h"
// =============================================================================
#ifdef __cplusplus
extern "C" {
#endif // ifdef __cplusplus
#endif
LINPHONE_PUBLIC LinphoneEventLog *linphone_event_log_new ();
LINPHONE_PUBLIC LinphoneEventLogType linphone_event_log_get_type (const LinphoneEventLog *event_log);

View file

@ -19,77 +19,29 @@
#ifndef _C_TOOLS_H_
#define _C_TOOLS_H_
#include <memory>
#include <string>
// From coreapi.
#include "private.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
class Wrapper {
private:
template<typename T>
struct WrappedObject {
belle_sip_object_t base;
std::shared_ptr<T> cppPtr;
};
public:
template<typename T>
static inline decltype (std::declval<T>().getPrivate()) getPrivate (T *object) {
if (!object)
return nullptr;
return object->getPrivate();
}
template<typename T>
static inline std::shared_ptr<T> getCppPtrFromC (void *object) {
L_ASSERT(object);
return static_cast<WrappedObject<T> *>(object)->cppPtr;
}
template<typename T>
static inline std::shared_ptr<const T> getCppPtrFromC (const void *object) {
L_ASSERT(object);
return static_cast<const WrappedObject<const T> *>(object)->cppPtr;
}
template<typename T>
static inline void setCppPtrFromC (void *object, std::shared_ptr<T> &cppPtr) {
L_ASSERT(object);
static_cast<WrappedObject<T> *>(object)->cppPtr = cppPtr;
}
private:
Wrapper ();
L_DISABLE_COPY(Wrapper);
};
LINPHONE_END_NAMESPACE
// -----------------------------------------------------------------------------
#define L_DECLARE_C_STRUCT_IMPL(STRUCT, C_NAME) \
struct _Linphone ## STRUCT { \
belle_sip_object_t base; \
std::shared_ptr<LINPHONE_NAMESPACE::STRUCT> cppPtr; \
shared_ptr<LINPHONE_NAMESPACE::STRUCT> cppPtr; \
}; \
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(Linphone ## STRUCT); \
static Linphone ## STRUCT *_linphone_ ## C_NAME ## _init() { \
Linphone ## STRUCT * object = belle_sip_object_new(Linphone ## STRUCT); \
new(&object->cppPtr) std::shared_ptr<LINPHONE_NAMESPACE::STRUCT>(); \
new(&object->cppPtr) shared_ptr<LINPHONE_NAMESPACE::STRUCT>(); \
return object; \
} \
static void _linphone_ ## C_NAME ## _uninit(Linphone ## STRUCT * object) { \
object->cppPtr.~shared_ptr (); \
object->cppPtr.reset(); \
object->cppPtr->~STRUCT (); \
} \
static void _linphone_ ## C_NAME ## _clone(Linphone ## STRUCT * dest, const Linphone ## STRUCT * src) { \
new(&dest->cppPtr) std::shared_ptr<LINPHONE_NAMESPACE::STRUCT>(); \
dest->cppPtr = std::make_shared<LINPHONE_NAMESPACE::STRUCT>(*src->cppPtr.get()); \
new(&dest->cppPtr) shared_ptr<LINPHONE_NAMESPACE::STRUCT>(); \
dest->cppPtr = make_shared<LINPHONE_NAMESPACE::STRUCT>(*src->cppPtr.get()); \
} \
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(Linphone ## STRUCT); \
BELLE_SIP_INSTANCIATE_VPTR(Linphone ## STRUCT, belle_sip_object_t, \
@ -102,23 +54,8 @@ LINPHONE_END_NAMESPACE
#define L_DECLARE_C_STRUCT_NEW_DEFAULT(STRUCT, C_NAME) \
Linphone ## STRUCT * linphone_ ## C_NAME ## _new() { \
Linphone ## STRUCT * object = _linphone_ ## C_NAME ## _init(); \
object->cppPtr = std::make_shared<LINPHONE_NAMESPACE::STRUCT>(); \
object->cppPtr = make_shared<LINPHONE_NAMESPACE::STRUCT>(); \
return object; \
}
#define L_STRING_TO_C(STR) ((STR).empty() ? NULL : (STR).c_str())
#define L_C_TO_STRING(STR) ((STR) == NULL ? std::string() : (STR))
#define L_GET_CPP_PTR_FROM_C_STRUCT(OBJECT, TYPE) \
LINPHONE_NAMESPACE::Wrapper::getCppPtrFromC<LINPHONE_NAMESPACE::TYPE>(OBJECT)
#define L_SET_CPP_PTR_FROM_C_STRUCT(OBJECT, CPP_PTR) \
LINPHONE_NAMESPACE::Wrapper::setCppPtrFromC(OBJECT, CPP_PTR)
#define L_GET_PRIVATE(OBJECT) \
LINPHONE_NAMESPACE::Wrapper::getPrivate(OBJECT)
#define L_GET_PRIVATE_FROM_C_STRUCT(OBJECT, TYPE) \
L_GET_PRIVATE(L_GET_CPP_PTR_FROM_C_STRUCT(OBJECT, TYPE).get())
#endif // ifndef _C_TOOLS_H_

View file

@ -23,63 +23,31 @@
// Enable C enums.
#define L_USE_C_ENUM
// TODO: Remove me in the future.
#include "linphone/types.h"
#include "linphone/enums/event-log-enums.h"
#include "event-log/event-log-enums.h"
#define L_DECLARE_C_ENUM(CLASS, ENUM, VALUES) enum Linphone ## CLASS ## ENUM { VALUES }
#define L_DECLARE_C_STRUCT(STRUCT) typedef struct _Linphone ## STRUCT Linphone ## STRUCT;
// =============================================================================
#ifdef __cplusplus
extern "C" {
#endif // ifdef __cplusplus
// =============================================================================
// Misc.
// =============================================================================
typedef int LinphoneStatus;
typedef unsigned char bool_t;
#ifdef TRUE
#undef TRUE
#endif
#ifdef FALSE
#undef FALSE
#endif
#define TRUE 1
#define FALSE 0
// =============================================================================
// C Structures.
// =============================================================================
/**
* Object that represents a SIP address.
*
* The LinphoneAddress is an opaque object to represents SIP addresses, ie
* the content of SIP's 'from' and 'to' headers.
* A SIP address is made of display name, username, domain name, port, and various
* uri headers (such as tags). It looks like 'Alice <sip:alice@example.net>'.
* The LinphoneAddress has methods to extract and manipulate all parts of the address.
* When some part of the address (for example the username) is empty, the accessor methods
* return NULL.
* @ingroup linphone_address
*/
typedef struct _LinphoneAddress LinphoneAddress;
L_DECLARE_C_STRUCT(Call);
L_DECLARE_C_STRUCT(CallEvent);
L_DECLARE_C_STRUCT(ConferenceEvent);
L_DECLARE_C_STRUCT(ConferenceParticipantEvent);
L_DECLARE_C_STRUCT(EventLog);
L_DECLARE_C_STRUCT(Message);
L_DECLARE_C_STRUCT(MessageEvent);
typedef struct _LinphoneCall LinphoneCall;
typedef struct _LinphoneCallEvent LinphoneCallEvent;
typedef struct _LinphoneConferenceEvent LinphoneConferenceEvent;
typedef struct _LinphoneConferenceParticipantEvent LinphoneConferenceParticipantEvent;
typedef struct _LinphoneEventLog LinphoneEventLog;
typedef struct _LinphoneMessage LinphoneMessage;
typedef struct _LinphoneMessageEvent LinphoneMessageEvent;
// TODO: Remove me in the future.
typedef struct SalAddress LinphoneAddress;
// =============================================================================
// C Enums.
@ -89,6 +57,6 @@ L_DECLARE_C_ENUM(EventLog, Type, L_ENUM_VALUES_EVENT_LOG_TYPE);
#ifdef __cplusplus
}
#endif // ifdef __cplusplus
#endif
#endif // ifndef _C_TYPES_H_

View file

@ -1,113 +0,0 @@
/*
* chat-room-p.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CHAT_ROOM_P_H_
#define _CHAT_ROOM_P_H_
// From coreapi.
#include "private.h"
#include "chat-room.h"
#include "is-composing.h"
#include "is-composing-listener.h"
#include "object/object-p.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
class ChatRoomPrivate : public ObjectPrivate, public IsComposingListener {
public:
ChatRoomPrivate (LinphoneCore *core);
virtual ~ChatRoomPrivate ();
private:
static int createChatMessageFromDb (void *data, int argc, char **argv, char **colName);
static void onWeakMessageDestroyed (void *obj, belle_sip_object_t *messageBeingDestroyed);
public:
void addTransientMessage (LinphoneChatMessage *msg);
void addWeakMessage (LinphoneChatMessage *msg);
std::list<LinphoneChatMessage *> getTransientMessages () const {
return transientMessages;
}
void moveTransientMessageToWeakMessages (LinphoneChatMessage *msg);
void removeTransientMessage (LinphoneChatMessage *msg);
void release ();
void sendImdn (const std::string &content, LinphoneReason reason);
int getMessagesCount (bool unreadOnly);
void setCBackPointer (LinphoneChatRoom *cr) {
this->cBackPointer = cr;
}
void setCall (LinphoneCall *call) {
this->call = call;
}
private:
void sendIsComposingNotification ();
int createChatMessageFromDb (int argc, char **argv, char **colName);
void onWeakMessageDestroyed (LinphoneChatMessage *messageBeingDestroyed);
LinphoneChatMessage *getTransientMessage (unsigned int storageId) const;
LinphoneChatMessage *getWeakMessage (unsigned int storageId) const;
int sqlRequest (sqlite3 *db, const std::string &stmt);
void sqlRequestMessage (sqlite3 *db, const std::string &stmt);
std::list<LinphoneChatMessage *> findMessages (const std::string &messageId);
void storeOrUpdateMessage (LinphoneChatMessage *msg);
public:
LinphoneReason messageReceived (SalOp *op, const SalMessage *msg);
void realtimeTextReceived (uint32_t character, LinphoneCall *call);
private:
void chatMessageReceived (LinphoneChatMessage *msg);
void imdnReceived (const std::string &text);
void isComposingReceived (const std::string &text);
private:
void isComposingStateChanged (bool isComposing);
void isRemoteComposingStateChanged (bool isComposing);
void isComposingRefreshNeeded ();
public:
LinphoneChatRoom *cBackPointer = nullptr;
LinphoneCore *core = nullptr;
LinphoneCall *call = nullptr;
LinphoneAddress *peerAddress = nullptr;
std::string peer;
int unreadCount = -1;
bool isComposing = false;
bool remoteIsComposing = false;
std::list<LinphoneChatMessage *> messages;
std::list<LinphoneChatMessage *> transientMessages;
std::list<LinphoneChatMessage *> weakMessages;
std::list<LinphoneChatMessageCharacter *> receivedRttCharacters;
LinphoneChatMessage *pendingMessage = nullptr;
IsComposing isComposingHandler;
private:
L_DECLARE_PUBLIC(ChatRoom);
};
LINPHONE_END_NAMESPACE
#endif // ifndef _CHAT_ROOM_P_H_

View file

@ -1,993 +0,0 @@
/*
* chat-room.cpp
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include "linphone/utils/utils.h"
#include "chat-room-p.h"
#include "imdn.h"
#include "logger/logger.h"
#include "utils/content-type.h"
#include "chat-room.h"
// =============================================================================
using namespace std;
LINPHONE_BEGIN_NAMESPACE
ChatRoomPrivate::ChatRoomPrivate (LinphoneCore *core)
: core(core), isComposingHandler(core, this) {}
ChatRoomPrivate::~ChatRoomPrivate () {
for (auto it = transientMessages.begin(); it != transientMessages.end(); it++) {
linphone_chat_message_release(*it);
}
if (!receivedRttCharacters.empty()) {
for (auto it = receivedRttCharacters.begin(); it != receivedRttCharacters.end(); it++)
bctbx_free(*it);
}
if (core) {
if (bctbx_list_find(core->chatrooms, cBackPointer)) {
lError() << "LinphoneChatRoom[" << cBackPointer << "] is destroyed while still being used by the LinphoneCore. " <<
"This is abnormal. linphone_core_get_chat_room() doesn't give a reference, there is no need to call linphone_chat_room_unref(). " <<
"In order to remove a chat room from the core, use linphone_core_delete_chat_room().";
core->chatrooms = bctbx_list_remove(core->chatrooms, cBackPointer);
}
}
linphone_address_unref(peerAddress);
if (pendingMessage)
linphone_chat_message_destroy(pendingMessage);
}
// -----------------------------------------------------------------------------
int ChatRoomPrivate::createChatMessageFromDb (void *data, int argc, char **argv, char **colName) {
ChatRoomPrivate *d = reinterpret_cast<ChatRoomPrivate *>(data);
return d->createChatMessageFromDb(argc, argv, colName);
}
void ChatRoomPrivate::onWeakMessageDestroyed (void *obj, belle_sip_object_t *messageBeingDestroyed) {
ChatRoomPrivate *d = reinterpret_cast<ChatRoomPrivate *>(obj);
d->onWeakMessageDestroyed(reinterpret_cast<LinphoneChatMessage *>(messageBeingDestroyed));
}
// -----------------------------------------------------------------------------
void ChatRoomPrivate::addTransientMessage (LinphoneChatMessage *msg) {
auto iter = find(transientMessages.begin(), transientMessages.end(), msg);
if (iter == transientMessages.end())
transientMessages.push_back(linphone_chat_message_ref(msg));
}
void ChatRoomPrivate::addWeakMessage (LinphoneChatMessage *msg) {
auto iter = find(weakMessages.begin(), weakMessages.end(), msg);
if (iter == weakMessages.end())
weakMessages.push_back(reinterpret_cast<LinphoneChatMessage *>(belle_sip_object_weak_ref(msg, onWeakMessageDestroyed, this)));
}
void ChatRoomPrivate::moveTransientMessageToWeakMessages (LinphoneChatMessage *msg) {
auto iter = find(transientMessages.begin(), transientMessages.end(), msg);
if (iter != transientMessages.end()) {
/* msg is not transient anymore, we can remove it from our transient list and unref it */
addWeakMessage(msg);
removeTransientMessage(msg);
} else {
/* msg has already been removed from the transient messages, do nothing */
}
}
void ChatRoomPrivate::removeTransientMessage (LinphoneChatMessage *msg) {
auto iter = find(transientMessages.begin(), transientMessages.end(), msg);
if (iter != transientMessages.end()) {
linphone_chat_message_unref(*iter);
transientMessages.erase(iter);
}
}
// -----------------------------------------------------------------------------
void ChatRoomPrivate::release () {
isComposingHandler.stopTimers();
for (auto it = weakMessages.begin(); it != weakMessages.end(); it++) {
linphone_chat_message_deactivate(*it);
}
for (auto it = transientMessages.begin(); it != transientMessages.end(); it++) {
linphone_chat_message_deactivate(*it);
}
core = nullptr;
linphone_chat_room_unref(cBackPointer);
}
void ChatRoomPrivate::sendImdn (const string &content, LinphoneReason reason) {
L_Q(ChatRoom);
const char *identity = nullptr;
LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(core, peerAddress);
if (proxy)
identity = linphone_address_as_string(linphone_proxy_config_get_identity_address(proxy));
else
identity = linphone_core_get_primary_contact(core);
/* Sending out of call */
SalOp *op = sal_op_new(core->sal);
linphone_configure_op(core, op, peerAddress, nullptr, lp_config_get_int(core->config, "sip", "chat_msg_with_contact", 0));
LinphoneChatMessage *msg = q->createMessage(content);
LinphoneAddress *fromAddr = linphone_address_new(identity);
linphone_chat_message_set_from_address(msg, fromAddr);
LinphoneAddress *toAddr = linphone_address_new(peer.c_str());
linphone_chat_message_set_to_address(msg, toAddr);
linphone_chat_message_set_content_type(msg, "message/imdn+xml");
/* Do not try to encrypt the notification when it is reporting an error (maybe it should be bypassed only for some reasons). */
int retval = -1;
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(core);
if (imee && (reason == LinphoneReasonNone)) {
LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs);
if (cbProcessOutgoingMessage) {
retval = cbProcessOutgoingMessage(imee, cBackPointer, msg);
}
}
if (retval <= 0) {
sal_message_send(op, identity, peer.c_str(), msg->content_type, msg->message, nullptr);
}
linphone_chat_message_unref(msg);
linphone_address_unref(fromAddr);
linphone_address_unref(toAddr);
sal_op_unref(op);
}
// -----------------------------------------------------------------------------
int ChatRoomPrivate::getMessagesCount (bool unreadOnly) {
if (!core->db) return 0;
/* Optimization: do not read database if the count is already available in memory */
if (unreadOnly && unreadCount >= 0) return unreadCount;
char *peer = linphone_address_as_string_uri_only(peerAddress);
char *option = nullptr;
if (unreadOnly)
option = bctbx_strdup_printf("AND status!=%i AND direction=%i", LinphoneChatMessageStateDisplayed, LinphoneChatMessageIncoming);
char *buf = sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;", peer, unreadOnly ? option : "");
sqlite3_stmt *selectStatement;
int numrows = 0;
int returnValue = sqlite3_prepare_v2(core->db, buf, -1, &selectStatement, nullptr);
if (returnValue == SQLITE_OK) {
if (sqlite3_step(selectStatement) == SQLITE_ROW) {
numrows = sqlite3_column_int(selectStatement, 0);
}
}
sqlite3_finalize(selectStatement);
sqlite3_free(buf);
ms_free(peer);
/* No need to test the sign of unreadCount here because it has been tested above */
if (unreadOnly) {
unreadCount = numrows;
}
if (option) bctbx_free(option);
return numrows;
}
// -----------------------------------------------------------------------------
void ChatRoomPrivate::sendIsComposingNotification () {
L_Q(ChatRoom);
LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(core);
if (linphone_im_notif_policy_get_send_is_composing(policy)) {
LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(core, peerAddress);
const char *identity = nullptr;
if (proxy)
identity = linphone_address_as_string(linphone_proxy_config_get_identity_address(proxy));
else
identity = linphone_core_get_primary_contact(core);
/* Sending out of call */
SalOp *op = sal_op_new(core->sal);
linphone_configure_op(core, op, peerAddress, nullptr, lp_config_get_int(core->config, "sip", "chat_msg_with_contact", 0));
string content = isComposingHandler.marshal(isComposing);
if (!content.empty()) {
int retval = -1;
LinphoneAddress *fromAddr = linphone_address_new(identity);
LinphoneChatMessage *msg = q->createMessage(content);
linphone_chat_message_set_from_address(msg, fromAddr);
linphone_chat_message_set_to_address(msg, peerAddress);
linphone_chat_message_set_content_type(msg, "application/im-iscomposing+xml");
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(core);
if (imee) {
LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs);
if (cbProcessOutgoingMessage) {
retval = cbProcessOutgoingMessage(imee, cBackPointer, msg);
}
}
if (retval <= 0) {
sal_message_send(op, identity, peer.c_str(), msg->content_type, msg->message, nullptr);
}
linphone_chat_message_unref(msg);
linphone_address_unref(fromAddr);
sal_op_unref(op);
}
}
}
// -----------------------------------------------------------------------------
/**
* DB layout:
*
* | 0 | storage_id
* | 1 | localContact
* | 2 | remoteContact
* | 3 | direction flag (LinphoneChatMessageDir)
* | 4 | message (text content of the message)
* | 5 | time (unused now, used to be string-based timestamp, replaced by the utc timestamp)
* | 6 | read flag (no longer used, replaced by the LinphoneChatMessageStateDisplayed state)
* | 7 | status (LinphoneChatMessageState)
* | 8 | external body url (deprecated file transfer system)
* | 9 | utc timestamp
* | 10 | app data text
* | 11 | linphone content id (LinphoneContent describing a file transfer)
* | 12 | message id (used for IMDN)
* | 13 | content type (of the message field [must be text representable])
* | 14 | secured flag
*/
int ChatRoomPrivate::createChatMessageFromDb (int argc, char **argv, char **colName) {
L_Q(ChatRoom);
unsigned int storageId = (unsigned int)atoi(argv[0]);
/* Check if the message exists in the weak messages list, in which case we should return that one. */
LinphoneChatMessage *newMessage = getWeakMessage(storageId);
if (!newMessage) {
/* Check if the message exists in the transient list, in which case we should return that one. */
newMessage = getTransientMessage(storageId);
}
if (!newMessage) {
newMessage = q->createMessage(argv[4] ? argv[4] : "");
if (atoi(argv[3]) == LinphoneChatMessageIncoming) {
newMessage->dir = LinphoneChatMessageIncoming;
linphone_chat_message_set_from(newMessage, peerAddress);
newMessage->to = nullptr; /* Will be filled at the end */
} else {
newMessage->dir = LinphoneChatMessageOutgoing;
newMessage->from = nullptr; /* Will be filled at the end */
linphone_chat_message_set_to(newMessage, peerAddress);
}
newMessage->time = (time_t)atol(argv[9]);
newMessage->is_read = atoi(argv[6]);
newMessage->state = static_cast<LinphoneChatMessageState>(atoi(argv[7]));
newMessage->storage_id = storageId;
newMessage->external_body_url = ms_strdup(argv[8]);
newMessage->appdata = ms_strdup(argv[10]);
newMessage->message_id = ms_strdup(argv[12]);
linphone_chat_message_set_content_type(newMessage, argv[13]);
newMessage->is_secured = (bool_t)atoi(argv[14]);
if (argv[11]) {
int id = atoi(argv[11]);
if (id >= 0)
linphone_chat_message_fetch_content_from_database(core->db, newMessage, id);
}
/* Fix content type for old messages that were stored without it */
if (!newMessage->content_type) {
if (newMessage->file_transfer_information) {
newMessage->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml");
} else if (newMessage->external_body_url) {
newMessage->content_type = ms_strdup("message/external-body");
} else {
newMessage->content_type = ms_strdup("text/plain");
}
}
/* Add the new message to the weak messages list. */
addWeakMessage(newMessage);
}
messages.push_front(newMessage);
return 0;
}
void ChatRoomPrivate::onWeakMessageDestroyed (LinphoneChatMessage *messageBeingDestroyed) {
auto iter = find(weakMessages.begin(), weakMessages.end(), messageBeingDestroyed);
if (iter != transientMessages.end())
weakMessages.erase(iter);
}
LinphoneChatMessage *ChatRoomPrivate::getTransientMessage (unsigned int storageId) const {
for (auto it = transientMessages.begin(); it != transientMessages.end(); it++) {
if (linphone_chat_message_get_storage_id(*it) == storageId)
return linphone_chat_message_ref(*it);
}
return nullptr;
}
LinphoneChatMessage *ChatRoomPrivate::getWeakMessage (unsigned int storageId) const {
for (auto it = weakMessages.begin(); it != weakMessages.end(); it++) {
if (linphone_chat_message_get_storage_id(*it) == storageId)
return linphone_chat_message_ref(*it);
}
return nullptr;
}
int ChatRoomPrivate::sqlRequest (sqlite3 *db, const string &stmt) {
char *errmsg = nullptr;
int ret = sqlite3_exec(db, stmt.c_str(), nullptr, nullptr, &errmsg);
if (ret != SQLITE_OK) {
lError() << "ChatRoomPrivate::sqlRequest: statement " << stmt << " -> error sqlite3_exec(): " << errmsg;
sqlite3_free(errmsg);
}
return ret;
}
void ChatRoomPrivate::sqlRequestMessage (sqlite3 *db, const string &stmt) {
char *errmsg = nullptr;
int ret = sqlite3_exec(db, stmt.c_str(), createChatMessageFromDb, this, &errmsg);
if (ret != SQLITE_OK) {
lError() << "Error in creation: " << errmsg;
sqlite3_free(errmsg);
}
}
list<LinphoneChatMessage *> ChatRoomPrivate::findMessages (const string &messageId) {
if (!core->db)
return list<LinphoneChatMessage *>();
char *peer = linphone_address_as_string_uri_only(peerAddress);
char *buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND messageId = %Q", peer, messageId.c_str());
messages.clear();
sqlRequestMessage(core->db, buf);
sqlite3_free(buf);
ms_free(peer);
list<LinphoneChatMessage *> result = messages;
messages.clear();
return result;
}
/**
* TODO: Should be handled directly by the LinphoneChatMessage object!
*/
void ChatRoomPrivate::storeOrUpdateMessage (LinphoneChatMessage *msg) {
if (msg->storage_id != 0) {
/* The message has already been stored (probably because of file transfer), update it */
linphone_chat_message_store_update(msg);
} else {
/* Store the new message */
msg->storage_id = linphone_chat_message_store(msg);
}
}
// -----------------------------------------------------------------------------
LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *salMsg) {
L_Q(ChatRoom);
bool increaseMsgCount = true;
LinphoneReason reason = LinphoneReasonNone;
LinphoneChatMessage *msg;
/* Check if this is a duplicate message */
if ((msg = q->findMessageWithDirection(sal_op_get_call_id(op), LinphoneChatMessageIncoming))) {
reason = core->chat_deny_code;
if (msg)
linphone_chat_message_unref(msg);
return reason;
}
msg = q->createMessage(salMsg->text ? salMsg->text : "");
linphone_chat_message_set_content_type(msg, salMsg->content_type);
linphone_chat_message_set_from(msg, peerAddress);
LinphoneAddress *to = sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(core));
msg->to = to;
msg->time = salMsg->time;
msg->state = LinphoneChatMessageStateDelivered;
msg->dir = LinphoneChatMessageIncoming;
msg->message_id = ms_strdup(sal_op_get_call_id(op));
const SalCustomHeader *ch = sal_op_get_recv_custom_header(op);
if (ch)
msg->custom_headers = sal_custom_header_clone(ch);
if (salMsg->url)
linphone_chat_message_set_external_body_url(msg, salMsg->url);
int retval = -1;
LinphoneImEncryptionEngine *imee = core->im_encryption_engine;
if (imee) {
LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsIncomingMessageCb cbProcessIncomingMessage = linphone_im_encryption_engine_cbs_get_process_incoming_message(imeeCbs);
if (cbProcessIncomingMessage) {
retval = cbProcessIncomingMessage(imee, cBackPointer, msg);
if (retval == 0) {
msg->is_secured = TRUE;
} else if (retval > 0) {
/* Unable to decrypt message */
linphone_core_notify_message_received_unable_decrypt(core, cBackPointer, msg);
reason = linphone_error_code_to_reason(retval);
linphone_chat_message_send_delivery_notification(msg, reason);
/* Return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt */
reason = LinphoneReasonNone;
goto end;
}
}
}
if ((retval <= 0) && (linphone_core_is_content_type_supported(core, msg->content_type) == FALSE)) {
retval = 415;
lError() << "Unsupported MESSAGE (content-type " << msg->content_type << " not recognized)";
}
if (retval > 0) {
reason = linphone_error_code_to_reason(retval);
linphone_chat_message_send_delivery_notification(msg, reason);
goto end;
}
if (ContentType::isFileTransfer(msg->content_type)) {
create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(msg);
linphone_chat_message_set_to_be_stored(msg, TRUE);
} else if (ContentType::isImIsComposing(msg->content_type)) {
isComposingReceived(msg->message);
linphone_chat_message_set_to_be_stored(msg, FALSE);
increaseMsgCount = FALSE;
if (lp_config_get_int(core->config, "sip", "deliver_imdn", 0) != 1) {
goto end;
}
} else if (ContentType::isImdn(msg->content_type)) {
imdnReceived(msg->message);
linphone_chat_message_set_to_be_stored(msg, FALSE);
increaseMsgCount = FALSE;
if (lp_config_get_int(core->config, "sip", "deliver_imdn", 0) != 1) {
goto end;
}
} else if (ContentType::isText(msg->content_type)) {
linphone_chat_message_set_to_be_stored(msg, TRUE);
}
if (increaseMsgCount) {
if (unreadCount < 0)
unreadCount = 1;
else
unreadCount++;
/* Mark the message as pending so that if linphone_core_chat_room_mark_as_read() is called
in the linphone_chat_room_message_received() callback, it will effectively be marked as
being read before being stored. */
pendingMessage = msg;
}
chatMessageReceived(msg);
if (linphone_chat_message_get_to_be_stored(msg)) {
msg->storage_id = linphone_chat_message_store(msg);
}
pendingMessage = nullptr;
end:
if (msg)
linphone_chat_message_unref(msg);
return reason;
}
void ChatRoomPrivate::realtimeTextReceived (uint32_t character, LinphoneCall *call) {
L_Q(ChatRoom);
const uint32_t new_line = 0x2028;
const uint32_t crlf = 0x0D0A;
const uint32_t lf = 0x0A;
if (call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) {
LinphoneChatMessageCharacter *cmc = bctbx_new0(LinphoneChatMessageCharacter, 1);
if (!pendingMessage)
pendingMessage = q->createMessage("");
cmc->value = character;
cmc->has_been_read = FALSE;
receivedRttCharacters.push_back(cmc);
remoteIsComposing = true;
linphone_core_notify_is_composing_received(core, cBackPointer);
if ((character == new_line) || (character == crlf) || (character == lf)) {
/* End of message */
lDebug() << "New line received, forge a message with content " << pendingMessage->message;
linphone_chat_message_set_from(pendingMessage, peerAddress);
if (pendingMessage->to)
linphone_address_unref(pendingMessage->to);
pendingMessage->to = call->dest_proxy
? linphone_address_clone(call->dest_proxy->identity_address)
: linphone_address_new(linphone_core_get_identity(core));
pendingMessage->time = ms_time(0);
pendingMessage->state = LinphoneChatMessageStateDelivered;
pendingMessage->dir = LinphoneChatMessageIncoming;
if (lp_config_get_int(core->config, "misc", "store_rtt_messages", 1) == 1)
storeOrUpdateMessage(pendingMessage);
if (unreadCount < 0) unreadCount = 1;
else unreadCount++;
chatMessageReceived(pendingMessage);
linphone_chat_message_unref(pendingMessage);
pendingMessage = nullptr;
for (auto it = receivedRttCharacters.begin(); it != receivedRttCharacters.end(); it++)
ms_free(*it);
receivedRttCharacters.clear();
} else {
char *value = Utils::utf8ToChar(character);
pendingMessage->message = ms_strcat_printf(pendingMessage->message, value);
lDebug() << "Received RTT character: " << value << " (" << character << "), pending text is " << pendingMessage->message;
delete value;
}
}
}
// -----------------------------------------------------------------------------
void ChatRoomPrivate::chatMessageReceived (LinphoneChatMessage *msg) {
if (msg->message) {
/* Legacy API */
linphone_core_notify_text_message_received(core, cBackPointer, msg->from, msg->message);
}
linphone_core_notify_message_received(core, cBackPointer, msg);
if (!ContentType::isImdn(msg->content_type) && !ContentType::isImIsComposing(msg->content_type)) {
remoteIsComposing = false;
linphone_core_notify_is_composing_received(core, cBackPointer);
linphone_chat_message_send_delivery_notification(msg, LinphoneReasonNone);
}
}
void ChatRoomPrivate::imdnReceived (const string &text) {
L_Q(ChatRoom);
Imdn::parse(*q, text);
}
void ChatRoomPrivate::isComposingReceived (const string &text) {
isComposingHandler.parse(text);
}
// -----------------------------------------------------------------------------
void ChatRoomPrivate::isComposingStateChanged (bool isComposing) {
this->isComposing = isComposing;
sendIsComposingNotification();
}
void ChatRoomPrivate::isRemoteComposingStateChanged (bool isComposing) {
remoteIsComposing = isComposing;
linphone_core_notify_is_composing_received(core, cBackPointer);
}
void ChatRoomPrivate::isComposingRefreshNeeded () {
sendIsComposingNotification();
}
// =============================================================================
ChatRoom::ChatRoom (LinphoneCore *core, LinphoneAddress *peerAddress) : Object(*new ChatRoomPrivate(core)) {
L_D(ChatRoom);
d->peerAddress = peerAddress;
char *peerStr = linphone_address_as_string(d->peerAddress);
d->peer = peerStr;
ms_free(peerStr);
}
// -----------------------------------------------------------------------------
void ChatRoom::compose () {
L_D(ChatRoom);
if (!d->isComposing) {
d->isComposing = true;
d->sendIsComposingNotification();
d->isComposingHandler.startRefreshTimer();
}
d->isComposingHandler.startIdleTimer();
}
LinphoneChatMessage *ChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) {
L_D(ChatRoom);
LinphoneChatMessage *cm = belle_sip_object_new(LinphoneChatMessage);
cm->callbacks = linphone_chat_message_cbs_new();
cm->chat_room = d->cBackPointer;
cm->message = nullptr;
cm->file_transfer_information = linphone_content_copy(initialContent);
cm->dir = LinphoneChatMessageOutgoing;
linphone_chat_message_set_to(cm, d->peerAddress);
cm->from = linphone_address_new(linphone_core_get_identity(d->core));
/* This will be set to application/vnd.gsma.rcs-ft-http+xml when we will transfer the xml reply from server to the peers */
cm->content_type = nullptr;
/* This will store the http request during file upload to the server */
cm->http_request = nullptr;
cm->time = ms_time(0);
return cm;
}
LinphoneChatMessage *ChatRoom::createMessage (const string &msg) {
L_D(ChatRoom);
LinphoneChatMessage *cm = belle_sip_object_new(LinphoneChatMessage);
cm->state = LinphoneChatMessageStateIdle;
cm->callbacks = linphone_chat_message_cbs_new();
cm->chat_room = d->cBackPointer;
cm->message = msg.empty() ? nullptr : ms_strdup(msg.c_str());
cm->content_type = ms_strdup("text/plain");
cm->file_transfer_information = nullptr; /* this property is used only when transfering file */
cm->http_request = nullptr;
cm->time = ms_time(0);
cm->is_secured = FALSE;
return cm;
}
void ChatRoom::deleteHistory () {
L_D(ChatRoom);
if (!d->core->db) return;
char *peer = linphone_address_as_string_uri_only(d->peerAddress);
char *buf = sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;", peer);
d->sqlRequest(d->core->db, buf);
sqlite3_free(buf);
ms_free(peer);
if (d->unreadCount > 0) d->unreadCount = 0;
}
void ChatRoom::deleteMessage (LinphoneChatMessage *msg) {
L_D(ChatRoom);
if (!d->core->db) return;
char *buf = sqlite3_mprintf("DELETE FROM history WHERE id = %u;", msg->storage_id);
d->sqlRequest(d->core->db, buf);
sqlite3_free(buf);
/* Invalidate unread_count when we modify the database, so that next
time we need it it will be recomputed from latest database state */
d->unreadCount = -1;
}
LinphoneChatMessage *ChatRoom::findMessage (const string &messageId) {
L_D(ChatRoom);
LinphoneChatMessage *cm = nullptr;
list<LinphoneChatMessage *> l = d->findMessages(messageId);
if (!l.empty()) {
cm = l.front();
linphone_chat_message_ref(cm);
for (auto it = l.begin(); it != l.end(); it++)
linphone_chat_message_unref(*it);
}
return cm;
}
LinphoneChatMessage * ChatRoom::findMessageWithDirection (const string &messageId, LinphoneChatMessageDir direction) {
L_D(ChatRoom);
LinphoneChatMessage *ret = nullptr;
list<LinphoneChatMessage *> l = d->findMessages(messageId);
for (auto it = l.begin(); it != l.end(); it++) {
LinphoneChatMessage *cm = *it;
if (cm->dir == direction) {
linphone_chat_message_ref(cm);
ret = cm;
break;
}
}
if (!l.empty()) {
for (auto it = l.begin(); it != l.end(); it++)
linphone_chat_message_unref(*it);
}
return ret;
}
uint32_t ChatRoom::getChar () const {
L_D(const ChatRoom);
if (!d->receivedRttCharacters.empty()) {
for (auto it = d->receivedRttCharacters.begin(); it != d->receivedRttCharacters.end(); it++) {
LinphoneChatMessageCharacter *cmc = *it;
if (!cmc->has_been_read) {
cmc->has_been_read = TRUE;
return cmc->value;
}
}
}
return 0;
}
list<LinphoneChatMessage *> ChatRoom::getHistory (int nbMessages) {
return getHistoryRange(0, nbMessages - 1);
}
int ChatRoom::getHistorySize () {
L_D(ChatRoom);
return d->getMessagesCount(false);
}
list<LinphoneChatMessage *> ChatRoom::getHistoryRange (int startm, int endm) {
L_D(ChatRoom);
if (!d->core->db) return list<LinphoneChatMessage *>();
char *peer = linphone_address_as_string_uri_only(d->peerAddress);
d->messages.clear();
/* Since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf */
const int bufMaxSize = 512;
char *buf = reinterpret_cast<char *>(ms_malloc(bufMaxSize));
buf = sqlite3_snprintf(bufMaxSize - 1, buf, "SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC", peer);
if (startm < 0) startm = 0;
if (((endm > 0) && (endm >= startm)) || ((startm == 0) && (endm == 0))) {
char *buf2 = ms_strdup_printf("%s LIMIT %i ", buf, endm + 1 - startm);
ms_free(buf);
buf = buf2;
} else if (startm > 0) {
ms_message("%s(): end is lower than start (%d < %d). Assuming no end limit.", __FUNCTION__, endm, startm);
char *buf2 = ms_strdup_printf("%s LIMIT -1", buf);
ms_free(buf);
buf = buf2;
}
if (startm > 0) {
char *buf2 = ms_strdup_printf("%s OFFSET %i ", buf, startm);
ms_free(buf);
buf = buf2;
}
uint64_t begin = ortp_get_cur_time_ms();
d->sqlRequestMessage(d->core->db, buf);
uint64_t end = ortp_get_cur_time_ms();
if ((endm + 1 - startm) > 1) {
/* Display message only if at least 2 messages are loaded */
ms_message("%s(): completed in %i ms", __FUNCTION__, (int)(end - begin));
}
ms_free(buf);
if (!d->messages.empty()) {
/* Fill local addr with core identity instead of per message */
LinphoneAddress *localAddr = linphone_address_new(linphone_core_get_identity(d->core));
for (auto it = d->messages.begin(); it != d->messages.end(); it++) {
LinphoneChatMessage *msg = *it;
if (msg->dir == LinphoneChatMessageOutgoing) {
if (msg->from != NULL) linphone_address_unref(msg->from);
msg->from = linphone_address_ref(localAddr);
} else {
msg->to = linphone_address_ref(localAddr);
}
}
linphone_address_unref(localAddr);
}
list<LinphoneChatMessage *> result = d->messages;
d->messages.clear();
ms_free(peer);
return result;
}
int ChatRoom::getUnreadMessagesCount () {
L_D(ChatRoom);
return d->getMessagesCount(true);
}
bool ChatRoom::isRemoteComposing () const {
L_D(const ChatRoom);
return d->remoteIsComposing;
}
void ChatRoom::markAsRead () {
L_D(ChatRoom);
if (!d->core->db) return;
/* Optimization: do not modify the database if no message is marked as unread */
if (getUnreadMessagesCount() == 0) return;
char *peer = linphone_address_as_string_uri_only(d->peerAddress);
char *buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND direction = %i AND status != %i", peer, LinphoneChatMessageIncoming, LinphoneChatMessageStateDisplayed);
d->sqlRequestMessage(d->core->db, buf);
sqlite3_free(buf);
for (auto it = d->messages.begin(); it != d->messages.end(); it++) {
linphone_chat_message_send_display_notification(*it);
linphone_chat_message_unref(*it);
}
d->messages.clear();
buf = sqlite3_mprintf("UPDATE history SET status=%i WHERE remoteContact=%Q AND direction=%i;", LinphoneChatMessageStateDisplayed, peer, LinphoneChatMessageIncoming);
d->sqlRequest(d->core->db, buf);
sqlite3_free(buf);
ms_free(peer);
if (d->pendingMessage) {
linphone_chat_message_set_state(d->pendingMessage, LinphoneChatMessageStateDisplayed);
linphone_chat_message_send_display_notification(d->pendingMessage);
}
d->unreadCount = 0;
}
void ChatRoom::sendMessage (LinphoneChatMessage *msg) {
L_D(ChatRoom);
/* Stubed rtt */
if (d->call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(d->call))) {
uint32_t new_line = 0x2028;
linphone_chat_message_put_char(msg, new_line);
linphone_chat_message_unref(msg);
return;
}
msg->dir = LinphoneChatMessageOutgoing;
/* Check if we shall upload a file to a server */
if (msg->file_transfer_information && !msg->content_type) {
/* Open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */
if (linphone_chat_room_upload_file(msg) == 0) {
/* Add to transient list only if message is going out */
d->addTransientMessage(msg);
/* Store the message so that even if the upload is stopped, it can be done again */
d->storeOrUpdateMessage(msg);
} else {
linphone_chat_message_unref(msg);
return;
}
} else {
SalOp *op = msg->op;
LinphoneCall *call = nullptr;
const char *identity = nullptr;
char *clearTextMessage = nullptr;
char *clearTextContentType = nullptr;
if (msg->message) {
clearTextMessage = ms_strdup(msg->message);
}
if (msg->content_type) {
clearTextContentType = ms_strdup(msg->content_type);
}
/* Add to transient list */
d->addTransientMessage(msg);
msg->time = ms_time(0);
if (lp_config_get_int(d->core->config, "sip", "chat_use_call_dialogs", 0) != 0) {
call = linphone_core_get_call_by_remote_address(d->core, d->peer.c_str());
if (call) {
if (call->state == LinphoneCallConnected || call->state == LinphoneCallStreamsRunning ||
call->state == LinphoneCallPaused || call->state == LinphoneCallPausing ||
call->state == LinphoneCallPausedByRemote) {
ms_message("send SIP msg through the existing call.");
op = call->op;
identity = linphone_core_find_best_identity(d->core, linphone_call_get_remote_address(call));
}
}
}
if (!identity) {
LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(d->core, d->peerAddress);
if (proxy) {
identity = linphone_address_as_string(linphone_proxy_config_get_identity_address(proxy));
} else {
identity = linphone_core_get_primary_contact(d->core);
}
}
if (msg->from) {
/* BUG: the file transfer message constructor sets the from, but doesn't do it as well as here */
linphone_address_unref(msg->from);
}
msg->from = linphone_address_new(identity);
int retval = -1;
LinphoneImEncryptionEngine *imee = d->core->im_encryption_engine;
if (imee) {
LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs);
if (cbProcessOutgoingMessage) {
retval = cbProcessOutgoingMessage(imee, d->cBackPointer, msg);
if (retval == 0) {
msg->is_secured = TRUE;
}
}
}
if (!op) {
/* Sending out of call */
msg->op = op = sal_op_new(d->core->sal);
linphone_configure_op(d->core, op, d->peerAddress, msg->custom_headers,
lp_config_get_int(d->core->config, "sip", "chat_msg_with_contact", 0));
sal_op_set_user_pointer(op, msg); /* If out of call, directly store msg */
}
if (retval > 0) {
sal_error_info_set((SalErrorInfo *)sal_op_get_error_info(op), SalReasonNotAcceptable, "SIP", retval, "Unable to encrypt IM", nullptr);
d->storeOrUpdateMessage(msg);
linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered);
linphone_chat_message_unref(msg);
return;
}
if (msg->external_body_url) {
char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", msg->external_body_url);
sal_message_send(op, identity, d->peer.c_str(), content_type, nullptr, nullptr);
ms_free(content_type);
} else {
char *peerUri = linphone_address_as_string_uri_only(d->peerAddress);
if (msg->content_type) {
sal_message_send(op, identity, d->peer.c_str(), msg->content_type, msg->message, peerUri);
} else {
sal_text_send(op, identity, d->peer.c_str(), msg->message);
}
ms_free(peerUri);
}
if (msg->message && clearTextMessage && strcmp(msg->message, clearTextMessage) != 0) {
/* We replace the encrypted message by the original one so it can be correctly stored and displayed by the application */
ms_free(msg->message);
msg->message = ms_strdup(clearTextMessage);
}
if (msg->content_type && clearTextContentType && (strcmp(msg->content_type, clearTextContentType) != 0)) {
/* We replace the encrypted content type by the original one */
ms_free(msg->content_type);
msg->content_type = ms_strdup(clearTextContentType);
}
msg->message_id = ms_strdup(sal_op_get_call_id(op)); /* must be known at that time */
d->storeOrUpdateMessage(msg);
if (d->isComposing)
d->isComposing = false;
d->isComposingHandler.stopIdleTimer();
d->isComposingHandler.stopRefreshTimer();
if (clearTextMessage) {
ms_free(clearTextMessage);
}
if (clearTextContentType) {
ms_free(clearTextContentType);
}
if (call && call->op == op) {
/* In this case, chat delivery status is not notified, so unrefing chat message right now */
/* Might be better fixed by delivering status, but too costly for now */
linphone_chat_room_remove_transient_message(msg->chat_room, msg);
linphone_chat_message_unref(msg);
return;
}
}
/* If operation failed, we should not change message state */
if (msg->dir == LinphoneChatMessageOutgoing) {
linphone_chat_message_set_state(msg, LinphoneChatMessageStateInProgress);
}
}
// -----------------------------------------------------------------------------
LinphoneCall *ChatRoom::getCall () const {
L_D(const ChatRoom);
return d->call;
}
LinphoneCore *ChatRoom::getCore () const {
L_D(const ChatRoom);
return d->core;
}
// -----------------------------------------------------------------------------
const LinphoneAddress *ChatRoom::getPeerAddress () const {
L_D(const ChatRoom);
return d->peerAddress;
}
LINPHONE_END_NAMESPACE

View file

@ -1,70 +0,0 @@
/*
* chat-room.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CHAT_ROOM_H_
#define _CHAT_ROOM_H_
// From coreapi
#include "private.h"
#include <list>
#include "object/object.h"
#include "linphone/types.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
class ChatRoomPrivate;
class ChatRoom : public Object {
public:
ChatRoom (LinphoneCore *core, LinphoneAddress *peerAddress);
virtual ~ChatRoom () = default;
void compose ();
LinphoneChatMessage *createFileTransferMessage (const LinphoneContent *initialContent);
LinphoneChatMessage *createMessage (const std::string &msg);
void deleteHistory ();
void deleteMessage (LinphoneChatMessage *msg);
LinphoneChatMessage * findMessage (const std::string& messageId);
LinphoneChatMessage * findMessageWithDirection (const std::string &messageId, LinphoneChatMessageDir direction);
uint32_t getChar () const;
std::list<LinphoneChatMessage *> getHistory (int nbMessages);
int getHistorySize ();
std::list<LinphoneChatMessage *> getHistoryRange (int startm, int endm);
int getUnreadMessagesCount ();
bool isRemoteComposing () const;
void markAsRead ();
void sendMessage (LinphoneChatMessage *msg);
LinphoneCall *getCall () const;
LinphoneCore *getCore () const;
const LinphoneAddress *getPeerAddress () const;
private:
L_DECLARE_PRIVATE(ChatRoom);
L_DISABLE_COPY(ChatRoom);
};
LINPHONE_END_NAMESPACE
#endif // ifndef _CHAT_ROOM_H_

View file

@ -1,104 +0,0 @@
/*
* imdn.cpp
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "logger/logger.h"
#include "imdn.h"
// =============================================================================
using namespace std;
LINPHONE_BEGIN_NAMESPACE
const string Imdn::imdnPrefix = "/imdn:imdn";
void Imdn::parse (ChatRoom &cr, const string &text) {
xmlparsing_context_t *xmlCtx = linphone_xmlparsing_context_new();
xmlSetGenericErrorFunc(xmlCtx, linphone_xmlparsing_genericxml_error);
xmlCtx->doc = xmlReadDoc((const unsigned char *)text.c_str(), 0, nullptr, 0);
if (xmlCtx->doc)
parse(cr, xmlCtx);
else
lWarning() << "Wrongly formatted IMDN XML: " << xmlCtx->errorBuffer;
linphone_xmlparsing_context_destroy(xmlCtx);
}
void Imdn::parse (ChatRoom &cr, xmlparsing_context_t *xmlCtx) {
char xpathStr[MAX_XPATH_LENGTH];
char *messageIdStr = nullptr;
char *datetimeStr = nullptr;
if (linphone_create_xml_xpath_context(xmlCtx) < 0)
return;
xmlXPathRegisterNs(xmlCtx->xpath_ctx, (const xmlChar *)"imdn", (const xmlChar *)"urn:ietf:params:xml:ns:imdn");
xmlXPathObjectPtr imdnObject = linphone_get_xml_xpath_object_for_node_list(xmlCtx, imdnPrefix.c_str());
if (imdnObject) {
if (imdnObject->nodesetval && (imdnObject->nodesetval->nodeNr >= 1)) {
snprintf(xpathStr, sizeof(xpathStr), "%s[1]/imdn:message-id", imdnPrefix.c_str());
messageIdStr = linphone_get_xml_text_content(xmlCtx, xpathStr);
snprintf(xpathStr, sizeof(xpathStr), "%s[1]/imdn:datetime", imdnPrefix.c_str());
datetimeStr = linphone_get_xml_text_content(xmlCtx, xpathStr);
}
xmlXPathFreeObject(imdnObject);
}
if (messageIdStr && datetimeStr) {
LinphoneChatMessage *cm = cr.findMessageWithDirection(messageIdStr, LinphoneChatMessageOutgoing);
if (!cm) {
lWarning() << "Received IMDN for unknown message " << messageIdStr;
} else {
LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(cr.getCore());
snprintf(xpathStr, sizeof(xpathStr), "%s[1]/imdn:delivery-notification/imdn:status", imdnPrefix.c_str());
xmlXPathObjectPtr deliveryStatusObject = linphone_get_xml_xpath_object_for_node_list(xmlCtx, xpathStr);
snprintf(xpathStr, sizeof(xpathStr), "%s[1]/imdn:display-notification/imdn:status", imdnPrefix.c_str());
xmlXPathObjectPtr displayStatusObject = linphone_get_xml_xpath_object_for_node_list(xmlCtx, xpathStr);
if (deliveryStatusObject && linphone_im_notif_policy_get_recv_imdn_delivered(policy)) {
if (deliveryStatusObject->nodesetval && (deliveryStatusObject->nodesetval->nodeNr >= 1)) {
xmlNodePtr node = deliveryStatusObject->nodesetval->nodeTab[0];
if (node->children && node->children->name) {
if (strcmp((const char *)node->children->name, "delivered") == 0) {
linphone_chat_message_update_state(cm, LinphoneChatMessageStateDeliveredToUser);
} else if (strcmp((const char *)node->children->name, "error") == 0) {
linphone_chat_message_update_state(cm, LinphoneChatMessageStateNotDelivered);
}
}
}
xmlXPathFreeObject(deliveryStatusObject);
}
if (displayStatusObject && linphone_im_notif_policy_get_recv_imdn_displayed(policy)) {
if (displayStatusObject->nodesetval && (displayStatusObject->nodesetval->nodeNr >= 1)) {
xmlNodePtr node = displayStatusObject->nodesetval->nodeTab[0];
if (node->children && node->children->name) {
if (strcmp((const char *)node->children->name, "displayed") == 0) {
linphone_chat_message_update_state(cm, LinphoneChatMessageStateDisplayed);
}
}
}
xmlXPathFreeObject(displayStatusObject);
}
linphone_chat_message_unref(cm);
}
}
if (messageIdStr)
linphone_free_xml_text_content(messageIdStr);
if (datetimeStr)
linphone_free_xml_text_content(datetimeStr);
}
LINPHONE_END_NAMESPACE

View file

@ -1,47 +0,0 @@
/*
* imdn.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _IMDN_H_
#define _IMDN_H_
#include <string>
#include "linphone/utils/general.h"
#include "chat-room.h"
#include "private.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
class Imdn {
public:
static void parse (ChatRoom &cr, const std::string &content);
private:
static void parse (ChatRoom &cr, xmlparsing_context_t *xmlCtx);
private:
static const std::string imdnPrefix;
};
LINPHONE_END_NAMESPACE
#endif // ifndef _IMDN_H_

View file

@ -1,37 +0,0 @@
/*
* is-composing-listener.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _IS_COMPOSING_LISTENER_H_
#define _IS_COMPOSING_LISTENER_H_
#include "linphone/utils/general.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
class IsComposingListener {
public:
virtual void isComposingStateChanged (bool isComposing) = 0;
virtual void isRemoteComposingStateChanged (bool isComposing) = 0;
virtual void isComposingRefreshNeeded () = 0;
};
LINPHONE_END_NAMESPACE
#endif // ifndef _IS_COMPOSING_LISTENER_H_

View file

@ -1,267 +0,0 @@
/*
* is-composing.cpp
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "linphone/utils/utils.h"
#include "chat-room-p.h"
#include "logger/logger.h"
#include "is-composing.h"
// =============================================================================
using namespace std;
LINPHONE_BEGIN_NAMESPACE
const string IsComposing::isComposingPrefix = "/xsi:isComposing";
// -----------------------------------------------------------------------------
IsComposing::IsComposing (LinphoneCore *core, IsComposingListener *listener)
: core(core), listener(listener) {}
IsComposing::~IsComposing () {
stopTimers();
}
// -----------------------------------------------------------------------------
std::string IsComposing::marshal (bool isComposing) {
string content;
xmlBufferPtr buf = xmlBufferCreate();
if (!buf) {
lError() << "Error creating the XML buffer";
return content;
}
xmlTextWriterPtr writer = xmlNewTextWriterMemory(buf, 0);
if (!writer) {
lError() << "Error creating the XML writer";
return content;
}
int err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", nullptr);
if (err >= 0) {
err = xmlTextWriterStartElementNS(writer, nullptr, (const xmlChar *)"isComposing",
(const xmlChar *)"urn:ietf:params:xml:ns:im-iscomposing");
}
if (err >= 0) {
err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"xsi", nullptr,
(const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance");
}
if (err >= 0) {
err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xsi", (const xmlChar *)"schemaLocation", nullptr,
(const xmlChar *)"urn:ietf:params:xml:ns:im-composing iscomposing.xsd");
}
if (err >= 0) {
err = xmlTextWriterWriteElement(writer, (const xmlChar *)"state",
isComposing ? (const xmlChar *)"active" : (const xmlChar *)"idle");
}
if ((err >= 0) && isComposing) {
int refreshTimeout = lp_config_get_int(core->config, "sip", "composing_refresh_timeout", defaultRefreshTimeout);
err = xmlTextWriterWriteElement(writer, (const xmlChar *)"refresh", (const xmlChar *)Utils::toString(refreshTimeout).c_str());
}
if (err >= 0) {
/* Close the "isComposing" element. */
err = xmlTextWriterEndElement(writer);
}
if (err >= 0) {
err = xmlTextWriterEndDocument(writer);
}
if (err > 0) {
/* xmlTextWriterEndDocument returns the size of the content. */
content = (char *)buf->content;
}
xmlFreeTextWriter(writer);
xmlBufferFree(buf);
return content;
}
void IsComposing::parse (const string &text) {
xmlparsing_context_t *xmlCtx = linphone_xmlparsing_context_new();
xmlSetGenericErrorFunc(xmlCtx, linphone_xmlparsing_genericxml_error);
xmlCtx->doc = xmlReadDoc((const unsigned char *)text.c_str(), 0, nullptr, 0);
if (xmlCtx->doc)
parse(xmlCtx);
else
lWarning() << "Wrongly formatted presence XML: " << xmlCtx->errorBuffer;
linphone_xmlparsing_context_destroy(xmlCtx);
}
void IsComposing::startIdleTimer () {
int duration = getIdleTimerDuration();
if (!idleTimer) {
idleTimer = sal_create_timer(core->sal, idleTimerExpired, this,
duration * 1000, "composing idle timeout");
} else {
belle_sip_source_set_timeout(idleTimer, duration * 1000);
}
}
void IsComposing::startRefreshTimer () {
int duration = getRefreshTimerDuration();
if (!refreshTimer) {
refreshTimer = sal_create_timer(core->sal, refreshTimerExpired, this,
duration * 1000, "composing refresh timeout");
} else {
belle_sip_source_set_timeout(refreshTimer, duration * 1000);
}
}
void IsComposing::startRemoteRefreshTimer (const char *refreshStr) {
int duration = getRemoteRefreshTimerDuration();
if (refreshStr)
duration = atoi(refreshStr);
if (!remoteRefreshTimer) {
remoteRefreshTimer = sal_create_timer(core->sal, remoteRefreshTimerExpired, this,
duration * 1000, "composing remote refresh timeout");
} else {
belle_sip_source_set_timeout(remoteRefreshTimer, duration * 1000);
}
}
#if 0
void IsComposing::idleTimerExpired () {
stopRefreshTimer();
stopIdleTimer();
}
#endif
void IsComposing::stopTimers () {
stopIdleTimer();
stopRefreshTimer();
stopRemoteRefreshTimer();
}
// -----------------------------------------------------------------------------
void IsComposing::stopIdleTimer () {
if (idleTimer) {
if (core && core->sal)
sal_cancel_timer(core->sal, idleTimer);
belle_sip_object_unref(idleTimer);
idleTimer = nullptr;
}
}
void IsComposing::stopRefreshTimer () {
if (refreshTimer) {
if (core && core->sal)
sal_cancel_timer(core->sal, refreshTimer);
belle_sip_object_unref(refreshTimer);
refreshTimer = nullptr;
}
}
void IsComposing::stopRemoteRefreshTimer () {
if (remoteRefreshTimer) {
if (core && core->sal)
sal_cancel_timer(core->sal, remoteRefreshTimer);
belle_sip_object_unref(remoteRefreshTimer);
remoteRefreshTimer = nullptr;
}
}
// -----------------------------------------------------------------------------
int IsComposing::getIdleTimerDuration () {
return lp_config_get_int(core->config, "sip", "composing_idle_timeout", defaultIdleTimeout);
}
int IsComposing::getRefreshTimerDuration () {
return lp_config_get_int(core->config, "sip", "composing_refresh_timeout", defaultRefreshTimeout);
}
int IsComposing::getRemoteRefreshTimerDuration () {
return lp_config_get_int(core->config, "sip", "composing_remote_refresh_timeout", defaultRemoteRefreshTimeout);
}
void IsComposing::parse (xmlparsing_context_t *xmlCtx) {
char xpathStr[MAX_XPATH_LENGTH];
char *stateStr = nullptr;
char *refreshStr = nullptr;
int i;
bool state = false;
if (linphone_create_xml_xpath_context(xmlCtx) < 0)
return;
xmlXPathRegisterNs(xmlCtx->xpath_ctx, (const xmlChar *)"xsi", (const xmlChar *)"urn:ietf:params:xml:ns:im-iscomposing");
xmlXPathObjectPtr isComposingObject = linphone_get_xml_xpath_object_for_node_list(xmlCtx, isComposingPrefix.c_str());
if (isComposingObject) {
if (isComposingObject->nodesetval) {
for (i = 1; i <= isComposingObject->nodesetval->nodeNr; i++) {
snprintf(xpathStr, sizeof(xpathStr), "%s[%i]/xsi:state", isComposingPrefix.c_str(), i);
stateStr = linphone_get_xml_text_content(xmlCtx, xpathStr);
if (!stateStr)
continue;
snprintf(xpathStr, sizeof(xpathStr), "%s[%i]/xsi:refresh", isComposingPrefix.c_str(), i);
refreshStr = linphone_get_xml_text_content(xmlCtx, xpathStr);
}
}
xmlXPathFreeObject(isComposingObject);
}
if (stateStr) {
if (strcmp(stateStr, "active") == 0) {
state = true;
startRemoteRefreshTimer(refreshStr);
} else {
stopRemoteRefreshTimer();
}
listener->isRemoteComposingStateChanged(state);
linphone_free_xml_text_content(stateStr);
}
if (refreshStr)
linphone_free_xml_text_content(refreshStr);
}
int IsComposing::idleTimerExpired (unsigned int revents) {
listener->isComposingStateChanged(false);
return BELLE_SIP_STOP;
}
int IsComposing::refreshTimerExpired (unsigned int revents) {
listener->isComposingRefreshNeeded();
return BELLE_SIP_CONTINUE;
}
int IsComposing::remoteRefreshTimerExpired (unsigned int revents) {
stopRemoteRefreshTimer();
listener->isRemoteComposingStateChanged(false);
return BELLE_SIP_STOP;
}
int IsComposing::idleTimerExpired (void *data, unsigned int revents) {
IsComposing *d = reinterpret_cast<IsComposing *>(data);
return d->idleTimerExpired(revents);
}
int IsComposing::refreshTimerExpired (void *data, unsigned int revents) {
IsComposing *d = reinterpret_cast<IsComposing *>(data);
return d->refreshTimerExpired(revents);
}
int IsComposing::remoteRefreshTimerExpired (void *data, unsigned int revents) {
IsComposing *d = reinterpret_cast<IsComposing *>(data);
return d->remoteRefreshTimerExpired(revents);
}
LINPHONE_END_NAMESPACE

View file

@ -1,78 +0,0 @@
/*
* is-composing.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _IS_COMPOSING_H_
#define _IS_COMPOSING_H_
#include <string>
#include "linphone/utils/general.h"
#include "is-composing-listener.h"
#include "private.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
class IsComposing {
public:
IsComposing (LinphoneCore *core, IsComposingListener *listener);
~IsComposing ();
std::string marshal (bool isComposing);
void parse (const std::string &content);
void startIdleTimer ();
void startRefreshTimer ();
void startRemoteRefreshTimer (const char *refreshStr);
void stopComposing ();
void stopIdleTimer ();
void stopRefreshTimer ();
void stopRemoteRefreshTimer ();
void stopTimers ();
private:
int getIdleTimerDuration ();
int getRefreshTimerDuration ();
int getRemoteRefreshTimerDuration ();
void parse (xmlparsing_context_t *xmlCtx);
int idleTimerExpired (unsigned int revents);
int refreshTimerExpired (unsigned int revents);
int remoteRefreshTimerExpired (unsigned int revents);
static int idleTimerExpired (void *data, unsigned int revents);
static int refreshTimerExpired (void *data, unsigned int revents);
static int remoteRefreshTimerExpired (void *data, unsigned int revents);
private:
static const int defaultIdleTimeout = 15;
static const int defaultRefreshTimeout = 60;
static const int defaultRemoteRefreshTimeout = 120;
static const std::string isComposingPrefix;
LinphoneCore *core = nullptr;
IsComposingListener *listener = nullptr;
belle_sip_source_t *remoteRefreshTimer = nullptr;
belle_sip_source_t *idleTimer = nullptr;
belle_sip_source_t *refreshTimer = nullptr;
};
LINPHONE_END_NAMESPACE
#endif // ifndef _IS_COMPOSING_H_

View file

@ -18,10 +18,9 @@
#include <set>
#include "linphone/utils/utils.h"
#include "cpim-header-p.h"
#include "cpim/parser/cpim-parser.h"
#include "utils/utils.h"
#include "cpim-generic-header.h"

View file

@ -18,10 +18,9 @@
#include <algorithm>
#include "linphone/utils/utils.h"
#include "cpim/parser/cpim-parser.h"
#include "object/object-p.h"
#include "utils/utils.h"
#include "cpim-message.h"

View file

@ -19,7 +19,7 @@
#ifndef _CPIM_GRAMMAR_H_
#define _CPIM_GRAMMAR_H_
#include "linphone/utils/general.h"
#include "utils/general.h"
// =============================================================================

View file

@ -21,11 +21,10 @@
#include <belr/abnf.h>
#include <belr/grammarbuilder.h>
#include "linphone/utils/utils.h"
#include "cpim-grammar.h"
#include "logger/logger.h"
#include "object/object-p.h"
#include "utils/utils.h"
#include "cpim-parser.h"

View file

@ -18,7 +18,6 @@
#include "abstract-db-p.h"
#include "db/provider/db-session-provider.h"
#include "logger/logger.h"
#include "abstract-db.h"
@ -33,22 +32,12 @@ AbstractDb::AbstractDb (AbstractDbPrivate &p) : Object(*new AbstractDbPrivate) {
bool AbstractDb::connect (Backend backend, const string &parameters) {
L_D(AbstractDb);
d->backend = backend;
d->dbSession = DbSessionProvider::getInstance()->getSession(
(backend == Mysql ? "mysql://" : "sqlite3://") + parameters
);
if (d->dbSession) {
try {
init();
} catch (const exception &e) {
lWarning() << "Unable to init database: " << e.what();
// Reset session.
d->dbSession = DbSession();
}
}
if (d->dbSession)
init();
return d->dbSession;
}

View file

@ -23,10 +23,10 @@
#endif // ifdef SOCI_ENABLED
#include "abstract/abstract-db-p.h"
#include "chat/chat-message.h"
#include "event-log/call-event.h"
#include "event-log/message-event.h"
#include "logger/logger.h"
#include "message/message.h"
#include "events-db.h"
@ -75,25 +75,25 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
);
}
static constexpr EnumToSql<ChatMessage::State> messageStateToSql[] = {
{ ChatMessage::Idle, "1" },
{ ChatMessage::InProgress, "2" },
{ ChatMessage::Delivered, "3" },
{ ChatMessage::NotDelivered, "4" },
{ ChatMessage::FileTransferError, "5" },
{ ChatMessage::FileTransferDone, "6" },
{ ChatMessage::DeliveredToUser, "7" },
{ ChatMessage::Displayed, "8" }
static constexpr EnumToSql<Message::State> messageStateToSql[] = {
{ Message::Idle, "1" },
{ Message::InProgress, "2" },
{ Message::Delivered, "3" },
{ Message::NotDelivered, "4" },
{ Message::FileTransferError, "5" },
{ Message::FileTransferDone, "6" },
{ Message::DeliveredToUser, "7" },
{ Message::Displayed, "8" }
};
static constexpr const char *mapMessageStateToSql (ChatMessage::State state) {
static constexpr const char *mapMessageStateToSql (Message::State state) {
return mapEnumToSql(
messageStateToSql, sizeof messageStateToSql / sizeof messageStateToSql[0], state
);
}
static constexpr const char *mapMessageDirectionToSql (ChatMessage::Direction direction) {
return direction == ChatMessage::Direction::Incoming ? "1" : "2";
static constexpr const char *mapMessageDirectionToSql (Message::Direction direction) {
return direction == Message::Direction::Incoming ? "1" : "2";
}
// -----------------------------------------------------------------------------
@ -135,13 +135,13 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
*session <<
"CREATE TABLE IF NOT EXISTS sip_address ("
" id" + primaryKeyAutoIncrementStr() + ","
" value VARCHAR(255) UNIQUE NOT NULL"
" value VARCHAR(255) NOT NULL"
")";
*session <<
"CREATE TABLE IF NOT EXISTS event_type ("
" id TINYINT UNSIGNED,"
" value VARCHAR(255) UNIQUE NOT NULL"
" id" + primaryKeyAutoIncrementStr("TINYINT") + ","
" value VARCHAR(255) NOT NULL"
")";
*session <<
@ -156,14 +156,14 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
*session <<
"CREATE TABLE IF NOT EXISTS message_state ("
" id TINYINT UNSIGNED,"
" value VARCHAR(255) UNIQUE NOT NULL"
" id" + primaryKeyAutoIncrementStr("TINYINT") + ","
" state VARCHAR(255) NOT NULL"
")";
*session <<
"CREATE TABLE IF NOT EXISTS message_direction ("
" id TINYINT UNSIGNED,"
" value VARCHAR(255) UNIQUE NOT NULL"
" id" + primaryKeyAutoIncrementStr("TINYINT") + ","
" direction VARCHAR(255) NOT NULL"
")";
*session <<
@ -184,19 +184,13 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
*session <<
"CREATE TABLE IF NOT EXISTS message_event ("
" id" + primaryKeyAutoIncrementStr() + ","
" event_id INT UNSIGNED NOT NULL,"
" dialog_id INT UNSIGNED NOT NULL,"
" state_id TINYINT UNSIGNED NOT NULL,"
" direction_id TINYINT UNSIGNED NOT NULL,"
" sender_sip_address_id INT UNSIGNED NOT NULL,"
" imdn_message_id VARCHAR(255) NOT NULL," // See: https://tools.ietf.org/html/rfc5438#section-6.3
" content_type VARCHAR(255) NOT NULL,"
" is_secured BOOLEAN NOT NULL,"
" content_type VARCHAR(255) NOT NULL," // Content type of text. (Html or text for example.)
" text TEXT,"
" app_data VARCHAR(2048)," // App user data.
" FOREIGN KEY (event_id)"
" REFERENCES event(id)"
" ON DELETE CASCADE,"
" app_data VARCHAR(2048),"
" FOREIGN KEY (dialog_id)"
" REFERENCES dialog(id)"
" ON DELETE CASCADE,"
@ -205,24 +199,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
" ON DELETE CASCADE,"
" FOREIGN KEY (direction_id)"
" REFERENCES message_direction(id)"
" ON DELETE CASCADE,"
" FOREIGN KEY (sender_sip_address_id)"
" REFERENCES sip_address(id)"
" ON DELETE CASCADE"
")";
*session <<
"CREATE TABLE IF NOT EXISTS message_file_info ("
" id" + primaryKeyAutoIncrementStr() + ","
" message_id INT UNSIGNED NOT NULL,"
" content_type VARCHAR(255) NOT NULL," // File content type.
" name VARCHAR(255) NOT NULL," // File name.
" size INT UNSIGNED NOT NULL," // File size.
" url VARCHAR(255) NOT NULL," // File url.
" key VARCHAR(4096),"
" key_size INT UNSIGNED,"
" FOREIGN KEY (message_id)"
" REFERENCES message(id)"
" ON DELETE CASCADE"
")";
@ -274,11 +250,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
}
bool EventsDb::addEvent (const EventLog &eventLog) {
if (!isConnected()) {
lWarning() << "Unable to add event. Not connected.";
return false;
}
// TODO.
switch (eventLog.getType()) {
case EventLog::TypeNone:
@ -299,22 +270,12 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
}
bool EventsDb::deleteEvent (const EventLog &eventLog) {
if (!isConnected()) {
lWarning() << "Unable to delete event. Not connected.";
return false;
}
// TODO.
(void)eventLog;
return true;
}
void EventsDb::cleanEvents (FilterMask mask) {
if (!isConnected()) {
lWarning() << "Unable to clean events. Not connected.";
return;
}
// TODO.
(void)mask;
}
@ -322,11 +283,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
int EventsDb::getEventsCount (FilterMask mask) const {
L_D(const EventsDb);
if (!isConnected()) {
lWarning() << "Unable to get events count. Not connected.";
return 0;
}
string query = "SELECT COUNT(*) FROM event" +
buildSqlEventFilter({ MessageFilter, CallFilter, ConferenceFilter }, mask);
int count = 0;
@ -344,11 +300,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
int EventsDb::getMessagesCount (const string &remoteAddress) const {
L_D(const EventsDb);
if (!isConnected()) {
lWarning() << "Unable to get messages count. Not connected.";
return 0;
}
string query = "SELECT COUNT(*) FROM message_event";
if (!remoteAddress.empty())
query += " WHERE dialog_id = ("
@ -371,11 +322,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
int EventsDb::getUnreadMessagesCount (const string &remoteAddress) const {
L_D(const EventsDb);
if (!isConnected()) {
lWarning() << "Unable to get unread messages count. Not connected.";
return 0;
}
string query = "SELECT COUNT(*) FROM message_event";
if (!remoteAddress.empty())
query += " WHERE dialog_id = ("
@ -383,8 +329,8 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
" SELECT id FROM sip_address WHERE value = :remote_address"
" )"
" )"
" AND direction_id = " + string(mapMessageDirectionToSql(ChatMessage::Incoming)) +
" AND state_id = " + string(mapMessageStateToSql(ChatMessage::Displayed));
" AND direction_id = " + string(mapMessageDirectionToSql(Message::Incoming)) +
" AND state_id = " + string(mapMessageStateToSql(Message::Displayed));
int count = 0;
L_BEGIN_LOG_EXCEPTION
@ -398,11 +344,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
}
list<shared_ptr<EventLog>> EventsDb::getHistory (const string &remoteAddress, int nLast, FilterMask mask) const {
if (!isConnected()) {
lWarning() << "Unable to get history. Not connected.";
return list<shared_ptr<EventLog>>();
}
// TODO.
(void)remoteAddress;
(void)nLast;
@ -411,11 +352,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
}
list<shared_ptr<EventLog>> EventsDb::getHistory (const string &remoteAddress, int begin, int end, FilterMask mask) const {
if (!isConnected()) {
lWarning() << "Unable to get history. Not connected.";
return list<shared_ptr<EventLog>>();
}
// TODO.
(void)remoteAddress;
(void)begin;
@ -425,11 +361,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
}
void EventsDb::cleanHistory (const string &remoteAddress) {
if (!isConnected()) {
lWarning() << "Unable to clean history. Not connected.";
return;
}
// TODO.
(void)remoteAddress;
}

View file

@ -1,37 +0,0 @@
/*
* enums.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ENUMS_H_
#define _ENUMS_H_
#include "linphone/utils/general.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
enum class Transport {
Udp,
Tcp,
Tls,
Dtls
};
LINPHONE_END_NAMESPACE
#endif // ifndef _ENUMS_H_

View file

@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "address/address.h"
#include "conference-event-p.h"
#include "conference-event.h"
@ -32,7 +31,8 @@ ConferenceEvent::ConferenceEvent (Type type, const shared_ptr<const Address> &ad
L_D(ConferenceEvent);
L_ASSERT(type == TypeConferenceCreated || type == TypeConferenceDestroyed);
L_ASSERT(address);
d->address = make_shared<Address>(*address);
// TODO: Duplicate address.
d->address = address;
}
ConferenceEvent::ConferenceEvent (const ConferenceEvent &src) : ConferenceEvent(src.getType(), src.getAddress()) {}
@ -41,22 +41,24 @@ ConferenceEvent::ConferenceEvent (ConferenceEventPrivate &p, Type type, const sh
EventLog(p, type) {
L_D(ConferenceEvent);
L_ASSERT(address);
d->address = make_shared<Address>(*address);
// TODO: Duplicate address.
d->address = address;
}
ConferenceEvent &ConferenceEvent::operator= (const ConferenceEvent &src) {
L_D(ConferenceEvent);
if (this != &src) {
EventLog::operator=(src);
d->address = make_shared<Address>(*src.getPrivate()->address);
// TODO: Duplicate address.
d->address = src.getPrivate()->address;
}
return *this;
}
shared_ptr<const Address> ConferenceEvent::getAddress () const {
L_D(const ConferenceEvent);
return d->address;
// TODO.
return nullptr;
}
LINPHONE_END_NAMESPACE

View file

@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "address/address.h"
#include "conference-event-p.h"
#include "conference-participant-event.h"
@ -47,7 +46,8 @@ ConferenceParticipantEvent::ConferenceParticipantEvent (
type == TypeConferenceParticipantUnsetAdmin
);
L_ASSERT(participantAddress);
d->participantAddress = make_shared<Address>(*participantAddress);
// TODO: Duplicate address.
d->participantAddress = participantAddress;
}
ConferenceParticipantEvent::ConferenceParticipantEvent (const ConferenceParticipantEvent &src) :
@ -57,15 +57,16 @@ ConferenceParticipantEvent &ConferenceParticipantEvent::operator= (const Confere
L_D(ConferenceParticipantEvent);
if (this != &src) {
ConferenceEvent::operator=(src);
d->participantAddress = make_shared<Address>(*src.getPrivate()->participantAddress);
// TODO: Duplicate address.
d->participantAddress = src.getPrivate()->participantAddress;
}
return *this;
}
shared_ptr<const Address> ConferenceParticipantEvent::getParticipantAddress () const {
L_D(const ConferenceParticipantEvent);
return d->participantAddress;
// TODO.
return nullptr;
}
LINPHONE_END_NAMESPACE

View file

@ -19,7 +19,7 @@
#ifndef _EVENT_LOG_ENUMS_H_
#define _EVENT_LOG_ENUMS_H_
#include "linphone/utils/enum-generator.h"
#include "utils/enum-generator.h"
// =============================================================================

View file

@ -19,9 +19,8 @@
#ifndef _EVENT_LOG_H_
#define _EVENT_LOG_H_
#include "linphone/enums/event-log-enums.h"
#include "object/clonable-object.h"
#include "event-log-enums.h"
// =============================================================================

View file

@ -51,11 +51,11 @@ private:
LINPHONE_END_NAMESPACE
#define lDebug() LINPHONE_NAMESPACE::Logger(LINPHONE_NAMESPACE::Logger::Debug).getOutput()
#define lInfo() LINPHONE_NAMESPACE::Logger(LINPHONE_NAMESPACE::Logger::Info).getOutput()
#define lWarning() LINPHONE_NAMESPACE::Logger(LINPHONE_NAMESPACE::Logger::Warning).getOutput()
#define lError() LINPHONE_NAMESPACE::Logger(LINPHONE_NAMESPACE::Logger::Error).getOutput()
#define lFatal() LINPHONE_NAMESPACE::Logger(LINPHONE_NAMESPACE::Logger::Fatal).getOutput()
#define lDebug() LINPHONE_NAMESPACE::Logger(Logger::Debug).getOutput()
#define lInfo() LINPHONE_NAMESPACE::Logger(Logger::Info).getOutput()
#define lWarning() LINPHONE_NAMESPACE::Logger(Logger::Warning).getOutput()
#define lError() LINPHONE_NAMESPACE::Logger(Logger::Error).getOutput()
#define lFatal() LINPHONE_NAMESPACE::Logger(Logger::Fatal).getOutput()
#define L_BEGIN_LOG_EXCEPTION try {
#define L_END_LOG_EXCEPTION \

View file

@ -1,5 +1,5 @@
/*
* chat-message.cpp
* message.cpp
* Copyright (C) 2017 Belledonne Communications SARL
*
* This program is free software: you can redistribute it and/or modify
@ -21,7 +21,7 @@
#include "db/events-db.h"
#include "object/object-p.h"
#include "chat-message.h"
#include "message.h"
// =============================================================================
@ -29,10 +29,10 @@ LINPHONE_BEGIN_NAMESPACE
using namespace std;
class ChatMessagePrivate : public ObjectPrivate {
class MessagePrivate : public ObjectPrivate {
private:
weak_ptr<ChatRoom> chatRoom;
ChatMessage::Direction direction = ChatMessage::Incoming;
Message::Direction direction = Message::Incoming;
// LinphoneAddress *from;
// LinphoneAddress *to;
shared_ptr<ErrorInfo> errorInfo;
@ -44,18 +44,18 @@ private:
string appData;
list<shared_ptr<Content> > contents;
unordered_map<string, string> customHeaders;
ChatMessage::State state = ChatMessage::Idle;
Message::State state = Message::Idle;
shared_ptr<EventsDb> eventsDb;
L_DECLARE_PUBLIC(ChatMessage);
L_DECLARE_PUBLIC(Message);
};
// -----------------------------------------------------------------------------
ChatMessage::ChatMessage (ChatMessagePrivate &p) : Object(p) {}
Message::Message (MessagePrivate &p) : Object(p) {}
shared_ptr<ChatRoom> ChatMessage::getChatRoom () const {
L_D(const ChatMessage);
shared_ptr<ChatRoom> Message::getChatRoom () const {
L_D(const Message);
shared_ptr<ChatRoom> chatRoom = d->chatRoom.lock();
if (!chatRoom) {
// TODO.
@ -63,110 +63,110 @@ shared_ptr<ChatRoom> ChatMessage::getChatRoom () const {
return chatRoom;
}
ChatMessage::Direction ChatMessage::getDirection () const {
L_D(const ChatMessage);
Message::Direction Message::getDirection () const {
L_D(const Message);
return d->direction;
}
shared_ptr<const Address> ChatMessage::getFromAddress () const {
shared_ptr<const Address> Message::getFromAddress () const {
// TODO.
return nullptr;
}
shared_ptr<const Address> ChatMessage::getToAddress () const {
shared_ptr<const Address> Message::getToAddress () const {
// TODO.
return nullptr;
}
shared_ptr<const Address> ChatMessage::getLocalAddress () const {
shared_ptr<const Address> Message::getLocalAddress () const {
// TODO.
return nullptr;
}
shared_ptr<const Address> ChatMessage::getRemoteAddress () const {
shared_ptr<const Address> Message::getRemoteAddress () const {
// TODO.
return nullptr;
}
ChatMessage::State ChatMessage::getState () const {
L_D(const ChatMessage);
Message::State Message::getState () const {
L_D(const Message);
return d->state;
}
shared_ptr<const ErrorInfo> ChatMessage::getErrorInfo () const {
L_D(const ChatMessage);
shared_ptr<const ErrorInfo> Message::getErrorInfo () const {
L_D(const Message);
return d->errorInfo;
}
string ChatMessage::getContentType () const {
L_D(const ChatMessage);
string Message::getContentType () const {
L_D(const Message);
return d->contentType;
}
string ChatMessage::getText () const {
L_D(const ChatMessage);
string Message::getText () const {
L_D(const Message);
return d->text;
}
void ChatMessage::setText (const string &text) {
L_D(ChatMessage);
void Message::setText (const string &text) {
L_D(Message);
d->text = text;
}
void ChatMessage::send () const {
void Message::send () const {
// TODO.
}
bool ChatMessage::containsReadableText () const {
bool Message::containsReadableText () const {
// TODO: Check content type.
return true;
}
bool ChatMessage::isSecured () const {
L_D(const ChatMessage);
bool Message::isSecured () const {
L_D(const Message);
return d->isSecured;
}
time_t ChatMessage::getTime () const {
L_D(const ChatMessage);
time_t Message::getTime () const {
L_D(const Message);
return d->time;
}
string ChatMessage::getId () const {
L_D(const ChatMessage);
string Message::getId () const {
L_D(const Message);
return d->id;
}
string ChatMessage::getAppdata () const {
L_D(const ChatMessage);
string Message::getAppdata () const {
L_D(const Message);
return d->appData;
}
void ChatMessage::setAppdata (const string &appData) {
L_D(ChatMessage);
void Message::setAppdata (const string &appData) {
L_D(Message);
d->appData = appData;
}
list<shared_ptr<const Content> > ChatMessage::getContents () const {
L_D(const ChatMessage);
list<shared_ptr<const Content> > Message::getContents () const {
L_D(const Message);
list<shared_ptr<const Content> > contents;
for (const auto &content : d->contents)
contents.push_back(content);
return contents;
}
void ChatMessage::addContent (const shared_ptr<Content> &content) {
L_D(ChatMessage);
void Message::addContent (const shared_ptr<Content> &content) {
L_D(Message);
d->contents.push_back(content);
}
void ChatMessage::removeContent (const shared_ptr<const Content> &content) {
L_D(ChatMessage);
void Message::removeContent (const shared_ptr<const Content> &content) {
L_D(Message);
d->contents.remove(const_pointer_cast<Content>(content));
}
string ChatMessage::getCustomHeaderValue (const string &headerName) const {
L_D(const ChatMessage);
string Message::getCustomHeaderValue (const string &headerName) const {
L_D(const Message);
try {
return d->customHeaders.at(headerName);
} catch (const exception &) {
@ -175,13 +175,13 @@ string ChatMessage::getCustomHeaderValue (const string &headerName) const {
return "";
}
void ChatMessage::addCustomHeader (const string &headerName, const string &headerValue) {
L_D(ChatMessage);
void Message::addCustomHeader (const string &headerName, const string &headerValue) {
L_D(Message);
d->customHeaders[headerName] = headerValue;
}
void ChatMessage::removeCustomHeader (const string &headerName) {
L_D(ChatMessage);
void Message::removeCustomHeader (const string &headerName) {
L_D(Message);
d->customHeaders.erase(headerName);
}

View file

@ -1,5 +1,5 @@
/*
* chat-message.h
* message.h
* Copyright (C) 2017 Belledonne Communications SARL
*
* This program is free software: you can redistribute it and/or modify
@ -16,11 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CHAT_MESSAGE_H_
#define _CHAT_MESSAGE_H_
#ifndef _MESSAGE_H_
#define _MESSAGE_H_
#include <list>
#include <memory>
#include <string>
#include "object/object.h"
@ -32,9 +33,9 @@ class Address;
class ChatRoom;
class Content;
class ErrorInfo;
class ChatMessagePrivate;
class MessagePrivate;
class LINPHONE_PUBLIC ChatMessage : public Object {
class LINPHONE_PUBLIC Message : public Object {
friend class ChatRoom;
public:
@ -94,12 +95,12 @@ public:
void removeCustomHeader (const std::string &headerName);
private:
ChatMessage (ChatMessagePrivate &p);
Message (MessagePrivate &p);
L_DECLARE_PRIVATE(ChatMessage);
L_DISABLE_COPY(ChatMessage);
L_DECLARE_PRIVATE(Message);
L_DISABLE_COPY(Message);
};
LINPHONE_END_NAMESPACE
#endif // ifndef _CHAT_MESSAGE_H_
#endif // ifndef _MESSAGE_H_

View file

@ -21,7 +21,7 @@
#include <unordered_map>
#include "linphone/utils/general.h"
#include "utils/general.h"
// =============================================================================
@ -29,7 +29,6 @@ LINPHONE_BEGIN_NAMESPACE
class ClonableObjectPrivate {
public:
ClonableObjectPrivate () = default;
virtual ~ClonableObjectPrivate () = default;
protected:
@ -42,10 +41,6 @@ private:
int nRefs = 0;
L_DECLARE_PUBLIC(ClonableObject);
// It's forbidden to copy directly one Clonable object private.
// To allow copy, you must define copy constructor in inherited object.
L_DISABLE_COPY(ClonableObjectPrivate);
};
LINPHONE_END_NAMESPACE

View file

@ -45,7 +45,7 @@ ClonableObject::ClonableObject (ClonableObjectPrivate &p) : mPrivate(&p) {
// Q-pointer must be empty. It's a constructor that takes a new private data.
L_ASSERT(!mPrivate->mPublic);
mPrivate->mPublic = new remove_pointer<decltype(mPrivate->mPublic)>::type();
mPrivate->mPublic = new remove_pointer<decltype(mPrivate->mPublic)>::type;
(*mPrivate->mPublic)[mPrivate] = this;
mPrivate->ref();
}

View file

@ -19,7 +19,7 @@
#ifndef _CLONABLE_OBJECT_H_
#define _CLONABLE_OBJECT_H_
#include "linphone/utils/general.h"
#include "utils/general.h"
// =============================================================================

View file

@ -19,7 +19,7 @@
#ifndef _OBJECT_P_H_
#define _OBJECT_P_H_
#include "linphone/utils/general.h"
#include "utils/general.h"
// =============================================================================

View file

@ -19,7 +19,7 @@
#ifndef _OBJECT_H_
#define _OBJECT_H_
#include "linphone/utils/general.h"
#include "utils/general.h"
// =============================================================================

View file

@ -1,43 +0,0 @@
/*
* content-type.cpp
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "content-type.h"
// =============================================================================
using namespace std;
LINPHONE_BEGIN_NAMESPACE
bool ContentType::isFileTransfer (const string &contentType) {
return "application/vnd.gsma.rcs-ft-http+xml" == contentType;
}
bool ContentType::isImIsComposing (const string &contentType) {
return "application/im-iscomposing+xml" == contentType;
}
bool ContentType::isImdn (const string &contentType) {
return "message/imdn+xml" == contentType;
}
bool ContentType::isText (const string &contentType) {
return "text/plain" == contentType;
}
LINPHONE_END_NAMESPACE

View file

@ -1,39 +0,0 @@
/*
* content-type.h
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CONTENT_TYPE_H_
#define _CONTENT_TYPE_H_
#include <string>
#include "linphone/utils/general.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
namespace ContentType {
bool isFileTransfer (const std::string &contentType);
bool isImIsComposing (const std::string &contentType);
bool isImdn (const std::string &contentType);
bool isText (const std::string &contentType);
}
LINPHONE_END_NAMESPACE
#endif // ifndef _CONTENT_TYPE_H_

View file

@ -19,7 +19,7 @@
#ifndef _ENUM_GENERATOR_H_
#define _ENUM_GENERATOR_H_
#include "linphone/utils/magic-macros.h"
#include "magic-macros.h"
// =============================================================================

View file

@ -16,10 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "linphone/utils/general.h"
#include "logger/logger.h"
#include "general.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE

View file

@ -51,14 +51,6 @@ LINPHONE_BEGIN_NAMESPACE
#endif
#endif
#ifndef LINPHONE_DEPRECATED
#if defined(_MSC_VER)
#define LINPHONE_DEPRECATED __declspec(deprecated)
#else
#define LINPHONE_DEPRECATED __attribute__ ((deprecated))
#endif
#endif
// -----------------------------------------------------------------------------
#ifdef __cplusplus
@ -71,8 +63,6 @@ void l_assert (const char *condition, const char *file, int line);
#define L_ASSERT(CONDITION) ((CONDITION) ? static_cast<void>(0) : l_assert(#CONDITION, __FILE__, __LINE__))
#endif
// Allows access to private internal data.
// Gives a control to C Wrapper.
#define L_DECLARE_PRIVATE(CLASS) \
inline CLASS ## Private * getPrivate() { \
return reinterpret_cast<CLASS ## Private *>(mPrivate); \
@ -80,8 +70,7 @@ void l_assert (const char *condition, const char *file, int line);
inline const CLASS ## Private *getPrivate() const { \
return reinterpret_cast<const CLASS ## Private *>(mPrivate); \
} \
friend class CLASS ## Private; \
friend class Wrapper;
friend class CLASS ## Private;
class ClonableObject;
class ClonableObjectPrivate;

View file

@ -19,7 +19,7 @@
#ifndef _MAGIC_MACROS_H_
#define _MAGIC_MACROS_H_
#include "linphone/utils/general.h"
#include "general.h"
// =============================================================================
// Original header.

View file

@ -17,11 +17,8 @@
*/
#include <cstdlib>
#include <sstream>
#include <bctoolbox/port.h>
#include "linphone/utils/utils.h"
#include "utils.h"
// =============================================================================
@ -53,30 +50,6 @@ vector<string> Utils::split (const string &str, const string &delimiter) {
return out;
}
#ifndef __ANDROID__
#define TO_STRING_IMPL(TYPE) \
string Utils::toString(TYPE val) { \
return to_string(val); \
}
#else
#define TO_STRING_IMPL(TYPE) \
string Utils::toString(TYPE val) { \
ostringstream os; \
os << val; \
return os.str(); \
}
#endif // ifndef __ANDROID__
TO_STRING_IMPL(int)
TO_STRING_IMPL(long)
TO_STRING_IMPL(long long)
TO_STRING_IMPL(unsigned)
TO_STRING_IMPL(unsigned long)
TO_STRING_IMPL(unsigned long long)
TO_STRING_IMPL(float)
TO_STRING_IMPL(double)
TO_STRING_IMPL(long double)
int Utils::stoi (const string &str, size_t *idx, int base) {
char *p;
int v = strtol(str.c_str(), &p, base);
@ -87,30 +60,4 @@ int Utils::stoi (const string &str, size_t *idx, int base) {
return v;
}
char *Utils::utf8ToChar (uint32_t ic) {
char *result = new char[5];
int size = 0;
if (ic < 0x80) {
result[0] = ic;
size = 1;
} else if (ic < 0x800) {
result[1] = 0x80 + ((ic & 0x3F));
result[0] = 0xC0 + ((ic >> 6) & 0x1F);
size = 2;
} else if (ic < 0x100000) {
result[2] = 0x80 + (ic & 0x3F);
result[1] = 0x80 + ((ic >> 6) & 0x3F);
result[0] = 0xE0 + ((ic >> 12) & 0xF);
size = 3;
} else if (ic < 0x110000) {
result[3] = 0x80 + (ic & 0x3F);
result[2] = 0x80 + ((ic >> 6) & 0x3F);
result[1] = 0x80 + ((ic >> 12) & 0x3F);
result[0] = 0xF0 + ((ic >> 18) & 0x7);
size = 4;
}
result[size] = '\0';
return result;
}
LINPHONE_END_NAMESPACE

View file

@ -22,7 +22,7 @@
#include <string>
#include <vector>
#include "linphone/utils/general.h"
#include "general.h"
// =============================================================================
@ -37,26 +37,7 @@ namespace Utils {
return split(str, std::string(1, delimiter));
}
LINPHONE_PUBLIC std::string toString (int val);
LINPHONE_PUBLIC std::string toString (long val);
LINPHONE_PUBLIC std::string toString (long long val);
LINPHONE_PUBLIC std::string toString (unsigned val);
LINPHONE_PUBLIC std::string toString (unsigned long val);
LINPHONE_PUBLIC std::string toString (unsigned long long val);
LINPHONE_PUBLIC std::string toString (float val);
LINPHONE_PUBLIC std::string toString (double val);
LINPHONE_PUBLIC std::string toString (long double val);
LINPHONE_PUBLIC int stoi (const std::string &str, size_t *idx = 0, int base = 10);
// Return a buffer allocated with new.
LINPHONE_PUBLIC char *utf8ToChar (uint32_t ic);
template<typename T>
LINPHONE_PUBLIC const T &getEmptyConstRefObject () {
static const T object;
return object;
}
}
LINPHONE_END_NAMESPACE

View file

@ -76,11 +76,6 @@ set(CERTIFICATE_CLIENT_FILES
set(CERTIFICATE_FILES ${CERTIFICATE_ALT_FILES} ${CERTIFICATE_CN_FILES} ${CERTIFICATE_CLIENT_FILES})
set(DB_FILES
db/linphone.db
db/messages.db
)
set(RC_FILES
rcfiles/account_creator_rc
rcfiles/assistant_create.rc
@ -151,11 +146,11 @@ set(VCARD_FILES
set(OTHER_FILES
tester_hosts
local_tester_hosts
messages.db
)
set(IOS_RESOURCES_FILES
${OTHER_FILES}
${DB_FILES}
certificates
images
rcfiles
@ -198,9 +193,7 @@ set(SOURCE_FILES_C
)
set(SOURCE_FILES_CXX
clonable-object-tester.cpp
cpim-tester.cpp
events-db-tester.cpp
cpim_tester.cpp
)
set(SOURCE_FILES_OBJC )
@ -314,15 +307,14 @@ if (NOT ANDROID AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
install(FILES ${CERTIFICATE_ALT_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/altname")
install(FILES ${CERTIFICATE_CLIENT_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/client")
install(FILES ${CERTIFICATE_CN_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/cn")
install(FILES ${DB_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/db")
install(FILES ${IMAGE_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/images")
install(FILES ${OTHER_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester")
install(FILES ${RC_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/rcfiles")
install(FILES ${SIPP_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/sipp")
install(FILES ${SOUND_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/sounds")
install(FILES ${SIPP_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/sipp")
install(FILES ${CERTIFICATE_ALT_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/altname")
install(FILES ${CERTIFICATE_CN_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/cn")
install(FILES ${CERTIFICATE_CLIENT_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/client")
install(FILES ${RC_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/rcfiles")
install(FILES ${IMAGE_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/images")
install(FILES ${VCARD_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/vcards")
endif()
endif()

View file

@ -1044,7 +1044,6 @@ static void terminate_call_with_error(void) {
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rei), "Call refused for security reason");
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(ei), "SIP");
}
BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(call_callee)), LinphoneCallAcceptedElsewhere, int, "%d");
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1));
@ -1095,7 +1094,6 @@ static void cancel_call_with_error(void) {
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rei), "Call has been cancelled");
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(rei), "SIP");
}
BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(call_callee)), LinphoneCallDeclinedElsewhere, int, "%d");
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1));
@ -1144,7 +1142,6 @@ static void cancel_other_device_after_accept(void) {
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rei), "Call completed elsewhere");
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(rei), "SIP");
}
BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(call_callee_2)), LinphoneCallAcceptedElsewhere, int, "%d");
}
linphone_call_terminate(out_call);
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1));
@ -1182,12 +1179,10 @@ static void cancel_other_device_after_decline(void) {
BC_ASSERT_PTR_NOT_NULL(call_callee_2);
BC_ASSERT_EQUAL(linphone_call_decline(call_callee, LinphoneReasonDeclined), 0 , int, "%d");
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallEnd,1));
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1));
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallReleased, 1));
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallEnd,1));
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallReleased, 1));
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr_2->lc, &callee_mgr_2->stat.number_of_LinphoneCallEnd,1));
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr_2->lc, &callee_mgr_2->stat.number_of_LinphoneCallReleased,1));
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr_2->lc,&callee_mgr_2->stat.number_of_LinphoneCallEnd,1));
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr_2->lc,&callee_mgr_2->stat.number_of_LinphoneCallReleased,1));
rei = linphone_call_get_error_info(call_callee_2);
BC_ASSERT_PTR_NOT_NULL(rei);
@ -1197,7 +1192,6 @@ static void cancel_other_device_after_decline(void) {
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rei), "Busy Everywhere");
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(rei), "SIP");
}
BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(call_callee_2)), LinphoneCallDeclinedElsewhere, int, "%d");
}
if (out_call) linphone_call_unref(out_call);
if (call_callee) linphone_call_unref(call_callee);
@ -3427,7 +3421,7 @@ static void call_redirect(void){
LinphoneCoreManager* laure = linphone_core_manager_new("laure_rc_udp");
bctbx_list_t* lcs = NULL;
char *laure_url = NULL;
LinphoneCall* marie_call, *laure_call;
LinphoneCall* marie_call;
lcs = bctbx_list_append(lcs,marie->lc);
lcs = bctbx_list_append(lcs,pauline->lc);
@ -3452,20 +3446,16 @@ static void call_redirect(void){
/* the call should still be ringing on marie's side */
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingRinging, 1, int, "%i");
laure_call = linphone_core_get_current_call(laure->lc);
BC_ASSERT_PTR_NOT_NULL(laure_call);
if (laure_call) {
linphone_call_accept(laure_call);
linphone_call_accept(linphone_core_get_current_call(laure->lc));
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallStreamsRunning, 1,5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallStreamsRunning, 1,5000));
BC_ASSERT_PTR_EQUAL(marie_call, linphone_core_get_current_call(marie->lc));
BC_ASSERT_PTR_EQUAL(marie_call, linphone_core_get_current_call(marie->lc));
liblinphone_tester_check_rtcp(marie, laure);
liblinphone_tester_check_rtcp(marie, laure);
end_call(laure, marie);
}
end_call(laure, marie);
}
bctbx_list_free(lcs);

View file

@ -1,66 +0,0 @@
/*
* clonable-object-tester.cpp
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "object/clonable-object-p.h"
#include "object/clonable-object.h"
#include "liblinphone_tester.h"
// =============================================================================
using namespace std;
using namespace LinphonePrivate;
// -----------------------------------------------------------------------------
class TestObjectPrivate : public ClonableObjectPrivate {
public:
TestObjectPrivate () = default;
TestObjectPrivate (const TestObjectPrivate &) : TestObjectPrivate() {}
};
class TestObject : public ClonableObject {
public:
TestObject () : ClonableObject(*new TestObjectPrivate) {}
TestObject (const TestObject &src) : ClonableObject(*new TestObjectPrivate(*src.getPrivate())) {}
private:
L_DECLARE_PRIVATE(TestObject);
};
// -----------------------------------------------------------------------------
static void check_clonable_object_creation () {
TestObject *object = new TestObject();
TestObject *object2 = new TestObject(*object);
delete object;
delete object2;
}
test_t clonable_object_tests[] = {
TEST_NO_TAG("Check clonable object creation", check_clonable_object_creation)
};
test_suite_t clonable_object_test_suite = {
"ClonableObject", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
sizeof(clonable_object_tests) / sizeof(clonable_object_tests[0]), clonable_object_tests
};

View file

@ -1,5 +1,5 @@
/*
* cpim-tester.cpp
* liblinphone_tester - liblinphone test suite
* Copyright (C) 2017 Belledonne Communications SARL
*
* This program is free software: you can redistribute it and/or modify
@ -20,13 +20,13 @@
#include "liblinphone_tester.h"
// =============================================================================
using namespace std;
using namespace LINPHONE_NAMESPACE;
using namespace LinphonePrivate;
static void parse_minimal_message () {
// =============================================================================
static void parse_minimal_message (void) {
const string str = "Content-type: Message/CPIM\r\n"
"\r\n"
"Content-Type: text/plain; charset=utf-8\r\n"
@ -39,7 +39,7 @@ static void parse_minimal_message () {
BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str());
}
static void set_generic_header_name () {
static void set_generic_header_name (void) {
const list<pair<string, bool> > entries = {
{ "toto", true },
{ "george.abitbol", true },
@ -82,7 +82,7 @@ static void set_generic_header_name () {
}
}
static void set_generic_header_value () {
static void set_generic_header_value (void) {
const list<pair<string, bool> > entries = {
{ "MyFeatures <mid:MessageFeatures@id.foo.com>", true },
{ "2000-12-13T13:40:00-08:00", true },
@ -106,7 +106,7 @@ static void set_generic_header_value () {
}
}
static void check_core_header_names () {
static void check_core_header_names (void) {
const list<pair<shared_ptr<Cpim::CoreHeader>, string> > entries = {
{ make_shared<Cpim::FromHeader>(), "From" },
{ make_shared<Cpim::ToHeader>(), "To" },
@ -123,7 +123,7 @@ static void check_core_header_names () {
}
}
static void set_core_header_values () {
static void set_core_header_values (void) {
const list<pair<shared_ptr<Cpim::Header>, list<pair<string, bool> > > > entries = {
{ make_shared<Cpim::FromHeader>(), {
{ "Winnie the Pooh <im:pooh@100akerwood.com>", true },
@ -196,7 +196,7 @@ static void set_core_header_values () {
}
}
static void check_subject_header_language () {
static void check_subject_header_language (void) {
Cpim::SubjectHeader subjectHeader;
// Check for not defined language.
@ -226,7 +226,7 @@ static void check_subject_header_language () {
}
}
static void parse_rfc_example () {
static void parse_rfc_example (void) {
const string str = "Content-type: Message/CPIM\r\n"
"\r\n"
"From: MR SANDERS <im:piglet@100akerwood.com>\r\n"
@ -253,7 +253,7 @@ static void parse_rfc_example () {
BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str());
}
static void parse_message_with_generic_header_parameters () {
static void parse_message_with_generic_header_parameters (void) {
const string str = "Content-type: Message/CPIM\r\n"
"\r\n"
"From: MR SANDERS <im:piglet@100akerwood.com>\r\n"
@ -275,7 +275,7 @@ static void parse_message_with_generic_header_parameters () {
BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str());
}
static void build_message () {
static void build_message (void) {
Cpim::Message message;
if (!BC_ASSERT_FALSE(message.isValid()))
return;

Binary file not shown.

View file

@ -1,50 +0,0 @@
/*
* events-db-tester.cpp
* Copyright (C) 2017 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "db/events-db.h"
#include "liblinphone_tester.h"
// =============================================================================
using namespace std;
using namespace LinphonePrivate;
// -----------------------------------------------------------------------------
static const string getDatabasePath () {
static const string path = string(bc_tester_get_resource_dir_prefix()) + "/db/linphone.db";
return path;
}
// -----------------------------------------------------------------------------
static void open_database () {
EventsDb eventsDb;
BC_ASSERT_TRUE(eventsDb.connect(EventsDb::Sqlite3, getDatabasePath()));
}
test_t events_db_tests[] = {
TEST_NO_TAG("Open database", open_database)
};
test_suite_t events_db_test_suite = {
"EventsDb", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
sizeof(events_db_tests) / sizeof(events_db_tests[0]), events_db_tests
};

View file

@ -955,7 +955,7 @@ static void dos_module_trigger(void) {
// At this point we should be banned for a minute
wait_for_until(marie->lc, pauline->lc, &dummy, 1, 65000);; // Wait several seconds to ensure we are not banned anymore
BC_ASSERT_LOWER_STRICT(marie->stat.number_of_LinphoneMessageReceived, number_of_messge_to_send, int, "%d");
BC_ASSERT_LOWER(marie->stat.number_of_LinphoneMessageReceived, number_of_messge_to_send, int, "%d");
reset_counters(&marie->stat);
reset_counters(&pauline->stat);

View file

@ -171,7 +171,6 @@ static void log_handler(int lev, const char *fmt, va_list args) {
}
void liblinphone_tester_init(void(*ftester_printf)(int level, const char *fmt, va_list args)) {
bctbx_init_logger(FALSE);
if (! log_file) {
#if defined(__ANDROID__)
linphone_core_set_log_handler(liblinphone_android_ortp_log_handler);

View file

@ -42,11 +42,9 @@ extern "C" {
extern test_suite_t account_creator_test_suite;
extern test_suite_t call_test_suite;
extern test_suite_t call_video_test_suite;
extern test_suite_t clonable_object_test_suite;
extern test_suite_t cpim_test_suite;
extern test_suite_t dtmf_test_suite;
extern test_suite_t event_test_suite;
extern test_suite_t events_db_test_suite;
extern test_suite_t flexisip_test_suite;
extern test_suite_t log_collection_test_suite;
extern test_suite_t message_test_suite;

View file

@ -161,7 +161,7 @@ void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneC
void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
stats *counters = get_stats(lc);
if (linphone_chat_room_is_remote_composing(room)) {
if (room->remote_is_composing == LinphoneIsComposingActive) {
counters->number_of_LinphoneIsComposingActiveReceived++;
} else {
counters->number_of_LinphoneIsComposingIdleReceived++;
@ -236,7 +236,7 @@ LinphoneChatMessage* create_message_from_sintel_trailer(LinphoneChatRoom *chat_r
file_size = ftell(file_to_send);
fseek(file_to_send, 0, SEEK_SET);
content = linphone_core_create_content(linphone_chat_room_get_core(chat_room));
content = linphone_core_create_content(chat_room->lc);
belle_sip_object_set_name(&content->base, "sintel trailer content");
linphone_content_set_type(content,"video");
linphone_content_set_subtype(content,"mkv");
@ -262,7 +262,7 @@ LinphoneChatMessage* create_file_transfer_message_from_sintel_trailer(LinphoneCh
LinphoneChatMessage* msg;
char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv");
content = linphone_core_create_content(linphone_chat_room_get_core(chat_room));
content = linphone_core_create_content(chat_room->lc);
belle_sip_object_set_name(&content->base, "sintel trailer content");
linphone_content_set_type(content,"video");
linphone_content_set_subtype(content,"mkv");
@ -413,15 +413,15 @@ static void text_message_with_send_error(void) {
linphone_chat_room_send_chat_message(chat_room,msg);
/* check transient msg list: the msg should be in it, and should be the only one */
BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_chat_room_get_transient_messages(chat_room)), 1, unsigned int, "%u");
BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(linphone_chat_room_get_transient_messages(chat_room),0), msg);
BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 1, unsigned int, "%u");
BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(chat_room->transient_messages,0), msg);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1));
/*BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageInProgress,1, int, "%d");*/
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceived,0, int, "%d");
/* the msg should have been discarded from transient list after an error */
BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_chat_room_get_transient_messages(chat_room)), 0, unsigned int, "%u");
BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 0, unsigned int, "%u");
sal_set_send_error(marie->lc->sal, 0);
@ -446,8 +446,8 @@ static void text_message_with_external_body(void) {
linphone_chat_room_send_chat_message(chat_room,msg);
/* check transient msg list: the msg should be in it, and should be the only one */
BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_chat_room_get_transient_messages(chat_room)), 1, unsigned int, "%u");
BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(linphone_chat_room_get_transient_messages(chat_room),0), msg);
BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 1, unsigned int, "%u");
BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(chat_room->transient_messages,0), msg);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1));
@ -455,7 +455,7 @@ static void text_message_with_external_body(void) {
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,1, int, "%d");
BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_chat_room_get_transient_messages(chat_room)), 0, unsigned int, "%u");
BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 0, unsigned int, "%u");
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);

View file

@ -306,40 +306,6 @@ static void subscribe_failure_handle_by_app(void) {
linphone_core_manager_destroy(pauline);
}
static void publish_with_network_state_changes(void) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneProxyConfig* proxy;
LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
linphone_core_cbs_set_publish_state_changed(cbs, linphone_publish_state_changed);
_linphone_core_add_callbacks(marie->lc, cbs,TRUE);
linphone_core_cbs_unref(cbs);
proxy = linphone_core_get_default_proxy_config(marie->lc);
linphone_proxy_config_edit(proxy);
linphone_proxy_config_enable_publish(proxy,TRUE);
linphone_proxy_config_done(proxy);
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,1));
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,1));
linphone_core_set_network_reachable(marie->lc, FALSE);
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationNone,1));
BC_ASSERT_FALSE(wait_for_until(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,2,1000));
BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,1,int,"%i");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishError,0,int,"%i");
linphone_core_set_network_reachable(marie->lc, TRUE);
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,2));
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,2));
linphone_core_manager_stop(marie);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishCleared,1,int,"%i"); /*yes it is 3 because when we change the expires, a new LinphoneEvent is created*/
BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,2,int,"%i");
linphone_core_manager_destroy(marie);
}
static void simple_subscribe(void) {
LinphoneCoreManager* marie = presence_linphone_core_manager_new("marie");
LinphoneCoreManager* pauline = presence_linphone_core_manager_new("pauline");
@ -643,11 +609,10 @@ test_t presence_tests[] = {
TEST_NO_TAG("Simple Publish", simple_publish),
TEST_NO_TAG("Publish with 2 identities", publish_with_dual_identity),
TEST_NO_TAG("Simple Publish with expires", publish_with_expires),
TEST_ONE_TAG("Publish with network state changes", publish_with_network_state_changes, "presence"),
/*TEST_ONE_TAG("Call with presence", call_with_presence, "LeaksMemory"),*/
TEST_NO_TAG("Unsubscribe while subscribing", unsubscribe_while_subscribing),
TEST_NO_TAG("Presence information", presence_information),
TEST_ONE_TAG("App managed presence failure", subscribe_failure_handle_by_app, "LeaksMemory"),
TEST_NO_TAG("App managed presence failure", subscribe_failure_handle_by_app),
TEST_NO_TAG("Presence SUBSCRIBE forked", subscribe_presence_forked),
TEST_NO_TAG("Presence SUBSCRIBE expired", subscribe_presence_expired),
};

View file

@ -553,7 +553,6 @@ static void network_state_change(void){
linphone_core_set_network_reachable(lc,FALSE);
BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_NetworkReachableFalse,1));
BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationNone,register_ok));
BC_ASSERT_FALSE(wait_for_until(lc,lc,&counters->number_of_LinphoneRegistrationProgress,register_ok+1,1000)); /*make sure no register is tried*/
linphone_core_set_network_reachable(lc,TRUE);
BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_NetworkReachableTrue,1));
wait_for(lc,lc,&counters->number_of_LinphoneRegistrationOk,2*register_ok);
@ -613,7 +612,7 @@ static void transport_dont_bind(void){
LinphoneTransports *tr = linphone_transports_new();
linphone_transports_set_tcp_port(tr, LC_SIP_TRANSPORT_DONTBIND);
linphone_transports_set_tls_port(tr, LC_SIP_TRANSPORT_DONTBIND);
linphone_core_set_transports(pauline->lc, tr);
BC_ASSERT_TRUE(wait_for_until(pauline->lc,pauline->lc,&counters->number_of_LinphoneRegistrationOk,2,15000));
linphone_transports_unref(tr);
@ -628,14 +627,14 @@ static void transport_dont_bind(void){
static void transport_busy(void){
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
LCSipTransports tr;
memset(&tr, 0, sizeof(tr));
tr.udp_port = 5070;
tr.tcp_port = 5070;
tr.tls_port = 5071;
linphone_core_set_sip_transports(pauline->lc, &tr);
{
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
linphone_core_set_sip_transports(marie->lc, &tr);
@ -646,7 +645,7 @@ static void transport_busy(void){
BC_ASSERT_EQUAL(tr.tls_port, 0, int, "%i");*/
linphone_core_manager_destroy(marie);
}
linphone_core_manager_destroy(pauline);
}
@ -915,7 +914,7 @@ char *read_file(const char *path) {
size_t readbytes;
char *buffer = NULL;
FILE *infile = fopen(path, "rb");
BC_ASSERT_PTR_NOT_NULL(infile);
if (infile) {
fseek(infile, 0L, SEEK_END);

View file

@ -184,8 +184,8 @@ static void linphone_lpconfig_from_xml_zerolen_value(void){
* This test makes a provisionning by xml outside of the Configuring state of the LinphoneCore.
* It is leaking memory because the config is litterally erased and rewritten by the invocation
* of the private function linphone_remote_provisioning_load_file .
*/
*/
BC_ASSERT_EQUAL(linphone_remote_provisioning_load_file(mgr->lc, xml_path), 0, int, "%d");
conf = mgr->lc->config;
@ -349,7 +349,7 @@ static void codec_setup(void){
BC_ASSERT_TRUE(codecs->data == vp8);
BC_ASSERT_TRUE(codecs->next->data == h264);
linphone_core_manager_destroy(mgr);
mgr = linphone_core_manager_new2("marie_h264_rc", FALSE);
vp8 = linphone_core_find_payload_type(mgr->lc, "VP8", 90000, -1);
h264 = linphone_core_find_payload_type(mgr->lc, "H264", 90000, -1);
@ -360,7 +360,7 @@ static void codec_setup(void){
BC_ASSERT_TRUE(codecs->data == vp8);
BC_ASSERT_TRUE(codecs->next->data == h264);
linphone_core_manager_destroy(mgr);
mgr = linphone_core_manager_new2("marie_rc", FALSE);
vp8 = linphone_core_find_payload_type(mgr->lc, "VP8", 90000, -1);
h264 = linphone_core_find_payload_type(mgr->lc, "H264", 90000, -1);
@ -371,13 +371,13 @@ static void codec_setup(void){
BC_ASSERT_TRUE(codecs->data == vp8);
BC_ASSERT_TRUE(codecs->next->data == h264);
linphone_core_manager_destroy(mgr);
}
static void custom_tones_setup(void){
LinphoneCoreManager *mgr = linphone_core_manager_new2("empty_rc", FALSE);
const char *tone;
linphone_core_set_tone(mgr->lc, LinphoneToneCallOnHold, "callonhold.wav");
tone = linphone_core_get_tone_file(mgr->lc, LinphoneToneCallOnHold);
BC_ASSERT_PTR_NOT_NULL(tone);
@ -409,7 +409,7 @@ test_t setup_tests[] = {
TEST_NO_TAG("Devices reload", devices_reload_test),
TEST_NO_TAG("Codec usability", codec_usability_test),
TEST_NO_TAG("Codec setup", codec_setup),
TEST_NO_TAG("Custom tones setup", custom_tones_setup)
TEST_NO_TAG("Custom tones setup", custom_tones_setup)
};
test_suite_t setup_test_suite = {"Setup", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,

View file

@ -574,8 +574,6 @@ void liblinphone_tester_add_suites() {
bc_tester_add_suite(&player_test_suite);
bc_tester_add_suite(&dtmf_test_suite);
bc_tester_add_suite(&cpim_test_suite);
bc_tester_add_suite(&clonable_object_test_suite);
bc_tester_add_suite(&events_db_test_suite);
#if defined(VIDEO_ENABLED) && defined(HAVE_GTK)
bc_tester_add_suite(&video_test_suite);
#endif
@ -677,7 +675,6 @@ void liblinphone_tester_uninit(void) {
all_leaks_buffer = NULL;
}
bc_tester_uninit();
bctbx_uninit_logger();
}
static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStreamType stream_type) {

View file

@ -22,7 +22,7 @@ import sys
import pystache
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools'))
print(sys.path)
print sys.path
import genapixml as CApi
import abstractapi as AbsApi
import metadoc
@ -604,18 +604,17 @@ def main():
interfaces = []
classes = []
for index in [parser.classesIndex, parser.interfacesIndex]:
for _class in index.values():
if _class is not None:
try:
if type(_class) is AbsApi.Class:
impl = ClassImpl(_class, translator)
classes.append(impl)
else:
impl = InterfaceImpl(_class, translator)
interfaces.append(impl)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
for _class in parser.classesIndex.values() + parser.interfacesIndex.values():
if _class is not None:
try:
if type(_class) is AbsApi.Class:
impl = ClassImpl(_class, translator)
classes.append(impl)
else:
impl = InterfaceImpl(_class, translator)
interfaces.append(impl)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
wrapper = WrapperImpl(enums, interfaces, classes)
render(renderer, wrapper, args.outputdir + "/" + args.outputfile)