mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-30 01:39:20 +00:00
Add API to resend a chat message that has not been delivered.
This commit is contained in:
parent
87cfca94b5
commit
5193bb34e1
9 changed files with 101 additions and 54 deletions
|
|
@ -159,6 +159,7 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
|
|||
belle_sip_request_t *req;
|
||||
belle_sip_uri_t* req_uri;
|
||||
belle_sip_uri_t* to_uri;
|
||||
belle_sip_header_call_id_t *call_id_header;
|
||||
|
||||
const SalAddress* to_address;
|
||||
const MSList *elem=sal_op_get_route_addresses(op);
|
||||
|
|
@ -189,11 +190,15 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
|
|||
belle_sip_uri_set_secure(req_uri,sal_op_is_secure(op));
|
||||
|
||||
to_header = belle_sip_header_to_create(BELLE_SIP_HEADER_ADDRESS(to_address),NULL);
|
||||
call_id_header = belle_sip_provider_create_call_id(prov);
|
||||
if (sal_op_get_call_id(op)) {
|
||||
belle_sip_header_call_id_set_call_id(call_id_header, sal_op_get_call_id(op));
|
||||
}
|
||||
|
||||
req=belle_sip_request_create(
|
||||
req_uri,
|
||||
method,
|
||||
belle_sip_provider_create_call_id(prov),
|
||||
call_id_header,
|
||||
belle_sip_header_cseq_create(20,method),
|
||||
from_header,
|
||||
to_header,
|
||||
|
|
|
|||
|
|
@ -1148,34 +1148,12 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){
|
|||
}
|
||||
}
|
||||
|
||||
static bool_t is_duplicate_msg(LinphoneCore *lc, const char *msg_id){
|
||||
bctbx_list_t *elem=lc->last_recv_msg_ids;
|
||||
bctbx_list_t *tail=NULL;
|
||||
int i;
|
||||
bool_t is_duplicate=FALSE;
|
||||
for(i=0;elem!=NULL;elem=elem->next,i++){
|
||||
if (strcmp((const char*)elem->data,msg_id)==0){
|
||||
is_duplicate=TRUE;
|
||||
}
|
||||
tail=elem;
|
||||
}
|
||||
if (!is_duplicate){
|
||||
lc->last_recv_msg_ids=bctbx_list_prepend(lc->last_recv_msg_ids,ms_strdup(msg_id));
|
||||
}
|
||||
if (i>=10){
|
||||
ms_free(tail->data);
|
||||
lc->last_recv_msg_ids=bctbx_list_erase_link(lc->last_recv_msg_ids,tail);
|
||||
}
|
||||
return is_duplicate;
|
||||
}
|
||||
|
||||
|
||||
static void message_received(SalOp *op, const SalMessage *msg){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
LinphoneReason reason = lc->chat_deny_code;
|
||||
if (reason == LinphoneReasonNone && is_duplicate_msg(lc, msg->message_id) == FALSE) {
|
||||
reason = linphone_core_message_received(lc, op, msg);
|
||||
if (reason == LinphoneReasonNone) {
|
||||
linphone_core_message_received(lc, op, msg);
|
||||
}
|
||||
sal_message_reply(op, linphone_reason_to_sal(reason));
|
||||
if (!call) sal_op_release(op);
|
||||
|
|
|
|||
|
|
@ -383,7 +383,6 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
|
|||
|
||||
msg->dir = LinphoneChatMessageOutgoing;
|
||||
|
||||
|
||||
/* Check if we shall upload a file to a server */
|
||||
if (msg->file_transfer_information != NULL && msg->content_type == NULL) {
|
||||
/* open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */
|
||||
|
|
@ -397,16 +396,20 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
SalOp *op = NULL;
|
||||
SalOp *op = msg->op;
|
||||
LinphoneCall *call=NULL;
|
||||
char *content_type;
|
||||
const char *identity = NULL;
|
||||
char *message_not_encrypted = NULL;
|
||||
|
||||
char *clear_text_message = NULL;
|
||||
char *clear_text_content_type = NULL;
|
||||
|
||||
if (msg->message) {
|
||||
message_not_encrypted = ms_strdup(msg->message);
|
||||
clear_text_message = ms_strdup(msg->message);
|
||||
}
|
||||
|
||||
if (msg->content_type) {
|
||||
clear_text_content_type = ms_strdup(msg->content_type);
|
||||
}
|
||||
|
||||
/* Add to transient list */
|
||||
linphone_chat_room_add_transient_message(cr, msg);
|
||||
msg->time = ms_time(0);
|
||||
|
|
@ -421,7 +424,7 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!identity) {
|
||||
LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(cr->lc, cr->peer_url);
|
||||
if (proxy) {
|
||||
|
|
@ -438,7 +441,7 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
|
|||
linphone_address_unref(msg->from);
|
||||
}
|
||||
msg->from = linphone_address_new(identity);
|
||||
|
||||
|
||||
if (imee) {
|
||||
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
|
||||
LinphoneImEncryptionEngineCbsOutgoingMessageCb cb_process_outgoing_message = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imee_cbs);
|
||||
|
|
@ -449,7 +452,7 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (op == NULL) {
|
||||
/*sending out of calls*/
|
||||
msg->op = op = sal_op_new(cr->lc->sal);
|
||||
|
|
@ -457,7 +460,7 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
|
|||
lp_config_get_int(cr->lc->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, retval, "Unable to encrypt IM", NULL);
|
||||
store_or_update_chat_message(msg);
|
||||
|
|
@ -481,10 +484,15 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
|
|||
ms_free(peer_uri);
|
||||
}
|
||||
|
||||
if (msg->message && message_not_encrypted && strcmp(msg->message, message_not_encrypted) != 0) {
|
||||
if (msg->message && clear_text_message && strcmp(msg->message, clear_text_message) != 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(message_not_encrypted);
|
||||
msg->message = ms_strdup(clear_text_message);
|
||||
}
|
||||
if (msg->content_type && clear_text_content_type && (strcmp(msg->content_type, clear_text_content_type) != 0)) {
|
||||
/* We replace the encrypted content type by the original one */
|
||||
ms_free(msg->content_type);
|
||||
msg->content_type = ms_strdup(clear_text_content_type);
|
||||
}
|
||||
msg->message_id = ms_strdup(sal_op_get_call_id(op)); /* must be known at that time */
|
||||
store_or_update_chat_message(msg);
|
||||
|
|
@ -495,8 +503,11 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
|
|||
linphone_chat_room_delete_composing_idle_timer(cr);
|
||||
linphone_chat_room_delete_composing_refresh_timer(cr);
|
||||
|
||||
if (message_not_encrypted) {
|
||||
ms_free(message_not_encrypted);
|
||||
if (clear_text_message) {
|
||||
ms_free(clear_text_message);
|
||||
}
|
||||
if (clear_text_content_type) {
|
||||
ms_free(clear_text_content_type);
|
||||
}
|
||||
|
||||
if (call && call->op == op) {
|
||||
|
|
@ -648,6 +659,12 @@ LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const
|
|||
linphone_address_clean(addr);
|
||||
cr = linphone_core_get_chat_room(lc, addr);
|
||||
|
||||
/* Check if this is a duplicate message */
|
||||
if (linphone_chat_room_find_message(cr, sal_op_get_call_id(op)) != NULL) {
|
||||
reason = lc->chat_deny_code;
|
||||
goto end;
|
||||
}
|
||||
|
||||
msg = linphone_chat_room_create_message(cr, sal_msg->text);
|
||||
linphone_chat_message_set_content_type(msg, sal_msg->content_type);
|
||||
linphone_chat_message_set_from(msg, cr->peer_url);
|
||||
|
|
@ -950,6 +967,28 @@ void linphone_chat_room_send_chat_message(LinphoneChatRoom *cr, LinphoneChatMess
|
|||
_linphone_chat_room_send_message(cr, msg);
|
||||
}
|
||||
|
||||
void _linphone_chat_message_resend(LinphoneChatMessage *msg, bool_t ref_msg) {
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(msg);
|
||||
LinphoneChatRoom *cr;
|
||||
|
||||
if (state != LinphoneChatMessageStateNotDelivered) {
|
||||
ms_warning("Cannot resend chat message in state %s", linphone_chat_message_state_to_string(state));
|
||||
return;
|
||||
}
|
||||
|
||||
cr = linphone_chat_message_get_chat_room(msg);
|
||||
if (ref_msg) linphone_chat_message_ref(msg);
|
||||
_linphone_chat_room_send_message(cr, msg);
|
||||
}
|
||||
|
||||
void linphone_chat_message_resend(LinphoneChatMessage *msg) {
|
||||
_linphone_chat_message_resend(msg, FALSE);
|
||||
}
|
||||
|
||||
void linphone_chat_message_resend_2(LinphoneChatMessage *msg) {
|
||||
_linphone_chat_message_resend(msg, TRUE);
|
||||
}
|
||||
|
||||
static char *linphone_chat_room_create_is_composing_xml(LinphoneChatRoom *cr) {
|
||||
xmlBufferPtr buf;
|
||||
xmlTextWriterPtr writer;
|
||||
|
|
|
|||
|
|
@ -5523,9 +5523,6 @@ static void linphone_core_uninit(LinphoneCore *lc)
|
|||
bctbx_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref);
|
||||
lc->call_logs=bctbx_list_free(lc->call_logs);
|
||||
|
||||
bctbx_list_for_each(lc->last_recv_msg_ids,ms_free);
|
||||
lc->last_recv_msg_ids=bctbx_list_free(lc->last_recv_msg_ids);
|
||||
|
||||
if(lc->zrtp_secrets_cache != NULL) {
|
||||
ms_free(lc->zrtp_secrets_cache);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1051,7 +1051,6 @@ struct _LinphoneCore
|
|||
int max_calls;
|
||||
LinphoneTunnel *tunnel;
|
||||
char* device_id;
|
||||
MSList *last_recv_msg_ids;
|
||||
char *chat_db_file;
|
||||
char *logs_db_file;
|
||||
char *friends_db_file;
|
||||
|
|
|
|||
|
|
@ -412,6 +412,12 @@ LINPHONE_PUBLIC int linphone_chat_message_download_file(LinphoneChatMessage *mes
|
|||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_cancel_file_transfer(LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Resend a chat message if it is in the 'not delivered' state for whatever reason.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_resend(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Linphone message has an app-specific field that can store a text. The application might want
|
||||
* to use it for keeping data over restarts, like thumbnail image path.
|
||||
|
|
|
|||
|
|
@ -44,12 +44,22 @@ extern "C" {
|
|||
* @note Unlike linphone_chat_room_send_chat_message(), that function only takes a reference on the #LinphoneChatMessage
|
||||
* instead of totaly takes ownership on it. Thus, the #LinphoneChatMessage object must be released by the API user after calling
|
||||
* that function.
|
||||
*
|
||||
*
|
||||
* @param[in] cr A chat room.
|
||||
* @param[in] msg The message to send.
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_room_send_chat_message_2(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Resend a chat message if it is in the 'not delivered' state for whatever reason.
|
||||
* @note Unlike linphone_chat_message_resend(), that function only takes a reference on the #LinphoneChatMessage
|
||||
* instead of totaly takes ownership on it. Thus, the #LinphoneChatMessage object must be released by the API user after calling
|
||||
* that function.
|
||||
*
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_resend(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Accessor for the shared_ptr<BelCard> stored by a #LinphoneVcard
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1090,7 +1090,8 @@ static void im_notification_policy_with_lime(void) {
|
|||
static void _im_error_delivery_notification(bool_t online) {
|
||||
FILE *ZIDCacheMarieFD, *ZIDCachePaulineFD;
|
||||
LinphoneChatRoom *chat_room;
|
||||
char *filepath;
|
||||
char *marie_filepath;
|
||||
char *pauline_filepath;
|
||||
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
|
||||
LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_tcp_rc");
|
||||
LinphoneChatMessage *msg;
|
||||
|
|
@ -1114,13 +1115,12 @@ static void _im_error_delivery_notification(bool_t online) {
|
|||
fclose(ZIDCacheMarieFD);
|
||||
fclose(ZIDCachePaulineFD);
|
||||
|
||||
filepath = bc_tester_file("tmpZIDCacheMarie.xml");
|
||||
linphone_core_set_zrtp_secrets_file(marie->lc, filepath);
|
||||
bc_free(filepath);
|
||||
marie_filepath = bc_tester_file("tmpZIDCacheMarie.xml");
|
||||
linphone_core_set_zrtp_secrets_file(marie->lc, marie_filepath);
|
||||
|
||||
filepath = bc_tester_file("tmpZIDCachePauline.xml");
|
||||
linphone_core_set_zrtp_secrets_file(pauline->lc, filepath);
|
||||
bc_free(filepath);
|
||||
pauline_filepath = bc_tester_file("tmpZIDCachePauline.xml");
|
||||
linphone_core_set_zrtp_secrets_file(pauline->lc, pauline_filepath);
|
||||
bc_free(pauline_filepath);
|
||||
|
||||
chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
|
||||
|
||||
|
|
@ -1154,13 +1154,21 @@ static void _im_error_delivery_notification(bool_t online) {
|
|||
wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /* Just to sleep while iterating */
|
||||
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceived, 1, int, "%d"); /* Check the new message is not considered as received */
|
||||
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageNotDelivered, 1));
|
||||
|
||||
/* Restore the ZID cache of the receiver and resend the chat message */
|
||||
linphone_core_set_zrtp_secrets_file(marie->lc, marie_filepath);
|
||||
linphone_chat_message_ref(msg);
|
||||
linphone_chat_message_resend(msg);
|
||||
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 2)); /* Check the new message is now received */
|
||||
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDeliveredToUser, 1));
|
||||
linphone_chat_message_unref(msg);
|
||||
bc_free(marie_filepath);
|
||||
|
||||
end:
|
||||
remove("tmpZIDCacheMarie.xml");
|
||||
remove("tmpZIDCachePauline.xml");
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
remove("tmpZIDCacheMarie.xml");
|
||||
remove("tmpZIDCachePauline.xml");
|
||||
}
|
||||
|
||||
static void im_error_delivery_notification_online(void) {
|
||||
|
|
@ -1260,7 +1268,11 @@ static void lime_text_message_to_non_lime(bool_t sender_policy_mandatory, bool_t
|
|||
if (chat_room_size == 1) {
|
||||
bctbx_list_t *history = linphone_chat_room_get_history(chat_room, 0);
|
||||
LinphoneChatMessage *sent_msg = (LinphoneChatMessage *)bctbx_list_get_data(history);
|
||||
BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateDelivered, int, "%d");
|
||||
if (lime_key_available) {
|
||||
BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateDelivered, int, "%d");
|
||||
} else {
|
||||
BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateNotDelivered, int, "%d");
|
||||
}
|
||||
bctbx_list_free_with_data(history, (bctbx_list_free_func)linphone_chat_message_unref);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -440,6 +440,7 @@ class CParser(object):
|
|||
'linphone_factory_create_core_with_config', # manualy wrapped
|
||||
'linphone_buffer_get_content',
|
||||
'linphone_chat_room_send_chat_message', # overloaded
|
||||
'linphone_chat_message_resend', # overloaded
|
||||
'linphone_config_read_relative_file',
|
||||
'linphone_vcard_get_belcard', # manualy wrapped
|
||||
'linphone_chat_room_destroy', # was deprecated when the wrapper generator was made
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue